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") {
63 } else if (model == "nonInteracting") {
65 } else {
66 throw ProcessError("Unknown pedestrian model '" + model + "'");
67 }
68 } else {
70 }
71 if (oc.isSet("vehroute-output")) {
73 }
74 if (oc.isSet("personroute-output")) {
75 OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
77 }
78 myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
79}
80
81
83 clearState();
85 delete myMovementModel;
86 }
88}
89
90
91bool
93 const SUMOVehicleParameter& param = transportable->getParameter();
94 if (myTransportables.find(param.id) == myTransportables.end()) {
95 myTransportables[param.id] = transportable;
96 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
97 myWaiting4Departure[step].push_back(transportable);
100 return true;
101 }
102 return false;
103}
104
105
106void
109 if (transportable->hasDeparted()) {
110 const SUMOVehicleParameter& param = transportable->getParameter();
111 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
113 auto it = std::find(waiting.begin(), waiting.end(), transportable);
114 if (it != waiting.end()) {
115 waiting.erase(it);
116 if (waiting.size() == 0) {
117 myWaiting4Departure.erase(step);
118 }
119 }
120 }
121}
122
123
125MSTransportableControl::get(const std::string& id) const {
126 std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
127 if (i == myTransportables.end()) {
128 return nullptr;
129 }
130 return (*i).second;
131}
132
133
134void
137 if (oc.isSet("tripinfo-output")) {
138 transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
139 } else if (oc.getBool("duration-log.statistics")) {
140 // collecting statistics is a sideffect
142 transportable->tripInfoOutput(dev);
143 }
144 if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
145 if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
146 if (oc.getBool("vehroute-output.sorted")) {
147 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
149 transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
151 departure, transportable->getID(), od.getString());
152 } else {
153 transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
154 }
155 }
156 }
157 const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
158 if (i != myTransportables.end()) {
163 delete i->second;
164 myTransportables.erase(i);
165 }
166}
167
168
169void
171 const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
172 // avoid double registration
173 const TransportableVector& transportables = myWaitingUntil[step];
174 if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
175 myWaitingUntil[step].push_back(transportable);
177 }
178}
179
180
181void
183 myHaveNewWaiting = false;
184 while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
185 TransportableVector& transportables = myWaiting4Departure[time];
186 // we cannot use an iterator here because there might be additions to the vector while proceeding
187 for (auto it = transportables.begin(); it != transportables.end();) {
188 MSTransportable* t = *it;
189 it = transportables.erase(it);
191 const bool isPerson = t->isPerson();
192 if (t->proceed(net, time)) {
197 if (oc.getBool("vehroute-output.sorted")) {
198 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
199 if (oc.isSet("personroute-output")) {
200 myRouteInfos.departureCounts[departure]++;
201 } else {
203 }
204 }
205 } else {
206 erase(t);
207 }
208 }
209 myWaiting4Departure.erase(time);
210 }
211 while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
212 // make a copy because 0-duration stops might modify the vector
213 const TransportableVector transportables = myWaitingUntil[time];
214 myWaitingUntil.erase(time);
215 for (MSTransportable* t : transportables) {
217 if (!t->proceed(net, time)) {
218 erase(t);
219 }
220 }
221 }
222}
223
224
225void
228}
229
230
231void
233 myWaiting4Vehicle[edge].push_back(transportable);
235 myHaveNewWaiting = true;
236 if (myAbortWaitingTimeout >= 0) {
238 }
239}
240
241
242bool
244 const auto wait = myWaiting4Vehicle.find(edge);
245 if (wait != myWaiting4Vehicle.end()) {
246 for (const MSTransportable* t : wait->second) {
247 if (t->isWaitingFor(vehicle)
248 && vehicle->allowsBoarding(t)
249 && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
250 return true;
251 }
252 }
253 }
254 return false;
255}
256
257
258bool
259MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration) {
260 bool ret = false;
261 const auto wait = myWaiting4Vehicle.find(edge);
262 if (wait != myWaiting4Vehicle.end()) {
263 const SUMOTime currentTime = SIMSTEP;
264 TransportableVector& transportables = wait->second;
265 for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
266 MSTransportable* const t = *i;
267 if (t->isWaitingFor(vehicle)
268 && vehicle->allowsBoarding(t)
269 && timeToLoadNext - DELTA_T <= currentTime
271 edge->removeTransportable(t);
272 vehicle->addTransportable(t);
273 if (myAbortWaitingTimeout >= 0) {
274 t->setAbortWaiting(-1);
275 }
276 if (timeToLoadNext >= 0) { // meso does not have loading times
277 const SUMOTime loadingDuration = vehicle->getVehicleType().getLoadingDuration(t->isPerson());
278 //update the time point at which the next transportable can be loaded on the vehicle
279 if (timeToLoadNext > currentTime - DELTA_T) {
280 timeToLoadNext += loadingDuration;
281 } else {
282 timeToLoadNext = currentTime + loadingDuration;
283 }
284 }
285
286 static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
287 if (t->getCurrentStage()->getOriginStop() != nullptr) {
289 }
290 i = transportables.erase(i);
292 ret = true;
293 } else {
294 ++i;
295 }
296 }
297 if (transportables.empty()) {
298 myWaiting4Vehicle.erase(wait);
299 }
300 if (ret && timeToLoadNext >= 0) {
301 //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
302 //the duration by setting it to the loading duration of the transportable
303 stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
304 }
305 }
306 return ret;
307}
308
309
310bool
312 return !myTransportables.empty();
313}
314
315
316bool
319}
320
321
322int
325}
326
327
328int
331}
332
333
334int
337}
338
339int
342}
343
344void
346 for (const auto& it : myWaiting4Vehicle) {
347 const MSEdge* edge = it.first;
348 for (MSTransportable* const p : it.second) {
349 edge->removeTransportable(p);
350 MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
351 const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
352 WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
353 if (myAbortWaitingTimeout >= 0) {
354 p->setAbortWaiting(-1);
355 }
356 erase(p);
357 }
358 }
359 myWaiting4Vehicle.clear();
361}
362
363void
365 const MSEdge* edge = t->getEdge();
366 auto it = myWaiting4Vehicle.find(edge);
367 if (it != myWaiting4Vehicle.end()) {
368 TransportableVector& waiting = it->second;
369 auto it2 = std::find(waiting.begin(), waiting.end(), t);
370 if (it2 != waiting.end()) {
371 if (myAbortWaitingTimeout >= 0) {
372 (*it2)->setAbortWaiting(-1);
373 }
374 waiting.erase(it2);
375 }
376 }
377}
378
379void
381 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
382 TransportableVector& ts = it->second;
383 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
384 if (it2 != ts.end()) {
385 ts.erase(it2);
386 }
387 }
388 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
389 TransportableVector& ts = it->second;
390 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
391 if (it2 != ts.end()) {
392 ts.erase(it2);
393 }
394 }
395}
396
397
400 SumoRNG* rng) const {
401 const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
402 return new MSPerson(pars, vtype, plan, speedFactor);
403}
404
405
408 return new MSTransportable(pars, vtype, plan, false);
409}
410
411
412void
414 std::ostringstream oss;
415 oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
416 oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
417 out.writeAttr(SUMO_ATTR_STATE, oss.str());
418 for (const auto& it : myTransportables) {
419 it.second->saveState(out);
420 }
421}
422
423
424void
425MSTransportableControl::loadState(const std::string& state) {
426 std::istringstream iss(state);
429}
430
431void
433 for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
434 delete (*i).second;
435 }
436 myTransportables.clear();
437 myWaiting4Vehicle.clear();
438 myWaiting4Departure.clear();
439 myWaitingUntil.clear();
440 myLoadedNumber = 0;
442 myRunningNumber = 0;
443 myJammedNumber = 0;
447 myEndedNumber = 0;
448 myArrivedNumber = 0;
449 myHaveNewWaiting = false;
452 }
454}
455
456/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define SIMSTEP
Definition: SUMOTime.h:60
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition: StdDefs.h:77
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:1094
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition: MSGlobals.h:162
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:1209
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
@ CONTAINER_DEPARTED
The transportable container has departed (was inserted into the network)
@ PERSON_DEPARTED
The transportable person has departed (was inserted into the network)
@ PERSON_ARRIVED
The transportable person arrived at his destination (is deleted)
@ CONTAINER_ARRIVED
The transportable container arrived at his destination (is deleted)
The pedestrian following model.
The pedestrian following model.
virtual int getActiveNumber()=0
return the number of active objects
virtual void clearState()=0
Resets pedestrians when quick-loading state.
std::string getWaitingDescription() const
Return where the person waits and for what.
virtual MSStoppingPlace * getOriginStop() const
returns the origin stop (if any). only needed for MSStageTrip
Definition: MSStage.h:85
void removeTransportable(const MSTransportable *p)
Removes a transportable from this stop.
void loadState(const std::string &state)
Reconstruct the current state.
void setWaitEnd(SUMOTime time, MSTransportable *transportable)
sets the arrival time for a waiting transportable
bool hasTransportables() const
checks whether any transportable waits to finish her plan
int myWaitingForDepartureNumber
The number of transportables waiting for departure.
void forceDeparture()
register forced (traci) departure
void fixLoadCount(const MSTransportable *transportable)
decrement counter to avoid double counting transportables loaded from state
void checkWaiting(MSNet *net, const SUMOTime time)
checks whether any transportables waiting time is over
void saveState(OutputDevice &out)
Saves the current state into the given stream.
MSTransportableControl(const bool isPerson)
Constructor.
bool hasAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle) const
check whether any transportables are waiting for the given vehicle
int myLoadedNumber
The number of build transportables.
std::map< std::string, MSTransportable * > myTransportables
all currently created transportables by id
void abortWaiting(MSTransportable *t)
aborts waiting stage of transportable
void abortWaitingForVehicle(MSTransportable *t)
let the given transportable abort waiting for a vehicle (when removing stage via TraCI)
void abortAnyWaitingForVehicle()
aborts the plan for any transportable that is still waiting for a ride
bool hasNonWaiting() const
checks whether any transportable is still engaged in walking / stopping
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
int myArrivedNumber
The number of transportables that arrived at their destination.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, SumoRNG *rng) const
Builds a new person.
int getMovingNumber() const
Returns the number of transportables moving by themselvs (i.e. walking)
void addWaiting(const MSEdge *edge, MSTransportable *person)
adds a transportable to the list of transportables waiting for a vehicle on the specified edge
SUMOTime myAbortWaitingTimeout
The time until waiting for a ride is aborted.
int myEndedNumber
The number of transportables that exited the simulation.
bool loadAnyWaiting(const MSEdge *edge, SUMOVehicle *vehicle, SUMOTime &timeToLoadNext, SUMOTime &stopDuration)
load any applicable transportables Loads any person / container that is waiting on that edge for the ...
std::map< const MSEdge *, TransportableVector > myWaiting4Vehicle
the lists of waiting transportables
int myWaitingUntilNumber
The number of transportables waiting for a specified time.
void clearState()
Resets transportables when quick-loading state.
virtual void erase(MSTransportable *transportable)
removes a single transportable
int myDiscardedNumber
The number of discarded transportables.
std::map< SUMOTime, TransportableVector > myWaitingUntil
the lists of walking / stopping transportables
bool add(MSTransportable *transportable)
Adds a single transportable, returns false if an id clash occurred.
bool myHaveNewWaiting
whether a new transportable waiting for a vehicle has been added in the last step
virtual ~MSTransportableControl()
Destructor.
int myJammedNumber
The number of jammed transportables.
std::map< SUMOTime, TransportableVector > myWaiting4Departure
Transportables waiting for departure.
std::vector< MSTransportable * > TransportableVector
Definition of a list of transportables.
int myRunningNumber
The number of transportables within the network (build and inserted but not removed)
int myWaitingForVehicleNumber
The number of transportables waiting for vehicles.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
MSDevice_Vehroutes::SortedRouteInfo myRouteInfos
Information needed to sort transportable output by departure time.
int getActiveCount()
return the number of active transportable objects
int getRidingNumber() const
Returns the number of transportables riding a vehicle.
virtual double getEdgePos() const
Return the position on the edge.
bool hasDeparted() const
return whether the transportable has started it's plan
SUMOTime getDeparture() const
logs depart time of the current stage
void setAbortWaiting(const SUMOTime timeout)
void routeOutput(OutputDevice &os, const bool withRouteLength) const
Called on writing vehroute output.
MSStage * getCurrentStage() const
Return the current stage.
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
bool isPerson() const
Whether it is a person.
std::string getObjectType()
bool hasArrived() const
return whether the person has reached the end of its plan
void tripInfoOutput(OutputDevice &os) const
Called on writing tripinfo output.
const MSEdge * getEdge() const
Returns the current edge.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
bool isWaitingFor(const SUMOVehicle *vehicle) const
Whether the transportable waits for the given vehicle in the current step.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
The car-following model and parameter.
Definition: MSVehicleType.h:63
SUMOTime getLoadingDuration(const bool isPerson) const
Get this vehicle type's loading duration.
double computeChosenSpeedDeviation(SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
An output device that encapsulates an ofstream.
std::string getString() const
Returns the current content as a string.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:251
static bool createDeviceByOption(const std::string &optionName, const std::string &rootElement="", const std::string &schemaFile="")
Creates the device using the output definition stored in the named option.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
Representation of a vehicle.
Definition: SUMOVehicle.h: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