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-2023 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>
23#include <microsim/MSNet.h>
24#include <microsim/MSEdge.h>
26#include "MSRoutingEngine.h"
27#include "MSDispatch.h"
28
29//#define DEBUG_RESERVATION
30//#define DEBUG_DETOUR
31//#define DEBUG_COND2(obj) (obj->getID() == "p0")
32#define DEBUG_COND2(obj) (true)
33
34
35// ===========================================================================
36// Reservation methods
37// ===========================================================================
38
39std::string
41 return toString(persons);
42}
43
44// ===========================================================================
45// MSDispatch methods
46// ===========================================================================
47
49 Parameterised(params),
50 myOutput(nullptr),
51 myReservationCount(0) {
52 const std::string opt = "device.taxi.dispatch-algorithm.output";
53 if (OptionsCont::getOptions().isSet(opt)) {
54 OutputDevice::createDeviceByOption(opt, "DispatchInfo");
56 }
57}
58
60 for (auto item : myGroupReservations) {
61 for (Reservation* res : item.second) {
62 delete res;
63 }
64 }
65 myGroupReservations.clear();
66}
67
68
71 SUMOTime reservationTime,
72 SUMOTime pickupTime,
73 const MSEdge* from, double fromPos,
74 const MSEdge* to, double toPos,
75 std::string group,
76 const std::string& line,
77 int maxCapacity,
78 int maxContainerCapacity) {
79 // no new reservation nedded if the person can be added to an existing group
80 if (group == "") {
81 // the default empty group implies, no grouping is wanted (and
82 // transportable ids are unique)
83 group = person->getID();
84 }
85 Reservation* result = nullptr;
86 bool added = false;
87 auto it = myGroupReservations.find(group);
88 if (it != myGroupReservations.end()) {
89 // try to add to existing reservation
90 for (Reservation* res : it->second) {
91 if (res->persons.count(person) == 0
92 && res->from == from
93 && res->to == to
94 && res->fromPos == fromPos
95 && res->toPos == toPos) {
96 if (res->persons.size() > 0 && (*res->persons.begin())->isPerson() != person->isPerson()) {
97 WRITE_WARNINGF(TL("Mixing reservations of persons and containers with the same group is not supported for % and %"),
98 (*res->persons.begin())->getID(), person->getID());
99 }
100 if ((person->isPerson() && (int)res->persons.size() >= maxCapacity) ||
101 (!person->isPerson() && (int)res->persons.size() >= maxContainerCapacity)) {
102 // split group to ensure that at least one taxi is capable of delivering group size.
103 continue;
104 }
105 res->persons.insert(person);
106 result = res;
107 added = true;
108 break;
109 }
110 }
111 }
112 if (!added) {
113 Reservation* newRes = new Reservation(toString(myReservationCount++), {person}, reservationTime, pickupTime, from, fromPos, to, toPos, group, line);
114 myGroupReservations[group].push_back(newRes);
115 result = newRes;
116 }
118#ifdef DEBUG_RESERVATION
119 if (DEBUG_COND2(person)) std::cout << SIMTIME
120 << " addReservation p=" << person->getID()
121 << " rT=" << time2string(reservationTime)
122 << " pT=" << time2string(pickupTime)
123 << " from=" << from->getID() << " fromPos=" << fromPos
124 << " to=" << to->getID() << " toPos=" << toPos
125 << " group=" << group
126 << " added=" << added
127 << "\n";
128#endif
129 return result;
130}
131
132
133std::string
135 const MSEdge* from, double fromPos,
136 const MSEdge* to, double toPos,
137 std::string group) {
138 if (group == "") {
139 // the default empty group implies, no grouping is wanted (and
140 // transportable ids are unique)
141 group = person->getID();
142 }
143 std::string removedID = "";
144 auto it = myGroupReservations.find(group);
145 if (it != myGroupReservations.end()) {
146 // try to add to existing reservation
147 for (auto itRes = it->second.begin(); itRes != it->second.end(); itRes++) {
148 Reservation* res = *itRes;
149 if (res->persons.count(person) != 0
150 && res->from == from
151 && res->to == to
152 && res->fromPos == fromPos
153 && res->toPos == toPos) {
154 res->persons.erase(person);
155 if (res->persons.empty()) {
156 removedID = res->id;
158 it->second.erase(itRes);
159 }
160 break;
161 }
162 }
163 }
164#ifdef DEBUG_RESERVATION
165 if (DEBUG_COND2(person)) std::cout << SIMTIME
166 << " removeReservation p=" << person->getID()
167 << " from=" << from->getID() << " fromPos=" << fromPos
168 << " to=" << to->getID() << " toPos=" << toPos
169 << " group=" << group
170 << " removedID=" << removedID
171 << "\n";
172#endif
173 return removedID;
174}
175
176
177std::vector<Reservation*>
179 std::vector<Reservation*> reservations;
180 for (const auto& it : myGroupReservations) {
181 reservations.insert(reservations.end(), it.second.begin(), it.second.end());
182 }
183 return reservations;
184}
185
186
187std::vector<const Reservation*>
189 return std::vector<const Reservation*>(myRunningReservations.begin(), myRunningReservations.end());
190}
191
192
193void
195 if (myRunningReservations.count(res)) {
196 return; // was redispatch
197 }
198 auto it = myGroupReservations.find(res->group);
199 if (it == myGroupReservations.end()) {
200 throw ProcessError(TL("Inconsistent group reservations."));
201 }
202 auto it2 = std::find(it->second.begin(), it->second.end(), res);
203 if (it2 == it->second.end()) {
204 throw ProcessError(TL("Inconsistent group reservations (2)."));
205 }
206 myRunningReservations.insert(*it2);
207 const_cast<Reservation*>(*it2)->state = Reservation::ASSIGNED;
208 it->second.erase(it2);
209 if (it->second.empty()) {
210 myGroupReservations.erase(it);
211 }
212}
213
214
215void
217 myRunningReservations.erase(res);
218 delete res;
219}
220
221
224 ConstMSEdgeVector edges;
225 router.compute(taxi->getHolder().getEdge(), taxi->getHolder().getPositionOnLane() - NUMERICAL_EPS,
226 res.from, res.fromPos, &taxi->getHolder(), t, edges, true);
227 return TIME2STEPS(router.recomputeCosts(edges, &taxi->getHolder(), t));
228}
229
230
231double
233 const MSEdge* from, double fromPos,
234 const MSEdge* via, double viaPos,
235 const MSEdge* to, double toPos,
237 double& timeDirect) {
238 ConstMSEdgeVector edges;
239 if (timeDirect < 0) {
240 router.compute(from, fromPos, to, toPos, &taxi->getHolder(), t, edges, true);
241 timeDirect = router.recomputeCostsPos(edges, &taxi->getHolder(), fromPos, toPos, t);
242 edges.clear();
243 }
244
245 router.compute(from, fromPos, via, viaPos, &taxi->getHolder(), t, edges, true);
246 const double start = STEPS2TIME(t);
247 const double leg1 = router.recomputeCostsPos(edges, &taxi->getHolder(), fromPos, viaPos, t);
248#ifdef DEBUG_DETOUR
249 std::cout << " leg1=" << toString(edges) << " startPos=" << fromPos << " toPos=" << viaPos << " time=" << leg1 << "\n";
250#endif
251 const double wait = MAX2(0.0, STEPS2TIME(viaTime) - (start + leg1));
252 edges.clear();
253 const SUMOTime timeContinue = TIME2STEPS(start + leg1 + wait);
254 router.compute(via, viaPos, to, toPos, &taxi->getHolder(), timeContinue, edges, true);
255 const double leg2 = router.recomputeCostsPos(edges, &taxi->getHolder(), viaPos, toPos, timeContinue);
256 const double timeDetour = leg1 + wait + leg2;
257#ifdef DEBUG_DETOUR
258 std::cout << " leg2=" << toString(edges) << " startPos=" << viaPos << " toPos=" << toPos << " time=" << leg2 << "\n";
259 std::cout << " t=" << STEPS2TIME(t) << " vt=" << STEPS2TIME(viaTime)
260 << " from=" << from->getID() << " to=" << to->getID() << " via=" << via->getID()
261 << " direct=" << timeDirect << " detour=" << timeDetour << " wait=" << wait << "\n";
262#endif
263 return timeDetour;
264}
265
266
267int
269 assert(res->persons.size() > 0);
270 return ((*res->persons.begin())->isPerson()
272 : taxi->getHolder().getVehicleType().getContainerCapacity()) - (int)res->persons.size();
273}
274
275
276/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define DEBUG_COND2(obj)
Definition MESegment.cpp:52
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:271
#define TL(string)
Definition MsgHandler.h:287
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:69
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A device which collects info on the vehicle trip (mainly on departure and arrival)
OutputDevice * myOutput
optional file output for dispatch information
Definition MSDispatch.h:182
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 it's id
bool myHasServableReservations
whether the last call to computeDispatch has left servable reservations
Definition MSDispatch.h:170
std::map< std::string, std::vector< Reservation * > > myGroupReservations
Definition MSDispatch.h:185
std::vector< Reservation * > getReservations()
retrieve all reservations
virtual std::vector< const Reservation * > getRunningReservations()
retrieve all reservations that were already dispatched and are still active
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 Reservation * addReservation(MSTransportable *person, SUMOTime reservationTime, SUMOTime pickupTime, const MSEdge *from, double fromPos, const MSEdge *to, double toPos, std::string group, const std::string &line, int maxCapacity, int maxContainerCapacity)
add a new reservation
int myReservationCount
Definition MSDispatch.h:184
virtual void fulfilledReservation(const Reservation *res)
erase reservation from storage
MSDispatch(const Parameterised::Map &params)
Constructor;.
void servedReservation(const Reservation *res)
std::set< const Reservation * > myRunningReservations
Definition MSDispatch.h:179
virtual ~MSDispatch()
Destructor.
A road/street connecting two junctions.
Definition MSEdge.h:77
bool isPerson() const
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 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.
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...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
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.
std::string id
Definition MSDispatch.h:69
const MSEdge * to
Definition MSDispatch.h:75
std::string getID() const
debug identification
double fromPos
Definition MSDispatch.h:74
const MSEdge * from
Definition MSDispatch.h:73
std::string group
Definition MSDispatch.h:77
ReservationState state
Definition MSDispatch.h:80
std::set< MSTransportable * > persons
Definition MSDispatch.h:70
double toPos
Definition MSDispatch.h:76