Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSDispatch.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2007-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/****************************************************************************/
18// An algorithm that performs dispatch for the taxi device
19/****************************************************************************/
20#include <config.h>
21
22#include <limits>
24#include <microsim/MSNet.h>
25#include <microsim/MSEdge.h>
26#include <microsim/MSGlobals.h>
28#include "MSRoutingEngine.h"
29#include "MSDispatch.h"
30
31//#define DEBUG_RESERVATION
32//#define DEBUG_DETOUR
33//#define DEBUG_COND2(obj) (obj->getID() == "p0")
34#define DEBUG_COND2(obj) (true)
35
36
37// ===========================================================================
38// Reservation methods
39// ===========================================================================
40
41// ===========================================================================
42// MSDispatch methods
43// ===========================================================================
44
46 Parameterised(params),
47 myOutput(nullptr),
48 myReservationCount(0),
49 myRoutingMode(StringUtils::toInt(getParameter("routingMode", "1"))) {
50 const std::string opt = "device.taxi.dispatch-algorithm.output";
51 if (OptionsCont::getOptions().isSet(opt)) {
52 OutputDevice::createDeviceByOption(opt, "DispatchInfo");
54 }
55 myKeepUnreachableResTime = string2time(OptionsCont::getOptions().getString("device.taxi.dispatch-keep-unreachable"));
56}
57
59 for (auto item : myGroupReservations) {
60 for (Reservation* res : item.second) {
61 delete res;
62 }
63 }
64 myGroupReservations.clear();
65}
66
67
70 SUMOTime reservationTime,
71 SUMOTime pickupTime,
72 SUMOTime earliestPickupTime,
73 const MSEdge* from, double fromPos,
74 const MSStoppingPlace* fromStop,
75 const MSEdge* to, double toPos,
76 const MSStoppingPlace* toStop,
77 std::string group,
78 const std::string& line,
79 int maxCapacity,
80 int maxContainerCapacity) {
81 std::string resID;
82 if (myLoadedReservations.size() > 0) {
83 auto itL = myLoadedReservations.find(person->getID());
84 if (itL != myLoadedReservations.end()) {
85 resID = itL->second;
86 myLoadedReservations.erase(itL);
87 }
88 }
89 // no new reservation nedded if the person can be added to an existing group
90 if (group == "") {
91 // the default empty group implies, no grouping is wanted (and
92 // transportable ids are unique)
93 group = person->getID();
94 } else {
95 auto it2 = myRunningReservations.find(group);
96 if (it2 != myRunningReservations.end()) {
97 for (auto item : it2->second) {
98 Reservation* res = const_cast<Reservation*>(item.first);
99 if (res->from == from
100 && res->to == to
101 && (res->fromPos == fromPos || res->fromStop == fromStop)
102 && (res->toPos == toPos || res->toStop == toStop)) {
103 MSDevice_Taxi* taxi = item.second;
104 if ((taxi->getState() == taxi->PICKUP
105 && remainingCapacity(taxi, res) > 0
106 && taxi->compatibleLine(taxi->getHolder().getParameter().line, line))
107 || resID == res->id) {
108 //std::cout << SIMTIME << " addPerson=" << person->getID() << " extendRes=" << toString(res->persons) << " taxi=" << taxi->getHolder().getID() << " state=" << taxi->getState() << "\n";
109 res->persons.insert(person);
110 taxi->addCustomer(person, res);
111#ifdef DEBUG_RESERVATION
112 if (DEBUG_COND2(person)) std::cout << SIMTIME << " extendedReservation p=" << person->getID() << " resID=" << res->getID() << " taxi=" << taxi->getID() << "\n";
113#endif
114 return res;
115 }
116 }
117 }
118 }
119 }
120 Reservation* result = nullptr;
121 bool added = false;
122 auto it = myGroupReservations.find(group);
123 if (it != myGroupReservations.end()) {
124 // try to add to existing reservation
125 for (Reservation* res : it->second) {
126 if (res->persons.count(person) == 0
127 && res->from == from
128 && res->to == to
129 && (res->fromPos == fromPos || res->fromStop == fromStop)
130 && (res->toPos == toPos || res->toStop == toStop)
131 && (resID.empty() || res->id == resID)) {
132 if (res->persons.size() > 0 && (*res->persons.begin())->isPerson() != person->isPerson()) {
133 WRITE_WARNINGF(TL("Mixing reservations of persons and containers with the same group is not supported for % and %"),
134 (*res->persons.begin())->getID(), person->getID());
135 }
136 if ((person->isPerson() && (int)res->persons.size() >= maxCapacity) ||
137 (!person->isPerson() && (int)res->persons.size() >= maxContainerCapacity)) {
138 // split group to ensure that at least one taxi is capable of delivering group size.
139 continue;
140 }
141 res->persons.insert(person);
142 result = res;
143 added = true;
144 break;
145 }
146 }
147 }
148 if (!added) {
149 if (resID.empty()) {
150 resID = toString(myReservationCount++);
151 }
152 Reservation* newRes = new Reservation(resID, {person}, reservationTime, pickupTime, earliestPickupTime, from, fromPos, fromStop, to, toPos, toStop, group, line);
153 myGroupReservations[group].push_back(newRes);
154 result = newRes;
155 }
157#ifdef DEBUG_RESERVATION
158 if (DEBUG_COND2(person)) std::cout << SIMTIME
159 << " addReservation p=" << person->getID()
160 << " addID=" << result->getID()
161 << " rT=" << time2string(reservationTime)
162 << " pT=" << time2string(pickupTime)
163 << " from=" << from->getID() << " fromPos=" << fromPos
164 << " to=" << to->getID() << " toPos=" << toPos
165 << " group=" << group
166 << " added=" << added
167 << "\n";
168#endif
169 return result;
170}
171
172
173std::string
175 const MSEdge* from, double fromPos,
176 const MSEdge* to, double toPos,
177 std::string group) {
178 if (group == "") {
179 // the default empty group implies, no grouping is wanted (and
180 // transportable ids are unique)
181 group = person->getID();
182 }
183 std::string removedID = "";
184 auto it = myGroupReservations.find(group);
185 if (it != myGroupReservations.end()) {
186 for (auto itRes = it->second.begin(); itRes != it->second.end(); itRes++) {
187 Reservation* res = *itRes;
188 if (res->persons.count(person) != 0
189 && res->from == from
190 && res->to == to
191 && res->fromPos == fromPos
192 && res->toPos == toPos) {
193 res->persons.erase(person);
194 if (res->persons.empty()) {
195 removedID = res->id;
196 it->second.erase(itRes);
197 // cleans up MSDispatch_Greedy
199 if (it->second.empty()) {
200 myGroupReservations.erase(it);
201 }
202 }
203 break;
204 }
205 }
206 } else {
207 auto it2 = myRunningReservations.find(group);
208 if (it2 != myRunningReservations.end()) {
209 for (auto item : it2->second) {
210 const Reservation* const res = item.first;
211 if (res->persons.count(person) != 0
212 && res->from == from
213 && res->to == to
214 && res->fromPos == fromPos
215 && res->toPos == toPos) {
216 if (res->persons.size() == 1) {
217 removedID = res->id;
218 }
219 item.second->cancelCustomer(person); // will delete res via fulfilledReservation if necessary
220 break;
221 }
222 }
223 }
224 }
226#ifdef DEBUG_RESERVATION
227 if (DEBUG_COND2(person)) std::cout << SIMTIME
228 << " removeReservation p=" << person->getID()
229 << " from=" << from->getID() << " fromPos=" << fromPos
230 << " to=" << to->getID() << " toPos=" << toPos
231 << " group=" << group
232 << " removedID=" << removedID
233 << " hasServable=" << myHasServableReservations
234 << "\n";
235#endif
236 return removedID;
237}
238
239
242 const MSEdge* from, double fromPos,
243 const MSEdge* to, double toPos,
244 std::string group, double newFromPos) {
245 if (group == "") {
246 // the default empty group implies, no grouping is wanted (and
247 // transportable ids are unique)
248 group = person->getID();
249 }
250 Reservation* result = nullptr;
251 std::string updatedID = "";
252 auto it = myGroupReservations.find(group);
253 if (it != myGroupReservations.end()) {
254 for (auto itRes = it->second.begin(); itRes != it->second.end(); itRes++) {
255 Reservation* res = *itRes;
256 // TODO: if there is already a reservation with the newFromPos, add to this reservation
257 // TODO: if there are other persons in this reservation, create a new reservation for the updated one
258 if (res->persons.count(person) != 0
259 && res->from == from
260 && res->to == to
261 && res->fromPos == fromPos
262 && res->toPos == toPos) {
263 // update fromPos
264 res->fromPos = newFromPos;
265 result = res;
266 updatedID = res->id;
267 break;
268 }
269 }
270 }
271#ifdef DEBUG_RESERVATION
272 if (DEBUG_COND2(person)) std::cout << SIMTIME
273 << " updateReservationFromPos p=" << person->getID()
274 << " from=" << from->getID() << " fromPos=" << fromPos
275 << " to=" << to->getID() << " toPos=" << toPos
276 << " group=" << group
277 << " newFromPos=" << newFromPos
278 << " updatedID=" << updatedID
279 << "\n";
280#endif
281 return result;
282}
283
284
285std::vector<Reservation*>
287 std::vector<Reservation*> reservations;
288 for (const auto& it : myGroupReservations) {
289 reservations.insert(reservations.end(), it.second.begin(), it.second.end());
290 }
291 return reservations;
292}
293
294
295std::vector<const Reservation*>
297 std::vector<const Reservation*> result;
298 for (auto item : myRunningReservations) {
299 for (auto item2 : item.second) {
300 result.push_back(item2.first);
301 }
302 }
303 return result;
304}
305
306
307void
309 auto itR = myRunningReservations.find(res->group);
310 if (itR != myRunningReservations.end() && itR->second.count(res) != 0) {
311#ifdef DEBUG_RESERVATION
312 std::cout << SIMTIME << " servedReservation res=" << res->id << " taxi=" << taxi->getID() << " (running)\n";
313#endif
314 return; // was redispatch
315 }
316#ifdef DEBUG_RESERVATION
317 std::cout << SIMTIME << " servedReservation res=" << res->id << " taxi=" << taxi->getID() << "\n";
318#endif
319 auto it = myGroupReservations.find(res->group);
320 if (it == myGroupReservations.end()) {
321 throw ProcessError(TL("Inconsistent group reservations."));
322 }
323 auto it2 = std::find(it->second.begin(), it->second.end(), res);
324 if (it2 == it->second.end()) {
325 throw ProcessError(TL("Inconsistent group reservations (2)."));
326 }
327 myRunningReservations[res->group][res] = taxi;
328 const_cast<Reservation*>(*it2)->state = Reservation::ASSIGNED;
329 it->second.erase(it2);
330 if (it->second.empty()) {
331 myGroupReservations.erase(it);
332 }
333}
334
335
336void
338#ifdef DEBUG_RESERVATION
339 std::cout << SIMTIME << " swapped res=" << res->id << " old=" << myRunningReservations[res->group][res]->getID() << " new=" << taxi->getID() << "\n";
340#endif
341 myRunningReservations[res->group][res] = taxi;
342}
343
344
345void
347#ifdef DEBUG_RESERVATION
348 std::cout << SIMTIME << " fullfilled res=" << res->id << "\n";
349#endif
350 myRunningReservations[res->group].erase(res);
351 if (myRunningReservations[res->group].empty()) {
352 myRunningReservations.erase(res->group);
353 }
354 delete res;
355}
356
357
362
363
366 ConstMSEdgeVector edges;
367 double fromPos = taxi->getHolder().getPositionOnLane() - NUMERICAL_EPS;
368 const MSEdge* from = *taxi->getHolder().getRerouteOrigin();
369 const bool originDiffers = from != taxi->getHolder().getEdge();
370 router.compute(from, originDiffers ? 0 : fromPos, res.from, res.fromPos, &taxi->getHolder(), t, edges, true);
371 if (edges.empty()) {
372 return SUMOTime_MAX;
373 } else {
374 if (originDiffers) {
375 assert(from == *(taxi->getHolder().getCurrentRouteEdge() + 1));
376 edges.insert(edges.begin(), taxi->getHolder().getEdge());
377 }
378 return TIME2STEPS(router.recomputeCostsPos(edges, &taxi->getHolder(), fromPos, res.fromPos, t));
379 }
380}
381
382
383bool
385 ConstMSEdgeVector edges;
386 router.compute(res.from, res.fromPos, res.to, res.toPos, &taxi->getHolder(), t, edges, true);
387 return !edges.empty();
388}
389
390
391double
393 const MSEdge* from, double fromPos,
394 const MSEdge* via, double viaPos,
395 const MSEdge* to, double toPos,
397 double& timeDirect) {
398 ConstMSEdgeVector edges;
399 if (timeDirect < 0) {
400 router.compute(from, fromPos, to, toPos, &taxi->getHolder(), t, edges, true);
401 timeDirect = router.recomputeCostsPos(edges, &taxi->getHolder(), fromPos, toPos, t);
402 edges.clear();
403 }
404
405 router.compute(from, fromPos, via, viaPos, &taxi->getHolder(), t, edges, true);
406 const double start = STEPS2TIME(t);
407 const double leg1 = router.recomputeCostsPos(edges, &taxi->getHolder(), fromPos, viaPos, t);
408#ifdef DEBUG_DETOUR
409 std::cout << " leg1=" << toString(edges) << " startPos=" << fromPos << " toPos=" << viaPos << " time=" << leg1 << "\n";
410#endif
411 const double wait = MAX2(0.0, STEPS2TIME(viaTime) - (start + leg1));
412 edges.clear();
413 const SUMOTime timeContinue = TIME2STEPS(start + leg1 + wait);
414 router.compute(via, viaPos, to, toPos, &taxi->getHolder(), timeContinue, edges, true);
415 const double leg2 = router.recomputeCostsPos(edges, &taxi->getHolder(), viaPos, toPos, timeContinue);
416 const double timeDetour = leg1 + wait + leg2;
417#ifdef DEBUG_DETOUR
418 std::cout << " leg2=" << toString(edges) << " startPos=" << viaPos << " toPos=" << toPos << " time=" << leg2 << "\n";
419 std::cout << " t=" << STEPS2TIME(t) << " vt=" << STEPS2TIME(viaTime)
420 << " from=" << from->getID() << " to=" << to->getID() << " via=" << via->getID()
421 << " direct=" << timeDirect << " detour=" << timeDetour << " wait=" << wait << "\n";
422#endif
423 return timeDetour;
424}
425
426
427int
429 assert(res->persons.size() > 0);
430 return ((*res->persons.begin())->isPerson()
432 : taxi->getHolder().getVehicleType().getContainerCapacity()) - (int)res->persons.size();
433}
434
435
436void
437MSDispatch::saveState(OutputDevice& out, SUMOTime nextDispatch) const {
439 out.writeAttr(SUMO_ATTR_NEXT, nextDispatch);
441
442 std::ostringstream internals;
443 for (const auto& it : myRunningReservations) {
444 for (const auto& item : it.second) {
445 for (const MSTransportable* t : item.first->persons) {
446 internals << t->getID() << " " << item.first->id << " ";
447 }
448 }
449 }
450 for (const auto& it : myGroupReservations) {
451 for (const Reservation* res : it.second) {
452 for (const MSTransportable* t : res->persons) {
453 internals << t->getID() << " " << res->id << " ";
454 }
455 }
456 }
457 out.writeAttr(SUMO_ATTR_CUSTOMERS, internals.str());
458 out.closeTag();
459}
460
461
462void
464 bool ok = true;
465 myReservationCount = attrs.get<int>(SUMO_ATTR_COUNT, "dispatcher", ok);
466 std::istringstream bis(attrs.getString(SUMO_ATTR_CUSTOMERS));
467 std::string tID, rID;
468 while (bis >> tID && bis >> rID) {
469 myLoadedReservations[tID] = rID;
470 }
471}
472
473
474
475/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define DEBUG_COND2(obj)
Definition MESegment.cpp:54
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:304
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:65
#define TIME2STEPS(x)
Definition SUMOTime.h:60
@ SVC_TAXI
vehicle is a taxi
@ SUMO_TAG_DISPATCHER
Dispatcher state for saving.
@ SUMO_ATTR_CUSTOMERS
@ SUMO_ATTR_NEXT
succesor phase index
@ SUMO_ATTR_COUNT
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
A device which collects info on the vehicle trip (mainly on departure and arrival)
void addCustomer(const MSTransportable *t, const Reservation *res)
add person after extending reservation
int getState() const
bool compatibleLine(const Reservation *res)
whether the given reservation is compatible with the taxi line
OutputDevice * myOutput
optional file output for dispatch information
Definition MSDispatch.h:226
const int myRoutingMode
which router/edge weights to use
Definition MSDispatch.h:236
bool isReachable(SUMOTime t, const MSDevice_Taxi *taxi, const Reservation &res, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router)
compute whether the reservation is servable
void swappedRunning(const Reservation *res, MSDevice_Taxi *taxi)
int remainingCapacity(const MSDevice_Taxi *taxi, const Reservation *res)
whether the given taxi has sufficient capacity to serve the reservation
static SUMOTime computePickupTime(SUMOTime t, const MSDevice_Taxi *taxi, const Reservation &res, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router)
compute time to pick up the given reservation
virtual std::string removeReservation(MSTransportable *person, const MSEdge *from, double fromPos, const MSEdge *to, double toPos, std::string group)
remove person from reservation. If the whole reservation is removed, return its id
bool myHasServableReservations
whether the last call to computeDispatch has left servable reservations
Definition MSDispatch.h:198
virtual Reservation * updateReservationFromPos(MSTransportable *person, const MSEdge *from, double fromPos, const MSEdge *to, double toPos, std::string group, double newFromPos)
update fromPos of the person's reservation. TODO: if there is already a reservation with the newFromP...
std::map< std::string, std::vector< Reservation * > > myGroupReservations
Definition MSDispatch.h:233
std::vector< Reservation * > getReservations()
retrieve all reservations
virtual std::vector< const Reservation * > getRunningReservations()
retrieve all reservations that were already dispatched and are still active
SUMOTime myKeepUnreachableResTime
the duration before canceling unreachable reservations
Definition MSDispatch.h:231
std::map< std::string, std::string > myLoadedReservations
reservations loaded from state
Definition MSDispatch.h:239
static double computeDetourTime(SUMOTime t, SUMOTime viaTime, const MSDevice_Taxi *taxi, const MSEdge *from, double fromPos, const MSEdge *via, double viaPos, const MSEdge *to, double toPos, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, double &timeDirect)
compute directTime and detourTime
virtual SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouter() const
virtual Reservation * addReservation(MSTransportable *person, SUMOTime reservationTime, SUMOTime pickupTime, SUMOTime earliestPickupTime, const MSEdge *from, double fromPos, const MSStoppingPlace *fromStop, const MSEdge *to, double toPos, const MSStoppingPlace *tostop, std::string group, const std::string &line, int maxCapacity, int maxContainerCapacity)
add a new reservation
virtual void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the device from the given description.
int myReservationCount
Definition MSDispatch.h:228
virtual void fulfilledReservation(const Reservation *res)
erase reservation from storage
virtual void saveState(OutputDevice &out, SUMOTime nextDispatch) const
Saves the state of the device.
MSDispatch(const Parameterised::Map &params)
Constructor;.
std::map< std::string, std::map< const Reservation *, MSDevice_Taxi *, ComparatorIdLess > > myRunningReservations
Definition MSDispatch.h:223
virtual ~MSDispatch()
Destructor.
void servedReservation(const Reservation *res, MSDevice_Taxi *taxi)
A road/street connecting two junctions.
Definition MSEdge.h:77
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:199
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1628
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
A lane area vehicles can halt at.
bool isPerson() const override
Whether it is a person.
SUMOVehicle & getHolder() const
Returns the vehicle that holds this device.
int getPersonCapacity() const
Get this vehicle type's person capacity.
int getContainerCapacity() const
Get this vehicle type's container capacity.
const std::string & getID() const
Returns the id.
Definition Named.h:74
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
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.
An upper class for objects with additional parameters.
std::map< std::string, std::string > Map
parameters map
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const =0
Returns the starting point for reroutes (usually the current edge)
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
std::string line
The vehicle's line (mainly for public transport)
Some static methods for string processing.
Definition StringUtils.h:40
const MSStoppingPlace * toStop
Definition MSDispatch.h:86
const MSStoppingPlace * fromStop
Definition MSDispatch.h:83
std::string id
Definition MSDispatch.h:76
const MSEdge * to
Definition MSDispatch.h:84
std::string getID() const
for sorting by id
Definition MSDispatch.h:105
double fromPos
Definition MSDispatch.h:82
const MSEdge * from
Definition MSDispatch.h:81
std::string group
Definition MSDispatch.h:87
ReservationState state
Definition MSDispatch.h:90
std::set< const MSTransportable *, ComparatorNumericalIdLess > persons
Definition MSDispatch.h:77
double toPos
Definition MSDispatch.h:85