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::map<SUMOVehicleClass, std::string> MSDevice_Taxi::myTaxiTypes;
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 oc.doRegister("device.taxi.vclasses", new Option_StringVector({"taxi"}));
108 oc.addSynonyme("device.taxi.vclasses", "taxi.vclasses");
109 oc.addDescription("device.taxi.vclasses", "Taxi Device", TL("Network permissions that can be accessed by taxis"));
110}
111
112
113void
114MSDevice_Taxi::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
116 if (equippedByDefaultAssignmentOptions(oc, "taxi", v, false)) {
117 // build the device
118 MSDevice_Taxi* device = new MSDevice_Taxi(v, "taxi_" + v.getID());
119 into.push_back(device);
120 myFleet.push_back(device);
121 if (v.getParameter().line == "") {
122 // automatically set the line so that persons are willing to enter
123 // (see MSStageDriving::isWaitingFor)
124 const_cast<SUMOVehicleParameter&>(v.getParameter()).line = TAXI_SERVICE;
125 }
126 const int personCapacity = v.getVehicleType().getPersonCapacity();
127 const int containerCapacity = v.getVehicleType().getContainerCapacity();
128 myMaxCapacity = MAX2(myMaxCapacity, personCapacity);
130 if (myTaxiTypes[v.getVClass()] == "") {
132 }
133 if ((gTaxiClasses & v.getVClass()) == 0) {
134 gTaxiClasses |= v.getVClass();
136 }
137 if (personCapacity < 1 && containerCapacity < 1) {
138 WRITE_WARNINGF(TL("Vehicle '%' with personCapacity % and containerCapacity % is not usable as taxi."), v.getID(), toString(personCapacity), toString(containerCapacity));
139 }
140 }
141}
142
143
144void
147 myDispatchPeriod = string2time(oc.getString("device.taxi.dispatch-period"));
148 // init dispatch algorithm
149 std::string algo = oc.getString("device.taxi.dispatch-algorithm");
150 Parameterised params;
151 params.setParametersStr(OptionsCont::getOptions().getString("device.taxi.dispatch-algorithm.params"), ":", ",");
152 if (algo == "greedy") {
154 } else if (algo == "greedyClosest") {
156 } else if (algo == "greedyShared") {
158 } else if (algo == "routeExtension") {
160 } else if (algo == "traci") {
162 } else {
163 throw ProcessError(TLF("Dispatch algorithm '%' is not known", algo));
164 }
166 // round to next multiple of myDispatchPeriod
168 const SUMOTime begin = string2time(oc.getString("begin"));
169 const SUMOTime delay = (myDispatchPeriod - ((now - begin) % myDispatchPeriod)) % myDispatchPeriod;
171}
172
173bool
174MSDevice_Taxi::isReservation(const std::set<std::string>& lines) {
175 return lines.size() == 1 && (
176 *lines.begin() == TAXI_SERVICE
177 || StringUtils::startsWith(*lines.begin(), TAXI_SERVICE_PREFIX));
178}
179
180void
182 const std::set<std::string>& lines,
183 SUMOTime reservationTime,
184 SUMOTime pickupTime,
185 SUMOTime earliestPickupTime,
186 const MSEdge* from, double fromPos,
187 const MSStoppingPlace* fromStop,
188 const MSEdge* to, double toPos,
189 const MSStoppingPlace* toStop,
190 const std::string& group) {
191 if (!isReservation(lines)) {
192 return;
193 }
194 if ((to->getPermissions() & gTaxiClasses) == 0) {
195 throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
196 + " '" + person->getID() + "' because destination edge '" + to->getID() + "'"
197 + " does not permit taxi access");
198 }
199 if ((from->getPermissions() & gTaxiClasses) == 0) {
200 throw ProcessError("Cannot add taxi reservation for " + std::string(person->isPerson() ? "person" : "container")
201 + " '" + person->getID() + "' because origin edge '" + from->getID() + "'"
202 + " does not permit taxi access");
203 }
204 if (myDispatchCommand == nullptr) {
205 initDispatch();
206 }
207 if (fromStop != nullptr && &fromStop->getLane().getEdge() == from) {
208 // pickup position should be at the stop-endPos
209 fromPos = fromStop->getEndLanePosition();
210 }
211 myDispatcher->addReservation(person, reservationTime, pickupTime, earliestPickupTime, from, fromPos, fromStop, to, toPos, toStop, group, *lines.begin(), myMaxCapacity, myMaxContainerCapacity);
212}
213
214void
216 const std::set<std::string>& lines,
217 const MSEdge* from, double fromPos,
218 const MSEdge* to, double toPos,
219 const std::string& group) {
220 if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
221 myDispatcher->removeReservation(person, from, fromPos, to, toPos, group);
222 }
223}
224
225void
227 const std::set<std::string>& lines,
228 const MSEdge* from, double fromPos,
229 const MSEdge* to, double toPos,
230 const std::string& group, double newFromPos) {
231 if (myDispatcher != nullptr && lines.size() == 1 && *lines.begin() == TAXI_SERVICE) {
232 myDispatcher->updateReservationFromPos(person, from, fromPos, to, toPos, group, newFromPos);
233 }
234}
235
236
239 std::vector<MSDevice_Taxi*> active;
240 for (MSDevice_Taxi* taxi : myFleet) {
241 if (taxi->getHolder().hasDeparted()) {
242 active.push_back(taxi);
243 }
244 }
245 myDispatcher->computeDispatch(currentTime, active);
246 return myDispatchPeriod;
247}
248
249bool
253
254void
256 if (myDispatcher != nullptr) {
257 delete myDispatcher;
258 myDispatcher = nullptr;
259 }
260 myDispatchCommand = nullptr;
261 myTaxiTypes.clear();
262}
263
264
265void
267 for (MSDevice_Taxi* taxi : myFleet) {
268 // disable taskSwap
269 taxi->myState = EMPTY;
270 }
271}
272
273
274const std::map<SUMOVehicleClass, std::string>&
276 const int numClasses = std::bitset<64>(gTaxiClasses).count();
277 if ((int)myTaxiTypes.size() < numClasses) {
278 for (const std::string& vClassName : OptionsCont::getOptions().getStringVector("device.taxi.vclasses")) {
280 if (myTaxiTypes[svc] == "") {
281 switch(svc) {
282 // @see MSVehicleControl::initDefaultTypes()
283 case SVC_TAXI:
285 break;
286 case SVC_RAIL:
288 break;
289 case SVC_BICYCLE:
291 break;
292 case SVC_PASSENGER:
294 break;
295 default: {
296 const std::string typeID = "DEFAULT_" + StringUtils::to_upper_case(vClassName) + "TYPE";
298 if (!vc.hasVType(typeID)) {
299 SUMOVTypeParameter tp(typeID, svc);
301 vc.addVType(t);
302 }
303 myTaxiTypes[svc] = typeID;;
304 }
305 }
306 }
307 }
308 }
309 return myTaxiTypes;
310}
311
312
313// ---------------------------------------------------------------------------
314// MSDevice_Taxi-methods
315// ---------------------------------------------------------------------------
316MSDevice_Taxi::MSDevice_Taxi(SUMOVehicle& holder, const std::string& id) :
317 MSVehicleDevice(holder, id) {
318 std::string defaultServiceEnd = toString(1e15);
319 const std::string algo = holder.getStringParam("device.taxi.idle-algorithm");
320 if (algo == "stop") {
322 } else if (algo == "randomCircling") {
324 // make sure simulation terminates
325 defaultServiceEnd = toString(STEPS2TIME(
328 : MSNet::getInstance()->getCurrentTimeStep()) + (3600 * 8));
329 } else if (algo == "taxistand") {
330 const std::string rerouterID = holder.getStringParam("device.taxi.stands-rerouter");
331 if (rerouterID.empty()) {
332 throw ProcessError("Idle algorithm '" + algo + "' requires a rerouter id to be defined using device param 'stands-rerouter' for vehicle '" + myHolder.getID() + "'");
333 }
334 if (MSTriggeredRerouter::getInstances().count(rerouterID) == 0) {
335 throw ProcessError("Unknown rerouter '" + rerouterID + "' when loading taxi stands for vehicle '" + myHolder.getID() + "'");
336 }
337 MSTriggeredRerouter* rerouter = MSTriggeredRerouter::getInstances().find(rerouterID)->second;
338 myIdleAlgorithm = new MSIdling_TaxiStand(rerouter);
339 } else {
340 throw ProcessError("Idle algorithm '" + algo + "' is not known for vehicle '" + myHolder.getID() + "'");
341 }
342 myServiceEnd = string2time(holder.getStringParam("device.taxi.end", false, defaultServiceEnd));
344}
345
346
348 myFleet.erase(std::find(myFleet.begin(), myFleet.end(), this));
349 // recompute myMaxCapacity
350 myMaxCapacity = 0;
352 for (MSDevice_Taxi* taxi : myFleet) {
353 myMaxCapacity = MAX2(myMaxCapacity, taxi->getHolder().getVehicleType().getPersonCapacity());
354 myMaxContainerCapacity = MAX2(myMaxContainerCapacity, taxi->getHolder().getVehicleType().getContainerCapacity());
355 }
356 delete myIdleAlgorithm;
357}
358
359
360bool
362 return myFleet.size() > 0;;
363}
364
365
366void
368 dispatchShared({&res, &res});
369}
370
371
372void
373MSDevice_Taxi::dispatchShared(std::vector<const Reservation*> reservations) {
374#ifdef DEBUG_DISPATCH
375 if (DEBUG_COND) {
376 std::cout << SIMTIME << " taxi=" << myHolder.getID() << " dispatch:\n";
377 for (const Reservation* res : reservations) {
378 std::cout << " persons=" << toString(res->persons) << "\n";
379 }
380 }
381#endif
382 myLastDispatch = reservations;
383 ConstMSEdgeVector tmpEdges;
384 StopParVector stops;
385 double lastPos = myHolder.getPositionOnLane();
386 const MSEdge* rerouteOrigin = *myHolder.getRerouteOrigin();
387 if (isEmpty()) {
388 // start fresh from the current edge
390 // parking stop must be ended normally
392 stop.duration = 0;
393 lastPos = stop.pars.endPos;
395 stop.triggered = false;
396 stop.containerTriggered = false;
397 stop.joinTriggered = false;
399 }
400 // prevent unauthorized/premature entry
401 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).permitted.insert("");
402 while (myHolder.getStops().size() > 1) {
404 }
405 } else {
406 while (myHolder.hasStops()) {
407 // in meso there might be more than 1 stop at this point
409 }
410 assert(!myHolder.hasStops());
411 }
412 tmpEdges.push_back(myHolder.getEdge());
413 if (myHolder.getEdge() != rerouteOrigin) {
414 tmpEdges.push_back(rerouteOrigin);
415 }
416 } else {
417 assert(myHolder.hasStops());
418 // check how often existing customers appear in the new reservations
419 std::map<const MSTransportable*, int> nOccur;
420 for (const Reservation* res : reservations) {
421 for (const MSTransportable* person : res->persons) {
422 if (myCustomers.count(person) != 0) {
423 nOccur[person] += 1;
424 if (myCurrentReservations.count(res) == 0) {
425 throw ProcessError(TLF("Invalid Re-dispatch for existing customer '%' with a new reservation", person->getID()));
426 }
427 }
428 }
429 }
430#ifdef DEBUG_DISPATCH
431 if (DEBUG_COND) {
432 for (auto item : nOccur) {
433 std::cout << " previousCustomer=" << item.first->getID() << " occurs=" << item.second << "\n";
434 }
435 }
436#endif
437 if (nOccur.size() == 0) {
438 // no overlap with existing customers - extend route
439 tmpEdges = myHolder.getRoute().getEdges();
440 lastPos = myHolder.getStops().back().pars.endPos;
441#ifdef DEBUG_DISPATCH
442 if (DEBUG_COND) {
443 std::cout << " re-dispatch with route-extension\n";
444 }
445#endif
446 } else if (nOccur.size() == myCustomers.size()) {
447 // redefine route (verify correct number of mentions)
448 std::set<const MSTransportable*> onBoard;
449 const std::vector<MSTransportable*>& onBoardP = myHolder.getPersons();
450 const std::vector<MSTransportable*>& onBoardC = myHolder.getContainers();
451 onBoard.insert(onBoardP.begin(), onBoardP.end());
452 onBoard.insert(onBoardC.begin(), onBoardC.end());
453 std::set<const MSTransportable*> redundantPickup;
454 for (auto item : nOccur) {
455 if (item.second == 1) {
456 // customers must already be on board
457 if (onBoard.count(item.first) == 0) {
458 throw ProcessError(TLF("Re-dispatch did not mention pickup for existing customer '%'", item.first->getID()));
459 }
460 } else if (item.second == 2) {
461 if (onBoard.count(item.first) == 0) {
462 // treat like a new customer
463 // TODO: need to be checked
464 myCustomers.erase(item.first);
465 } else {
466 redundantPickup.insert(item.first);
467 }
468 } else {
469 throw ProcessError("Re-dispatch mentions existing customer '" + item.first->getID() + "' " + toString(item.second) + " times");
470 }
471 }
472 // remove redundancy
473 if (!redundantPickup.empty()) {
474 for (auto it = reservations.begin(); it != reservations.end();) {
475 bool isRedundant = false;
476 for (const MSTransportable* person : (*it)->persons) {
477 if (redundantPickup.count(person) != 0) {
478 isRedundant = true;
479 break;
480 }
481 }
482 if (isRedundant) {
483 for (const MSTransportable* person : (*it)->persons) {
484 redundantPickup.erase(person);
485 }
486 it = reservations.erase(it);
487 } else {
488 it++;
489 }
490 }
491 }
492 while (myHolder.hasStops()) {
494 }
495 tmpEdges.push_back(myHolder.getEdge());
496 if (myHolder.getEdge() != rerouteOrigin) {
497 tmpEdges.push_back(rerouteOrigin);
498 }
499#ifdef DEBUG_DISPATCH
500 if (DEBUG_COND) {
501 std::cout << " re-dispatch from scratch\n";
502 }
503#endif
504 } else {
505 // inconsistent re-dispatch
506 std::vector<std::string> missing;
507 for (const MSTransportable* c : myCustomers) {
508 if (nOccur.count(c) == 0) {
509 missing.push_back(c->getID());
510 }
511 }
512 throw ProcessError("Re-dispatch did mention some customers but failed to mention " + joinToStringSorting(missing, " "));
513 }
514 }
515
517 bool hasPickup = false;
518 for (const Reservation* res : reservations) {
519 myCurrentReservations.insert(res);
520 bool isPickup = false;
521 for (const MSTransportable* person : res->persons) {
522 if (myCustomers.count(person) == 0) {
523 myCustomers.insert(person);
524 isPickup = true;
525 hasPickup = true;
526 }
527 }
528 if (isPickup) {
529 prepareStop(tmpEdges, stops, lastPos, res->from, res->fromPos, res->fromStop, "pickup " + toString(res->persons) + " (" + res->id + ")", res, isPickup);
530 for (const MSTransportable* const transportable : res->persons) {
531 if (transportable->isPerson()) {
532 stops.back().triggered = true;
533 } else {
534 stops.back().containerTriggered = true;
535 }
536 stops.back().permitted.insert(transportable->getID());
537 }
538 // proof this lines: Is needed for pre-booking?
539 std::set<const MSTransportable*> persons = res->persons;
540 for (auto itr = persons.begin(); itr != persons.end(); itr++) {
541 stops.back().awaitedPersons.insert((*itr)->getID());
542 }
543
544 stops.back().parametersSet |= STOP_PERMITTED_SET;
545 if (stops.back().duration == -1) {
546 // keep dropOffDuration if the stop is dropOff and pickUp
547 stops.back().duration = TIME2STEPS(myHolder.getFloatParam("device.taxi.pickUpDuration", false, 0));
548 }
549 } else {
550 prepareStop(tmpEdges, stops, lastPos, res->to, res->toPos, res->toStop, "dropOff " + toString(res->persons) + " (" + res->id + ")", res, isPickup);
551 stops.back().duration = TIME2STEPS(myHolder.getFloatParam("device.taxi.dropOffDuration", false, 60)); // pay and collect bags
552 }
553 }
554#ifdef DEBUG_DISPATCH
555 if (DEBUG_COND) {
556 std::cout << " tmpEdges=" << toString(tmpEdges) << "\n";
557 }
558#endif
559 if (!myHolder.replaceRouteEdges(tmpEdges, -1, 0, "taxi:prepare_dispatch", false, false, false)) {
560 throw ProcessError("Route replacement for taxi dispatch failed for vehicle '" + myHolder.getID()
561 + "' at time=" + time2string(t) + ".");
562 }
563#ifdef DEBUG_DISPATCH
564 if (DEBUG_COND) std::cout << " replacedRoute=" << toString(tmpEdges)
565 << "\n actualRoute=" << toString(myHolder.getRoute().getEdges()) << "\n";
566#endif
567 for (SUMOVehicleParameter::Stop& stop : stops) {
568 std::string error;
569 if (!myHolder.addStop(stop, error)) {
570 WRITE_WARNINGF(TL("Could not add taxi stop for %, desc=% time=% error=%"), myHolder.getID(), stop.actType, time2string(t), error)
571 }
572 }
574 // SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = myHolder.getInfluencer().getRouterTT(veh->getRNGIndex())
575 myHolder.reroute(t, "taxi:dispatch", router, false);
576#ifdef DEBUG_DISPATCH
577 if (DEBUG_COND) {
578 std::cout << "\n finalRoute=" << toString(myHolder.getRoute().getEdges()) << " routeIndex=" << myHolder.getRoutePosition() << "\n";
579 }
580#endif
581 if (hasPickup) {
582 myState |= PICKUP;
583 }
584}
585
586
587void
589 // check if taxi has stopped
590 if (myHolder.getNextStopParameter() == nullptr) {
591 return;
592 }
593 // find customers of the current stop
594 std::set<const MSTransportable*> customersToBeRemoved;
595 std::set<const MSTransportable*> onBoard;
596 onBoard.insert(myHolder.getPersons().begin(), myHolder.getPersons().end());
597 onBoard.insert(myHolder.getContainers().begin(), myHolder.getContainers().end());
598 for (std::string tID : myHolder.getNextStopParameter()->permitted) {
599 for (auto t : myCustomers) {
600 if (t->getID() == tID && onBoard.count(t) == 0) {
601 customersToBeRemoved.insert(t);
602 }
603 }
604 }
605 if (!customersToBeRemoved.empty()) {
606 WRITE_WARNINGF(TL("Taxi '%' aborts waiting for customers: % at time=%."),
607 myHolder.getID(), toString(customersToBeRemoved), time2string(SIMSTEP));
608 }
609 for (auto t : customersToBeRemoved) {
611 }
612}
613
614
615bool
617#ifdef DEBUG_CANCEL
618 if (DEBUG_COND) {
619 std::cout << SIMTIME << " taxi=" << myHolder.getID() << " cancelCustomer " << t->getID() << "\n";
620 }
621#endif
622
623 // is the given transportable a customer of the reservations?
624 if (myCustomers.count(t) == 0) {
625 return false;
626 }
627 myCustomers.erase(t);
628 // check whether a single reservation has been fulfilled or another customer is part of the reservation
629 for (auto resIt = myCurrentReservations.begin(); resIt != myCurrentReservations.end();) {
630 bool fulfilled = false;
631 if ((*resIt)->persons.size() == 1 && (*resIt)->persons.count(t) != 0) {
632 // the reservation contains only the customer
633 fulfilled = true;
634 }
635 if (fulfilled) {
636 const Reservation* res = *resIt;
637 // remove reservation from the current dispatch
638 for (auto it = myLastDispatch.begin(); it != myLastDispatch.end();) {
639 if (*it == res) {
640 it = myLastDispatch.erase(it);
641 } else {
642 ++it;
643 }
644 }
645 // remove reservation from the served reservations
646 resIt = myCurrentReservations.erase(resIt);
647 // delete the reservation
649 } else {
650 ++resIt;
651 }
652 }
653 myState &= ~PICKUP; // remove state PICKUP
654 for (const Reservation* res : myCurrentReservations) {
655 // if there is another pickup in the dispatch left, add the state PICKUP
656 if (std::count(myLastDispatch.begin(), myLastDispatch.end(), res) == 2) {
657 myState |= PICKUP; // add state PICKUP
658 }
659 }
660 // we also have to clean reservations from myLastDispatch where the customers arrived in the meantime
661 for (auto it = myLastDispatch.begin(); it != myLastDispatch.end();) {
662 if (myCurrentReservations.count(*it) == 0) {
663 it = myLastDispatch.erase(it);
664 } else {
665 ++it;
666 }
667 }
668 // if there are reservations left, go on with the dispatch
669 // in meso, wait for the next dispatch cycle to avoid updating stops in this stage
672 }
673 return true;
674}
675
676
677void
679 myCustomers.insert(t);
680 MSBaseVehicle& veh = dynamic_cast<MSBaseVehicle&>(myHolder);
681 for (const MSStop& stop : veh.getStops()) {
682 SUMOVehicleParameter::Stop& pars = const_cast<SUMOVehicleParameter::Stop&>(stop.pars);
683 //std::cout << " sE=" << (*stop.edge)->getID() << " sStart=" << pars.startPos << " sEnd=" << pars.endPos << " rFrom=" <<
684 // res->from->getID() << " rTo=" << res->to->getID() << " rFromPos=" << res->fromPos << " resToPos=" << res->toPos << "\n";
685 if (*stop.edge == res->from
686 && pars.startPos <= res->fromPos
687 && pars.endPos >= res->fromPos) {
688 pars.awaitedPersons.insert(t->getID());
689 pars.permitted.insert(t->getID());
690 pars.actType += " +" + t->getID();
691 } else if (*stop.edge == res->to
692 && pars.startPos <= res->toPos
693 && pars.endPos >= res->toPos) {
694 pars.actType += " +" + t->getID();
695 break;
696 }
697 }
698}
699
700
701void
703 StopParVector& stops,
704 double& lastPos, const MSEdge* stopEdge, double stopPos,
705 const MSStoppingPlace* stopPlace,
706 const std::string& action, const Reservation* res, const bool isPickup) {
707 assert(!edges.empty());
708 if (stopPlace != nullptr && &stopPlace->getLane().getEdge() == stopEdge) {
709 stopPos = stopPlace->getEndLanePosition();
710 }
711 if (stopPos < lastPos && stopPos + NUMERICAL_EPS >= lastPos) {
712 stopPos = lastPos;
713 }
714 bool addedEdge = false;
715
716 if (stops.empty()) {
717 // check brakeGap
718 double distToStop = stopPos - lastPos;
719 const double brakeGap = myHolder.getBrakeGap();
720 if (myHolder.getLane() != nullptr && myHolder.getLane()->isInternal()) {
721 distToStop += myHolder.getLane()->getLength();
722 }
723 if (stopEdge != edges.back()) {
724 distToStop += edges.back()->getLength();
725 if (distToStop < brakeGap) {
726 // the distance between current edge and stop edge may be small
728 ConstMSEdgeVector toFirstStop;
729 router.compute(edges.back(), stopEdge, &myHolder, SIMSTEP, toFirstStop, true);
730 for (int i = 1; i < (int)toFirstStop.size() - 1; i++) {
731 distToStop += toFirstStop[i]->getLength();
732 }
733 }
734 }
735 if (distToStop < brakeGap) {
736 // circle back to stopEdge
737 //std::cout << SIMTIME << " taxi=" << getID() << " brakeGap=" << brakeGap << " distToStop=" << distToStop << "\n";
738 edges.push_back(stopEdge);
739 addedEdge = true;
740 }
741 }
742
743 if (stopEdge == edges.back() && !stops.empty()) {
744 if (stopPos >= lastPos && stopPos <= stops.back().endPos) {
745 // no new stop and no adaption needed
746 stops.back().actType += "," + action;
747 return;
748 }
749 if (stopPos >= lastPos && stopPos <= lastPos + myHolder.getVehicleType().getLength()) {
750 // stop length adaption needed
751 stops.back().endPos = MIN2(lastPos + myHolder.getVehicleType().getLength(), stopEdge->getLength());
752 stops.back().actType += "," + action;
753 return;
754 }
755 }
756 if (!addedEdge && (stopEdge != edges.back() || stopPos < lastPos)) {
757 //std::cout << SIMTIME << " stopPos=" << stopPos << " lastPos=" << lastPos << "\n";
758 edges.push_back(stopEdge);
759 }
760 lastPos = stopPos;
762 stop.lane = getStopLane(stopEdge, action)->getID();
763 if (stopPlace != nullptr && &stopPlace->getLane().getEdge() == stopEdge) {
764 stop.startPos = stopPlace->getBeginLanePosition();
765 stop.endPos = stopPlace->getEndLanePosition();
766 const SumoXMLTag tag = stopPlace->getElement();
767 if (tag == SUMO_TAG_BUS_STOP || tag == SUMO_TAG_TRAIN_STOP) {
768 stop.busstop = stopPlace->getID();
769 } else if (tag == SUMO_TAG_PARKING_AREA) {
770 stop.parkingarea = stopPlace->getID();
771 } else if (tag == SUMO_TAG_CONTAINER_STOP) {
772 stop.containerstop = stopPlace->getID();
773 }
774 } else {
775 stop.startPos = stopPos;
776 stop.endPos = MAX2(stopPos, MIN2(myHolder.getVehicleType().getLength(), stopEdge->getLength()));
777 }
778 stop.parking = SUMOVehicleParameter::parseParkingType(myHolder.getStringParam("device.taxi.parking", false, "true"));
779 stop.actType = action;
780 stop.index = STOP_INDEX_END;
781 // In case of prebooking if person is not there/ comes to late for pickup set maximum waiting time:
782 SUMOTime earliestPickupTime = res->earliestPickupTime;
783 if (isPickup && earliestPickupTime >= 0) {
784 stop.waitUntil = earliestPickupTime;
785 // TODO: replace hard coded extension with parameter
786 stop.extension = static_cast<SUMOTime>(3 * 60 * 1000); // 3mins
787 }
788 stops.push_back(stop);
789}
790
791
792MSLane*
793MSDevice_Taxi::getStopLane(const MSEdge* edge, const std::string& action) {
794 const std::vector<MSLane*>* allowedLanes = edge->allowedLanes(myHolder.getVClass());
795 if (allowedLanes == nullptr) {
796 throw ProcessError("Taxi vehicle '" + myHolder.getID() + "' cannot stop on edge '" + edge->getID() + "' (" + action + ")");
797 }
798 return allowedLanes->front();
799}
800
801bool
803 return myState == EMPTY;
804}
805
806
807bool
809 return myCustomers.count(t) != 0;
810}
811
812
813void
814MSDevice_Taxi::updateMove(const SUMOTime traveltime, const double travelledDist) {
816 myOccupiedDistance += travelledDist;
817 myOccupiedTime += traveltime;
818 }
819 if (isEmpty()) {
820 if (MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
821 myIdleAlgorithm->idle(this);
822 if (myRoutingDevice != nullptr) {
823 // prevent rerouting during idling (#11079)
825 }
826 } else if (!myReachedServiceEnd) {
827 WRITE_WARNINGF(TL("Taxi '%' reaches scheduled end of service at time=%."), myHolder.getID(), time2string(SIMSTEP));
828 myReachedServiceEnd = true;
829 }
830 } else if (myRoutingDevice != nullptr) {
832 }
834 // limit duration of stop (but only for idling-related stops)
836 }
837#ifdef DEBUG_DISPATCH
839 std::cout << SIMTIME << " updateMove veh=" << myHolder.getID() << " myIsStopped=" << myIsStopped << " myHolderStopped=" << myHolder.isStopped() << " myState=" << myState << "\n";
840 }
841#endif
843}
844
845
846bool
848 double newPos, double /*newSpeed*/) {
849 updateMove(DELTA_T, newPos - oldPos);
850 return true; // keep the device
851}
852
853
854void
856 const double /* frontOnLane */,
857 const double timeOnLane,
858 const double /* meanSpeedFrontOnLane */,
859 const double /* meanSpeedVehicleOnLane */,
860 const double travelledDistanceFrontOnLane,
861 const double /* travelledDistanceVehicleOnLane */,
862 const double /* meanLengthOnLane */) {
863 updateMove(TIME2STEPS(timeOnLane), travelledDistanceFrontOnLane);
864}
865
866
867bool
869 if (isEmpty() && MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
870 myIdleAlgorithm->idle(this);
871 }
872 return true; // keep the device
873}
874
875
876void
878 myState |= OCCUPIED;
879 if (!hasFuturePickup()) {
880 myState &= ~PICKUP;
881 }
882 for (const Reservation* res : myCurrentReservations) {
883 for (const MSTransportable* cand : res->persons) {
884 if (cand == t) {
885 const_cast<Reservation*>(res)->state = Reservation::ONBOARD;
886 break;
887 }
888 }
889 }
890}
891
892
893void
896 myCustomers.erase(person);
898 myState &= ~OCCUPIED;
899 if (myHolder.getStops().size() > 1 && (myState & PICKUP) == 0) {
900 WRITE_WARNINGF(TL("All customers left vehicle '%' at time=% but there are % remaining stops"),
902 while (myHolder.getStops().size() > 1) {
904 }
905 }
906 }
907 if (isEmpty()) {
908 // cleanup
909 for (const Reservation* res : myCurrentReservations) {
911 }
912 myCurrentReservations.clear();
914 if (isEmpty()) {
915 if (MSGlobals::gUseMesoSim && MSNet::getInstance()->getCurrentTimeStep() < myServiceEnd) {
916 myIdleAlgorithm->idle(this);
917 }
918 }
919 } else {
920 // check whether a single reservation has been fulfilled
921 for (auto resIt = myCurrentReservations.begin(); resIt != myCurrentReservations.end();) {
922 bool fulfilled = true;
923 for (const MSTransportable* t : (*resIt)->persons) {
924 if (myCustomers.count(t) != 0) {
925 fulfilled = false;
926 break;
927 }
928 }
929 if (fulfilled) {
931 resIt = myCurrentReservations.erase(resIt);
932 } else {
933 ++resIt;
934 }
935 }
936 }
937}
938
939
940void
942 const std::string swapGroup = myHolder.getStringParam("device.taxi.swapGroup", false, "");
943 if (swapGroup != "") {
945 const double stopTime = myHolder.isStopped() ? MAX2(0.0, STEPS2TIME(myHolder.getNextStop().duration)) : 0;
946 double maxSaving = 0;
947 MSDevice_Taxi* bestSwap = nullptr;
948 for (MSDevice_Taxi* taxi : myFleet) {
949 if (taxi->getHolder().hasDeparted() && taxi->getState() == PICKUP
950 && taxi->getHolder().getStringParam("device.taxi.swapGroup", false, "") == swapGroup) {
951 SUMOVehicle& veh = taxi->getHolder();
952 const MSStop& stop = veh.getNextStop();
953 ConstMSEdgeVector toPickup(veh.getCurrentRouteEdge(), stop.edge + 1);
954 const double cost = router.recomputeCostsPos(toPickup, &veh, veh.getPositionOnLane(), stop.pars.endPos, SIMSTEP);
955 ConstMSEdgeVector toPickup2;
956 router.compute(myHolder.getEdge(), myHolder.getPositionOnLane(), *stop.edge, stop.pars.endPos, &myHolder, SIMSTEP, toPickup2, true);
957 if (!toPickup2.empty()) {
958 const double cost2 = router.recomputeCostsPos(toPickup2, &myHolder, myHolder.getPositionOnLane(), stop.pars.endPos, SIMSTEP);
959 const double saving = cost - cost2 - stopTime;
960 //std::cout << SIMTIME << " taxi=" << getID() << " other=" << veh.getID() << " cost=" << cost << " cost2=" << cost2 << " stopTime=" << stopTime << " saving=" << saving << " route1=" << toString(toPickup) << " route2=" << toString(toPickup2) << "\n";
961 if (saving > maxSaving) {
962 maxSaving = saving;
963 bestSwap = taxi;
964 }
965 }
966 }
967 }
968 if (maxSaving > SWAP_THRESHOLD) {
969#ifdef DEBUG_DISPATCH
970 if (DEBUG_COND) {
971 std::cout << SIMTIME << " taxi=" << myHolder.getID() << " swapWith=" << bestSwap->getHolder().getID() << " saving=" << maxSaving << " lastDispatch=";
972 for (const Reservation* res : bestSwap->myLastDispatch) {
973 std::cout << toString(res->persons) << "; ";
974 }
975 std::cout << "\n";
976 }
977#endif
979 bestSwap->myCurrentReservations.clear();
980 bestSwap->myCustomers.clear();
981 bestSwap->myState = EMPTY;
982 while (bestSwap->getHolder().hasStops()) {
983 bestSwap->getHolder().abortNextStop();
984 }
985 for (const Reservation* res : myCurrentReservations) {
986 myDispatcher->swappedRunning(res, this);
987 }
988 }
989 }
990}
991
992
993bool
995 for (const auto& stop : myHolder.getStops()) {
996 if (stop.reached) {
997 continue;
998 }
999 if (stop.pars.permitted.size() > 0) {
1000 return true;
1001 }
1002 }
1003 return false;
1004}
1005
1006void
1008 if (tripinfoOut != nullptr) {
1009 tripinfoOut->openTag("taxi");
1010 tripinfoOut->writeAttr("customers", toString(myCustomersServed));
1011 tripinfoOut->writeAttr("occupiedDistance", toString(myOccupiedDistance));
1012 tripinfoOut->writeAttr("occupiedTime", time2string(myOccupiedTime));
1013 tripinfoOut->closeTag();
1014 }
1015}
1016
1017std::string
1018MSDevice_Taxi::getParameter(const std::string& key) const {
1019 if (key == "customers") {
1021 } else if (key == "occupiedDistance") {
1023 } else if (key == "occupiedTime") {
1025 } else if (key == "state") {
1026 return toString(myState);
1027 } else if (key == "currentCustomers") {
1029 } else if (key == "pickUpDuration") {
1030 return myHolder.getStringParam("device.taxi.pickUpDuration", false, "0");
1031 } else if (key == "dropOffDuration") {
1032 return myHolder.getStringParam("device.taxi.dropOffDuration", false, "60");
1033 }
1034 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
1035}
1036
1037
1038void
1039MSDevice_Taxi::setParameter(const std::string& key, const std::string& value) {
1040 double doubleValue;
1041 try {
1042 doubleValue = StringUtils::toDouble(value);
1043 } catch (NumberFormatException&) {
1044 throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
1045 }
1046 if (key == "pickUpDuration" || key == "dropOffDuration") {
1047 // store as generic vehicle parameters
1048 ((SUMOVehicleParameter&)myHolder.getParameter()).setParameter("device.taxi." + key, value);
1049 } else {
1050 UNUSED_PARAMETER(doubleValue);
1051 throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
1052 }
1053}
1054
1055bool
1056MSDevice_Taxi::compatibleLine(const std::string& taxiLine, const std::string& rideLine) {
1057 return ((taxiLine == rideLine && StringUtils::startsWith(rideLine, "taxi") && StringUtils::startsWith(taxiLine, "taxi"))
1058 || (taxiLine == TAXI_SERVICE && StringUtils::startsWith(rideLine, "taxi:"))
1059 || (rideLine == TAXI_SERVICE && StringUtils::startsWith(taxiLine, "taxi:")));
1060}
1061
1062bool
1066
1067
1068/****************************************************************************/
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
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
const std::string DEFAULT_TAXITYPE_ID
const std::string DEFAULT_RAILTYPE_ID
const std::string DEFAULT_VTYPE_ID
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_RAIL
vehicle is a not electrified rail
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TAXI
vehicle is a taxi
const std::string DEFAULT_BIKETYPE_ID
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)
int gTaxiClasses
Definition StdDefs.cpp:38
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:329
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
std::string joinNamedToStringSorting(const std::set< T * > &ns, const T_BETWEEN &between)
Definition ToString.h:337
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
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
static const std::map< SUMOVehicleClass, std::string > & getTaxiTypes()
return all types that are known to carry a taxi device (or the default type if no devices are initial...
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.
static std::map< SUMOVehicleClass, std::string > myTaxiTypes
storing only one type per vClass
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:2641
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:199
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:495
void resetIntermodalRouter() const
force reconstruction of intermodal network
Definition MSNet.cpp:1685
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:392
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
The class responsible for building and deletion of vehicles.
bool hasVType(const std::string &id) const
Asks for existence of a vehicle type.
bool addVType(MSVehicleType *vehType)
Adds a vehicle type.
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
SUMOVehicle & getHolder() const
Returns the vehicle that holds this device.
The car-following model and parameter.
int getPersonCapacity() const
Get this vehicle type's person capacity.
const std::string & getID() const
Returns the name of the vehicle type.
static MSVehicleType * build(SUMOVTypeParameter &from, const std::string &fileName="")
Builds the microsim vehicle type described by the given parameter.
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 addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
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.
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
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.
Structure representing possible vehicle parameter.
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 std::string to_upper_case(const std::string &str)
Transfers the content to upper case.
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