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-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18// 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#define SWAP_THRESHOLD 5
74
75// ===========================================================================
76// method definitions
77// ===========================================================================
78// ---------------------------------------------------------------------------
79// static initialisation methods
80// ---------------------------------------------------------------------------
81void
83 oc.addOptionSubTopic("Taxi Device");
84 insertDefaultAssignmentOptions("taxi", "Taxi Device", oc);
85
86 oc.doRegister("device.taxi.dispatch-algorithm", new Option_String("greedy"));
87 oc.addDescription("device.taxi.dispatch-algorithm", "Taxi Device", TL("The dispatch algorithm [greedy|greedyClosest|greedyShared|routeExtension|traci]"));
88
89 oc.doRegister("device.taxi.dispatch-algorithm.output", new Option_FileName());
90 oc.addDescription("device.taxi.dispatch-algorithm.output", "Taxi Device", TL("Write information from the dispatch algorithm to FILE"));
91
92 oc.doRegister("device.taxi.dispatch-algorithm.params", new Option_String(""));
93 oc.addDescription("device.taxi.dispatch-algorithm.params", "Taxi Device", TL("Load dispatch algorithm parameters in format KEY1:VALUE1[,KEY2:VALUE]"));
94
95 oc.doRegister("device.taxi.dispatch-period", new Option_String("60", "TIME"));
96 oc.addDescription("device.taxi.dispatch-period", "Taxi Device", TL("The period between successive calls to the dispatcher"));
97
98 oc.doRegister("device.taxi.dispatch-keep-unreachable", new Option_String("3600", "TIME"));
99 oc.addDescription("device.taxi.dispatch-keep-unreachable", "Taxi Device", TL("The time before aborting unreachable reservations"));
100
101 oc.doRegister("device.taxi.idle-algorithm", new Option_String("stop"));
102 oc.addDescription("device.taxi.idle-algorithm", "Taxi Device", TL("The behavior of idle taxis [stop|randomCircling|taxistand]"));
103
104 oc.doRegister("device.taxi.idle-algorithm.output", new Option_FileName());
105 oc.addDescription("device.taxi.idle-algorithm.output", "Taxi Device", TL("Write information from the idling algorithm to FILE"));
106}
107
108
109void
110MSDevice_Taxi::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
112 if (equippedByDefaultAssignmentOptions(oc, "taxi", v, false)) {
113 // build the device
114 MSDevice_Taxi* device = new MSDevice_Taxi(v, "taxi_" + v.getID());
115 into.push_back(device);
116 myFleet.push_back(device);
117 if (v.getParameter().line == "") {
118 // automatically set the line so that persons are willing to enter
119 // (see MSStageDriving::isWaitingFor)
120 const_cast<SUMOVehicleParameter&>(v.getParameter()).line = TAXI_SERVICE;
121 }
122 if (v.getVClass() != SVC_TAXI && myVClassWarningVTypes.count(v.getVehicleType().getID()) == 0) {
123 WRITE_WARNINGF(TL("Vehicle '%' with device.taxi should have vClass taxi instead of '%'."), v.getID(), toString(v.getVClass()));
125 }
126 const int personCapacity = v.getVehicleType().getPersonCapacity();
127 const int containerCapacity = v.getVehicleType().getContainerCapacity();
128 myMaxCapacity = MAX2(myMaxCapacity, personCapacity);
130 if (personCapacity < 1 && containerCapacity < 1) {
131 WRITE_WARNINGF(TL("Vehicle '%' with personCapacity % and containerCapacity % is not usable as taxi."), v.getID(), toString(personCapacity), toString(containerCapacity));
132 }
133 }
134}
135
136
137void
140 myDispatchPeriod = string2time(oc.getString("device.taxi.dispatch-period"));
141 // init dispatch algorithm
142 std::string algo = oc.getString("device.taxi.dispatch-algorithm");
143 Parameterised params;
144 params.setParametersStr(OptionsCont::getOptions().getString("device.taxi.dispatch-algorithm.params"), ":", ",");
145 if (algo == "greedy") {
147 } else if (algo == "greedyClosest") {
149 } else if (algo == "greedyShared") {
151 } else if (algo == "routeExtension") {
153 } else if (algo == "traci") {
155 } else {
156 throw ProcessError(TLF("Dispatch algorithm '%' is not known", algo));
157 }
159 // round to next multiple of myDispatchPeriod
161 const SUMOTime begin = string2time(oc.getString("begin"));
162 const SUMOTime delay = (myDispatchPeriod - ((now - begin) % myDispatchPeriod)) % myDispatchPeriod;
164}
165
166bool
167MSDevice_Taxi::isReservation(const std::set<std::string>& lines) {
168 return lines.size() == 1 && (
169 *lines.begin() == TAXI_SERVICE
170 || StringUtils::startsWith(*lines.begin(), TAXI_SERVICE_PREFIX));
171}
172
173void
175 const std::set<std::string>& lines,
176 SUMOTime reservationTime,
177 SUMOTime pickupTime,
178 SUMOTime earliestPickupTime,
179 const MSEdge* from, double fromPos,
180 const MSStoppingPlace* fromStop,
181 const MSEdge* to, double toPos,
182 const MSStoppingPlace* toStop,
183 const std::string& group) {
184 if (!isReservation(lines)) {
185 return;
186 }
187 if ((to->getPermissions() & SVC_TAXI) == 0) {
188 throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
189 + " '" + person->getID() + "' because destination edge '" + to->getID() + "'"
190 + " does not permit taxi access");
191 }
192 if ((from->getPermissions() & SVC_TAXI) == 0) {
193 throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
194 + " '" + person->getID() + "' because origin edge '" + from->getID() + "'"
195 + " does not permit taxi access");
196 }
197 if (myDispatchCommand == nullptr) {
198 initDispatch();
199 }
200 if (fromStop != nullptr && &fromStop->getLane().getEdge() == from) {
201 // pickup position should be at the stop-endPos
202 fromPos = fromStop->getEndLanePosition();
203 }
204 myDispatcher->addReservation(person, reservationTime, pickupTime, earliestPickupTime, from, fromPos, fromStop, to, toPos, toStop, group, *lines.begin(), myMaxCapacity, myMaxContainerCapacity);
205}
206
207void
209 const std::set<std::string>& lines,
210 const MSEdge* from, double fromPos,
211 const MSEdge* to, double toPos,
212 const std::string& group) {
213 if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
214 myDispatcher->removeReservation(person, from, fromPos, to, toPos, group);
215 }
216}
217
218void
220 const std::set<std::string>& lines,
221 const MSEdge* from, double fromPos,
222 const MSEdge* to, double toPos,
223 const std::string& group, double newFromPos) {
224 if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
225 myDispatcher->updateReservationFromPos(person, from, fromPos, to, toPos, group, newFromPos);
226 }
227}
228
229
232 std::vector<MSDevice_Taxi*> active;
233 for (MSDevice_Taxi* taxi : myFleet) {
234 if (taxi->getHolder().hasDeparted()) {
235 active.push_back(taxi);
236 }
237 }
238 myDispatcher->computeDispatch(currentTime, active);
239 return myDispatchPeriod;
240}
241
242bool
246
247void
249 if (myDispatcher != nullptr) {
250 delete myDispatcher;
251 myDispatcher = nullptr;
252 }
253 myDispatchCommand = nullptr;
254 myVClassWarningVTypes.clear();
255}
256
257
258void
260 for (MSDevice_Taxi* taxi : myFleet) {
261 // disable taskSwap
262 taxi->myState = EMPTY;
263 }
264}
265
266// ---------------------------------------------------------------------------
267// MSDevice_Taxi-methods
268// ---------------------------------------------------------------------------
269MSDevice_Taxi::MSDevice_Taxi(SUMOVehicle& holder, const std::string& id) :
270 MSVehicleDevice(holder, id) {
271 std::string defaultServiceEnd = toString(1e15);
272 const std::string algo = holder.getStringParam("device.taxi.idle-algorithm");
273 if (algo == "stop") {
275 } else if (algo == "randomCircling") {
277 // make sure simulation terminates
278 defaultServiceEnd = toString(STEPS2TIME(
281 : MSNet::getInstance()->getCurrentTimeStep()) + (3600 * 8));
282 } else if (algo == "taxistand") {
283 const std::string rerouterID = holder.getStringParam("device.taxi.stands-rerouter");
284 if (rerouterID.empty()) {
285 throw ProcessError("Idle algorithm '" + algo + "' requires a rerouter id to be defined using device param 'stands-rerouter' for vehicle '" + myHolder.getID() + "'");
286 }
287 if (MSTriggeredRerouter::getInstances().count(rerouterID) == 0) {
288 throw ProcessError("Unknown rerouter '" + rerouterID + "' when loading taxi stands for vehicle '" + myHolder.getID() + "'");
289 }
290 MSTriggeredRerouter* rerouter = MSTriggeredRerouter::getInstances().find(rerouterID)->second;
291 myIdleAlgorithm = new MSIdling_TaxiStand(rerouter);
292 } else {
293 throw ProcessError("Idle algorithm '" + algo + "' is not known for vehicle '" + myHolder.getID() + "'");
294 }
295 myServiceEnd = string2time(holder.getStringParam("device.taxi.end", false, defaultServiceEnd));
297}
298
299
301 myFleet.erase(std::find(myFleet.begin(), myFleet.end(), this));
302 // recompute myMaxCapacity
303 myMaxCapacity = 0;
305 for (MSDevice_Taxi* taxi : myFleet) {
306 myMaxCapacity = MAX2(myMaxCapacity, taxi->getHolder().getVehicleType().getPersonCapacity());
307 myMaxContainerCapacity = MAX2(myMaxContainerCapacity, taxi->getHolder().getVehicleType().getContainerCapacity());
308 }
309 delete myIdleAlgorithm;
310}
311
312
313bool
315 return myFleet.size() > 0;;
316}
317
318
319void
321 dispatchShared({&res, &res});
322}
323
324
325void
326MSDevice_Taxi::dispatchShared(std::vector<const Reservation*> reservations) {
327#ifdef DEBUG_DISPATCH
328 if (DEBUG_COND) {
329 std::cout << SIMTIME << " taxi=" << myHolder.getID() << " dispatch:\n";
330 for (const Reservation* res : reservations) {
331 std::cout << " persons=" << toString(res->persons) << "\n";
332 }
333 }
334#endif
335 myLastDispatch = reservations;
336 ConstMSEdgeVector tmpEdges;
337 StopParVector stops;
338 double lastPos = myHolder.getPositionOnLane();
339 const MSEdge* rerouteOrigin = *myHolder.getRerouteOrigin();
340 if (isEmpty()) {
341 // start fresh from the current edge
343 // parking stop must be ended normally
345 stop.duration = 0;
346 lastPos = stop.pars.endPos;
348 stop.triggered = false;
349 stop.containerTriggered = false;
350 stop.joinTriggered = false;
352 }
353 // prevent unauthorized/premature entry
354 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).permitted.insert("");
355 while (myHolder.getStops().size() > 1) {
357 }
358 } else {
359 while (myHolder.hasStops()) {
360 // in meso there might be more than 1 stop at this point
362 }
363 assert(!myHolder.hasStops());
364 }
365 tmpEdges.push_back(myHolder.getEdge());
366 if (myHolder.getEdge() != rerouteOrigin) {
367 tmpEdges.push_back(rerouteOrigin);
368 }
369 } else {
370 assert(myHolder.hasStops());
371 // check how often existing customers appear in the new reservations
372 std::map<const MSTransportable*, int> nOccur;
373 for (const Reservation* res : reservations) {
374 for (const MSTransportable* person : res->persons) {
375 if (myCustomers.count(person) != 0) {
376 nOccur[person] += 1;
377 if (myCurrentReservations.count(res) == 0) {
378 throw ProcessError(TLF("Invalid Re-dispatch for existing customer '%' with a new reservation", person->getID()));
379 }
380 }
381 }
382 }
383#ifdef DEBUG_DISPATCH
384 if (DEBUG_COND) {
385 for (auto item : nOccur) {
386 std::cout << " previousCustomer=" << item.first->getID() << " occurs=" << item.second << "\n";
387 }
388 }
389#endif
390 if (nOccur.size() == 0) {
391 // no overlap with existing customers - extend route
392 tmpEdges = myHolder.getRoute().getEdges();
393 lastPos = myHolder.getStops().back().pars.endPos;
394#ifdef DEBUG_DISPATCH
395 if (DEBUG_COND) {
396 std::cout << " re-dispatch with route-extension\n";
397 }
398#endif
399 } else if (nOccur.size() == myCustomers.size()) {
400 // redefine route (verify correct number of mentions)
401 std::set<const MSTransportable*> onBoard;
402 const std::vector<MSTransportable*>& onBoardP = myHolder.getPersons();
403 const std::vector<MSTransportable*>& onBoardC = myHolder.getContainers();
404 onBoard.insert(onBoardP.begin(), onBoardP.end());
405 onBoard.insert(onBoardC.begin(), onBoardC.end());
406 std::set<const MSTransportable*> redundantPickup;
407 for (auto item : nOccur) {
408 if (item.second == 1) {
409 // customers must already be on board
410 if (onBoard.count(item.first) == 0) {
411 throw ProcessError(TLF("Re-dispatch did not mention pickup for existing customer '%'", item.first->getID()));
412 }
413 } else if (item.second == 2) {
414 if (onBoard.count(item.first) == 0) {
415 // treat like a new customer
416 // TODO: need to be checked
417 myCustomers.erase(item.first);
418 } else {
419 redundantPickup.insert(item.first);
420 }
421 } else {
422 throw ProcessError("Re-dispatch mentions existing customer '" + item.first->getID() + "' " + toString(item.second) + " times");
423 }
424 }
425 // remove redundancy
426 if (!redundantPickup.empty()) {
427 for (auto it = reservations.begin(); it != reservations.end();) {
428 bool isRedundant = false;
429 for (const MSTransportable* person : (*it)->persons) {
430 if (redundantPickup.count(person) != 0) {
431 isRedundant = true;
432 break;
433 }
434 }
435 if (isRedundant) {
436 for (const MSTransportable* person : (*it)->persons) {
437 redundantPickup.erase(person);
438 }
439 it = reservations.erase(it);
440 } else {
441 it++;
442 }
443 }
444 }
445 while (myHolder.hasStops()) {
447 }
448 tmpEdges.push_back(myHolder.getEdge());
449 if (myHolder.getEdge() != rerouteOrigin) {
450 tmpEdges.push_back(rerouteOrigin);
451 }
452#ifdef DEBUG_DISPATCH
453 if (DEBUG_COND) {
454 std::cout << " re-dispatch from scratch\n";
455 }
456#endif
457 } else {
458 // inconsistent re-dispatch
459 std::vector<std::string> missing;
460 for (const MSTransportable* c : myCustomers) {
461 if (nOccur.count(c) == 0) {
462 missing.push_back(c->getID());
463 }
464 }
465 throw ProcessError("Re-dispatch did mention some customers but failed to mention " + joinToStringSorting(missing, " "));
466 }
467 }
468
470 bool hasPickup = false;
471 for (const Reservation* res : reservations) {
472 myCurrentReservations.insert(res);
473 bool isPickup = false;
474 for (const MSTransportable* person : res->persons) {
475 if (myCustomers.count(person) == 0) {
476 myCustomers.insert(person);
477 isPickup = true;
478 hasPickup = true;
479 }
480 }
481 if (isPickup) {
482 prepareStop(tmpEdges, stops, lastPos, res->from, res->fromPos, res->fromStop, "pickup " + toString(res->persons) + " (" + res->id + ")", res, isPickup);
483 for (const MSTransportable* const transportable : res->persons) {
484 if (transportable->isPerson()) {
485 stops.back().triggered = true;
486 } else {
487 stops.back().containerTriggered = true;
488 }
489 stops.back().permitted.insert(transportable->getID());
490 }
491 // proof this lines: Is needed for pre-booking?
492 std::set<const MSTransportable*> persons = res->persons;
493 for (auto itr = persons.begin(); itr != persons.end(); itr++) {
494 stops.back().awaitedPersons.insert((*itr)->getID());
495 }
496
497 stops.back().parametersSet |= STOP_PERMITTED_SET;
498 if (stops.back().duration == -1) {
499 // keep dropOffDuration if the stop is dropOff and pickUp
500 stops.back().duration = TIME2STEPS(myHolder.getFloatParam("device.taxi.pickUpDuration", false, 0));
501 }
502 } else {
503 prepareStop(tmpEdges, stops, lastPos, res->to, res->toPos, res->toStop, "dropOff " + toString(res->persons) + " (" + res->id + ")", res, isPickup);
504 stops.back().duration = TIME2STEPS(myHolder.getFloatParam("device.taxi.dropOffDuration", false, 60)); // pay and collect bags
505 }
506 }
507#ifdef DEBUG_DISPATCH
508 if (DEBUG_COND) {
509 std::cout << " tmpEdges=" << toString(tmpEdges) << "\n";
510 }
511#endif
512 if (!myHolder.replaceRouteEdges(tmpEdges, -1, 0, "taxi:prepare_dispatch", false, false, false)) {
513 throw ProcessError("Route replacement for taxi dispatch failed for vehicle '" + myHolder.getID()
514 + "' at time=" + time2string(t) + ".");
515 }
516#ifdef DEBUG_DISPATCH
517 if (DEBUG_COND) std::cout << " replacedRoute=" << toString(tmpEdges)
518 << "\n actualRoute=" << toString(myHolder.getRoute().getEdges()) << "\n";
519#endif
520 for (SUMOVehicleParameter::Stop& stop : stops) {
521 std::string error;
522 myHolder.addStop(stop, error);
523 if (error != "") {
524 WRITE_WARNINGF(TL("Could not add taxi stop, time=%, error=%"), myHolder.getID(), stop.actType, time2string(t), error)
525 }
526 }
528 // SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = myHolder.getInfluencer().getRouterTT(veh->getRNGIndex())
529 myHolder.reroute(t, "taxi:dispatch", router, false);
530#ifdef DEBUG_DISPATCH
531 if (DEBUG_COND) {
532 std::cout << "\n finalRoute=" << toString(myHolder.getRoute().getEdges()) << " routeIndex=" << myHolder.getRoutePosition() << "\n";
533 }
534#endif
535 if (hasPickup) {
536 myState |= PICKUP;
537 }
538}
539
540
541void
543 // check if taxi has stopped
544 if (myHolder.getNextStopParameter() == nullptr) {
545 return;
546 }
547 // find customers of the current stop
548 std::set<const MSTransportable*> customersToBeRemoved;
549 std::set<const MSTransportable*> onBoard;
550 onBoard.insert(myHolder.getPersons().begin(), myHolder.getPersons().end());
551 onBoard.insert(myHolder.getContainers().begin(), myHolder.getContainers().end());
552 for (std::string tID : myHolder.getNextStopParameter()->permitted) {
553 for (auto t : myCustomers) {
554 if (t->getID() == tID && onBoard.count(t) == 0) {
555 customersToBeRemoved.insert(t);
556 }
557 }
558 }
559 if (!customersToBeRemoved.empty()) {
560 WRITE_WARNINGF(TL("Taxi '%' aborts waiting for customers: % at time=%."),
561 myHolder.getID(), toString(customersToBeRemoved), time2string(SIMSTEP));
562 }
563 for (auto t : customersToBeRemoved) {
565 }
566}
567
568
569bool
571#ifdef DEBUG_CANCEL
572 if (DEBUG_COND) {
573 std::cout << SIMTIME << " taxi=" << myHolder.getID() << " cancelCustomer " << t->getID() << "\n";
574 }
575#endif
576
577 // is the given transportable a customer of the reservations?
578 if (myCustomers.count(t) == 0) {
579 return false;
580 }
581 myCustomers.erase(t);
582 // check whether a single reservation has been fulfilled or another customer is part of the reservation
583 for (auto resIt = myCurrentReservations.begin(); resIt != myCurrentReservations.end();) {
584 bool fulfilled = false;
585 if ((*resIt)->persons.size() == 1 && (*resIt)->persons.count(t) != 0) {
586 // the reservation contains only the customer
587 fulfilled = true;
588 }
589 if (fulfilled) {
590 const Reservation* res = *resIt;
591 // remove reservation from the current dispatch
592 for (auto it = myLastDispatch.begin(); it != myLastDispatch.end();) {
593 if (*it == res) {
594 it = myLastDispatch.erase(it);
595 } else {
596 ++it;
597 }
598 }
599 // remove reservation from the served reservations
600 resIt = myCurrentReservations.erase(resIt);
601 // delete the reservation
603 } else {
604 ++resIt;
605 }
606 }
607 myState &= ~PICKUP; // remove state PICKUP
608 for (const Reservation* res : myCurrentReservations) {
609 // if there is another pickup in the dispatch left, add the state PICKUP
610 if (std::count(myLastDispatch.begin(), myLastDispatch.end(), res) == 2) {
611 myState |= PICKUP; // add state PICKUP
612 }
613 }
614 // we also have to clean reservations from myLastDispatch where the customers arrived in the meantime
615 for (auto it = myLastDispatch.begin(); it != myLastDispatch.end();) {
616 if (myCurrentReservations.count(*it) == 0) {
617 it = myLastDispatch.erase(it);
618 } else {
619 ++it;
620 }
621 }
622 // if there are reservations left, go on with the dispatch
623 // in meso, wait for the next dispatch cycle to avoid updating stops in this stage
626 }
627 return true;
628}
629
630
631void
633 myCustomers.insert(t);
634 MSBaseVehicle& veh = dynamic_cast<MSBaseVehicle&>(myHolder);
635 for (const MSStop& stop : veh.getStops()) {
636 SUMOVehicleParameter::Stop& pars = const_cast<SUMOVehicleParameter::Stop&>(stop.pars);
637 //std::cout << " sE=" << (*stop.edge)->getID() << " sStart=" << pars.startPos << " sEnd=" << pars.endPos << " rFrom=" <<
638 // res->from->getID() << " rTo=" << res->to->getID() << " rFromPos=" << res->fromPos << " resToPos=" << res->toPos << "\n";
639 if (*stop.edge == res->from
640 && pars.startPos <= res->fromPos
641 && pars.endPos >= res->fromPos) {
642 pars.awaitedPersons.insert(t->getID());
643 pars.permitted.insert(t->getID());
644 pars.actType += " +" + t->getID();
645 } else if (*stop.edge == res->to
646 && pars.startPos <= res->toPos
647 && pars.endPos >= res->toPos) {
648 pars.actType += " +" + t->getID();
649 break;
650 }
651 }
652}
653
654
655void
657 StopParVector& stops,
658 double& lastPos, const MSEdge* stopEdge, double stopPos,
659 const MSStoppingPlace* stopPlace,
660 const std::string& action, const Reservation* res, const bool isPickup) {
661 assert(!edges.empty());
662 if (stopPlace != nullptr && &stopPlace->getLane().getEdge() == stopEdge) {
663 stopPos = stopPlace->getEndLanePosition();
664 }
665 if (stopPos < lastPos && stopPos + NUMERICAL_EPS >= lastPos) {
666 stopPos = lastPos;
667 }
668 bool addedEdge = false;
669
670 if (stops.empty()) {
671 // check brakeGap
672 double distToStop = stopPos - lastPos;
673 const double brakeGap = myHolder.getBrakeGap();
674 if (myHolder.getLane() != nullptr && myHolder.getLane()->isInternal()) {
675 distToStop += myHolder.getLane()->getLength();
676 }
677 if (stopEdge != edges.back()) {
678 distToStop += edges.back()->getLength();
679 if (distToStop < brakeGap) {
680 // the distance between current edge and stop edge may be small
682 ConstMSEdgeVector toFirstStop;
683 router.compute(edges.back(), stopEdge, &myHolder, SIMSTEP, toFirstStop, true);
684 for (int i = 1; i < (int)toFirstStop.size() - 1; i++) {
685 distToStop += toFirstStop[i]->getLength();
686 }
687 }
688 }
689 if (distToStop < brakeGap) {
690 // circle back to stopEdge
691 //std::cout << SIMTIME << " taxi=" << getID() << " brakeGap=" << brakeGap << " distToStop=" << distToStop << "\n";
692 edges.push_back(stopEdge);
693 addedEdge = true;
694 }
695 }
696
697 if (stopEdge == edges.back() && !stops.empty()) {
698 if (stopPos >= lastPos && stopPos <= stops.back().endPos) {
699 // no new stop and no adaption needed
700 stops.back().actType += "," + action;
701 return;
702 }
703 if (stopPos >= lastPos && stopPos <= lastPos + myHolder.getVehicleType().getLength()) {
704 // stop length adaption needed
705 stops.back().endPos = MIN2(lastPos + myHolder.getVehicleType().getLength(), stopEdge->getLength());
706 stops.back().actType += "," + action;
707 return;
708 }
709 }
710 if (!addedEdge && (stopEdge != edges.back() || stopPos < lastPos)) {
711 //std::cout << SIMTIME << " stopPos=" << stopPos << " lastPos=" << lastPos << "\n";
712 edges.push_back(stopEdge);
713 }
714 lastPos = stopPos;
716 stop.lane = getStopLane(stopEdge, action)->getID();
717 if (stopPlace != nullptr && &stopPlace->getLane().getEdge() == stopEdge) {
718 stop.startPos = stopPlace->getBeginLanePosition();
719 stop.endPos = stopPlace->getEndLanePosition();
720 const SumoXMLTag tag = stopPlace->getElement();
721 if (tag == SUMO_TAG_BUS_STOP || tag == SUMO_TAG_TRAIN_STOP) {
722 stop.busstop = stopPlace->getID();
723 } else if (tag == SUMO_TAG_PARKING_AREA) {
724 stop.parkingarea = stopPlace->getID();
725 } else if (tag == SUMO_TAG_CONTAINER_STOP) {
726 stop.containerstop = stopPlace->getID();
727 }
728 } else {
729 stop.startPos = stopPos;
730 stop.endPos = MAX2(stopPos, MIN2(myHolder.getVehicleType().getLength(), stopEdge->getLength()));
731 }
732 stop.parking = SUMOVehicleParameter::parseParkingType(myHolder.getStringParam("device.taxi.parking", false, "true"));
733 stop.actType = action;
734 stop.index = STOP_INDEX_END;
735 // In case of prebooking if person is not there/ comes to late for pickup set maximum waiting time:
736 SUMOTime earliestPickupTime = res->earliestPickupTime;
737 if (isPickup && earliestPickupTime >= 0) {
738 stop.waitUntil = earliestPickupTime;
739 // TODO: replace hard coded extension with parameter
740 stop.extension = static_cast<SUMOTime>(3 * 60 * 1000); // 3mins
741 }
742 stops.push_back(stop);
743}
744
745
746MSLane*
747MSDevice_Taxi::getStopLane(const MSEdge* edge, const std::string& action) {
748 const std::vector<MSLane*>* allowedLanes = edge->allowedLanes(myHolder.getVClass());
749 if (allowedLanes == nullptr) {
750 throw ProcessError("Taxi vehicle '" + myHolder.getID() + "' cannot stop on edge '" + edge->getID() + "' (" + action + ")");
751 }
752 return allowedLanes->front();
753}
754
755bool
757 return myState == EMPTY;
758}
759
760
761bool
763 return myCustomers.count(t) != 0;
764}
765
766
767void
768MSDevice_Taxi::updateMove(const SUMOTime traveltime, const double travelledDist) {
770 myOccupiedDistance += travelledDist;
771 myOccupiedTime += traveltime;
772 }
773 if (isEmpty()) {
774 if (MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
775 myIdleAlgorithm->idle(this);
776 if (myRoutingDevice != nullptr) {
777 // prevent rerouting during idling (#11079)
779 }
780 } else if (!myReachedServiceEnd) {
781 WRITE_WARNINGF(TL("Taxi '%' reaches scheduled end of service at time=%."), myHolder.getID(), time2string(SIMSTEP));
782 myReachedServiceEnd = true;
783 }
784 } else if (myRoutingDevice != nullptr) {
786 }
788 // limit duration of stop (but only for idling-related stops)
790 }
791#ifdef DEBUG_DISPATCH
793 std::cout << SIMTIME << " updateMove veh=" << myHolder.getID() << " myIsStopped=" << myIsStopped << " myHolderStopped=" << myHolder.isStopped() << " myState=" << myState << "\n";
794 }
795#endif
797}
798
799
800bool
802 double newPos, double /*newSpeed*/) {
803 updateMove(DELTA_T, newPos - oldPos);
804 return true; // keep the device
805}
806
807
808void
810 const double /* frontOnLane */,
811 const double timeOnLane,
812 const double /* meanSpeedFrontOnLane */,
813 const double /* meanSpeedVehicleOnLane */,
814 const double travelledDistanceFrontOnLane,
815 const double /* travelledDistanceVehicleOnLane */,
816 const double /* meanLengthOnLane */) {
817 updateMove(TIME2STEPS(timeOnLane), travelledDistanceFrontOnLane);
818}
819
820
821bool
823 if (isEmpty() && MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
824 myIdleAlgorithm->idle(this);
825 }
826 return true; // keep the device
827}
828
829
830void
832 myState |= OCCUPIED;
833 if (!hasFuturePickup()) {
834 myState &= ~PICKUP;
835 }
836 for (const Reservation* res : myCurrentReservations) {
837 for (const MSTransportable* cand : res->persons) {
838 if (cand == t) {
839 const_cast<Reservation*>(res)->state = Reservation::ONBOARD;
840 break;
841 }
842 }
843 }
844}
845
846
847void
850 myCustomers.erase(person);
852 myState &= ~OCCUPIED;
853 if (myHolder.getStops().size() > 1 && (myState & PICKUP) == 0) {
854 WRITE_WARNINGF(TL("All customers left vehicle '%' at time=% but there are % remaining stops"),
856 while (myHolder.getStops().size() > 1) {
858 }
859 }
860 }
861 if (isEmpty()) {
862 // cleanup
863 for (const Reservation* res : myCurrentReservations) {
865 }
866 myCurrentReservations.clear();
868 if (isEmpty()) {
869 if (MSGlobals::gUseMesoSim && MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
870 myIdleAlgorithm->idle(this);
871 }
872 }
873 } else {
874 // check whether a single reservation has been fulfilled
875 for (auto resIt = myCurrentReservations.begin(); resIt != myCurrentReservations.end();) {
876 bool fulfilled = true;
877 for (const MSTransportable* t : (*resIt)->persons) {
878 if (myCustomers.count(t) != 0) {
879 fulfilled = false;
880 break;
881 }
882 }
883 if (fulfilled) {
885 resIt = myCurrentReservations.erase(resIt);
886 } else {
887 ++resIt;
888 }
889 }
890 }
891}
892
893
894void
896 const std::string swapGroup = myHolder.getStringParam("device.taxi.swapGroup", false, "");
897 if (swapGroup != "") {
899 const double stopTime = myHolder.isStopped() ? MAX2(0.0, STEPS2TIME(myHolder.getNextStop().duration)) : 0;
900 double maxSaving = 0;
901 MSDevice_Taxi* bestSwap = nullptr;
902 for (MSDevice_Taxi* taxi : myFleet) {
903 if (taxi->getHolder().hasDeparted() && taxi->getState() == PICKUP
904 && taxi->getHolder().getStringParam("device.taxi.swapGroup", false, "") == swapGroup) {
905 SUMOVehicle& veh = taxi->getHolder();
906 const MSStop& stop = veh.getNextStop();
907 ConstMSEdgeVector toPickup(veh.getCurrentRouteEdge(), stop.edge + 1);
908 const double cost = router.recomputeCostsPos(toPickup, &veh, veh.getPositionOnLane(), stop.pars.endPos, SIMSTEP);
909 ConstMSEdgeVector toPickup2;
910 router.compute(myHolder.getEdge(), myHolder.getPositionOnLane(), *stop.edge, stop.pars.endPos, &myHolder, SIMSTEP, toPickup2, true);
911 if (!toPickup2.empty()) {
912 const double cost2 = router.recomputeCostsPos(toPickup2, &myHolder, myHolder.getPositionOnLane(), stop.pars.endPos, SIMSTEP);
913 const double saving = cost - cost2 - stopTime;
914 //std::cout << SIMTIME << " taxi=" << getID() << " other=" << veh.getID() << " cost=" << cost << " cost2=" << cost2 << " stopTime=" << stopTime << " saving=" << saving << " route1=" << toString(toPickup) << " route2=" << toString(toPickup2) << "\n";
915 if (saving > maxSaving) {
916 maxSaving = saving;
917 bestSwap = taxi;
918 }
919 }
920 }
921 }
922 if (maxSaving > SWAP_THRESHOLD) {
923#ifdef DEBUG_DISPATCH
924 if (DEBUG_COND) {
925 std::cout << SIMTIME << " taxi=" << myHolder.getID() << " swapWith=" << bestSwap->getHolder().getID() << " saving=" << maxSaving << " lastDispatch=";
926 for (const Reservation* res : bestSwap->myLastDispatch) {
927 std::cout << toString(res->persons) << "; ";
928 }
929 std::cout << "\n";
930 }
931#endif
933 bestSwap->myCurrentReservations.clear();
934 bestSwap->myCustomers.clear();
935 bestSwap->myState = EMPTY;
936 while (bestSwap->getHolder().hasStops()) {
937 bestSwap->getHolder().abortNextStop();
938 }
939 for (const Reservation* res : myCurrentReservations) {
940 myDispatcher->swappedRunning(res, this);
941 }
942 }
943 }
944}
945
946
947bool
949 for (const auto& stop : myHolder.getStops()) {
950 if (stop.reached) {
951 continue;
952 }
953 if (stop.pars.permitted.size() > 0) {
954 return true;
955 }
956 }
957 return false;
958}
959
960void
962 if (tripinfoOut != nullptr) {
963 tripinfoOut->openTag("taxi");
964 tripinfoOut->writeAttr("customers", toString(myCustomersServed));
965 tripinfoOut->writeAttr("occupiedDistance", toString(myOccupiedDistance));
966 tripinfoOut->writeAttr("occupiedTime", time2string(myOccupiedTime));
967 tripinfoOut->closeTag();
968 }
969}
970
971std::string
972MSDevice_Taxi::getParameter(const std::string& key) const {
973 if (key == "customers") {
975 } else if (key == "occupiedDistance") {
977 } else if (key == "occupiedTime") {
979 } else if (key == "state") {
980 return toString(myState);
981 } else if (key == "currentCustomers") {
983 } else if (key == "pickUpDuration") {
984 return myHolder.getStringParam("device.taxi.pickUpDuration", false, "0");
985 } else if (key == "dropOffDuration") {
986 return myHolder.getStringParam("device.taxi.dropOffDuration", false, "60");
987 }
988 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
989}
990
991
992void
993MSDevice_Taxi::setParameter(const std::string& key, const std::string& value) {
994 double doubleValue;
995 try {
996 doubleValue = StringUtils::toDouble(value);
997 } catch (NumberFormatException&) {
998 throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
999 }
1000 if (key == "pickUpDuration" || key == "dropOffDuration") {
1001 // store as generic vehicle parameters
1002 ((SUMOVehicleParameter&)myHolder.getParameter()).setParameter("device.taxi." + key, value);
1003 } else {
1004 UNUSED_PARAMETER(doubleValue);
1005 throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
1006 }
1007}
1008
1009bool
1010MSDevice_Taxi::compatibleLine(const std::string& taxiLine, const std::string& rideLine) {
1011 return ((taxiLine == rideLine && StringUtils::startsWith(rideLine, "taxi") && StringUtils::startsWith(taxiLine, "taxi"))
1012 || (taxiLine == TAXI_SERVICE && StringUtils::startsWith(rideLine, "taxi:"))
1013 || (rideLine == TAXI_SERVICE && StringUtils::startsWith(taxiLine, "taxi:")));
1014}
1015
1016bool
1020
1021
1022/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define TAXI_SERVICE
#define SWAP_THRESHOLD
#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:58
#define SIMSTEP
Definition SUMOTime.h:64
#define SIMTIME
Definition SUMOTime.h:65
#define TIME2STEPS(x)
Definition SUMOTime.h:60
@ 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:305
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:313
Base (microsim) event class.
Definition Command.h:50
The base class for microscopic and mesoscopic vehicles.
const std::list< MSStop > & getStops() const
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
void addCustomer(const MSTransportable *t, const Reservation *res)
add person after extending reservation
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
static void allCustomersErased()
signal the end of the simulation and the removal of all customers
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
void checkTaskSwap()
optionally swap tasks when a taxi becomes idle
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:114
void swappedRunning(const Reservation *res, MSDevice_Taxi *taxi)
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 SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouter() const
virtual Reservation * addReservation(MSTransportable *person, SUMOTime reservationTime, SUMOTime pickupTime, SUMOTime earliestPickupTime, const MSEdge *from, double fromPos, const MSStoppingPlace *fromStop, const MSEdge *to, double toPos, const MSStoppingPlace *tostop, std::string group, const std::string &line, int maxCapacity, int maxContainerCapacity)
add a new reservation
bool hasServableReservations()
check whether there are still (servable) reservations in the system
Definition MSDispatch.h:176
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:658
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:480
double getLength() const
return the length of the edge
Definition MSEdge.h:694
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:617
bool isInternal() const
Definition MSLane.cpp:2626
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:775
Notification
Definition of a vehicle state.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
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:128
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
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
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 override
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.
SUMOVehicle & getHolder() const
Returns the vehicle that holds this 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...
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
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:63
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 ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
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::set< std::string > awaitedPersons
IDs of persons the vehicle has to wait for until departing.
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
const MSEdge * to
Definition MSDispatch.h:84
double fromPos
Definition MSDispatch.h:82
std::string line
Definition MSDispatch.h:88
const MSEdge * from
Definition MSDispatch.h:81
SUMOTime earliestPickupTime
Definition MSDispatch.h:80
double toPos
Definition MSDispatch.h:85