Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSTransportableControl.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2025 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>
33#ifdef JPS_VERSION
35#endif
39#include <microsim/MSNet.h>
40#include <microsim/MSEdge.h>
41#include <microsim/MSVehicle.h>
43
44
45// ===========================================================================
46// method definitions
47// ===========================================================================
49 myLoadedNumber(0),
50 myDiscardedNumber(0),
51 myRunningNumber(0),
52 myJammedNumber(0),
53 myWaitingForDepartureNumber(0),
54 myWaitingForVehicleNumber(0),
55 myWaitingUntilNumber(0),
56 myAccessNumber(0),
57 myEndedNumber(0),
58 myArrivedNumber(0),
59 myTeleportsAbortWait(0),
60 myTeleportsWrongDest(0),
61 myHaveNewWaiting(false) {
63 MSNet* const net = MSNet::getInstance();
65 if (isPerson) {
66 const std::string& model = oc.getString("pedestrian.model");
67 if (model == "striping") {
69#ifdef JPS_VERSION
70 } else if (model == "jupedsim") {
72#endif
73 } else if (model != "nonInteracting") {
75 throw ProcessError(TLF("Unknown pedestrian model '%'", model));
76 }
77 }
78 if (oc.isSet("vehroute-output")) {
80 }
81 if (oc.isSet("personroute-output")) {
82 OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
84 }
85 if (oc.isSet("personinfo-output")) {
86 OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
87 }
88 myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
89 myMaxTransportableNumber = isPerson ? oc.getInt("max-num-persons") : -1;
90}
91
92
100
101
102bool
104 const SUMOVehicleParameter& param = transportable->getParameter();
105 if (myTransportables.find(param.id) == myTransportables.end()) {
106 myTransportables[param.id] = transportable;
107 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
108 myWaiting4Departure[step].push_back(transportable);
111 return true;
112 }
113 return false;
114}
115
116
117void
120 if (transportable->hasDeparted()) {
121 const SUMOVehicleParameter& param = transportable->getParameter();
122 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
124 auto it = std::find(waiting.begin(), waiting.end(), transportable);
125 if (it != waiting.end()) {
126 waiting.erase(it);
127 if (waiting.size() == 0) {
128 myWaiting4Departure.erase(step);
129 }
130 }
131 }
132}
133
134
136MSTransportableControl::get(const std::string& id) const {
137 std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
138 if (i == myTransportables.end()) {
139 return nullptr;
140 }
141 return (*i).second;
142}
143
144
145void
148 if (oc.isSet("personinfo-output")) {
149 transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
150 } else if (oc.isSet("tripinfo-output")) {
151 transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
152 } else if (oc.getBool("duration-log.statistics")) {
153 // collecting statistics is a sideffect
155 transportable->tripInfoOutput(dev);
156 }
157 if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
158 if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
159 // @todo: adapt this if we ever introduce person-device.vehroute
160 if (transportable->getBoolParam("has.vehroute.person-device", false, true)) {
161 if (oc.getBool("vehroute-output.sorted")) {
162 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
164 transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
166 departure, transportable->getID(), od.getString());
167 } else {
168 transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
169 }
170 }
171 }
172 }
173 const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
174 if (i != myTransportables.end()) {
175 if (i->second->hasDeparted()) {
177 }
181 delete i->second;
182 myTransportables.erase(i);
183 }
184}
185
186
187void
189 const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
190 // avoid double registration
191 const TransportableVector& transportables = myWaitingUntil[step];
192 if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
193 myWaitingUntil[step].push_back(transportable);
195 }
196}
197
198
199void
201 myHaveNewWaiting = false;
202 while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
203 TransportableVector& transportables = myWaiting4Departure[time];
204 // we cannot use an iterator here because there might be additions to the vector while proceeding
205 for (auto it = transportables.begin(); it != transportables.end();) {
206 MSTransportable* t = *it;
209 nextStep.insert(nextStep.begin(), transportables.begin(), transportables.end());
210 transportables.clear();
211 break;
212 } else if (myMaxTransportableNumber == 0) {
213 erase(t);
214 it = transportables.erase(it);
215 continue;
216 }
217 it = transportables.erase(it);
219 const bool isPerson = t->isPerson();
220 t->setDeparted(time);
221 if (t->proceed(net, time)) {
226 if (oc.getBool("vehroute-output.sorted")) {
227 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
228 if (oc.isSet("personroute-output")) {
229 myRouteInfos.departureCounts[departure]++;
230 } else {
232 }
233 }
234 } else {
235 erase(t);
236 }
237 }
238 myWaiting4Departure.erase(time);
239 }
240 while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
241 // make a copy because 0-duration stops might modify the vector
242 const TransportableVector transportables = myWaitingUntil[time];
243 myWaitingUntil.erase(time);
244 for (MSTransportable* t : transportables) {
246 if (!t->proceed(net, time)) {
247 erase(t);
248 }
249 }
250 }
251}
252
253
254void
258
259
260void
262 myWaiting4Vehicle[edge].push_back(transportable);
264 myHaveNewWaiting = true;
265 if (myAbortWaitingTimeout >= 0) {
267 }
268}
269
270
271bool
273 const auto wait = myWaiting4Vehicle.find(edge);
274 if (wait != myWaiting4Vehicle.end()) {
275 for (const MSTransportable* t : wait->second) {
276 if (t->isWaitingFor(vehicle)
277 && vehicle->allowsBoarding(t)
278 && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
279 return true;
280 }
281 }
282 }
283 return false;
284}
285
286
287bool
288MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration, MSTransportable* const force) {
289 bool ret = false;
290 const auto wait = myWaiting4Vehicle.find(edge);
291 if (wait != myWaiting4Vehicle.end()) {
292 const SUMOTime currentTime = SIMSTEP;
293 TransportableVector& transportables = wait->second;
294 for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
295 MSTransportable* const t = *i;
296 if (t->isWaitingFor(vehicle) && (t == force ||
297 (vehicle->allowsBoarding(t)
298 && timeToLoadNext - DELTA_T <= currentTime
300 edge->removeTransportable(t);
301 vehicle->addTransportable(t);
302 if (myAbortWaitingTimeout >= 0) {
303 t->setAbortWaiting(-1);
304 }
305 if (timeToLoadNext >= 0) { // meso does not have loading times
306 const SUMOTime loadingDuration = (SUMOTime)((double)vehicle->getVehicleType().getLoadingDuration(t->isPerson()) * t->getVehicleType().getBoardingFactor());
307 //update the time point at which the next transportable can be loaded on the vehicle
308 if (timeToLoadNext > currentTime - DELTA_T) {
309 timeToLoadNext += loadingDuration;
310 } else {
311 timeToLoadNext = currentTime + loadingDuration;
312 }
313 }
314
315 static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
316 if (t->getCurrentStage()->getOriginStop() != nullptr) {
318 }
319 i = transportables.erase(i);
321 ret = true;
322 } else {
323 ++i;
324 }
325 }
326 if (transportables.empty()) {
327 myWaiting4Vehicle.erase(wait);
328 }
329 if (ret && timeToLoadNext >= 0) {
330 //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
331 //the duration by setting it to the loading duration of the transportable
332 stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
333 }
334 }
335 return ret;
336}
337
338
339bool
343
344
345bool
349
350
351int
355
356
357int
361
362
363int
367
368int
372
373void
375 for (const auto& it : myWaiting4Vehicle) {
376 const MSEdge* edge = it.first;
377 for (MSTransportable* const p : it.second) {
378 edge->removeTransportable(p);
379 MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
380 const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
381 WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
382 if (myAbortWaitingTimeout >= 0) {
383 p->setAbortWaiting(-1);
384 }
385 erase(p);
386 }
387 }
388 myWaiting4Vehicle.clear();
390}
391
392void
394 const MSEdge* edge = t->getEdge();
395 auto it = myWaiting4Vehicle.find(edge);
396 if (it != myWaiting4Vehicle.end()) {
397 TransportableVector& waiting = it->second;
398 auto it2 = std::find(waiting.begin(), waiting.end(), t);
399 if (it2 != waiting.end()) {
400 if (myAbortWaitingTimeout >= 0) {
401 (*it2)->setAbortWaiting(-1);
402 }
403 waiting.erase(it2);
405 }
406 }
407}
408
409void
411 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
412 TransportableVector& ts = it->second;
413 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
414 if (it2 != ts.end()) {
415 ts.erase(it2);
416 }
417 }
418 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
419 TransportableVector& ts = it->second;
420 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
421 if (it2 != ts.end()) {
422 ts.erase(it2);
423 }
424 }
425}
426
427
430 SumoRNG* rng) const {
431 const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
432 return new MSPerson(pars, vtype, plan, speedFactor);
433}
434
435
438 return new MSTransportable(pars, vtype, plan, false);
439}
440
441
442void
444 std::ostringstream oss;
445 oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
446 oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
447 out.writeAttr(SUMO_ATTR_STATE, oss.str());
448 for (const auto& it : myTransportables) {
449 it.second->saveState(out);
450 }
451}
452
453
454void
460
461void
463 for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
464 delete (*i).second;
465 }
466 myTransportables.clear();
467 myWaiting4Vehicle.clear();
468 myWaiting4Departure.clear();
469 myWaitingUntil.clear();
470 myLoadedNumber = 0;
472 myRunningNumber = 0;
473 myJammedNumber = 0;
477 myEndedNumber = 0;
478 myArrivedNumber = 0;
479 myHaveNewWaiting = false;
482 }
484}
485
486/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TLF(string,...)
Definition MsgHandler.h:306
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
#define SIMSTEP
Definition SUMOTime.h:61
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition StdDefs.h:86
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:1207
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition MSGlobals.h:168
The simulated network and simulation perfomer.
Definition MSNet.h:89
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:1363
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
@ 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)
A pedestrian following model that acts as a proxy for pedestrian models provided by the JuPedSim thir...
The pedestrian following model.
The pedestrian movement model using stripes on sidewalks.
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:93
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.
std::map< const MSEdge *, TransportableVector, ComparatorNumericalIdLess > myWaiting4Vehicle
the lists of waiting transportables
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.
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.
int myMaxTransportableNumber
maximum transportable count
std::map< SUMOTime, TransportableVector > myWaiting4Departure
Transportables waiting for departure.
bool loadAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle, SUMOTime &timeToLoadNext, SUMOTime &stopDuration, MSTransportable *const force=nullptr)
load any applicable transportables Loads any person / container that is waiting on that edge for the ...
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 its 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.
void setDeparted(SUMOTime now)
logs depart time of the current stage
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
bool isPerson() const
Whether it is a person.
const MSVehicleType & getVehicleType() const
Returns the object's "vehicle" type.
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.
SUMOTime getLoadingDuration(const bool isPerson) const
Get this vehicle type's loading duration.
double getBoardingFactor() const
Get this person type's factor for loading/boarding 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.
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
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.
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.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
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.
bool getBoolParam(const std::string &paramName, const bool required=false, const bool deflt=false) const
Retrieve a boolean parameter for the traffic object.
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