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 }
90 
91 
93  clearState();
95  delete myMovementModel;
96  }
97  delete myNonInteractingModel;
98 }
99 
100 
101 bool
103  const SUMOVehicleParameter& param = transportable->getParameter();
104  if (myTransportables.find(param.id) == myTransportables.end()) {
105  myTransportables[param.id] = transportable;
106  const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
107  myWaiting4Departure[step].push_back(transportable);
108  myLoadedNumber++;
110  return true;
111  }
112  return false;
113 }
114 
115 
116 void
118  myLoadedNumber--;
119  if (transportable->hasDeparted()) {
120  const SUMOVehicleParameter& param = transportable->getParameter();
121  const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
122  TransportableVector& waiting = myWaiting4Departure[step];
123  auto it = std::find(waiting.begin(), waiting.end(), transportable);
124  if (it != waiting.end()) {
125  waiting.erase(it);
126  if (waiting.size() == 0) {
127  myWaiting4Departure.erase(step);
128  }
129  }
130  }
131 }
132 
133 
135 MSTransportableControl::get(const std::string& id) const {
136  std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
137  if (i == myTransportables.end()) {
138  return nullptr;
139  }
140  return (*i).second;
141 }
142 
143 
144 void
146  const OptionsCont& oc = OptionsCont::getOptions();
147  if (oc.isSet("personinfo-output")) {
148  transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
149  } else if (oc.isSet("tripinfo-output")) {
150  transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
151  } else if (oc.getBool("duration-log.statistics")) {
152  // collecting statistics is a sideffect
154  transportable->tripInfoOutput(dev);
155  }
156  if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
157  if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
158  if (oc.getBool("vehroute-output.sorted")) {
159  const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
160  OutputDevice_String od(1);
161  transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
163  departure, transportable->getID(), od.getString());
164  } else {
165  transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
166  }
167  }
168  }
169  const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
170  if (i != myTransportables.end()) {
171  myRunningNumber--;
172  myEndedNumber++;
175  delete i->second;
176  myTransportables.erase(i);
177  }
178 }
179 
180 
181 void
183  const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
184  // avoid double registration
185  const TransportableVector& transportables = myWaitingUntil[step];
186  if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
187  myWaitingUntil[step].push_back(transportable);
189  }
190 }
191 
192 
193 void
195  myHaveNewWaiting = false;
196  while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
197  TransportableVector& transportables = myWaiting4Departure[time];
198  // we cannot use an iterator here because there might be additions to the vector while proceeding
199  for (auto it = transportables.begin(); it != transportables.end();) {
200  MSTransportable* t = *it;
201  it = transportables.erase(it);
203  const bool isPerson = t->isPerson();
204  if (t->proceed(net, time)) {
205  myRunningNumber++;
208  const OptionsCont& oc = OptionsCont::getOptions();
209  if (oc.getBool("vehroute-output.sorted")) {
210  const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
211  if (oc.isSet("personroute-output")) {
212  myRouteInfos.departureCounts[departure]++;
213  } else {
215  }
216  }
217  } else {
218  erase(t);
219  }
220  }
221  myWaiting4Departure.erase(time);
222  }
223  while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
224  // make a copy because 0-duration stops might modify the vector
225  const TransportableVector transportables = myWaitingUntil[time];
226  myWaitingUntil.erase(time);
227  for (MSTransportable* t : transportables) {
229  if (!t->proceed(net, time)) {
230  erase(t);
231  }
232  }
233  }
234 }
235 
236 
237 void
239  myRunningNumber++;
240 }
241 
242 
243 void
244 MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
245  myWaiting4Vehicle[edge].push_back(transportable);
247  myHaveNewWaiting = true;
248  if (myAbortWaitingTimeout >= 0) {
249  transportable->setAbortWaiting(myAbortWaitingTimeout);
250  }
251 }
252 
253 
254 bool
256  const auto wait = myWaiting4Vehicle.find(edge);
257  if (wait != myWaiting4Vehicle.end()) {
258  for (const MSTransportable* t : wait->second) {
259  if (t->isWaitingFor(vehicle)
260  && vehicle->allowsBoarding(t)
261  && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
262  return true;
263  }
264  }
265  }
266  return false;
267 }
268 
269 
270 bool
271 MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration) {
272  bool ret = false;
273  const auto wait = myWaiting4Vehicle.find(edge);
274  if (wait != myWaiting4Vehicle.end()) {
275  const SUMOTime currentTime = SIMSTEP;
276  TransportableVector& transportables = wait->second;
277  for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
278  MSTransportable* const t = *i;
279  if (t->isWaitingFor(vehicle)
280  && vehicle->allowsBoarding(t)
281  && timeToLoadNext - DELTA_T <= currentTime
283  edge->removeTransportable(t);
284  vehicle->addTransportable(t);
285  if (myAbortWaitingTimeout >= 0) {
286  t->setAbortWaiting(-1);
287  }
288  if (timeToLoadNext >= 0) { // meso does not have loading times
289  const SUMOTime loadingDuration = vehicle->getVehicleType().getLoadingDuration(t->isPerson());
290  //update the time point at which the next transportable can be loaded on the vehicle
291  if (timeToLoadNext > currentTime - DELTA_T) {
292  timeToLoadNext += loadingDuration;
293  } else {
294  timeToLoadNext = currentTime + loadingDuration;
295  }
296  }
297 
298  static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
299  if (t->getCurrentStage()->getOriginStop() != nullptr) {
301  }
302  i = transportables.erase(i);
304  ret = true;
305  } else {
306  ++i;
307  }
308  }
309  if (transportables.empty()) {
310  myWaiting4Vehicle.erase(wait);
311  }
312  if (ret && timeToLoadNext >= 0) {
313  //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
314  //the duration by setting it to the loading duration of the transportable
315  stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
316  }
317  }
318  return ret;
319 }
320 
321 
322 bool
324  return !myTransportables.empty();
325 }
326 
327 
328 bool
331 }
332 
333 
334 int
337 }
338 
339 
340 int
343 }
344 
345 
346 int
349 }
350 
351 int
354 }
355 
356 void
358  for (const auto& it : myWaiting4Vehicle) {
359  const MSEdge* edge = it.first;
360  for (MSTransportable* const p : it.second) {
361  edge->removeTransportable(p);
362  MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
363  const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
364  WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
365  if (myAbortWaitingTimeout >= 0) {
366  p->setAbortWaiting(-1);
367  }
368  erase(p);
369  }
370  }
371  myWaiting4Vehicle.clear();
373 }
374 
375 void
377  const MSEdge* edge = t->getEdge();
378  auto it = myWaiting4Vehicle.find(edge);
379  if (it != myWaiting4Vehicle.end()) {
380  TransportableVector& waiting = it->second;
381  auto it2 = std::find(waiting.begin(), waiting.end(), t);
382  if (it2 != waiting.end()) {
383  if (myAbortWaitingTimeout >= 0) {
384  (*it2)->setAbortWaiting(-1);
385  }
386  waiting.erase(it2);
387  }
388  }
389 }
390 
391 void
393  for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
394  TransportableVector& ts = it->second;
395  TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
396  if (it2 != ts.end()) {
397  ts.erase(it2);
398  }
399  }
400  for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
401  TransportableVector& ts = it->second;
402  TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
403  if (it2 != ts.end()) {
404  ts.erase(it2);
405  }
406  }
407 }
408 
409 
412  SumoRNG* rng) const {
413  const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
414  return new MSPerson(pars, vtype, plan, speedFactor);
415 }
416 
417 
420  return new MSTransportable(pars, vtype, plan, false);
421 }
422 
423 
424 void
426  std::ostringstream oss;
427  oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
428  oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
429  out.writeAttr(SUMO_ATTR_STATE, oss.str());
430  for (const auto& it : myTransportables) {
431  it.second->saveState(out);
432  }
433 }
434 
435 
436 void
437 MSTransportableControl::loadState(const std::string& state) {
438  std::istringstream iss(state);
441 }
442 
443 void
445  for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
446  delete (*i).second;
447  }
448  myTransportables.clear();
449  myWaiting4Vehicle.clear();
450  myWaiting4Departure.clear();
451  myWaitingUntil.clear();
452  myLoadedNumber = 0;
453  myDiscardedNumber = 0;
454  myRunningNumber = 0;
455  myJammedNumber = 0;
459  myEndedNumber = 0;
460  myArrivedNumber = 0;
461  myHaveNewWaiting = false;
464  }
466 }
467 
468 /****************************************************************************/
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:1133
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: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:1286
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
@ 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 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:89
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.
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 ...
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 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)
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
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 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: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:60
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