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