Eclipse SUMO - Simulation of Urban MObility
MSDevice_Taxi.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2013-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 // A device which controls a taxi
19 /****************************************************************************/
20 #include <config.h>
21 
31 #include <microsim/MSGlobals.h>
32 #include <microsim/MSVehicle.h>
33 #include <microsim/MSEdge.h>
34 #include <microsim/MSLane.h>
35 #include <microsim/MSStop.h>
38 
39 #include "MSDispatch.h"
40 #include "MSDispatch_Greedy.h"
43 #include "MSDispatch_TraCI.h"
44 
45 #include "MSIdling.h"
46 
47 #include "MSRoutingEngine.h"
48 #include "MSDevice_Routing.h"
49 #include "MSDevice_Taxi.h"
50 
51 //#define DEBUG_DISPATCH
52 //#define DEBUG_CANCEL
53 
54 //#define DEBUG_COND (myHolder.isSelected())
55 #define DEBUG_COND (true)
56 
57 // ===========================================================================
58 // static member variables
59 // ===========================================================================
65 // @brief the list of available taxis
66 std::vector<MSDevice_Taxi*> MSDevice_Taxi::myFleet;
69 std::set<std::string> MSDevice_Taxi::myVClassWarningVTypes;
70 
71 #define TAXI_SERVICE "taxi"
72 #define TAXI_SERVICE_PREFIX "taxi:"
73 
74 // ===========================================================================
75 // method definitions
76 // ===========================================================================
77 // ---------------------------------------------------------------------------
78 // static initialisation methods
79 // ---------------------------------------------------------------------------
80 void
82  oc.addOptionSubTopic("Taxi Device");
83  insertDefaultAssignmentOptions("taxi", "Taxi Device", oc);
84 
85  oc.doRegister("device.taxi.dispatch-algorithm", new Option_String("greedy"));
86  oc.addDescription("device.taxi.dispatch-algorithm", "Taxi Device", TL("The dispatch algorithm [greedy|greedyClosest|greedyShared|routeExtension|traci]"));
87 
88  oc.doRegister("device.taxi.dispatch-algorithm.output", new Option_FileName());
89  oc.addDescription("device.taxi.dispatch-algorithm.output", "Taxi Device", TL("Write information from the dispatch algorithm to FILE"));
90 
91  oc.doRegister("device.taxi.dispatch-algorithm.params", new Option_String(""));
92  oc.addDescription("device.taxi.dispatch-algorithm.params", "Taxi Device", TL("Load dispatch algorithm parameters in format KEY1:VALUE1[,KEY2:VALUE]"));
93 
94  oc.doRegister("device.taxi.dispatch-period", new Option_String("60", "TIME"));
95  oc.addDescription("device.taxi.dispatch-period", "Taxi Device", TL("The period between successive calls to the dispatcher"));
96 
97  oc.doRegister("device.taxi.idle-algorithm", new Option_String("stop"));
98  oc.addDescription("device.taxi.idle-algorithm", "Taxi Device", TL("The behavior of idle taxis [stop|randomCircling]"));
99 
100  oc.doRegister("device.taxi.idle-algorithm.output", new Option_FileName());
101  oc.addDescription("device.taxi.idle-algorithm.output", "Taxi Device", TL("Write information from the idling algorithm to FILE"));
102 }
103 
104 
105 void
106 MSDevice_Taxi::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
108  if (equippedByDefaultAssignmentOptions(oc, "taxi", v, false)) {
109  // build the device
110  MSDevice_Taxi* device = new MSDevice_Taxi(v, "taxi_" + v.getID());
111  into.push_back(device);
112  myFleet.push_back(device);
113  if (v.getParameter().line == "") {
114  // automatically set the line so that persons are willing to enter
115  // (see MSStageDriving::isWaitingFor)
116  const_cast<SUMOVehicleParameter&>(v.getParameter()).line = TAXI_SERVICE;
117  }
118  if (v.getVClass() != SVC_TAXI && myVClassWarningVTypes.count(v.getVehicleType().getID()) == 0) {
119  WRITE_WARNINGF(TL("Vehicle '%' with device.taxi should have vClass taxi instead of '%'."), v.getID(), toString(v.getVClass()));
121  }
122  const int personCapacity = v.getVehicleType().getPersonCapacity();
123  const int containerCapacity = v.getVehicleType().getContainerCapacity();
124  myMaxCapacity = MAX2(myMaxCapacity, personCapacity);
125  myMaxContainerCapacity = MAX2(myMaxContainerCapacity, containerCapacity);
126  if (personCapacity < 1 && containerCapacity < 1) {
127  WRITE_WARNINGF(TL("Vehicle '%' with personCapacity % and containerCapacity % is not usable as taxi."), v.getID(), toString(personCapacity), toString(containerCapacity));
128  }
129  }
130 }
131 
132 
133 void
136  myDispatchPeriod = string2time(oc.getString("device.taxi.dispatch-period"));
137  // init dispatch algorithm
138  std::string algo = oc.getString("device.taxi.dispatch-algorithm");
139  Parameterised params;
140  params.setParametersStr(OptionsCont::getOptions().getString("device.taxi.dispatch-algorithm.params"), ":", ",");
141  if (algo == "greedy") {
143  } else if (algo == "greedyClosest") {
145  } else if (algo == "greedyShared") {
147  } else if (algo == "routeExtension") {
149  } else if (algo == "traci") {
151  } else {
152  throw ProcessError(TLF("Dispatch algorithm '%' is not known", algo));
153  }
155  // round to next multiple of myDispatchPeriod
157  const SUMOTime begin = string2time(oc.getString("begin"));
158  const SUMOTime delay = (myDispatchPeriod - ((now - begin) % myDispatchPeriod)) % myDispatchPeriod;
160 }
161 
162 bool
163 MSDevice_Taxi::isReservation(const std::set<std::string>& lines) {
164  return lines.size() == 1 && (
165  *lines.begin() == TAXI_SERVICE
166  || StringUtils::startsWith(*lines.begin(), TAXI_SERVICE_PREFIX));
167 }
168 
169 void
171  const std::set<std::string>& lines,
172  SUMOTime reservationTime,
173  SUMOTime pickupTime,
174  SUMOTime earliestPickupTime,
175  const MSEdge* from, double fromPos,
176  const MSStoppingPlace* fromStop,
177  const MSEdge* to, double toPos,
178  const MSStoppingPlace* toStop,
179  const std::string& group) {
180  if (!isReservation(lines)) {
181  return;
182  }
183  if ((to->getPermissions() & SVC_TAXI) == 0) {
184  throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
185  + " '" + person->getID() + "' because destination edge '" + to->getID() + "'"
186  + " does not permit taxi access");
187  }
188  if ((from->getPermissions() & SVC_TAXI) == 0) {
189  throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
190  + " '" + person->getID() + "' because origin edge '" + from->getID() + "'"
191  + " does not permit taxi access");
192  }
193  if (myDispatchCommand == nullptr) {
194  initDispatch();
195  }
196  if (fromStop != nullptr && &fromStop->getLane().getEdge() == from) {
197  // pickup position should be at the stop-endPos
198  fromPos = fromStop->getEndLanePosition();
199  }
200  myDispatcher->addReservation(person, reservationTime, pickupTime, earliestPickupTime, from, fromPos, fromStop, to, toPos, toStop, group, *lines.begin(), myMaxCapacity, myMaxContainerCapacity);
201 }
202 
203 void
205  const std::set<std::string>& lines,
206  const MSEdge* from, double fromPos,
207  const MSEdge* to, double toPos,
208  const std::string& group) {
209  if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
210  myDispatcher->removeReservation(person, from, fromPos, to, toPos, group);
211  }
212 }
213 
214 void
216  const std::set<std::string>& lines,
217  const MSEdge* from, double fromPos,
218  const MSEdge* to, double toPos,
219  const std::string& group, double newFromPos) {
220  if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
221  myDispatcher->updateReservationFromPos(person, from, fromPos, to, toPos, group, newFromPos);
222  }
223 }
224 
225 
226 SUMOTime
228  std::vector<MSDevice_Taxi*> active;
229  for (MSDevice_Taxi* taxi : myFleet) {
230  if (taxi->getHolder().hasDeparted()) {
231  active.push_back(taxi);
232  }
233  }
234  myDispatcher->computeDispatch(currentTime, active);
235  return myDispatchPeriod;
236 }
237 
238 bool
240  return myDispatcher != nullptr && myDispatcher->hasServableReservations();
241 }
242 
243 void
245  if (myDispatcher != nullptr) {
246  delete myDispatcher;
247  myDispatcher = nullptr;
248  }
249  myDispatchCommand = nullptr;
250  myVClassWarningVTypes.clear();
251 }
252 
253 // ---------------------------------------------------------------------------
254 // MSDevice_Taxi-methods
255 // ---------------------------------------------------------------------------
256 MSDevice_Taxi::MSDevice_Taxi(SUMOVehicle& holder, const std::string& id) :
257  MSVehicleDevice(holder, id) {
258  std::string defaultServiceEnd = toString(1e15);
259  const std::string algo = holder.getStringParam("device.taxi.idle-algorithm");
260  if (algo == "stop") {
262  } else if (algo == "randomCircling") {
264  // make sure simulation terminates
265  defaultServiceEnd = toString(STEPS2TIME(
268  : MSNet::getInstance()->getCurrentTimeStep()) + (3600 * 8));
269  } else if (algo == "taxistand") {
270  const std::string rerouterID = holder.getStringParam("device.taxi.stands-rerouter");
271  if (rerouterID.empty()) {
272  throw ProcessError("Idle algorithm '" + algo + "' requires a rerouter id to be defined using device param 'stands-rerouter' for vehicle '" + myHolder.getID() + "'");
273  }
274  if (MSTriggeredRerouter::getInstances().count(rerouterID) == 0) {
275  throw ProcessError("Unknown rerouter '" + rerouterID + "' when loading taxi stands for vehicle '" + myHolder.getID() + "'");
276  }
277  MSTriggeredRerouter* rerouter = MSTriggeredRerouter::getInstances().find(rerouterID)->second;
278  myIdleAlgorithm = new MSIdling_TaxiStand(rerouter);
279  } else {
280  throw ProcessError("Idle algorithm '" + algo + "' is not known for vehicle '" + myHolder.getID() + "'");
281  }
282  myServiceEnd = string2time(holder.getStringParam("device.taxi.end", false, defaultServiceEnd));
284 }
285 
286 
288  myFleet.erase(std::find(myFleet.begin(), myFleet.end(), this));
289  // recompute myMaxCapacity
290  myMaxCapacity = 0;
292  for (MSDevice_Taxi* taxi : myFleet) {
293  myMaxCapacity = MAX2(myMaxCapacity, taxi->getHolder().getVehicleType().getPersonCapacity());
294  myMaxContainerCapacity = MAX2(myMaxContainerCapacity, taxi->getHolder().getVehicleType().getContainerCapacity());
295  }
296  delete myIdleAlgorithm;
297 }
298 
299 
302  if (myFleet.size() > 0) {
303  return &myFleet[0]->getHolder();
304  } else {
305  return nullptr;
306  }
307 }
308 
309 
310 void
312  dispatchShared({&res, &res});
313 }
314 
315 
316 void
317 MSDevice_Taxi::dispatchShared(std::vector<const Reservation*> reservations) {
318 #ifdef DEBUG_DISPATCH
319  if (DEBUG_COND) {
320  std::cout << SIMTIME << " taxi=" << myHolder.getID() << " dispatch:\n";
321  for (const Reservation* res : reservations) {
322  std::cout << " persons=" << toString(res->persons) << "\n";
323  }
324  }
325 #endif
326  myLastDispatch = reservations;
327  ConstMSEdgeVector tmpEdges;
328  std::vector<SUMOVehicleParameter::Stop> stops;
329  double lastPos = myHolder.getPositionOnLane();
330  const MSEdge* rerouteOrigin = *myHolder.getRerouteOrigin();
331  if (isEmpty()) {
332  // start fresh from the current edge
333  if (myHolder.isStoppedParking()) {
334  // parking stop must be ended normally
335  MSStop& stop = myHolder.getNextStop();
336  stop.duration = 0;
337  lastPos = stop.pars.endPos;
339  stop.triggered = false;
340  stop.containerTriggered = false;
341  stop.joinTriggered = false;
342  const_cast<SUMOVehicleParameter::Stop&>(stop.pars).permitted.insert("");
344  }
345  while (myHolder.getStops().size() > 1) {
347  }
348  } else {
349  while (myHolder.hasStops()) {
350  // in meso there might be more than 1 stop at this point
352  }
353  assert(!myHolder.hasStops());
354  }
355  tmpEdges.push_back(myHolder.getEdge());
356  if (myHolder.getEdge() != rerouteOrigin) {
357  tmpEdges.push_back(rerouteOrigin);
358  }
359  } else {
360  assert(myHolder.hasStops());
361  // check how often existing customers appear in the new reservations
362  std::map<const MSTransportable*, int> nOccur;
363  for (const Reservation* res : reservations) {
364  for (const MSTransportable* person : res->persons) {
365  if (myCustomers.count(person) != 0) {
366  nOccur[person] += 1;
367  if (myCurrentReservations.count(res) == 0) {
368  throw ProcessError(TLF("Invalid Re-dispatch for existing customer '%' with a new reservation", person->getID()));
369  }
370  }
371  }
372  }
373 #ifdef DEBUG_DISPATCH
374  if (DEBUG_COND) {
375  for (auto item : nOccur) {
376  std::cout << " previousCustomer=" << item.first->getID() << " occurs=" << item.second << "\n";
377  }
378  }
379 #endif
380  if (nOccur.size() == 0) {
381  // no overlap with existing customers - extend route
382  tmpEdges = myHolder.getRoute().getEdges();
383  lastPos = myHolder.getStops().back().pars.endPos;
384 #ifdef DEBUG_DISPATCH
385  if (DEBUG_COND) {
386  std::cout << " re-dispatch with route-extension\n";
387  }
388 #endif
389  } else if (nOccur.size() == myCustomers.size()) {
390  // redefine route (verify correct number of mentions)
391  std::set<const MSTransportable*> onBoard;
392  const std::vector<MSTransportable*>& onBoardP = myHolder.getPersons();
393  const std::vector<MSTransportable*>& onBoardC = myHolder.getContainers();
394  onBoard.insert(onBoardP.begin(), onBoardP.end());
395  onBoard.insert(onBoardC.begin(), onBoardC.end());
396  std::set<const MSTransportable*> redundantPickup;
397  for (auto item : nOccur) {
398  if (item.second == 1) {
399  // customers must already be on board
400  if (onBoard.count(item.first) == 0) {
401  throw ProcessError(TLF("Re-dispatch did not mention pickup for existing customer '%'", item.first->getID()));
402  }
403  } else if (item.second == 2) {
404  if (onBoard.count(item.first) == 0) {
405  // treat like a new customer
406  // TODO: need to be checked
407  myCustomers.erase(item.first);
408  } else {
409  redundantPickup.insert(item.first);
410  }
411  } else {
412  throw ProcessError("Re-dispatch mentions existing customer '" + item.first->getID() + "' " + toString(item.second) + " times");
413  }
414  }
415  // remove redundancy
416  if (!redundantPickup.empty()) {
417  for (auto it = reservations.begin(); it != reservations.end();) {
418  bool isRedundant = false;
419  for (const MSTransportable* person : (*it)->persons) {
420  if (redundantPickup.count(person) != 0) {
421  isRedundant = true;
422  break;
423  }
424  }
425  if (isRedundant) {
426  for (const MSTransportable* person : (*it)->persons) {
427  redundantPickup.erase(person);
428  }
429  it = reservations.erase(it);
430  } else {
431  it++;
432  }
433  }
434  }
435  while (myHolder.hasStops()) {
437  }
438  tmpEdges.push_back(myHolder.getEdge());
439  if (myHolder.getEdge() != rerouteOrigin) {
440  tmpEdges.push_back(rerouteOrigin);
441  }
442 #ifdef DEBUG_DISPATCH
443  if (DEBUG_COND) {
444  std::cout << " re-dispatch from scratch\n";
445  }
446 #endif
447  } else {
448  // inconsistent re-dispatch
449  std::vector<std::string> missing;
450  for (const MSTransportable* c : myCustomers) {
451  if (nOccur.count(c) == 0) {
452  missing.push_back(c->getID());
453  }
454  }
455  throw ProcessError("Re-dispatch did mention some customers but failed to mention " + joinToStringSorting(missing, " "));
456  }
457  }
458 
460  bool hasPickup = false;
461  for (const Reservation* res : reservations) {
462  myCurrentReservations.insert(res);
463  bool isPickup = false;
464  for (const MSTransportable* person : res->persons) {
465  if (myCustomers.count(person) == 0) {
466  myCustomers.insert(person);
467  isPickup = true;
468  hasPickup = true;
469  }
470  }
471  if (isPickup) {
472  prepareStop(tmpEdges, stops, lastPos, res->from, res->fromPos, res->fromStop, "pickup " + toString(res->persons) + " (" + res->id + ")", res, isPickup);
473  for (const MSTransportable* const transportable : res->persons) {
474  if (transportable->isPerson()) {
475  stops.back().triggered = true;
476  } else {
477  stops.back().containerTriggered = true;
478  }
479  stops.back().permitted.insert(transportable->getID());
480  }
481  // proof this lines: Is needed for pre-booking?
482  std::set<const MSTransportable*> persons = res->persons;
483  for (auto itr = persons.begin(); itr != persons.end(); itr++) {
484  stops.back().awaitedPersons.insert((*itr)->getID());
485  }
486 
487  stops.back().parametersSet |= STOP_PERMITTED_SET;
488  if (stops.back().duration == -1) {
489  // keep dropOffDuration if the stop is dropOff and pickUp
490  stops.back().duration = TIME2STEPS(myHolder.getFloatParam("device.taxi.pickUpDuration", false, 0));
491  }
492  } else {
493  prepareStop(tmpEdges, stops, lastPos, res->to, res->toPos, res->toStop, "dropOff " + toString(res->persons) + " (" + res->id + ")", res, isPickup);
494  stops.back().duration = TIME2STEPS(myHolder.getFloatParam("device.taxi.dropOffDuration", false, 60)); // pay and collect bags
495  }
496  }
497 #ifdef DEBUG_DISPATCH
498  if (DEBUG_COND) {
499  std::cout << " tmpEdges=" << toString(tmpEdges) << "\n";
500  }
501 #endif
502  if (!myHolder.replaceRouteEdges(tmpEdges, -1, 0, "taxi:prepare_dispatch", false, false, false)) {
503  throw ProcessError("Route replacement for taxi dispatch failed for vehicle '" + myHolder.getID()
504  + "' at time=" + time2string(t) + ".");
505  }
506 #ifdef DEBUG_DISPATCH
507  if (DEBUG_COND) std::cout << " replacedRoute=" << toString(tmpEdges)
508  << "\n actualRoute=" << toString(myHolder.getRoute().getEdges()) << "\n";
509 #endif
510  for (SUMOVehicleParameter::Stop& stop : stops) {
511  std::string error;
512  myHolder.addStop(stop, error);
513  if (error != "") {
514  WRITE_WARNINGF(TL("Could not add taxi stop, time=%, error=%"), myHolder.getID(), stop.actType, time2string(t), error)
515  }
516  }
518  // SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = myHolder.getInfluencer().getRouterTT(veh->getRNGIndex())
519  myHolder.reroute(t, "taxi:dispatch", router, false);
520 #ifdef DEBUG_DISPATCH
521  if (DEBUG_COND) {
522  std::cout << "\n finalRoute=" << toString(myHolder.getRoute().getEdges()) << " routeIndex=" << myHolder.getRoutePosition() << "\n";
523  }
524 #endif
525  if (hasPickup) {
526  myState |= PICKUP;
527  }
528 }
529 
530 
531 void
533  // check if taxi has stopped
534  if (myHolder.getNextStopParameter() == nullptr) {
535  return;
536  }
537  // find customers of the current stop
538  std::set<const MSTransportable*> customersToBeRemoved;
539  std::set<const MSTransportable*> onBoard;
540  onBoard.insert(myHolder.getPersons().begin(), myHolder.getPersons().end());
541  onBoard.insert(myHolder.getContainers().begin(), myHolder.getContainers().end());
542  for (std::string tID : myHolder.getNextStopParameter()->permitted) {
543  for (auto t : myCustomers) {
544  if (t->getID() == tID && onBoard.count(t) == 0) {
545  customersToBeRemoved.insert(t);
546  }
547  }
548  }
549  if (!customersToBeRemoved.empty()) {
550  WRITE_WARNINGF(TL("Taxi '%' aborts waiting for customers: % at time=%."),
551  myHolder.getID(), toString(customersToBeRemoved), time2string(SIMSTEP));
552  }
553  for (auto t : customersToBeRemoved) {
554  cancelCustomer(t);
555  }
556 }
557 
558 
559 bool
561 #ifdef DEBUG_CANCEL
562  if (DEBUG_COND) {
563  std::cout << SIMTIME << " taxi=" << myHolder.getID() << " cancelCustomer " << t->getID() << "\n";
564  }
565 #endif
566 
567  // is the given transportable a customer of the reservations?
568  if (myCustomers.count(t) == 0) {
569  return false;
570  }
571  myCustomers.erase(t);
572  // check whether a single reservation has been fulfilled or another customer is part of the reservation
573  for (auto resIt = myCurrentReservations.begin(); resIt != myCurrentReservations.end();) {
574  bool fulfilled = false;
575  if ((*resIt)->persons.size() == 1 && (*resIt)->persons.count(t) != 0) {
576  // the reservation contains only the customer
577  fulfilled = true;
578  }
579  if (fulfilled) {
580  const Reservation* res = *resIt;
581  // remove reservation from the current dispatch
582  for (auto it = myLastDispatch.begin(); it != myLastDispatch.end();) {
583  if (*it == res) {
584  it = myLastDispatch.erase(it);
585  } else {
586  ++it;
587  }
588  }
589  // remove reservation from the served reservations
590  resIt = myCurrentReservations.erase(resIt);
591  // delete the reservation
593  } else {
594  ++resIt;
595  }
596  }
597  myState &= ~PICKUP; // remove state PICKUP
598  for (const Reservation* res : myCurrentReservations) {
599  // if there is another pickup in the dispatch left, add the state PICKUP
600  if (std::count(myLastDispatch.begin(), myLastDispatch.end(), res) == 2) {
601  myState |= PICKUP; // add state PICKUP
602  }
603  }
604  // we also have to clean reservations from myLastDispatch where the customers arrived in the meantime
605  for (auto it = myLastDispatch.begin(); it != myLastDispatch.end();) {
606  if (myCurrentReservations.count(*it) == 0) {
607  it = myLastDispatch.erase(it);
608  } else {
609  ++it;
610  }
611  }
612  // if there are reservations left, go on with the dispatch
613  // in meso, wait for the next dispatch cycle to avoid updating stops in this stage
614  if (!MSGlobals::gUseMesoSim) {
616  }
617  return true;
618 }
619 
620 
621 void
623  std::vector<SUMOVehicleParameter::Stop>& stops,
624  double& lastPos, const MSEdge* stopEdge, double stopPos,
625  const MSStoppingPlace* stopPlace,
626  const std::string& action, const Reservation* res, const bool isPickup) {
627  assert(!edges.empty());
628  if (stopPlace != nullptr && &stopPlace->getLane().getEdge() == stopEdge) {
629  stopPos = stopPlace->getEndLanePosition();
630  }
631  if (stopPos < lastPos && stopPos + NUMERICAL_EPS >= lastPos) {
632  stopPos = lastPos;
633  }
634  bool addedEdge = false;
635 
636  if (stops.empty()) {
637  // check brakeGap
638  double distToStop = stopPos - lastPos;
639  const double brakeGap = myHolder.getBrakeGap();
640  if (myHolder.getLane() != nullptr && myHolder.getLane()->isInternal()) {
641  distToStop += myHolder.getLane()->getLength();
642  }
643  if (stopEdge != edges.back()) {
644  distToStop += edges.back()->getLength();
645  if (distToStop < brakeGap) {
646  // the distance between current edge and stop edge may be small
648  ConstMSEdgeVector toFirstStop;
649  router.compute(edges.back(), stopEdge, &myHolder, SIMSTEP, toFirstStop, true);
650  for (int i = 1; i < (int)toFirstStop.size() - 1; i++) {
651  distToStop += toFirstStop[i]->getLength();
652  }
653  }
654  }
655  if (distToStop < brakeGap) {
656  // circle back to stopEdge
657  //std::cout << SIMTIME << " taxi=" << getID() << " brakeGap=" << brakeGap << " distToStop=" << distToStop << "\n";
658  edges.push_back(stopEdge);
659  addedEdge = true;
660  }
661  }
662 
663  if (stopEdge == edges.back() && !stops.empty()) {
664  if (stopPos >= lastPos && stopPos <= stops.back().endPos) {
665  // no new stop and no adaption needed
666  stops.back().actType += "," + action;
667  return;
668  }
669  if (stopPos >= lastPos && stopPos <= lastPos + myHolder.getVehicleType().getLength()) {
670  // stop length adaption needed
671  stops.back().endPos = MIN2(lastPos + myHolder.getVehicleType().getLength(), stopEdge->getLength());
672  stops.back().actType += "," + action;
673  return;
674  }
675  }
676  if (!addedEdge && (stopEdge != edges.back() || stopPos < lastPos)) {
677  //std::cout << SIMTIME << " stopPos=" << stopPos << " lastPos=" << lastPos << "\n";
678  edges.push_back(stopEdge);
679  }
680  lastPos = stopPos;
682  stop.lane = getStopLane(stopEdge, action)->getID();
683  if (stopPlace != nullptr && &stopPlace->getLane().getEdge() == stopEdge) {
684  stop.startPos = stopPlace->getBeginLanePosition();
685  stop.endPos = stopPlace->getEndLanePosition();
686  } else {
687  stop.startPos = stopPos;
688  stop.endPos = MAX2(stopPos, MIN2(myHolder.getVehicleType().getLength(), stopEdge->getLength()));
689  }
690  stop.parking = SUMOVehicleParameter::parseParkingType(myHolder.getStringParam("device.taxi.parking", false, "true"));
691  stop.actType = action;
692  stop.index = STOP_INDEX_END;
693  // In case of prebooking if person is not there/ comes to late for pickup set maximum waiting time:
694  SUMOTime earliestPickupTime = res->earliestPickupTime;
695  if (isPickup && earliestPickupTime >= 0) {
696  stop.waitUntil = earliestPickupTime;
697  // TODO: replace hard coded extension with parameter
698  stop.extension = static_cast<SUMOTime>(3 * 60 * 1000); // 3mins
699  }
700  stops.push_back(stop);
701 }
702 
703 
704 MSLane*
705 MSDevice_Taxi::getStopLane(const MSEdge* edge, const std::string& action) {
706  const std::vector<MSLane*>* allowedLanes = edge->allowedLanes(myHolder.getVClass());
707  if (allowedLanes == nullptr) {
708  throw ProcessError("Taxi vehicle '" + myHolder.getID() + "' cannot stop on edge '" + edge->getID() + "' (" + action + ")");
709  }
710  return allowedLanes->front();
711 }
712 
713 bool
715  return myState == EMPTY;
716 }
717 
718 
719 bool
721  return myCustomers.count(t) != 0;
722 }
723 
724 
725 void
726 MSDevice_Taxi::updateMove(const SUMOTime traveltime, const double travelledDist) {
728  myOccupiedDistance += travelledDist;
729  myOccupiedTime += traveltime;
730  }
731  if (isEmpty()) {
732  if (MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
733  myIdleAlgorithm->idle(this);
734  if (myRoutingDevice != nullptr) {
735  // prevent rerouting during idling (#11079)
736  myRoutingDevice->setActive(false);
737  }
738  } else if (!myReachedServiceEnd) {
739  WRITE_WARNINGF(TL("Taxi '%' reaches scheduled end of service at time=%."), myHolder.getID(), time2string(SIMSTEP));
740  myReachedServiceEnd = true;
741  }
742  } else if (myRoutingDevice != nullptr) {
743  myRoutingDevice->setActive(true);
744  }
746  // limit duration of stop (but only for idling-related stops)
748  }
749 #ifdef DEBUG_DISPATCH
751  std::cout << SIMTIME << " updateMove veh=" << myHolder.getID() << " myIsStopped=" << myIsStopped << " myHolderStopped=" << myHolder.isStopped() << " myState=" << myState << "\n";
752  }
753 #endif
755 }
756 
757 
758 bool
759 MSDevice_Taxi::notifyMove(SUMOTrafficObject& /*tObject*/, double oldPos,
760  double newPos, double /*newSpeed*/) {
761  updateMove(DELTA_T, newPos - oldPos);
762  return true; // keep the device
763 }
764 
765 
766 void
768  const double /* frontOnLane */,
769  const double timeOnLane,
770  const double /* meanSpeedFrontOnLane */,
771  const double /* meanSpeedVehicleOnLane */,
772  const double travelledDistanceFrontOnLane,
773  const double /* travelledDistanceVehicleOnLane */,
774  const double /* meanLengthOnLane */) {
775  updateMove(TIME2STEPS(timeOnLane), travelledDistanceFrontOnLane);
776 }
777 
778 
779 bool
780 MSDevice_Taxi::notifyEnter(SUMOTrafficObject& /*veh*/, MSMoveReminder::Notification /*reason*/, const MSLane* /* enteredLane */) {
781  if (isEmpty() && MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
782  myIdleAlgorithm->idle(this);
783  }
784  return true; // keep the device
785 }
786 
787 
788 void
790  myState |= OCCUPIED;
791  if (!hasFuturePickup()) {
792  myState &= ~PICKUP;
793  }
794  for (const Reservation* res : myCurrentReservations) {
795  for (const MSTransportable* cand : res->persons) {
796  if (cand == t) {
797  const_cast<Reservation*>(res)->state = Reservation::ONBOARD;
798  break;
799  }
800  }
801  }
802 }
803 
804 
805 void
808  myCustomers.erase(person);
809  if (myHolder.getPersonNumber() == 0 && myHolder.getContainerNumber() == 0) {
810  myState &= ~OCCUPIED;
811  if (myHolder.getStops().size() > 1 && (myState & PICKUP) == 0) {
812  WRITE_WARNINGF(TL("All customers left vehicle '%' at time=% but there are % remaining stops"),
813  myHolder.getID(), time2string(SIMSTEP), myHolder.getStops().size() - 1);
814  while (myHolder.getStops().size() > 1) {
816  }
817  }
818  }
819  if (isEmpty()) {
820  // cleanup
821  for (const Reservation* res : myCurrentReservations) {
823  }
824  myCurrentReservations.clear();
825  if (MSGlobals::gUseMesoSim && MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
826  myIdleAlgorithm->idle(this);
827  }
828  } else {
829  // check whether a single reservation has been fulfilled
830  for (auto resIt = myCurrentReservations.begin(); resIt != myCurrentReservations.end();) {
831  bool fulfilled = true;
832  for (const MSTransportable* t : (*resIt)->persons) {
833  if (myCustomers.count(t) != 0) {
834  fulfilled = false;
835  break;
836  }
837  }
838  if (fulfilled) {
840  resIt = myCurrentReservations.erase(resIt);
841  } else {
842  ++resIt;
843  }
844  }
845  }
846 }
847 
848 
849 bool
851  for (const auto& stop : myHolder.getStops()) {
852  if (stop.reached) {
853  continue;
854  }
855  if (stop.pars.permitted.size() > 0) {
856  return true;
857  }
858  }
859  return false;
860 }
861 
862 void
864  if (tripinfoOut != nullptr) {
865  tripinfoOut->openTag("taxi");
866  tripinfoOut->writeAttr("customers", toString(myCustomersServed));
867  tripinfoOut->writeAttr("occupiedDistance", toString(myOccupiedDistance));
868  tripinfoOut->writeAttr("occupiedTime", time2string(myOccupiedTime));
869  tripinfoOut->closeTag();
870  }
871 }
872 
873 std::string
874 MSDevice_Taxi::getParameter(const std::string& key) const {
875  if (key == "customers") {
876  return toString(myCustomersServed);
877  } else if (key == "occupiedDistance") {
879  } else if (key == "occupiedTime") {
881  } else if (key == "state") {
882  return toString(myState);
883  } else if (key == "currentCustomers") {
885  } else if (key == "pickUpDuration") {
886  return myHolder.getStringParam("device.taxi.pickUpDuration", false, "0");
887  } else if (key == "dropOffDuration") {
888  return myHolder.getStringParam("device.taxi.dropOffDuration", false, "60");
889  }
890  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
891 }
892 
893 
894 void
895 MSDevice_Taxi::setParameter(const std::string& key, const std::string& value) {
896  double doubleValue;
897  try {
898  doubleValue = StringUtils::toDouble(value);
899  } catch (NumberFormatException&) {
900  throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
901  }
902  if (key == "pickUpDuration" || key == "dropOffDuration") {
903  // store as generic vehicle parameters
904  ((SUMOVehicleParameter&)myHolder.getParameter()).setParameter("device.taxi." + key, value);
905  } else {
906  UNUSED_PARAMETER(doubleValue);
907  throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
908  }
909 }
910 
911 bool
912 MSDevice_Taxi::compatibleLine(const std::string& taxiLine, const std::string& rideLine) {
913  return ((taxiLine == rideLine && StringUtils::startsWith(rideLine, "taxi") && StringUtils::startsWith(taxiLine, "taxi"))
914  || (taxiLine == TAXI_SERVICE && StringUtils::startsWith(rideLine, "taxi:"))
915  || (rideLine == TAXI_SERVICE && StringUtils::startsWith(taxiLine, "taxi:")));
916 }
917 
918 bool
920  return compatibleLine(myHolder.getParameter().line, res->line);
921 }
922 
923 
924 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define TAXI_SERVICE
#define DEBUG_COND
#define TAXI_SERVICE_PREFIX
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
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:69
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SIMSTEP
Definition: SUMOTime.h:61
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
@ SVC_TAXI
vehicle is a taxi
const int STOP_INDEX_END
const int STOP_PERMITTED_SET
@ GIVEN
The time is given.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string joinToStringSorting(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:299
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
std::string joinNamedToStringSorting(const std::set< T * > &ns, const T_BETWEEN &between)
Definition: ToString.h:307
Base (microsim) event class.
Definition: Command.h:50
A device that performs vehicle rerouting based on current edge speeds.
void setActive(bool active)
A device which collects info on the vehicle trip (mainly on departure and arrival)
Definition: MSDevice_Taxi.h:49
static void initDispatch()
initialize the dispatch algorithm
static Command * myDispatchCommand
The repeated call to the dispatcher.
void customerArrived(const MSTransportable *person)
called by MSDevice_Transportable upon unloading a person
static SUMOTime triggerDispatch(SUMOTime currentTime)
period command to trigger the dispatch algorithm
void dispatch(const Reservation &res)
service the given reservation
std::set< const MSTransportable * > myCustomers
the customer of the current reservation
SUMOTime myServiceEnd
the time at which the taxi service ends (end the vehicle may leave the simulation)
static void updateReservationFromPos(MSTransportable *person, const std::set< std::string > &lines, const MSEdge *from, double fromPos, const MSEdge *to, double toPos, const std::string &group, double newFromPos)
update reservation's fromPos due to pre-booking
bool cancelCustomer(const MSTransportable *t)
remove person from reservations
void generateOutput(OutputDevice *tripinfoOut) const
Called on writing tripinfo output.
static int myMaxCapacity
static std::set< std::string > myVClassWarningVTypes
void dispatchShared(std::vector< const Reservation * > reservations)
service the given reservations
static void addReservation(MSTransportable *person, const std::set< std::string > &lines, SUMOTime reservationTime, SUMOTime pickupTime, SUMOTime earliestPickupTime, const MSEdge *from, double fromPos, const MSStoppingPlace *fromStop, const MSEdge *to, double toPos, const MSStoppingPlace *toStop, const std::string &group)
add new reservation
MSIdling * myIdleAlgorithm
algorithm for controlling idle behavior
std::set< const Reservation * > myCurrentReservations
reservations currently being served
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks for waiting steps when the vehicle moves.
bool hasFuturePickup()
whether the taxi has another pickup scheduled
void cancelCurrentCustomers()
remove the persons the taxi is currently waiting for from reservations
std::vector< const Reservation * > myLastDispatch
the last dispatch order
static MSDispatch * myDispatcher
the dispatch algorithm
int myCustomersServed
number of customers that were served
void updateMove(const SUMOTime traveltime, const double travelledDist)
void notifyMoveInternal(const SUMOTrafficObject &veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane)
Internal notification about the vehicle moves, see MSMoveReminder::notifyMoveInternal()
static int myMaxContainerCapacity
MSDevice_Routing * myRoutingDevice
routing device (if the vehicle has one)
bool isEmpty()
whether the taxi is empty
const std::string deviceName() const
return the name for this type of device
static std::vector< MSDevice_Taxi * > myFleet
static void removeReservation(MSTransportable *person, const std::set< std::string > &lines, const MSEdge *from, double fromPos, const MSEdge *to, double toPos, const std::string &group)
retract reservation
static SUMOTime myDispatchPeriod
the time between successive calls to the dispatcher
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Saves departure info on insertion.
static void cleanup()
resets counters
static bool isReservation(const std::set< std::string > &lines)
whether the given lines description is a taxi call
double myOccupiedDistance
distance driven with customers
MSDevice_Taxi(SUMOVehicle &holder, const std::string &id)
Constructor.
bool allowsBoarding(const MSTransportable *t) const
whether the given person is allowed to board this taxi
static bool hasServableReservations()
check whether there are still (servable) reservations in the system
static SUMOVehicle * getTaxi()
returns a taxi if any exist or nullptr
void customerEntered(const MSTransportable *t)
called by MSDevice_Transportable upon loading a person
bool compatibleLine(const Reservation *res)
whether the given reservation is compatible with the taxi line
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
static void insertOptions(OptionsCont &oc)
Inserts MSDevice_Taxi-options.
bool myIsStopped
whether the vehicle is currently stopped
void setParameter(const std::string &key, const std::string &value)
try to set the given parameter for this device. Throw exception for unsupported key
SUMOTime myOccupiedTime
time spent driving with customers
bool myReachedServiceEnd
whether the taxi has reached its schedule service end
~MSDevice_Taxi()
Destructor.
void prepareStop(ConstMSEdgeVector &edges, std::vector< SUMOVehicleParameter::Stop > &stops, double &lastPos, const MSEdge *stopEdge, double stopPos, const MSStoppingPlace *stopPlace, const std::string &action, const Reservation *res, const bool isPickup)
prepare stop for the given action
MSLane * getStopLane(const MSEdge *edge, const std::string &action)
determine stopping lane for taxi
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key
static void insertDefaultAssignmentOptions(const std::string &deviceName, const std::string &optionsTopic, OptionsCont &oc, const bool isPerson=false)
Adds common command options that allow to assign devices to vehicles.
Definition: MSDevice.cpp:155
static bool equippedByDefaultAssignmentOptions(const OptionsCont &oc, const std::string &deviceName, DEVICEHOLDER &v, bool outputOptionSet, const bool isPerson=false)
Determines whether a vehicle should get a certain device.
Definition: MSDevice.h:195
A dispatch algorithm that services the reservations with the shortest traveltime-to-pickup first.
A dispatch algorithm that services customers in reservation order and always sends the closest availa...
A dispatch algorithm that services customers in reservation order and always sends the closest availa...
An algorithm that performs distpach for a taxi fleet.
Definition: MSDispatch.h:112
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
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
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
bool hasServableReservations()
check whether there are still (servable) reservations in the system
Definition: MSDispatch.h:174
virtual void fulfilledReservation(const Reservation *res)
erase reservation from storage
Definition: MSDispatch.cpp:264
virtual void computeDispatch(SUMOTime now, const std::vector< MSDevice_Taxi * > &fleet)=0
computes dispatch and updates reservations
A road/street connecting two junctions.
Definition: MSEdge.h:77
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition: MSEdge.h:634
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:479
double getLength() const
return the length of the edge
Definition: MSEdge.h:670
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition: MSGlobals.h:103
virtual void idle(MSDevice_Taxi *taxi)=0
computes Idling and updates reservations
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
bool isInternal() const
Definition: MSLane.cpp:2526
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
Notification
Definition of a vehicle state.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:481
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector &prohibited=MSEdgeVector())
return the vehicle router instance
Definition: MSStop.h:44
bool triggered
whether an arriving person lets the vehicle continue
Definition: MSStop.h:69
bool containerTriggered
whether an arriving container lets the vehicle continue
Definition: MSStop.h:71
bool joinTriggered
whether coupling another vehicle (train) the vehicle continue
Definition: MSStop.h:73
SUMOTime endBoarding
the maximum time at which persons may board this vehicle
Definition: MSStop.h:85
SUMOTime duration
The stopping duration.
Definition: MSStop.h:67
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition: MSStop.h:65
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
bool isPerson() const
Whether it is a person.
Reroutes traffic objects passing an edge.
static const std::map< std::string, MSTriggeredRerouter * > & getInstances()
return all rerouter instances
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
int getPersonCapacity() const
Get this vehicle type's person capacity.
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
double getLength() const
Get vehicle's length [m].
int getContainerCapacity() const
Get this vehicle type's container capacity.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void doRegister(const std::string &name, Option *o)
Adds an option under the given name.
Definition: OptionsCont.cpp:76
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
An upper class for objects with additional parameters.
Definition: Parameterised.h:41
void setParametersStr(const std::string &paramsString, const std::string kvsep="=", const std::string sep="|")
set the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN"
const Parameterised::Map & getParametersMap() const
Returns the inner key/value 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...
Representation of a vehicle, person, or container.
virtual MSDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or nullptr if not.
std::string getStringParam(const std::string &paramName, const bool required=false, const std::string &deflt="") const
Retrieve a string parameter for the traffic object.
virtual int getRNGIndex() const =0
virtual bool isStopped() const =0
Returns whether the object is at a stop.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
double getFloatParam(const std::string &paramName, const bool required=false, const double deflt=INVALID_DOUBLE) const
Retrieve a floating point parameter for the traffic object.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual int getRoutePosition() const =0
return index of edge within route
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
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.
Representation of a vehicle.
Definition: SUMOVehicle.h:62
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const =0
Returns the starting point for reroutes (usually the current edge)
virtual bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)=0
Performs a rerouting using the given router.
virtual bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)=0
Replaces the current route by the given edges.
virtual const MSRoute & getRoute() const =0
Returns the current route.
virtual const std::list< MSStop > & getStops() const =0
virtual const std::vector< MSTransportable * > & getContainers() const =0
retrieve riding containers
virtual bool hasStops() const =0
Returns whether the vehicle has to stop somewhere.
virtual bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, ConstMSEdgeVector::const_iterator *searchStart=0)=0
Adds a stop.
virtual MSStop & getNextStop()=0
virtual int getPersonNumber() const =0
Returns the number of persons.
virtual void unregisterWaiting()=0
mark vehicle as active
virtual bool isStoppedTriggered() const =0
Returns whether the vehicle is at a stop and waiting for a person or container to continue.
virtual const std::vector< MSTransportable * > & getPersons() const =0
retrieve riding persons
virtual int getContainerNumber() const =0
Returns the number of containers.
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
virtual bool isStoppedParking() const =0
Returns whether the vehicle is at a stop and parking.
virtual const SUMOVehicleParameter::Stop * getNextStopParameter() const =0
Returns parameters of the next stop or nullptr.
virtual bool abortNextStop(int nextStopIndex=0)=0
deletes the next stop at the given index if it exists
Definition of vehicle stop (position and duration)
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
SUMOTime extension
The maximum time extension for boarding / loading.
double startPos
The stopping position start.
std::set< std::string > permitted
IDs of persons or containers that may board/load at this stop.
int index
at which position in the stops list
std::string actType
act Type (only used by Persons) (used by netedit)
double endPos
The stopping position end.
SUMOTime waitUntil
The earliest pickup time for a taxi stop.
Structure representing possible vehicle parameter.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
std::string line
The vehicle's line (mainly for public transport)
static ParkingType parseParkingType(const std::string &value)
parses parking type value
A wrapper for a Command function.
Definition: StaticCommand.h:38
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
std::string line
Definition: MSDispatch.h:88
SUMOTime earliestPickupTime
Definition: MSDispatch.h:80