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-2022 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  myEndedNumber(0),
54  myArrivedNumber(0),
55  myHaveNewWaiting(false) {
57  MSNet* const net = MSNet::getInstance();
58  if (isPerson) {
59  const std::string model = oc.getString("pedestrian.model");
61  if (model == "striping") {
62  myMovementModel = new MSPModel_Striping(oc, net);
63  } else if (model == "nonInteracting") {
65  } else {
66  throw ProcessError("Unknown pedestrian model '" + model + "'");
67  }
68  } else {
70  }
71 }
72 
73 
75  clearState();
77  delete myMovementModel;
78  }
79  delete myNonInteractingModel;
80 }
81 
82 
83 bool
85  const SUMOVehicleParameter& param = transportable->getParameter();
86  if (myTransportables.find(param.id) == myTransportables.end()) {
87  myTransportables[param.id] = transportable;
88  const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
89  myWaiting4Departure[step].push_back(transportable);
92  return true;
93  }
94  return false;
95 }
96 
97 
99 MSTransportableControl::get(const std::string& id) const {
100  std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
101  if (i == myTransportables.end()) {
102  return nullptr;
103  }
104  return (*i).second;
105 }
106 
107 
108 void
110  const OptionsCont& oc = OptionsCont::getOptions();
111  if (oc.isSet("tripinfo-output")) {
112  transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
113  } else if (oc.getBool("duration-log.statistics")) {
114  // collecting statistics is a sideffect
116  transportable->tripInfoOutput(dev);
117  }
118  if (oc.isSet("vehroute-output")) {
119  if (oc.getBool("vehroute-output.sorted")) {
120  OutputDevice_String od(1);
121  transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
123  transportable->getDeparture(), transportable->getID(), od.getString());
124  } else {
125  transportable->routeOutput(OutputDevice::getDeviceByOption("vehroute-output"), oc.getBool("vehroute-output.route-length"));
126  }
127  }
128  const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
129  if (i != myTransportables.end()) {
130  myRunningNumber--;
131  myEndedNumber++;
134  delete i->second;
135  myTransportables.erase(i);
136  }
137 }
138 
139 
140 void
142  const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
143  // avoid double registration
144  const TransportableVector& transportables = myWaiting4Departure[step];
145  if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
146  myWaitingUntil[step].push_back(transportable);
148  }
149 }
150 
151 
152 void
154  myHaveNewWaiting = false;
155  while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
156  TransportableVector& transportables = myWaiting4Departure[time];
157  // we cannot use an iterator here because there might be additions to the vector while proceeding
158  for (auto it = transportables.begin(); it != transportables.end();) {
159  MSTransportable* t = *it;
160  it = transportables.erase(it);
162  const bool isPerson = t->isPerson();
163  if (t->proceed(net, time)) {
164  myRunningNumber++;
167  if (OptionsCont::getOptions().getBool("vehroute-output.sorted")) {
169  }
170  } else {
171  erase(t);
172  }
173  }
174  myWaiting4Departure.erase(time);
175  }
176  while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
177  const TransportableVector& transportables = myWaitingUntil[time];
178  // we cannot use an iterator here because there might be additions to the vector while proceeding
179  for (int i = 0; i < (int)transportables.size(); ++i) {
181  if (!transportables[i]->proceed(net, time)) {
182  erase(transportables[i]);
183  }
184  }
185  myWaitingUntil.erase(time);
186  }
187 }
188 
189 void
191  myRunningNumber++;
192 }
193 
194 void
195 MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
196  myWaiting4Vehicle[edge].push_back(transportable);
198  myHaveNewWaiting = true;
199 }
200 
201 
202 bool
203 MSTransportableControl::boardAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToBoardNextPerson, SUMOTime& stopDuration) {
204  bool ret = false;
205  if (myWaiting4Vehicle.find(edge) != myWaiting4Vehicle.end()) {
208  for (TransportableVector::iterator i = wait.begin(); i != wait.end();) {
209  if ((*i)->isWaitingFor(vehicle)
210  && vehicle->allowsBoarding(*i)
211  && timeToBoardNextPerson - DELTA_T <= currentTime
212  && vehicle->isStoppedInRange((*i)->getEdgePos(), MSGlobals::gStopTolerance)) {
213  edge->removePerson(*i);
214  vehicle->addTransportable(*i);
215  if (timeToBoardNextPerson >= 0) { // meso does not have boarding times
216  const SUMOTime boardingDuration = vehicle->getVehicleType().getBoardingDuration();
217  //update the time point at which the next person can board the vehicle
218  if (timeToBoardNextPerson > currentTime - DELTA_T) {
219  timeToBoardNextPerson += boardingDuration;
220  } else {
221  timeToBoardNextPerson = currentTime + boardingDuration;
222  }
223  }
224 
225  static_cast<MSStageDriving*>((*i)->getCurrentStage())->setVehicle(vehicle);
226  if ((*i)->getCurrentStage()->getOriginStop() != nullptr) {
227  (*i)->getCurrentStage()->getOriginStop()->removeTransportable(*i);
228  }
229  i = wait.erase(i);
231  ret = true;
232  } else {
233  ++i;
234  }
235  }
236  if (wait.size() == 0) {
237  myWaiting4Vehicle.erase(myWaiting4Vehicle.find(edge));
238  }
239  if (ret && timeToBoardNextPerson >= 0) {
240  //if the time a person needs to enter the vehicle extends the duration of the stop of the vehicle extend
241  //the duration by setting it to the boarding duration of the person
242  stopDuration = MAX2(stopDuration, timeToBoardNextPerson - currentTime);
243  }
244  }
245  return ret;
246 }
247 
248 
249 bool
250 MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNextContainer, SUMOTime& stopDuration) {
251  bool ret = false;
252  if (myWaiting4Vehicle.find(edge) != myWaiting4Vehicle.end()) {
254  TransportableVector& waitContainers = myWaiting4Vehicle[edge];
255  for (TransportableVector::iterator i = waitContainers.begin(); i != waitContainers.end();) {
256  if ((*i)->isWaitingFor(vehicle)
257  && vehicle->allowsBoarding(*i)
258  && timeToLoadNextContainer - DELTA_T <= currentTime
259  && vehicle->isStoppedInRange((*i)->getEdgePos(), MSGlobals::gStopTolerance)) {
260  edge->removeContainer(*i);
261  vehicle->addTransportable(*i);
262  if (timeToLoadNextContainer >= 0) { // meso does not have loading times
263  //if the time a person needs to enter the vehicle extends the duration of the stop of the vehicle extend
264  //the duration by setting it to the boarding duration of the person
265  const SUMOTime loadingDuration = vehicle->getVehicleType().getLoadingDuration();
266  //update the time point at which the next container can be loaded on the vehicle
267  if (timeToLoadNextContainer > currentTime - DELTA_T) {
268  timeToLoadNextContainer += loadingDuration;
269  } else {
270  timeToLoadNextContainer = currentTime + loadingDuration;
271  }
272  }
273 
274  static_cast<MSStageDriving*>((*i)->getCurrentStage())->setVehicle(vehicle);
275  if ((*i)->getCurrentStage()->getOriginStop() != nullptr) {
276  (*i)->getCurrentStage()->getOriginStop()->removeTransportable(*i);
277  }
278  i = waitContainers.erase(i);
280  ret = true;
281  } else {
282  ++i;
283  }
284  }
285  if (waitContainers.size() == 0) {
286  myWaiting4Vehicle.erase(myWaiting4Vehicle.find(edge));
287  }
288  if (ret && timeToLoadNextContainer >= 0) {
289  //if the time a container needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
290  //the duration by setting it to the loading duration of the container
291  stopDuration = MAX2(stopDuration, timeToLoadNextContainer - currentTime);
292  }
293  }
294  return ret;
295 }
296 
297 
298 bool
300  return !myTransportables.empty();
301 }
302 
303 
304 bool
307 }
308 
309 
310 int
313 }
314 
315 int
318 }
319 
320 
321 int
324 }
325 
326 int
329 }
330 
331 void
333  for (std::map<const MSEdge*, TransportableVector>::iterator i = myWaiting4Vehicle.begin(); i != myWaiting4Vehicle.end(); ++i) {
334  const MSEdge* edge = (*i).first;
335  for (MSTransportable* const p : i->second) {
336  std::string transportableType;
337  if (p->isPerson()) {
338  edge->removePerson(p);
339  transportableType = "Person";
340  } else {
341  transportableType = "Container";
342  edge->removeContainer(p);
343  }
344  MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
345  const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
346  WRITE_WARNING(transportableType + " '" + p->getID() + "' aborted " + waitDescription + ".");
347  erase(p);
348  }
349  }
350  myWaiting4Vehicle.clear();
352 }
353 
354 void
356  const MSEdge* edge = t->getEdge();
357  auto it = myWaiting4Vehicle.find(edge);
358  if (it != myWaiting4Vehicle.end()) {
359  TransportableVector& waiting = it->second;
360  auto it2 = std::find(waiting.begin(), waiting.end(), t);
361  if (it2 != waiting.end()) {
362  waiting.erase(it2);
363  }
364  }
365 }
366 
367 void
369  for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
370  TransportableVector& ts = it->second;
371  TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
372  if (it2 != ts.end()) {
373  ts.erase(it2);
374  }
375  }
376  for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
377  TransportableVector& ts = it->second;
378  TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
379  if (it2 != ts.end()) {
380  ts.erase(it2);
381  }
382  }
383 }
384 
385 
388  SumoRNG* rng) const {
389  const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
390  return new MSPerson(pars, vtype, plan, speedFactor);
391 }
392 
393 
396  return new MSTransportable(pars, vtype, plan, false);
397 }
398 
399 
400 void
402  std::ostringstream oss;
403  oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
404  oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
405  out.writeAttr(SUMO_ATTR_STATE, oss.str());
406  for (const auto& it : myTransportables) {
407  it.second->saveState(out);
408  }
409 }
410 
411 
412 void
413 MSTransportableControl::loadState(const std::string& state) {
414  std::istringstream iss(state);
417 }
418 
419 void
421  for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
422  delete (*i).second;
423  }
424  myTransportables.clear();
425  myWaiting4Vehicle.clear();
426  myWaiting4Departure.clear();
427  myWaitingUntil.clear();
428  myLoadedNumber = 0;
429  myDiscardedNumber = 0;
430  myRunningNumber = 0;
431  myJammedNumber = 0;
435  myEndedNumber = 0;
436  myArrivedNumber = 0;
437  myHaveNewWaiting = false;
440  }
442 }
443 
444 /****************************************************************************/
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
long long int SUMOTime
Definition: SUMOTime.h:32
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition: StdDefs.h:80
static void writeSortedOutput(OutputDevice &routeOut, 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 removeContainer(MSTransportable *container) const
Remove container from myContainers.
Definition: MSEdge.h:678
virtual void removePerson(MSTransportable *p) const
Definition: MSEdge.cpp:1024
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition: MSGlobals.h:151
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:1172
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
@ 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.
MSStoppingPlace * getOriginStop() const
returns the origin stop (if any). only needed for MSStageTrip
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 myWaitingForDepartureNumber
The number of transportables waiting for departure.
void forceDeparture()
register forced (traci) departure
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.
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
int myEndedNumber
The number of transportables that exited the simulation.
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.
bool boardAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle, SUMOTime &timeToBoardNextPerson, SUMOTime &stopDuration)
board any applicable persons Boards any people who wait on that edge for the given vehicle and remove...
std::map< SUMOTime, TransportableVector > myWaiting4Departure
Transportables waiting for departure.
bool loadAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle, SUMOTime &timeToLoadNextContainer, SUMOTime &stopDuration)
load any applicable containers Loads any container that is waiting on that edge for the given vehicle...
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.
int getActiveCount()
return the number of active transportable objects
int getRidingNumber() const
Returns the number of transportables riding a vehicle.
SUMOTime getDeparture() const
logs depart time of the current stage
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.
const MSEdge * getEdge() const
Returns the current edge.
MSStage * getCurrentStage() const
Return the current stage.
void tripInfoOutput(OutputDevice &os) const
Called on writing tripinfo output.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
The car-following model and parameter.
Definition: MSVehicleType.h:62
SUMOTime getLoadingDuration() const
Get this vehicle type's loading duration.
SUMOTime getBoardingDuration() const
Get this vehicle type's 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.
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:58
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:248
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 void addTransportable(MSTransportable *transportable)=0
Adds a person or container to this vehicle.
virtual bool isStoppedInRange(const double pos, const double tolerance) const =0
Returns whether the vehicle is stopped in the range of the given position.
virtual bool allowsBoarding(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.