Eclipse SUMO - Simulation of Urban MObility
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-2024 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 
39 std::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  SUMOTime earliestPickupTime,
74  const MSEdge* from, double fromPos,
75  const MSStoppingPlace* fromStop,
76  const MSEdge* to, double toPos,
77  const MSStoppingPlace* toStop,
78  std::string group,
79  const std::string& line,
80  int maxCapacity,
81  int maxContainerCapacity) {
82  // no new reservation nedded if the person can be added to an existing group
83  if (group == "") {
84  // the default empty group implies, no grouping is wanted (and
85  // transportable ids are unique)
86  group = person->getID();
87  }
88  Reservation* result = nullptr;
89  bool added = false;
90  auto it = myGroupReservations.find(group);
91  if (it != myGroupReservations.end()) {
92  // try to add to existing reservation
93  for (Reservation* res : it->second) {
94  if (res->persons.count(person) == 0
95  && res->from == from
96  && res->to == to
97  && res->fromPos == fromPos
98  && res->toPos == toPos) {
99  if (res->persons.size() > 0 && (*res->persons.begin())->isPerson() != person->isPerson()) {
100  WRITE_WARNINGF(TL("Mixing reservations of persons and containers with the same group is not supported for % and %"),
101  (*res->persons.begin())->getID(), person->getID());
102  }
103  if ((person->isPerson() && (int)res->persons.size() >= maxCapacity) ||
104  (!person->isPerson() && (int)res->persons.size() >= maxContainerCapacity)) {
105  // split group to ensure that at least one taxi is capable of delivering group size.
106  continue;
107  }
108  res->persons.insert(person);
109  result = res;
110  added = true;
111  break;
112  }
113  }
114  }
115  if (!added) {
116  Reservation* newRes = new Reservation(toString(myReservationCount++), {person}, reservationTime, pickupTime, earliestPickupTime, from, fromPos, fromStop, to, toPos, toStop, group, line);
117  myGroupReservations[group].push_back(newRes);
118  result = newRes;
119  }
121 #ifdef DEBUG_RESERVATION
122  if (DEBUG_COND2(person)) std::cout << SIMTIME
123  << " addReservation p=" << person->getID()
124  << " rT=" << time2string(reservationTime)
125  << " pT=" << time2string(pickupTime)
126  << " from=" << from->getID() << " fromPos=" << fromPos
127  << " to=" << to->getID() << " toPos=" << toPos
128  << " group=" << group
129  << " added=" << added
130  << "\n";
131 #endif
132  return result;
133 }
134 
135 
136 std::string
138  const MSEdge* from, double fromPos,
139  const MSEdge* to, double toPos,
140  std::string group) {
141  if (group == "") {
142  // the default empty group implies, no grouping is wanted (and
143  // transportable ids are unique)
144  group = person->getID();
145  }
146  std::string removedID = "";
147  auto it = myGroupReservations.find(group);
148  if (it != myGroupReservations.end()) {
149  // try to add to existing reservation
150  for (auto itRes = it->second.begin(); itRes != it->second.end(); itRes++) {
151  Reservation* res = *itRes;
152  if (res->persons.count(person) != 0
153  && res->from == from
154  && res->to == to
155  && res->fromPos == fromPos
156  && res->toPos == toPos) {
157  res->persons.erase(person);
158  if (res->persons.empty()) {
159  removedID = res->id;
161  it->second.erase(itRes);
162  }
163  break;
164  }
165  }
166  }
167 #ifdef DEBUG_RESERVATION
168  if (DEBUG_COND2(person)) std::cout << SIMTIME
169  << " removeReservation p=" << person->getID()
170  << " from=" << from->getID() << " fromPos=" << fromPos
171  << " to=" << to->getID() << " toPos=" << toPos
172  << " group=" << group
173  << " removedID=" << removedID
174  << "\n";
175 #endif
176  return removedID;
177 }
178 
179 
182  const MSEdge* from, double fromPos,
183  const MSEdge* to, double toPos,
184  std::string group, double newFromPos) {
185  if (group == "") {
186  // the default empty group implies, no grouping is wanted (and
187  // transportable ids are unique)
188  group = person->getID();
189  }
190  Reservation* result = nullptr;
191  std::string updatedID = "";
192  auto it = myGroupReservations.find(group);
193  if (it != myGroupReservations.end()) {
194  for (auto itRes = it->second.begin(); itRes != it->second.end(); itRes++) {
195  Reservation* res = *itRes;
196  // TODO: if there is already a reservation with the newFromPos, add to this reservation
197  // TODO: if there are other persons in this reservation, create a new reservation for the updated one
198  if (res->persons.count(person) != 0
199  && res->from == from
200  && res->to == to
201  && res->fromPos == fromPos
202  && res->toPos == toPos) {
203  // update fromPos
204  res->fromPos = newFromPos;
205  result = res;
206  updatedID = res->id;
207  break;
208  }
209  }
210  }
211 #ifdef DEBUG_RESERVATION
212  if (DEBUG_COND2(person)) std::cout << SIMTIME
213  << " updateReservationFromPos p=" << person->getID()
214  << " from=" << from->getID() << " fromPos=" << fromPos
215  << " to=" << to->getID() << " toPos=" << toPos
216  << " group=" << group
217  << " newFromPos=" << newFromPos
218  << " updatedID=" << updatedID
219  << "\n";
220 #endif
221  return result;
222 }
223 
224 
225 std::vector<Reservation*>
227  std::vector<Reservation*> reservations;
228  for (const auto& it : myGroupReservations) {
229  reservations.insert(reservations.end(), it.second.begin(), it.second.end());
230  }
231  return reservations;
232 }
233 
234 
235 std::vector<const Reservation*>
237  return std::vector<const Reservation*>(myRunningReservations.begin(), myRunningReservations.end());
238 }
239 
240 
241 void
243  if (myRunningReservations.count(res)) {
244  return; // was redispatch
245  }
246  auto it = myGroupReservations.find(res->group);
247  if (it == myGroupReservations.end()) {
248  throw ProcessError(TL("Inconsistent group reservations."));
249  }
250  auto it2 = std::find(it->second.begin(), it->second.end(), res);
251  if (it2 == it->second.end()) {
252  throw ProcessError(TL("Inconsistent group reservations (2)."));
253  }
254  myRunningReservations.insert(*it2);
255  const_cast<Reservation*>(*it2)->state = Reservation::ASSIGNED;
256  it->second.erase(it2);
257  if (it->second.empty()) {
258  myGroupReservations.erase(it);
259  }
260 }
261 
262 
263 void
265  myRunningReservations.erase(res);
266  delete res;
267 }
268 
269 
270 SUMOTime
272  ConstMSEdgeVector edges;
273  router.compute(taxi->getHolder().getEdge(), taxi->getHolder().getPositionOnLane() - NUMERICAL_EPS,
274  res.from, res.fromPos, &taxi->getHolder(), t, edges, true);
275  return TIME2STEPS(router.recomputeCosts(edges, &taxi->getHolder(), t));
276 }
277 
278 
279 double
281  const MSEdge* from, double fromPos,
282  const MSEdge* via, double viaPos,
283  const MSEdge* to, double toPos,
285  double& timeDirect) {
286  ConstMSEdgeVector edges;
287  if (timeDirect < 0) {
288  router.compute(from, fromPos, to, toPos, &taxi->getHolder(), t, edges, true);
289  timeDirect = router.recomputeCostsPos(edges, &taxi->getHolder(), fromPos, toPos, t);
290  edges.clear();
291  }
292 
293  router.compute(from, fromPos, via, viaPos, &taxi->getHolder(), t, edges, true);
294  const double start = STEPS2TIME(t);
295  const double leg1 = router.recomputeCostsPos(edges, &taxi->getHolder(), fromPos, viaPos, t);
296 #ifdef DEBUG_DETOUR
297  std::cout << " leg1=" << toString(edges) << " startPos=" << fromPos << " toPos=" << viaPos << " time=" << leg1 << "\n";
298 #endif
299  const double wait = MAX2(0.0, STEPS2TIME(viaTime) - (start + leg1));
300  edges.clear();
301  const SUMOTime timeContinue = TIME2STEPS(start + leg1 + wait);
302  router.compute(via, viaPos, to, toPos, &taxi->getHolder(), timeContinue, edges, true);
303  const double leg2 = router.recomputeCostsPos(edges, &taxi->getHolder(), viaPos, toPos, timeContinue);
304  const double timeDetour = leg1 + wait + leg2;
305 #ifdef DEBUG_DETOUR
306  std::cout << " leg2=" << toString(edges) << " startPos=" << viaPos << " toPos=" << toPos << " time=" << leg2 << "\n";
307  std::cout << " t=" << STEPS2TIME(t) << " vt=" << STEPS2TIME(viaTime)
308  << " from=" << from->getID() << " to=" << to->getID() << " via=" << via->getID()
309  << " direct=" << timeDirect << " detour=" << timeDetour << " wait=" << wait << "\n";
310 #endif
311  return timeDetour;
312 }
313 
314 
315 int
317  assert(res->persons.size() > 0);
318  return ((*res->persons.begin())->isPerson()
320  : taxi->getHolder().getVehicleType().getContainerCapacity()) - (int)res->persons.size();
321 }
322 
323 
324 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define DEBUG_COND2(obj)
Definition: MSDispatch.cpp:32
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define TL(string)
Definition: MsgHandler.h:315
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)
Definition: MSDevice_Taxi.h:49
OutputDevice * myOutput
optional file output for dispatch information
Definition: MSDispatch.h:203
int remainingCapacity(const MSDevice_Taxi *taxi, const Reservation *res)
whether the given taxi has sufficient capacity to serve the reservation
Definition: MSDispatch.cpp:316
static SUMOTime computePickupTime(SUMOTime t, const MSDevice_Taxi *taxi, const Reservation &res, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router)
compute time to pick up the given reservation
Definition: MSDispatch.cpp:271
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
Definition: MSDispatch.cpp:137
bool myHasServableReservations
whether the last call to computeDispatch has left servable reservations
Definition: MSDispatch.h:191
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...
Definition: MSDispatch.cpp:181
std::map< std::string, std::vector< Reservation * > > myGroupReservations
Definition: MSDispatch.h:206
std::vector< Reservation * > getReservations()
retrieve all reservations
Definition: MSDispatch.cpp:226
virtual std::vector< const Reservation * > getRunningReservations()
retrieve all reservations that were already dispatched and are still active
Definition: MSDispatch.cpp:236
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
Definition: MSDispatch.cpp:280
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
Definition: MSDispatch.cpp:70
int myReservationCount
Definition: MSDispatch.h:205
virtual void fulfilledReservation(const Reservation *res)
erase reservation from storage
Definition: MSDispatch.cpp:264
MSDispatch(const Parameterised::Map &params)
Constructor;.
Definition: MSDispatch.cpp:48
void servedReservation(const Reservation *res)
Definition: MSDispatch.cpp:242
std::set< const Reservation * > myRunningReservations
Definition: MSDispatch.h:200
virtual ~MSDispatch()
Destructor.
Definition: MSDispatch.cpp:59
A road/street connecting two junctions.
Definition: MSEdge.h:77
A lane area vehicles can halt at.
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.
Definition: OptionsCont.cpp:60
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.
Definition: Parameterised.h:41
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
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:76
const MSEdge * to
Definition: MSDispatch.h:84
std::string getID() const
debug identification
Definition: MSDispatch.cpp:40
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 * > persons
Definition: MSDispatch.h:77
double toPos
Definition: MSDispatch.h:85