Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2025 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
66std::vector<MSDevice_Taxi*> MSDevice_Taxi::myFleet;
69std::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// ---------------------------------------------------------------------------
80void
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.dispatch-keep-unreachable", new Option_String("3600", "TIME"));
98 oc.addDescription("device.taxi.dispatch-keep-unreachable", "Taxi Device", TL("The time before aborting unreachable reservations"));
99
100 oc.doRegister("device.taxi.idle-algorithm", new Option_String("stop"));
101 oc.addDescription("device.taxi.idle-algorithm", "Taxi Device", TL("The behavior of idle taxis [stop|randomCircling|taxistand]"));
102
103 oc.doRegister("device.taxi.idle-algorithm.output", new Option_FileName());
104 oc.addDescription("device.taxi.idle-algorithm.output", "Taxi Device", TL("Write information from the idling algorithm to FILE"));
105}
106
107
108void
109MSDevice_Taxi::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
111 if (equippedByDefaultAssignmentOptions(oc, "taxi", v, false)) {
112 // build the device
113 MSDevice_Taxi* device = new MSDevice_Taxi(v, "taxi_" + v.getID());
114 into.push_back(device);
115 myFleet.push_back(device);
116 if (v.getParameter().line == "") {
117 // automatically set the line so that persons are willing to enter
118 // (see MSStageDriving::isWaitingFor)
119 const_cast<SUMOVehicleParameter&>(v.getParameter()).line = TAXI_SERVICE;
120 }
121 if (v.getVClass() != SVC_TAXI && myVClassWarningVTypes.count(v.getVehicleType().getID()) == 0) {
122 WRITE_WARNINGF(TL("Vehicle '%' with device.taxi should have vClass taxi instead of '%'."), v.getID(), toString(v.getVClass()));
124 }
125 const int personCapacity = v.getVehicleType().getPersonCapacity();
126 const int containerCapacity = v.getVehicleType().getContainerCapacity();
127 myMaxCapacity = MAX2(myMaxCapacity, personCapacity);
129 if (personCapacity < 1 && containerCapacity < 1) {
130 WRITE_WARNINGF(TL("Vehicle '%' with personCapacity % and containerCapacity % is not usable as taxi."), v.getID(), toString(personCapacity), toString(containerCapacity));
131 }
132 }
133}
134
135
136void
139 myDispatchPeriod = string2time(oc.getString("device.taxi.dispatch-period"));
140 // init dispatch algorithm
141 std::string algo = oc.getString("device.taxi.dispatch-algorithm");
142 Parameterised params;
143 params.setParametersStr(OptionsCont::getOptions().getString("device.taxi.dispatch-algorithm.params"), ":", ",");
144 if (algo == "greedy") {
146 } else if (algo == "greedyClosest") {
148 } else if (algo == "greedyShared") {
150 } else if (algo == "routeExtension") {
152 } else if (algo == "traci") {
154 } else {
155 throw ProcessError(TLF("Dispatch algorithm '%' is not known", algo));
156 }
158 // round to next multiple of myDispatchPeriod
160 const SUMOTime begin = string2time(oc.getString("begin"));
161 const SUMOTime delay = (myDispatchPeriod - ((now - begin) % myDispatchPeriod)) % myDispatchPeriod;
163}
164
165bool
166MSDevice_Taxi::isReservation(const std::set<std::string>& lines) {
167 return lines.size() == 1 && (
168 *lines.begin() == TAXI_SERVICE
169 || StringUtils::startsWith(*lines.begin(), TAXI_SERVICE_PREFIX));
170}
171
172void
174 const std::set<std::string>& lines,
175 SUMOTime reservationTime,
176 SUMOTime pickupTime,
177 SUMOTime earliestPickupTime,
178 const MSEdge* from, double fromPos,
179 const MSStoppingPlace* fromStop,
180 const MSEdge* to, double toPos,
181 const MSStoppingPlace* toStop,
182 const std::string& group) {
183 if (!isReservation(lines)) {
184 return;
185 }
186 if ((to->getPermissions() & SVC_TAXI) == 0) {
187 throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
188 + " '" + person->getID() + "' because destination edge '" + to->getID() + "'"
189 + " does not permit taxi access");
190 }
191 if ((from->getPermissions() & SVC_TAXI) == 0) {
192 throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
193 + " '" + person->getID() + "' because origin edge '" + from->getID() + "'"
194 + " does not permit taxi access");
195 }
196 if (myDispatchCommand == nullptr) {
197 initDispatch();
198 }
199 if (fromStop != nullptr && &fromStop->getLane().getEdge() == from) {
200 // pickup position should be at the stop-endPos
201 fromPos = fromStop->getEndLanePosition();
202 }
203 myDispatcher->addReservation(person, reservationTime, pickupTime, earliestPickupTime, from, fromPos, fromStop, to, toPos, toStop, group, *lines.begin(), myMaxCapacity, myMaxContainerCapacity);
204}
205
206void
208 const std::set<std::string>& lines,
209 const MSEdge* from, double fromPos,
210 const MSEdge* to, double toPos,
211 const std::string& group) {
212 if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
213 myDispatcher->removeReservation(person, from, fromPos, to, toPos, group);
214 }
215}
216
217void
219 const std::set<std::string>& lines,
220 const MSEdge* from, double fromPos,
221 const MSEdge* to, double toPos,
222 const std::string& group, double newFromPos) {
223 if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
224 myDispatcher->updateReservationFromPos(person, from, fromPos, to, toPos, group, newFromPos);
225 }
226}
227
228
231 std::vector<MSDevice_Taxi*> active;
232 for (MSDevice_Taxi* taxi : myFleet) {
233 if (taxi->getHolder().hasDeparted()) {
234 active.push_back(taxi);
235 }
236 }
237 myDispatcher->computeDispatch(currentTime, active);
238 return myDispatchPeriod;
239}
240
241bool
245
246void
248 if (myDispatcher != nullptr) {
249 delete myDispatcher;
250 myDispatcher = nullptr;
251 }
252 myDispatchCommand = nullptr;
253 myVClassWarningVTypes.clear();
254}
255
256// ---------------------------------------------------------------------------
257// MSDevice_Taxi-methods
258// ---------------------------------------------------------------------------
259MSDevice_Taxi::MSDevice_Taxi(SUMOVehicle& holder, const std::string& id) :
260 MSVehicleDevice(holder, id) {
261 std::string defaultServiceEnd = toString(1e15);
262 const std::string algo = holder.getStringParam("device.taxi.idle-algorithm");
263 if (algo == "stop") {
265 } else if (algo == "randomCircling") {
267 // make sure simulation terminates
268 defaultServiceEnd = toString(STEPS2TIME(
271 : MSNet::getInstance()->getCurrentTimeStep()) + (3600 * 8));
272 } else if (algo == "taxistand") {
273 const std::string rerouterID = holder.getStringParam("device.taxi.stands-rerouter");
274 if (rerouterID.empty()) {
275 throw ProcessError("Idle algorithm '" + algo + "' requires a rerouter id to be defined using device param 'stands-rerouter' for vehicle '" + myHolder.getID() + "'");
276 }
277 if (MSTriggeredRerouter::getInstances().count(rerouterID) == 0) {
278 throw ProcessError("Unknown rerouter '" + rerouterID + "' when loading taxi stands for vehicle '" + myHolder.getID() + "'");
279 }
280 MSTriggeredRerouter* rerouter = MSTriggeredRerouter::getInstances().find(rerouterID)->second;
281 myIdleAlgorithm = new MSIdling_TaxiStand(rerouter);
282 } else {
283 throw ProcessError("Idle algorithm '" + algo + "' is not known for vehicle '" + myHolder.getID() + "'");
284 }
285 myServiceEnd = string2time(holder.getStringParam("device.taxi.end", false, defaultServiceEnd));
287}
288
289
291 myFleet.erase(std::find(myFleet.begin(), myFleet.end(), this));
292 // recompute myMaxCapacity
293 myMaxCapacity = 0;
295 for (MSDevice_Taxi* taxi : myFleet) {
296 myMaxCapacity = MAX2(myMaxCapacity, taxi->getHolder().getVehicleType().getPersonCapacity());
297 myMaxContainerCapacity = MAX2(myMaxContainerCapacity, taxi->getHolder().getVehicleType().getContainerCapacity());
298 }
299 delete myIdleAlgorithm;
300}
301
302
303bool
305 return myFleet.size() > 0;;
306}
307
308
309void
311 dispatchShared({&res, &res});
312}
313
314
315void
316MSDevice_Taxi::dispatchShared(std::vector<const Reservation*> reservations) {
317#ifdef DEBUG_DISPATCH
318 if (DEBUG_COND) {
319 std::cout << SIMTIME << " taxi=" << myHolder.getID() << " dispatch:\n";
320 for (const Reservation* res : reservations) {
321 std::cout << " persons=" << toString(res->persons) << "\n";
322 }
323 }
324#endif
325 myLastDispatch = reservations;
326 ConstMSEdgeVector tmpEdges;
327 StopParVector stops;
328 double lastPos = myHolder.getPositionOnLane();
329 const MSEdge* rerouteOrigin = *myHolder.getRerouteOrigin();
330 if (isEmpty()) {
331 // start fresh from the current edge
333 // parking stop must be ended normally
335 stop.duration = 0;
336 lastPos = stop.pars.endPos;
338 stop.triggered = false;
339 stop.containerTriggered = false;
340 stop.joinTriggered = false;
342 }
343 // prevent unauthorized/premature entry
344 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).permitted.insert("");
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
531void
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) {
555 }
556}
557
558
559bool
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
616 }
617 return true;
618}
619
620
621void
623 StopParVector& 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 const SumoXMLTag tag = stopPlace->getElement();
687 if (tag == SUMO_TAG_BUS_STOP || tag == SUMO_TAG_TRAIN_STOP) {
688 stop.busstop = stopPlace->getID();
689 } else if (tag == SUMO_TAG_PARKING_AREA) {
690 stop.parkingarea = stopPlace->getID();
691 } else if (tag == SUMO_TAG_CONTAINER_STOP) {
692 stop.containerstop = stopPlace->getID();
693 }
694 } else {
695 stop.startPos = stopPos;
696 stop.endPos = MAX2(stopPos, MIN2(myHolder.getVehicleType().getLength(), stopEdge->getLength()));
697 }
698 stop.parking = SUMOVehicleParameter::parseParkingType(myHolder.getStringParam("device.taxi.parking", false, "true"));
699 stop.actType = action;
700 stop.index = STOP_INDEX_END;
701 // In case of prebooking if person is not there/ comes to late for pickup set maximum waiting time:
702 SUMOTime earliestPickupTime = res->earliestPickupTime;
703 if (isPickup && earliestPickupTime >= 0) {
704 stop.waitUntil = earliestPickupTime;
705 // TODO: replace hard coded extension with parameter
706 stop.extension = static_cast<SUMOTime>(3 * 60 * 1000); // 3mins
707 }
708 stops.push_back(stop);
709}
710
711
712MSLane*
713MSDevice_Taxi::getStopLane(const MSEdge* edge, const std::string& action) {
714 const std::vector<MSLane*>* allowedLanes = edge->allowedLanes(myHolder.getVClass());
715 if (allowedLanes == nullptr) {
716 throw ProcessError("Taxi vehicle '" + myHolder.getID() + "' cannot stop on edge '" + edge->getID() + "' (" + action + ")");
717 }
718 return allowedLanes->front();
719}
720
721bool
723 return myState == EMPTY;
724}
725
726
727bool
729 return myCustomers.count(t) != 0;
730}
731
732
733void
734MSDevice_Taxi::updateMove(const SUMOTime traveltime, const double travelledDist) {
736 myOccupiedDistance += travelledDist;
737 myOccupiedTime += traveltime;
738 }
739 if (isEmpty()) {
740 if (MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
741 myIdleAlgorithm->idle(this);
742 if (myRoutingDevice != nullptr) {
743 // prevent rerouting during idling (#11079)
745 }
746 } else if (!myReachedServiceEnd) {
747 WRITE_WARNINGF(TL("Taxi '%' reaches scheduled end of service at time=%."), myHolder.getID(), time2string(SIMSTEP));
748 myReachedServiceEnd = true;
749 }
750 } else if (myRoutingDevice != nullptr) {
752 }
754 // limit duration of stop (but only for idling-related stops)
756 }
757#ifdef DEBUG_DISPATCH
759 std::cout << SIMTIME << " updateMove veh=" << myHolder.getID() << " myIsStopped=" << myIsStopped << " myHolderStopped=" << myHolder.isStopped() << " myState=" << myState << "\n";
760 }
761#endif
763}
764
765
766bool
768 double newPos, double /*newSpeed*/) {
769 updateMove(DELTA_T, newPos - oldPos);
770 return true; // keep the device
771}
772
773
774void
776 const double /* frontOnLane */,
777 const double timeOnLane,
778 const double /* meanSpeedFrontOnLane */,
779 const double /* meanSpeedVehicleOnLane */,
780 const double travelledDistanceFrontOnLane,
781 const double /* travelledDistanceVehicleOnLane */,
782 const double /* meanLengthOnLane */) {
783 updateMove(TIME2STEPS(timeOnLane), travelledDistanceFrontOnLane);
784}
785
786
787bool
789 if (isEmpty() && MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
790 myIdleAlgorithm->idle(this);
791 }
792 return true; // keep the device
793}
794
795
796void
798 myState |= OCCUPIED;
799 if (!hasFuturePickup()) {
800 myState &= ~PICKUP;
801 }
802 for (const Reservation* res : myCurrentReservations) {
803 for (const MSTransportable* cand : res->persons) {
804 if (cand == t) {
805 const_cast<Reservation*>(res)->state = Reservation::ONBOARD;
806 break;
807 }
808 }
809 }
810}
811
812
813void
816 myCustomers.erase(person);
818 myState &= ~OCCUPIED;
819 if (myHolder.getStops().size() > 1 && (myState & PICKUP) == 0) {
820 WRITE_WARNINGF(TL("All customers left vehicle '%' at time=% but there are % remaining stops"),
822 while (myHolder.getStops().size() > 1) {
824 }
825 }
826 }
827 if (isEmpty()) {
828 // cleanup
829 for (const Reservation* res : myCurrentReservations) {
831 }
832 myCurrentReservations.clear();
834 myIdleAlgorithm->idle(this);
835 }
836 } else {
837 // check whether a single reservation has been fulfilled
838 for (auto resIt = myCurrentReservations.begin(); resIt != myCurrentReservations.end();) {
839 bool fulfilled = true;
840 for (const MSTransportable* t : (*resIt)->persons) {
841 if (myCustomers.count(t) != 0) {
842 fulfilled = false;
843 break;
844 }
845 }
846 if (fulfilled) {
848 resIt = myCurrentReservations.erase(resIt);
849 } else {
850 ++resIt;
851 }
852 }
853 }
854}
855
856
857bool
859 for (const auto& stop : myHolder.getStops()) {
860 if (stop.reached) {
861 continue;
862 }
863 if (stop.pars.permitted.size() > 0) {
864 return true;
865 }
866 }
867 return false;
868}
869
870void
872 if (tripinfoOut != nullptr) {
873 tripinfoOut->openTag("taxi");
874 tripinfoOut->writeAttr("customers", toString(myCustomersServed));
875 tripinfoOut->writeAttr("occupiedDistance", toString(myOccupiedDistance));
876 tripinfoOut->writeAttr("occupiedTime", time2string(myOccupiedTime));
877 tripinfoOut->closeTag();
878 }
879}
880
881std::string
882MSDevice_Taxi::getParameter(const std::string& key) const {
883 if (key == "customers") {
885 } else if (key == "occupiedDistance") {
887 } else if (key == "occupiedTime") {
889 } else if (key == "state") {
890 return toString(myState);
891 } else if (key == "currentCustomers") {
893 } else if (key == "pickUpDuration") {
894 return myHolder.getStringParam("device.taxi.pickUpDuration", false, "0");
895 } else if (key == "dropOffDuration") {
896 return myHolder.getStringParam("device.taxi.dropOffDuration", false, "60");
897 }
898 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
899}
900
901
902void
903MSDevice_Taxi::setParameter(const std::string& key, const std::string& value) {
904 double doubleValue;
905 try {
906 doubleValue = StringUtils::toDouble(value);
907 } catch (NumberFormatException&) {
908 throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
909 }
910 if (key == "pickUpDuration" || key == "dropOffDuration") {
911 // store as generic vehicle parameters
912 ((SUMOVehicleParameter&)myHolder.getParameter()).setParameter("device.taxi." + key, value);
913 } else {
914 UNUSED_PARAMETER(doubleValue);
915 throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
916 }
917}
918
919bool
920MSDevice_Taxi::compatibleLine(const std::string& taxiLine, const std::string& rideLine) {
921 return ((taxiLine == rideLine && StringUtils::startsWith(rideLine, "taxi") && StringUtils::startsWith(taxiLine, "taxi"))
922 || (taxiLine == TAXI_SERVICE && StringUtils::startsWith(rideLine, "taxi:"))
923 || (rideLine == TAXI_SERVICE && StringUtils::startsWith(taxiLine, "taxi:")));
924}
925
926bool
930
931
932/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define TAXI_SERVICE
#define TAXI_SERVICE_PREFIX
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
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:91
#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
std::vector< SUMOVehicleParameter::Stop > StopParVector
const int STOP_PERMITTED_SET
@ GIVEN
The time is given.
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_TRAIN_STOP
A train stop (alias for bus stop)
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
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)
void prepareStop(ConstMSEdgeVector &edges, StopParVector &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
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.
static bool hasFleet()
returns whether taxis have been loaded
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
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.
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:157
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:200
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
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...
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
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
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:657
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:482
double getLength() const
return the length of the edge
Definition MSEdge.h:693
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
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:611
bool isInternal() const
Definition MSLane.cpp:2621
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:769
Notification
Definition of a vehicle state.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:495
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:125
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
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.
SumoXMLTag getElement() const
return the type of this stopping place
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.
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.
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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.
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 const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
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 const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual int getRNGIndex() const =0
virtual MSDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or nullptr if not.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
virtual int getRoutePosition() const =0
return index of edge within route
double getFloatParam(const std::string &paramName, const bool required=false, const double deflt=INVALID_DOUBLE, bool checkDist=true) const
Retrieve a floating point parameter for the traffic object.
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 std::vector< MSTransportable * > & getContainers() const =0
retrieve riding containers
virtual bool isStopped() const =0
Returns whether the vehicle is at a stop and waiting for a person or container to continue.
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 const std::list< MSStop > & getStops() const =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 const MSStop & getNextStop() const =0
virtual MSStop & getNextStopMutable()=0
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 const MSRoute & getRoute() const =0
Returns the current route.
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.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
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.
std::string busstop
(Optional) bus stop if one is assigned to the stop
std::string containerstop
(Optional) container stop if one is assigned to the 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.
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.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
std::string line
Definition MSDispatch.h:88
SUMOTime earliestPickupTime
Definition MSDispatch.h:80