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-2026 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 HAVE_JUPEDSIM_GRPC
35#endif
36#ifdef HAVE_JUPEDSIM_LEGACY
38#endif
43#include <microsim/MSNet.h>
44#include <microsim/MSEdge.h>
45#include <microsim/MSVehicle.h>
47
48
49// ===========================================================================
50// method definitions
51// ===========================================================================
53 myLoadedNumber(0),
54 myDiscardedNumber(0),
55 myRunningNumber(0),
56 myJammedNumber(0),
57 myWaitingForDepartureNumber(0),
58 myWaitingForVehicleNumber(0),
59 myWaitingUntilNumber(0),
60 myAccessNumber(0),
61 myEndedNumber(0),
62 myArrivedNumber(0),
63 myTeleportsAbortWait(0),
64 myTeleportsWrongDest(0),
65 myHaveNewWaiting(false) {
67 MSNet* const net = MSNet::getInstance();
69 if (isPerson) {
70 const std::string& model = oc.getString("pedestrian.model");
71 if (model == "striping") {
73#ifdef HAVE_JUPEDSIM_GRPC
74 } else if (model == "jupedsim") {
76#endif
77#ifdef HAVE_JUPEDSIM_LEGACY
78 } else if (model == "jupedsim_legacy") {
80#endif
81 } else if (model != "nonInteracting") {
83 throw ProcessError(TLF("Unknown pedestrian model '%'", model));
84 }
85 }
86 if (oc.isSet("vehroute-output")) {
88 }
89 if (oc.isSet("personroute-output")) {
90 OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
92 }
93 if (oc.isSet("personinfo-output")) {
94 OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
95 }
96 myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
97 myMaxTransportableNumber = isPerson ? oc.getInt("max-num-persons") : -1;
98}
99
100
108
109
110bool
112 const SUMOVehicleParameter& param = transportable->getParameter();
113 if (myTransportables.find(param.id) == myTransportables.end()) {
114 myTransportables[param.id] = transportable;
115 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
116 myWaiting4Departure[step].push_back(transportable);
119 return true;
120 }
121 return false;
122}
123
124
125void
128 if (transportable->hasDeparted()) {
129 const SUMOVehicleParameter& param = transportable->getParameter();
130 const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
132 auto it = std::find(waiting.begin(), waiting.end(), transportable);
133 if (it != waiting.end()) {
134 waiting.erase(it);
135 if (waiting.size() == 0) {
136 myWaiting4Departure.erase(step);
137 }
138 }
139 }
140}
141
142
144MSTransportableControl::get(const std::string& id) const {
145 std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
146 if (i == myTransportables.end()) {
147 return nullptr;
148 }
149 return (*i).second;
150}
151
152
153void
156 if (oc.isSet("personinfo-output")) {
157 transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
158 } else if (oc.isSet("tripinfo-output")) {
159 transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
160 } else if (oc.getBool("duration-log.statistics")) {
161 // collecting statistics is a sideffect
163 transportable->tripInfoOutput(dev);
164 }
165 if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
166 if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
167 // @todo: adapt this if we ever introduce person-device.vehroute
168 if (transportable->getBoolParam("has.vehroute.person-device", false, true)) {
169 if (oc.getBool("vehroute-output.sorted")) {
170 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
172 transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
174 departure, transportable->getNumericalID(), od.getString());
175 } else {
176 transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
177 }
178 }
179 }
180 }
181 const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
182 if (i != myTransportables.end()) {
183 if (i->second->hasDeparted()) {
185 }
189 delete i->second;
190 myTransportables.erase(i);
191 }
192}
193
194
195void
197 // avoid taxi device having dangling references to erased customers
199 while (loadedBegin() != loadedEnd()) {
200 erase(loadedBegin()->second);
201 }
202}
203
204
205void
207 const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
208 // avoid double registration
209 const TransportableVector& transportables = myWaitingUntil[step];
210 if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
211 myWaitingUntil[step].push_back(transportable);
213 }
214}
215
216
217void
219 myHaveNewWaiting = false;
220 while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
221 TransportableVector& transportables = myWaiting4Departure[time];
222 // we cannot use an iterator here because there might be additions to the vector while proceeding
223 for (auto it = transportables.begin(); it != transportables.end();) {
224 MSTransportable* t = *it;
227 nextStep.insert(nextStep.begin(), transportables.begin(), transportables.end());
228 transportables.clear();
229 break;
230 } else if (myMaxTransportableNumber == 0) {
231 erase(t);
232 it = transportables.erase(it);
233 continue;
234 }
235 it = transportables.erase(it);
237 const bool isPerson = t->isPerson();
238 t->setDeparted(time);
239 if (t->proceed(net, time)) {
244 if (oc.getBool("vehroute-output.sorted")) {
245 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
246 if (oc.isSet("personroute-output")) {
247 myRouteInfos.departureCounts[departure]++;
248 } else {
250 }
251 }
252 } else {
253 erase(t);
254 }
255 }
256 myWaiting4Departure.erase(time);
257 }
258 while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
259 // make a copy because 0-duration stops might modify the vector
260 const TransportableVector transportables = myWaitingUntil[time];
261 myWaitingUntil.erase(time);
262 for (MSTransportable* t : transportables) {
264 if (!t->proceed(net, time)) {
265 erase(t);
266 }
267 }
268 }
269}
270
271
272#ifndef THREAD_POOL
273#ifdef HAVE_FOX
274void
275MSTransportableControl::addPendingRouting(MSTransportable* transportable) {
276 myPendingRouting.push_back(transportable);
277}
278
279
280void
281MSTransportableControl::processPendingRouting(MSNet* net, const SUMOTime time) {
282 for (MSTransportable* t : myPendingRouting) {
283 if (!t->proceed(net, time)) {
284 erase(t);
285 }
286 }
287 myPendingRouting.clear();
288}
289#endif
290#endif
291
292
293void
297
298
299void
301 myWaiting4Vehicle[edge].push_back(transportable);
303 myHaveNewWaiting = true;
304 if (myAbortWaitingTimeout >= 0) {
306 }
307}
308
309
310bool
312 const auto wait = myWaiting4Vehicle.find(edge);
313 if (wait != myWaiting4Vehicle.end()) {
314 for (const MSTransportable* t : wait->second) {
315 if (t->isWaitingFor(vehicle)
316 && vehicle->allowsBoarding(t)
317 && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
318 return true;
319 }
320 }
321 }
322 return false;
323}
324
325
326bool
327MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration, MSTransportable* const force) {
328 bool ret = false;
329 const auto wait = myWaiting4Vehicle.find(edge);
330 if (wait != myWaiting4Vehicle.end()) {
331 const SUMOTime currentTime = SIMSTEP;
332 TransportableVector& transportables = wait->second;
333 for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
334 MSTransportable* const t = *i;
335 if (t->isWaitingFor(vehicle) && (t == force ||
336 (vehicle->allowsBoarding(t)
337 && timeToLoadNext - DELTA_T <= currentTime
339 edge->removeTransportable(t);
340 vehicle->addTransportable(t);
341 if (myAbortWaitingTimeout >= 0) {
342 t->setAbortWaiting(-1);
343 }
344 if (timeToLoadNext >= 0) { // meso does not have loading times
345 const SUMOTime loadingDuration = (SUMOTime)((double)vehicle->getVehicleType().getLoadingDuration(t->isPerson()) * t->getVehicleType().getBoardingFactor());
346 //update the time point at which the next transportable can be loaded on the vehicle
347 if (timeToLoadNext > currentTime - DELTA_T) {
348 timeToLoadNext += loadingDuration;
349 } else {
350 timeToLoadNext = currentTime + loadingDuration;
351 }
352 }
353
354 static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
355 if (t->getCurrentStage()->getOriginStop() != nullptr) {
357 }
358 i = transportables.erase(i);
360 ret = true;
361 } else {
362 ++i;
363 }
364 }
365 if (transportables.empty()) {
366 myWaiting4Vehicle.erase(wait);
367 }
368 if (ret && timeToLoadNext >= 0) {
369 //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
370 //the duration by setting it to the loading duration of the transportable
371 stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
372 }
373 }
374 return ret;
375}
376
377
378bool
382
383
384bool
388
389
390int
394
395
396int
400
401
402int
406
407int
411
412void
414 for (const auto& it : myWaiting4Vehicle) {
415 const MSEdge* edge = it.first;
416 for (MSTransportable* const p : it.second) {
417 edge->removeTransportable(p);
418 MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
419 const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
420 WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
421 if (myAbortWaitingTimeout >= 0) {
422 p->setAbortWaiting(-1);
423 }
424 erase(p);
425 }
426 }
427 myWaiting4Vehicle.clear();
429}
430
431void
433 const MSEdge* edge = t->getEdge();
434 auto it = myWaiting4Vehicle.find(edge);
435 if (it != myWaiting4Vehicle.end()) {
436 TransportableVector& waiting = it->second;
437 auto it2 = std::find(waiting.begin(), waiting.end(), t);
438 if (it2 != waiting.end()) {
439 if (myAbortWaitingTimeout >= 0) {
440 (*it2)->setAbortWaiting(-1);
441 }
442 waiting.erase(it2);
444 }
445 }
446}
447
448void
450 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
451 TransportableVector& ts = it->second;
452 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
453 if (it2 != ts.end()) {
454 ts.erase(it2);
455 }
456 }
457 for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
458 TransportableVector& ts = it->second;
459 TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
460 if (it2 != ts.end()) {
461 ts.erase(it2);
462 }
463 }
464}
465
466
469 SumoRNG* rng) const {
470 const double speedFactor = vtype->computeChosenSpeedDeviation(pars->speedFactor, rng);
471 return new MSPerson(pars, vtype, plan, speedFactor);
472}
473
474
477 return new MSTransportable(pars, vtype, plan, false);
478}
479
480
481void
483 std::ostringstream oss;
484 oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
485 oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myHaveNewWaiting;
486 out.writeAttr(SUMO_ATTR_STATE, oss.str());
487 for (const auto& it : myTransportables) {
488 it.second->saveState(out);
489 }
490}
491
492
493void
499
500void
502 for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
503 delete (*i).second;
504 }
505 myTransportables.clear();
506 myWaiting4Vehicle.clear();
507 myWaiting4Departure.clear();
508 myWaitingUntil.clear();
509 myLoadedNumber = 0;
511 myRunningNumber = 0;
512 myJammedNumber = 0;
516 myEndedNumber = 0;
517 myArrivedNumber = 0;
518 myHaveNewWaiting = false;
521 }
523}
524
525/****************************************************************************/
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:39
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:47
#define SIMSTEP
Definition SUMOTime.h:69
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition StdDefs.h:86
static void allCustomersErased()
signal the end of the simulation and the removal of all customers
static void writeSortedOutput(SortedRouteInfo *routeInfo, SUMOTime depart, const SUMOTrafficObject::NumericalID id, const std::string &xmlOutput)
static void registerTransportableDepart(SUMOTime depart)
A road/street connecting two junctions.
Definition MSEdge.h:78
virtual void removeTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1281
static double gStopTolerance
The tolerance to apply when matching waiting persons and vehicles.
Definition MSGlobals.h:171
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:1430
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:201
@ 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...
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.
constVehIt loadedBegin() const
Returns the begin of the internal transportables map.
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
void eraseAll()
@removes all transportables
int myLoadedNumber
The number of build transportables.
constVehIt loadedEnd() const
Returns the end of the internal transportables map.
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
NumericalID getNumericalID() const override
return the numerical ID which is only for internal usage
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 override
Whether it is a person.
const SUMOVehicleParameter & getParameter() const override
Returns the vehicle's parameter (including departure definition)
const MSVehicleType & getVehicleType() const override
Returns the object's "vehicle" type.
void tripInfoOutput(OutputDevice &os) const
Called on writing tripinfo output.
const MSEdge * getEdge() const override
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.
bool hasArrived() const override
return whether the person has reached the end of its plan
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(double speedFactorOverride, SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
const std::string & getID() const
Returns the id.
Definition Named.h:73
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 ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
static bool createDeviceByOption(const std::string &optionName, const std::string &rootElement="", const std::string &schemaFile="", const int maximumDepth=2)
Creates the device using the output definition stored in the named 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:63
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.
double speedFactor
individual speedFactor (overriding distribution from vType)
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