1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2002-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file ROPerson.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Axel Wegener
13 /// @author Michael Behrisch
14 /// @author Jakob Erdmann
15 /// @date Sept 2002
16 /// @version $Id$
17 ///
18 // A vehicle as used by router
19 /****************************************************************************/
20
21
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26
27 #include <string>
28 #include <iostream>
29 #include <utils/common/StringTokenizer.h>
30 #include <utils/common/ToString.h>
31 #include <utils/common/StringUtils.h>
32 #include <utils/common/MsgHandler.h>
33 #include <utils/vehicle/SUMOVTypeParameter.h>
34 #include <utils/options/OptionsCont.h>
35 #include <utils/iodevices/OutputDevice.h>
36 #include "RORouteDef.h"
37 #include "RORoute.h"
38 #include "ROVehicle.h"
39 #include "ROHelper.h"
40 #include "RONet.h"
41 #include "ROLane.h"
42 #include "ROPerson.h"
43
44
45 // ===========================================================================
46 // method definitions
47 // ===========================================================================
ROPerson(const SUMOVehicleParameter & pars,const SUMOVTypeParameter * type)48 ROPerson::ROPerson(const SUMOVehicleParameter& pars, const SUMOVTypeParameter* type)
49 : RORoutable(pars, type) {
50 }
51
52
~ROPerson()53 ROPerson::~ROPerson() {
54 for (std::vector<PlanItem*>::const_iterator it = myPlan.begin(); it != myPlan.end(); ++it) {
55 delete *it;
56 }
57 }
58
59
60 void
addTrip(const ROEdge * const from,const ROEdge * const to,const SVCPermissions modeSet,const std::string & vTypes,const double departPos,const double arrivalPos,const std::string & busStop,double walkFactor)61 ROPerson::addTrip(const ROEdge* const from, const ROEdge* const to, const SVCPermissions modeSet,
62 const std::string& vTypes, const double departPos, const double arrivalPos, const std::string& busStop, double walkFactor) {
63 PersonTrip* trip = new PersonTrip(from, to, modeSet, departPos, arrivalPos, busStop, walkFactor);
64 RONet* net = RONet::getInstance();
65 SUMOVehicleParameter pars;
66 pars.departProcedure = DEPART_TRIGGERED;
67
68 for (StringTokenizer st(vTypes); st.hasNext();) {
69 pars.vtypeid = st.next();
70 pars.parametersSet |= VEHPARS_VTYPE_SET;
71 SUMOVTypeParameter* type = net->getVehicleTypeSecure(pars.vtypeid);
72 if (type == nullptr) {
73 delete trip;
74 throw InvalidArgument("The vehicle type '" + pars.vtypeid + "' in a trip for person '" + getID() + "' is not known.");
75 }
76 pars.id = getID() + "_" + toString(trip->getVehicles().size());
77 trip->addVehicle(new ROVehicle(pars, new RORouteDef("!" + pars.id, 0, false, false), type, net));
78 }
79 if (trip->getVehicles().empty()) {
80 if ((modeSet & SVC_PASSENGER) != 0) {
81 pars.id = getID() + "_0";
82 trip->addVehicle(new ROVehicle(pars, new RORouteDef("!" + pars.id, 0, false, false), net->getVehicleTypeSecure(DEFAULT_VTYPE_ID), net));
83 }
84 if ((modeSet & SVC_BICYCLE) != 0) {
85 pars.id = getID() + "_b0";
86 pars.vtypeid = DEFAULT_BIKETYPE_ID;
87 pars.parametersSet |= VEHPARS_VTYPE_SET;
88 trip->addVehicle(new ROVehicle(pars, new RORouteDef("!" + pars.id, 0, false, false), net->getVehicleTypeSecure(DEFAULT_BIKETYPE_ID), net));
89 }
90 }
91 myPlan.push_back(trip);
92 }
93
94
95 void
addRide(const ROEdge * const from,const ROEdge * const to,const std::string & lines,double arrivalPos,const std::string & destStop)96 ROPerson::addRide(const ROEdge* const from, const ROEdge* const to, const std::string& lines, double arrivalPos, const std::string& destStop) {
97 if (myPlan.empty() || myPlan.back()->isStop()) {
98 myPlan.push_back(new PersonTrip());
99 }
100 myPlan.back()->addTripItem(new Ride(from, to, lines, -1., arrivalPos, destStop));
101 }
102
103
104 void
addWalk(const ConstROEdgeVector & edges,const double duration,const double speed,const double departPos,const double arrivalPos,const std::string & busStop)105 ROPerson::addWalk(const ConstROEdgeVector& edges, const double duration, const double speed, const double departPos, const double arrivalPos, const std::string& busStop) {
106 if (myPlan.empty() || myPlan.back()->isStop()) {
107 myPlan.push_back(new PersonTrip());
108 }
109 myPlan.back()->addTripItem(new Walk(edges, -1., duration, speed, departPos, arrivalPos, busStop));
110 }
111
112
113 void
addStop(const SUMOVehicleParameter::Stop & stopPar,const ROEdge * const stopEdge)114 ROPerson::addStop(const SUMOVehicleParameter::Stop& stopPar, const ROEdge* const stopEdge) {
115 myPlan.push_back(new Stop(stopPar, stopEdge));
116 }
117
118
119 void
saveAsXML(OutputDevice & os,const bool extended) const120 ROPerson::Ride::saveAsXML(OutputDevice& os, const bool extended) const {
121 os.openTag(SUMO_TAG_RIDE);
122 std::string comment = "";
123 if (extended && cost >= 0.) {
124 os.writeAttr(SUMO_ATTR_COST, cost);
125 }
126 if (from != nullptr) {
127 os.writeAttr(SUMO_ATTR_FROM, from->getID());
128 }
129 if (to != nullptr) {
130 os.writeAttr(SUMO_ATTR_TO, to->getID());
131 }
132 if (destStop != "") {
133 os.writeAttr(SUMO_ATTR_BUS_STOP, destStop);
134 const std::string name = RONet::getInstance()->getStoppingPlaceName(destStop);
135 if (name != "") {
136 comment = " <!-- " + name + " -->";
137 }
138 }
139 os.writeAttr(SUMO_ATTR_LINES, lines);
140 if (intended != "" && intended != lines) {
141 os.writeAttr(SUMO_ATTR_INTENDED, intended);
142 }
143 if (depart >= 0) {
144 os.writeAttr(SUMO_ATTR_DEPART, time2string(depart));
145 }
146 os.closeTag(comment);
147 }
148
149
150 void
saveAsXML(OutputDevice & os,const bool extended) const151 ROPerson::Walk::saveAsXML(OutputDevice& os, const bool extended) const {
152 os.openTag(SUMO_TAG_WALK);
153 std::string comment = "";
154 if (extended && cost >= 0.) {
155 os.writeAttr(SUMO_ATTR_COST, cost);
156 }
157 if (dur > 0) {
158 os.writeAttr(SUMO_ATTR_DURATION, dur);
159 }
160 if (v > 0) {
161 os.writeAttr(SUMO_ATTR_SPEED, v);
162 }
163 os.writeAttr(SUMO_ATTR_EDGES, edges);
164 if (dep != 0.) {
165 os.writeAttr(SUMO_ATTR_DEPARTPOS, dep);
166 }
167 if (arr != 0. && destStop == "") {
168 os.writeAttr(SUMO_ATTR_ARRIVALPOS, arr);
169 }
170 if (destStop != "") {
171 os.writeAttr(SUMO_ATTR_BUS_STOP, destStop);
172 const std::string name = RONet::getInstance()->getStoppingPlaceName(destStop);
173 if (name != "") {
174 comment = " <!-- " + name + " -->";
175 }
176 }
177 os.closeTag(comment);
178 }
179
180 ROPerson::PlanItem*
clone() const181 ROPerson::PersonTrip::clone() const {
182 PersonTrip* result = new PersonTrip(from, to, modes, dep, arr, stopDest, walkFactor);
183 for (auto* item : myTripItems) {
184 result->myTripItems.push_back(item->clone());
185 }
186 return result;
187 }
188
189 void
saveVehicles(OutputDevice & os,OutputDevice * const typeos,bool asAlternatives,OptionsCont & options) const190 ROPerson::PersonTrip::saveVehicles(OutputDevice& os, OutputDevice* const typeos, bool asAlternatives, OptionsCont& options) const {
191 for (std::vector<ROVehicle*>::const_iterator it = myVehicles.begin(); it != myVehicles.end(); ++it) {
192 (*it)->saveAsXML(os, typeos, asAlternatives, options);
193 }
194 }
195
196
197 SUMOTime
getDuration() const198 ROPerson::PersonTrip::getDuration() const {
199 SUMOTime result = 0;
200 for (TripItem* tItem : myTripItems) {
201 result += tItem->getDuration();
202 }
203 return result;
204 }
205
206 bool
computeIntermodal(SUMOTime time,const RORouterProvider & provider,PersonTrip * const trip,const ROVehicle * const veh,MsgHandler * const errorHandler)207 ROPerson::computeIntermodal(SUMOTime time, const RORouterProvider& provider,
208 PersonTrip* const trip, const ROVehicle* const veh, MsgHandler* const errorHandler) {
209 std::vector<ROIntermodalRouter::TripItem> result;
210 provider.getIntermodalRouter().compute(trip->getOrigin(), trip->getDestination(), trip->getDepartPos(), trip->getArrivalPos(), trip->getStopDest(),
211 getType()->maxSpeed * trip->getWalkFactor(), veh, trip->getModes(), time, result);
212 bool carUsed = false;
213 for (std::vector<ROIntermodalRouter::TripItem>::const_iterator it = result.begin(); it != result.end(); ++it) {
214 if (!it->edges.empty()) {
215 if (it->line == "") {
216 if (it + 1 == result.end() && trip->getStopDest() == "") {
217 trip->addTripItem(new Walk(it->edges, it->cost, trip->getDepartPos(false), trip->getArrivalPos(false)));
218 } else {
219 trip->addTripItem(new Walk(it->edges, it->cost, trip->getDepartPos(false), trip->getArrivalPos(false), it->destStop));
220 }
221 } else if (veh != nullptr && it->line == veh->getID()) {
222 trip->addTripItem(new Ride(it->edges.front(), it->edges.back(), veh->getID(), it->cost, trip->getArrivalPos(), it->destStop));
223 veh->getRouteDefinition()->addLoadedAlternative(new RORoute(veh->getID() + "_RouteDef", it->edges));
224 carUsed = true;
225 } else {
226 trip->addTripItem(new Ride(nullptr, nullptr, it->line, it->cost, trip->getArrivalPos(), it->destStop, it->intended, TIME2STEPS(it->depart)));
227 }
228 }
229 }
230 if (result.empty()) {
231 errorHandler->inform("No route for trip in person '" + getID() + "'.");
232 myRoutingSuccess = false;
233 }
234 return carUsed;
235 }
236
237
238 void
computeRoute(const RORouterProvider & provider,const bool,MsgHandler * errorHandler)239 ROPerson::computeRoute(const RORouterProvider& provider,
240 const bool /* removeLoops */, MsgHandler* errorHandler) {
241 myRoutingSuccess = true;
242 SUMOTime time = getParameter().depart;
243 for (std::vector<PlanItem*>::iterator it = myPlan.begin(); it != myPlan.end(); ++it) {
244 if ((*it)->needsRouting()) {
245 PersonTrip* trip = static_cast<PersonTrip*>(*it);
246 std::vector<ROVehicle*>& vehicles = trip->getVehicles();
247 if (vehicles.empty()) {
248 computeIntermodal(time, provider, trip, nullptr, errorHandler);
249 } else {
250 for (std::vector<ROVehicle*>::iterator v = vehicles.begin(); v != vehicles.end();) {
251 if (!computeIntermodal(time, provider, trip, *v, errorHandler)) {
252 v = vehicles.erase(v);
253 } else {
254 ++v;
255 }
256 }
257 }
258 }
259 time += (*it)->getDuration();
260 }
261 }
262
263
264 void
saveAsXML(OutputDevice & os,OutputDevice * const typeos,bool asAlternatives,OptionsCont & options) const265 ROPerson::saveAsXML(OutputDevice& os, OutputDevice* const typeos, bool asAlternatives, OptionsCont& options) const {
266 // write the person's vehicles
267 for (std::vector<PlanItem*>::const_iterator it = myPlan.begin(); it != myPlan.end(); ++it) {
268 (*it)->saveVehicles(os, typeos, asAlternatives, options);
269 }
270
271 if (typeos != nullptr && getType() != nullptr && !getType()->saved) {
272 getType()->write(*typeos);
273 getType()->saved = true;
274 }
275 if (getType() != nullptr && !getType()->saved) {
276 getType()->write(os);
277 getType()->saved = asAlternatives;
278 }
279
280 // write the person
281 getParameter().write(os, options, SUMO_TAG_PERSON);
282
283 for (std::vector<PlanItem*>::const_iterator it = myPlan.begin(); it != myPlan.end(); ++it) {
284 (*it)->saveAsXML(os, asAlternatives);
285 }
286
287 // write params
288 getParameter().writeParams(os);
289 os.closeTag();
290 }
291
292
293 /****************************************************************************/
294
295