Eclipse SUMO - Simulation of Urban MObility
MSTransportableControl.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2023 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// Stores all persons in the net and handles their waiting for cars.
22/****************************************************************************/
23#include <config.h>
24
25#include <vector>
26#include <algorithm>
36#include <microsim/MSNet.h>
37#include <microsim/MSEdge.h>
38#include <microsim/MSVehicle.h>
40
41
42// ===========================================================================
43// method definitions
44// ===========================================================================
46 myLoadedNumber(0),
47 myDiscardedNumber(0),
48 myRunningNumber(0),
49 myJammedNumber(0),
50 myWaitingForDepartureNumber(0),
51 myWaitingForVehicleNumber(0),
52 myWaitingUntilNumber(0),
53 myAccessNumber(0),
54 myEndedNumber(0),
55 myArrivedNumber(0),
56 myTeleportsAbortWait(0),
57 myTeleportsWrongDest(0),
58 myHaveNewWaiting(false) {
60 MSNet* const net = MSNet::getInstance();
61 if (isPerson) {
62 const std::string model = oc.getString("pedestrian.model");
64 if (model == "striping") {
66 } else if (model == "nonInteracting") {
68 } else {
69 throw ProcessError(TLF("Unknown pedestrian model '%'", model));
70 }
71 } else {
73 }
74 if (oc.isSet("vehroute-output")) {
76 }
77 if (oc.isSet("personroute-output")) {
78 OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
80 }
81 if (oc.isSet("personinfo-output")) {
82 OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
83 }
84 myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
85}
86
87
89 clearState();
91 delete myMovementModel;
92 }
94}
95
96
97bool
99 const SUMOVehicleParameter& param = transportable->getParameter();
100 if (myTransportables.find(param.id) == myTransportables.end()) {
101 myTransportables[param.id] = transportable;
102 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
103 myWaiting4Departure[step].push_back(transportable);
106 return true;
107 }
108 return false;
109}
110
111
112void
115 if (transportable->hasDeparted()) {
116 const SUMOVehicleParameter& param = transportable->getParameter();
117 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
119 auto it = std::find(waiting.begin(), waiting.end(), transportable);
120 if (it != waiting.end()) {
121 waiting.erase(it);
122 if (waiting.size() == 0) {
123 myWaiting4Departure.erase(step);
124 }
125 }
126 }
127}
128
129
131MSTransportableControl::get(const std::string& id) const {
132 std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
133 if (i == myTransportables.end()) {
134 return nullptr;
135 }
136 return (*i).second;
137}
138
139
140void
143 if (oc.isSet("personinfo-output")) {
144 transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
145 } else if (oc.isSet("tripinfo-output")) {
146 transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
147 } else if (oc.getBool("duration-log.statistics")) {
148 // collecting statistics is a sideffect
150 transportable->tripInfoOutput(dev);
151 }
152 if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
153 if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
154 if (oc.getBool("vehroute-output.sorted")) {
155 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
157 transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
159 departure, transportable->getID(), od.getString());
160 } else {
161 transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
162 }
163 }
164 }
165 const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
166 if (i != myTransportables.end()) {
171 delete i->second;
172 myTransportables.erase(i);
173 }
174}
175
176
177void
179 const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
180 // avoid double registration
181 const TransportableVector& transportables = myWaitingUntil[step];
182 if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
183 myWaitingUntil[step].push_back(transportable);
185 }
186}
187
188
189void
191 myHaveNewWaiting = false;
192 while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
193 TransportableVector& transportables = myWaiting4Departure[time];
194 // we cannot use an iterator here because there might be additions to the vector while proceeding
195 for (auto it = transportables.begin(); it != transportables.end();) {
196 MSTransportable* t = *it;
197 it = transportables.erase(it);
199 const bool isPerson = t->isPerson();
200 if (t->proceed(net, time)) {
205 if (oc.getBool("vehroute-output.sorted")) {
206 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
207 if (oc.isSet("personroute-output")) {
208 myRouteInfos.departureCounts[departure]++;
209 } else {
211 }
212 }
213 } else {
214 erase(t);
215 }
216 }
217 myWaiting4Departure.erase(time);
218 }
219 while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
220 // make a copy because 0-duration stops might modify the vector
221 const TransportableVector transportables = myWaitingUntil[time];
222 myWaitingUntil.erase(time);
223 for (MSTransportable* t : transportables) {
225 if (!t->proceed(net, time)) {
226 erase(t);
227 }
228 }
229 }
230}
231
232
233void
236}
237
238
239void
241 myWaiting4Vehicle[edge].push_back(transportable);
243 myHaveNewWaiting = true;
244 if (myAbortWaitingTimeout >= 0) {
246 }
247}
248
249
250bool
252 const auto wait = myWaiting4Vehicle.find(edge);
253 if (wait != myWaiting4Vehicle.end()) {
254 for (const MSTransportable* t : wait->second) {
255 if (t->isWaitingFor(vehicle)
256 && vehicle->allowsBoarding(t)
257 && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
258 return true;
259 }
260 }
261 }
262 return false;
263}
264
265
266bool
267MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration) {
268 bool ret = false;
269 const auto wait = myWaiting4Vehicle.find(edge);
270 if (wait != myWaiting4Vehicle.end()) {
271 const SUMOTime currentTime = SIMSTEP;
272 TransportableVector& transportables = wait->second;
273 for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
274 MSTransportable* const t = *i;
275 if (t->isWaitingFor(vehicle)
276 && vehicle->allowsBoarding(t)
277 && timeToLoadNext - DELTA_T <= currentTime
279 edge->removeTransportable(t);
280 vehicle->addTransportable(t);
281 if (myAbortWaitingTimeout >= 0) {
282 t->setAbortWaiting(-1);
283 }
284 if (timeToLoadNext >= 0) { // meso does not have loading times
285 const SUMOTime loadingDuration = vehicle->getVehicleType().getLoadingDuration(t->isPerson());
286 //update the time point at which the next transportable can be loaded on the vehicle
287 if (timeToLoadNext > currentTime - DELTA_T) {
288 timeToLoadNext += loadingDuration;
289 } else {
290 timeToLoadNext = currentTime + loadingDuration;
291 }
292 }
293
294 static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
295 if (t->getCurrentStage()->getOriginStop() != nullptr) {
297 }
298 i = transportables.erase(i);
300 ret = true;
301 } else {
302 ++i;
303 }
304 }
305 if (transportables.empty()) {
306 myWaiting4Vehicle.erase(wait);
307 }
308 if (ret && timeToLoadNext >= 0) {
309 //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
310 //the duration by setting it to the loading duration of the transportable
311 stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
312 }
313 }
314 return ret;
315}
316
317
318bool
320 return !myTransportables.empty();
321}
322
323
324bool
327}
328
329
330int
333}
334
335
336int
339}
340
341
342int
345}
346
347int
350}
351
352void
354 for (const auto& it : myWaiting4Vehicle) {
355 const MSEdge* edge = it.first;
356 for (MSTransportable* const p : it.second) {
357 edge->removeTransportable(p);
358 MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
359 const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
360 WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
361 if (myAbortWaitingTimeout >= 0) {
362 p->setAbortWaiting(-1);
363 }
364 erase(p);
365 }
366 }
367 myWaiting4Vehicle.clear();
369}
370
371void
373 const MSEdge* edge = t->getEdge();
374 auto it = myWaiting4Vehicle.find(edge);
375 if (it != myWaiting4Vehicle.end()) {
376 TransportableVector& waiting = it->second;
377 auto it2 = std::find(waiting.begin(), waiting.end(), t);
378 if (it2 != waiting.end()) {
379 if (myAbortWaitingTimeout >= 0) {
380 (*it2)->setAbortWaiting(-1);
381 }
382 waiting.erase(it2);
383 }
384 }
385}
386
387void
389 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
390 TransportableVector& ts = it->second;
391 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
392 if (it2 != ts.end()) {
393 ts.erase(it2);
394 }
395 }
396 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
397 TransportableVector& ts = it->second;
398 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
399 if (it2 != ts.end()) {
400 ts.erase(it2);
401 }
402 }
403}
404
405
408 SumoRNG* rng) const {
409 const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
410 return new MSPerson(pars, vtype, plan, speedFactor);
411}
412
413
416 return new MSTransportable(pars, vtype, plan, false);
417}
418
419
420void
422 std::ostringstream oss;
423 oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
424 oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
425 out.writeAttr(SUMO_ATTR_STATE, oss.str());
426 for (const auto& it : myTransportables) {
427 it.second->saveState(out);
428 }
429}
430
431
432void
433MSTransportableControl::loadState(const std::string& state) {
434 std::istringstream iss(state);
437}
438
439void
441 for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
442 delete (*i).second;
443 }
444 myTransportables.clear();
445 myWaiting4Vehicle.clear();
446 myWaiting4Departure.clear();
447 myWaitingUntil.clear();
448 myLoadedNumber = 0;
450 myRunningNumber = 0;
451 myJammedNumber = 0;
455 myEndedNumber = 0;
456 myArrivedNumber = 0;
457 myHaveNewWaiting = false;
460 }
462}
463
464/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:267
#define TLF(string,...)
Definition: MsgHandler.h:285
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define SIMSTEP
Definition: SUMOTime.h:60
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition: StdDefs.h:82
static void writeSortedOutput(SortedRouteInfo *routeInfo, SUMOTime depart, const std::string &id, const std::string &xmlOutput)
static void registerTransportableDepart(SUMOTime depart)
A road/street connecting two junctions.
Definition: MSEdge.h:77
virtual void removeTransportable(MSTransportable *t) const
Definition: MSEdge.cpp:1095
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition: MSGlobals.h:163
The simulated network and simulation perfomer.
Definition: MSNet.h:88
void informTransportableStateListener(const MSTransportable *const transportable, TransportableState to, const std::string &info="")
Informs all added listeners about a transportable's state change.
Definition: MSNet.cpp:1272
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
@ CONTAINER_DEPARTED
The transportable container has departed (was inserted into the network)
@ PERSON_DEPARTED
The transportable person has departed (was inserted into the network)
@ PERSON_ARRIVED
The transportable person arrived at his destination (is deleted)
@ CONTAINER_ARRIVED
The transportable container arrived at his destination (is deleted)
The pedestrian following model.
The pedestrian following model.
virtual int getActiveNumber()=0
return the number of active objects
virtual void clearState()=0
Resets pedestrians when quick-loading state.
std::string getWaitingDescription() const
Return where the person waits and for what.
virtual MSStoppingPlace * getOriginStop() const
returns the origin stop (if any). only needed for MSStageTrip
Definition: MSStage.h:85
void removeTransportable(const MSTransportable *p)
Removes a transportable from this stop.
void loadState(const std::string &state)
Reconstruct the current state.
void setWaitEnd(SUMOTime time, MSTransportable *transportable)
sets the arrival time for a waiting transportable
bool hasTransportables() const
checks whether any transportable waits to finish her plan
int myAccessNumber
The number of transportables currently in an access stage.
int myWaitingForDepartureNumber
The number of transportables waiting for departure.
void forceDeparture()
register forced (traci) departure
void fixLoadCount(const MSTransportable *transportable)
decrement counter to avoid double counting transportables loaded from state
void checkWaiting(MSNet *net, const SUMOTime time)
checks whether any transportables waiting time is over
void saveState(OutputDevice &out)
Saves the current state into the given stream.
MSTransportableControl(const bool isPerson)
Constructor.
bool hasAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle) const
check whether any transportables are waiting for the given vehicle
int myLoadedNumber
The number of build transportables.
std::map< std::string, MSTransportable * > myTransportables
all currently created transportables by id
void abortWaiting(MSTransportable *t)
aborts waiting stage of transportable
void abortWaitingForVehicle(MSTransportable *t)
let the given transportable abort waiting for a vehicle (when removing stage via TraCI)
void abortAnyWaitingForVehicle()
aborts the plan for any transportable that is still waiting for a ride
bool hasNonWaiting() const
checks whether any transportable is still engaged in walking / stopping
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
int myArrivedNumber
The number of transportables that arrived at their destination.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, SumoRNG *rng) const
Builds a new person.
int getMovingNumber() const
Returns the number of transportables moving by themselvs (i.e. walking)
void addWaiting(const MSEdge *edge, MSTransportable *person)
adds a transportable to the list of transportables waiting for a vehicle on the specified edge
SUMOTime myAbortWaitingTimeout
The time until waiting for a ride is aborted.
int myEndedNumber
The number of transportables that exited the simulation.
bool loadAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle, SUMOTime &timeToLoadNext, SUMOTime &stopDuration)
load any applicable transportables Loads any person / container that is waiting on that edge for the ...
std::map< const MSEdge *, TransportableVector > myWaiting4Vehicle
the lists of waiting transportables
int myWaitingUntilNumber
The number of transportables waiting for a specified time.
void clearState()
Resets transportables when quick-loading state.
virtual void erase(MSTransportable *transportable)
removes a single transportable
int myDiscardedNumber
The number of discarded transportables.
std::map< SUMOTime, TransportableVector > myWaitingUntil
the lists of walking / stopping transportables
bool add(MSTransportable *transportable)
Adds a single transportable, returns false if an id clash occurred.
bool myHaveNewWaiting
whether a new transportable waiting for a vehicle has been added in the last step
virtual ~MSTransportableControl()
Destructor.
int myJammedNumber
The number of jammed transportables.
std::map< SUMOTime, TransportableVector > myWaiting4Departure
Transportables waiting for departure.
std::vector< MSTransportable * > TransportableVector
Definition of a list of transportables.
int myRunningNumber
The number of transportables within the network (build and inserted but not removed)
int myWaitingForVehicleNumber
The number of transportables waiting for vehicles.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
MSDevice_Vehroutes::SortedRouteInfo myRouteInfos
Information needed to sort transportable output by departure time.
int getActiveCount()
return the number of active transportable objects
int getRidingNumber() const
Returns the number of transportables riding a vehicle.
virtual double getEdgePos() const
Return the position on the edge.
bool hasDeparted() const
return whether the transportable has started it's plan
SUMOTime getDeparture() const
logs depart time of the current stage
void setAbortWaiting(const SUMOTime timeout)
void routeOutput(OutputDevice &os, const bool withRouteLength) const
Called on writing vehroute output.
MSStage * getCurrentStage() const
Return the current stage.
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
bool isPerson() const
Whether it is a person.
std::string getObjectType()
bool hasArrived() const
return whether the person has reached the end of its plan
void tripInfoOutput(OutputDevice &os) const
Called on writing tripinfo output.
const MSEdge * getEdge() const
Returns the current edge.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
bool isWaitingFor(const SUMOVehicle *vehicle) const
Whether the transportable waits for the given vehicle in the current step.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
The car-following model and parameter.
Definition: MSVehicleType.h:63
SUMOTime getLoadingDuration(const bool isPerson) const
Get this vehicle type's loading duration.
double computeChosenSpeedDeviation(SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
An output device that encapsulates an ofstream.
std::string getString() const
Returns the current content as a string.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
static bool createDeviceByOption(const std::string &optionName, const std::string &rootElement="", const std::string &schemaFile="")
Creates the device using the output definition stored in the named option.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
Representation of a vehicle.
Definition: SUMOVehicle.h:62
virtual bool isStoppedInRange(const double pos, const double tolerance, bool checkFuture=false) const =0
Returns whether the vehicle is stopped in the range of the given position.
virtual void addTransportable(MSTransportable *transportable)=0
Adds a person or container to this vehicle.
virtual bool allowsBoarding(const MSTransportable *t) const =0
whether the given transportable is allowed to board this vehicle
Structure representing possible vehicle parameter.
std::string id
The vehicle's id.
std::map< const SUMOTime, int > departureCounts
Map needed to sort vehicles by departure time.
OutputDevice * routeOut
route output device