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.dev/sumo
3 // Copyright (C) 2001-2024 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") {
68  myMovementModel = new MSPModel_Striping(oc, net);
69 #ifdef JPS_VERSION
70  } else if (model == "jupedsim") {
71  myMovementModel = new MSPModel_JuPedSim(oc, net);
72 #endif
73  } else if (model != "nonInteracting") {
74  delete myNonInteractingModel;
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");
83  myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("personroute-output");
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 
94  clearState();
96  delete myMovementModel;
97  }
98  delete myNonInteractingModel;
99 }
100 
101 
102 bool
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);
109  myLoadedNumber++;
111  return true;
112  }
113  return false;
114 }
115 
116 
117 void
119  myLoadedNumber--;
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;
123  TransportableVector& waiting = myWaiting4Departure[step];
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 
136 MSTransportableControl::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 
145 void
147  const OptionsCont& oc = OptionsCont::getOptions();
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  if (oc.getBool("vehroute-output.sorted")) {
160  const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
161  OutputDevice_String od(1);
162  transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
164  departure, transportable->getID(), od.getString());
165  } else {
166  transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
167  }
168  }
169  }
170  const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
171  if (i != myTransportables.end()) {
172  myRunningNumber--;
173  myEndedNumber++;
176  delete i->second;
177  myTransportables.erase(i);
178  }
179 }
180 
181 
182 void
184  const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
185  // avoid double registration
186  const TransportableVector& transportables = myWaitingUntil[step];
187  if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
188  myWaitingUntil[step].push_back(transportable);
190  }
191 }
192 
193 
194 void
196  myHaveNewWaiting = false;
197  while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
198  TransportableVector& transportables = myWaiting4Departure[time];
199  // we cannot use an iterator here because there might be additions to the vector while proceeding
200  for (auto it = transportables.begin(); it != transportables.end();) {
201  MSTransportable* t = *it;
203  TransportableVector& nextStep = myWaiting4Departure[time + DELTA_T];
204  nextStep.insert(nextStep.begin(), transportables.begin(), transportables.end());
205  transportables.clear();
206  break;
207  }
208  it = transportables.erase(it);
210  const bool isPerson = t->isPerson();
211  t->setDeparted(time);
212  if (t->proceed(net, time)) {
213  myRunningNumber++;
216  const OptionsCont& oc = OptionsCont::getOptions();
217  if (oc.getBool("vehroute-output.sorted")) {
218  const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
219  if (oc.isSet("personroute-output")) {
220  myRouteInfos.departureCounts[departure]++;
221  } else {
223  }
224  }
225  } else {
226  erase(t);
227  }
228  }
229  myWaiting4Departure.erase(time);
230  }
231  while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
232  // make a copy because 0-duration stops might modify the vector
233  const TransportableVector transportables = myWaitingUntil[time];
234  myWaitingUntil.erase(time);
235  for (MSTransportable* t : transportables) {
237  if (!t->proceed(net, time)) {
238  erase(t);
239  }
240  }
241  }
242 }
243 
244 
245 void
247  myRunningNumber++;
248 }
249 
250 
251 void
252 MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
253  myWaiting4Vehicle[edge].push_back(transportable);
255  myHaveNewWaiting = true;
256  if (myAbortWaitingTimeout >= 0) {
257  transportable->setAbortWaiting(myAbortWaitingTimeout);
258  }
259 }
260 
261 
262 bool
264  const auto wait = myWaiting4Vehicle.find(edge);
265  if (wait != myWaiting4Vehicle.end()) {
266  for (const MSTransportable* t : wait->second) {
267  if (t->isWaitingFor(vehicle)
268  && vehicle->allowsBoarding(t)
269  && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
270  return true;
271  }
272  }
273  }
274  return false;
275 }
276 
277 
278 bool
279 MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration, MSTransportable* const force) {
280  bool ret = false;
281  const auto wait = myWaiting4Vehicle.find(edge);
282  if (wait != myWaiting4Vehicle.end()) {
283  const SUMOTime currentTime = SIMSTEP;
284  TransportableVector& transportables = wait->second;
285  for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
286  MSTransportable* const t = *i;
287  if (t->isWaitingFor(vehicle) && (t == force ||
288  (vehicle->allowsBoarding(t)
289  && timeToLoadNext - DELTA_T <= currentTime
291  edge->removeTransportable(t);
292  vehicle->addTransportable(t);
293  if (myAbortWaitingTimeout >= 0) {
294  t->setAbortWaiting(-1);
295  }
296  if (timeToLoadNext >= 0) { // meso does not have loading times
297  const SUMOTime loadingDuration = (SUMOTime)((double)vehicle->getVehicleType().getLoadingDuration(t->isPerson()) * t->getVehicleType().getBoardingFactor());
298  //update the time point at which the next transportable can be loaded on the vehicle
299  if (timeToLoadNext > currentTime - DELTA_T) {
300  timeToLoadNext += loadingDuration;
301  } else {
302  timeToLoadNext = currentTime + loadingDuration;
303  }
304  }
305 
306  static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
307  if (t->getCurrentStage()->getOriginStop() != nullptr) {
309  }
310  i = transportables.erase(i);
312  ret = true;
313  } else {
314  ++i;
315  }
316  }
317  if (transportables.empty()) {
318  myWaiting4Vehicle.erase(wait);
319  }
320  if (ret && timeToLoadNext >= 0) {
321  //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
322  //the duration by setting it to the loading duration of the transportable
323  stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
324  }
325  }
326  return ret;
327 }
328 
329 
330 bool
332  return !myTransportables.empty();
333 }
334 
335 
336 bool
339 }
340 
341 
342 int
345 }
346 
347 
348 int
351 }
352 
353 
354 int
357 }
358 
359 int
362 }
363 
364 void
366  for (const auto& it : myWaiting4Vehicle) {
367  const MSEdge* edge = it.first;
368  for (MSTransportable* const p : it.second) {
369  edge->removeTransportable(p);
370  MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
371  const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
372  WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
373  if (myAbortWaitingTimeout >= 0) {
374  p->setAbortWaiting(-1);
375  }
376  erase(p);
377  }
378  }
379  myWaiting4Vehicle.clear();
381 }
382 
383 void
385  const MSEdge* edge = t->getEdge();
386  auto it = myWaiting4Vehicle.find(edge);
387  if (it != myWaiting4Vehicle.end()) {
388  TransportableVector& waiting = it->second;
389  auto it2 = std::find(waiting.begin(), waiting.end(), t);
390  if (it2 != waiting.end()) {
391  if (myAbortWaitingTimeout >= 0) {
392  (*it2)->setAbortWaiting(-1);
393  }
394  waiting.erase(it2);
395  }
396  }
397 }
398 
399 void
401  for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
402  TransportableVector& ts = it->second;
403  TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
404  if (it2 != ts.end()) {
405  ts.erase(it2);
406  }
407  }
408  for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
409  TransportableVector& ts = it->second;
410  TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
411  if (it2 != ts.end()) {
412  ts.erase(it2);
413  }
414  }
415 }
416 
417 
420  SumoRNG* rng) const {
421  const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
422  return new MSPerson(pars, vtype, plan, speedFactor);
423 }
424 
425 
428  return new MSTransportable(pars, vtype, plan, false);
429 }
430 
431 
432 void
434  std::ostringstream oss;
435  oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
436  oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
437  out.writeAttr(SUMO_ATTR_STATE, oss.str());
438  for (const auto& it : myTransportables) {
439  it.second->saveState(out);
440  }
441 }
442 
443 
444 void
445 MSTransportableControl::loadState(const std::string& state) {
446  std::istringstream iss(state);
449 }
450 
451 void
453  for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
454  delete (*i).second;
455  }
456  myTransportables.clear();
457  myWaiting4Vehicle.clear();
458  myWaiting4Departure.clear();
459  myWaitingUntil.clear();
460  myLoadedNumber = 0;
461  myDiscardedNumber = 0;
462  myRunningNumber = 0;
463  myJammedNumber = 0;
467  myEndedNumber = 0;
468  myArrivedNumber = 0;
469  myHaveNewWaiting = false;
472  }
474 }
475 
476 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TLF(string,...)
Definition: MsgHandler.h:317
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: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:1145
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition: MSGlobals.h:165
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:1295
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
@ 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:90
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.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
void setDeparted(SUMOTime now)
logs depart time of the current stage
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
const MSVehicleType & getVehicleType() const
Returns the object's "vehicle" type.
bool isPerson() const
Whether it is a person.
std::string getObjectType()
const MSEdge * getEdge() const
Returns the current edge.
MSStage * getCurrentStage() const
Return the current stage.
bool hasArrived() const
return whether the person has reached the end of its plan
void tripInfoOutput(OutputDevice &os) const
Called on writing tripinfo output.
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.
The car-following model and parameter.
Definition: MSVehicleType.h:63
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.
Definition: OptionsCont.cpp:60
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
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.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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