Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSTriggeredRerouter.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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/****************************************************************************/
22// Reroutes vehicles passing an edge
23/****************************************************************************/
24#include <config.h>
25
26#include <string>
27#include <algorithm>
28#ifdef HAVE_FOX
30#endif
44#include <microsim/MSLane.h>
45#include <microsim/MSLink.h>
46#include <microsim/MSVehicle.h>
48#include <microsim/MSRoute.h>
49#include <microsim/MSEdge.h>
51#include <microsim/MSNet.h>
53#include <microsim/MSGlobals.h>
55#include <microsim/MSStop.h>
61#include "MSTriggeredRerouter.h"
62
63#include <mesosim/MELoop.h>
64#include <mesosim/MESegment.h>
65
66//#define DEBUG_REROUTER
67//#define DEBUG_OVERTAKING
68#define DEBUGCOND(veh) (veh.isSelected())
69//#define DEBUGCOND(veh) (true)
70//#define DEBUGCOND(veh) (veh.getID() == "")
71
73#define DEFAULT_PRIO_OVERTAKER 1
74#define DEFAULT_PRIO_OVERTAKEN 0.001
75
76// ===========================================================================
77// static member definition
78// ===========================================================================
79MSEdge MSTriggeredRerouter::mySpecialDest_keepDestination("MSTriggeredRerouter_keepDestination", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", "", -1, 0);
80MSEdge MSTriggeredRerouter::mySpecialDest_terminateRoute("MSTriggeredRerouter_terminateRoute", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", "", -1, 0);
82std::map<std::string, MSTriggeredRerouter*> MSTriggeredRerouter::myInstances;
83
84
85// ===========================================================================
86// method definitions
87// ===========================================================================
89 const MSEdgeVector& edges, double prob, bool off, bool optional,
90 SUMOTime timeThreshold, const std::string& vTypes, const Position& pos, const double radius) :
91 Named(id),
93 MSStoppingPlaceRerouter("parking"),
94 myEdges(edges),
95 myProbability(prob),
96 myUserProbability(prob),
97 myAmInUserMode(false),
98 myAmOptional(optional),
99 myPosition(pos),
100 myRadius(radius),
101 myTimeThreshold(timeThreshold),
102 myHaveParkProbs(false),
103 myHaveClosingUntil(false)
104{
105 myInstances[id] = this;
106 // build actors
107 for (const MSEdge* const e : edges) {
110 }
111 for (MSLane* const lane : e->getLanes()) {
112 lane->addMoveReminder(this);
113 }
114 }
115 if (off) {
116 setUserMode(true);
118 }
119 const std::vector<std::string> vt = StringTokenizer(vTypes).getVector();
120 myVehicleTypes.insert(vt.begin(), vt.end());
122 myPosition = edges.front()->getLanes()[0]->getShape()[0];
123 }
124}
125
126
130
131
132// ------------ loading begin
133void
135 const SUMOSAXAttributes& attrs) {
136 if (element == SUMO_TAG_INTERVAL) {
137 bool ok = true;
142 throw ProcessError(TLF("rerouter '%': interval end % is not after begin %.", getID(),
145 }
146 }
147 if (element == SUMO_TAG_DEST_PROB_REROUTE) {
148 // by giving probabilities of new destinations
149 // get the destination edge
150 std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
151 if (dest == "") {
152 throw ProcessError(TLF("rerouter '%': destProbReroute has no destination edge id.", getID()));
153 }
154 MSEdge* to = MSEdge::dictionary(dest);
155 if (to == nullptr) {
156 if (dest == "keepDestination") {
158 } else if (dest == "terminateRoute") {
160 } else {
161 throw ProcessError(TLF("rerouter '%': Destination edge '%' is not known.", getID(), dest));
162 }
163 }
164 // get the probability to reroute
165 bool ok = true;
166 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
167 if (!ok) {
168 throw ProcessError();
169 }
170 if (prob < 0) {
171 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for destination '%' is negative (must not).", getID(), dest));
172 }
173 // add
175 }
176
177 if (element == SUMO_TAG_CLOSING_REROUTE) {
178 // by closing edge
179 const std::string& closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
180 MSEdge* const closedEdge = MSEdge::dictionary(closed_id);
181 if (closedEdge == nullptr) {
182 throw ProcessError(TLF("rerouter '%': Edge '%' to close is not known.", getID(), closed_id));
183 }
184 bool ok;
185 SVCPermissions permissions = SVC_UNSPECIFIED;
187 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
188 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
189 permissions = parseVehicleClasses(allow, disallow);
190 }
191 const SUMOTime until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, TIME2STEPS(-1));
192 myParsedRerouteInterval.closed[closedEdge] = std::make_pair(permissions, STEPS2TIME(until));
193 myHaveClosingUntil |= until > 0;
194 }
195
196 if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
197 // by closing lane
198 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
199 MSLane* closedLane = MSLane::dictionary(closed_id);
200 if (closedLane == nullptr) {
201 throw ProcessError(TLF("rerouter '%': Lane '%' to close is not known.", getID(), closed_id));
202 }
203 SVCPermissions permissions = SVC_AUTHORITY;
205 bool ok;
206 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
207 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
208 permissions = parseVehicleClasses(allow, disallow);
209 }
210 myParsedRerouteInterval.closedLanes[closedLane] = permissions;
211 }
212
213 if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
214 // by explicit rerouting using routes
215 // check if route exists
216 std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
217 if (routeStr == "") {
218 throw ProcessError(TLF("rerouter '%': routeProbReroute has no alternative route id.", getID()));
219 }
220 ConstMSRoutePtr route = MSRoute::dictionary(routeStr);
221 if (route == nullptr) {
222 throw ProcessError(TLF("rerouter '%': Alternative route '%' does not exist.", getID(), routeStr));
223 }
224
225 // get the probability to reroute
226 bool ok = true;
227 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
228 if (!ok) {
229 throw ProcessError();
230 }
231 if (prob < 0) {
232 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for alternative route '%' is negative (must not).", getID(), routeStr));
233 }
234 // add
236 }
237
238 if (element == SUMO_TAG_PARKING_AREA_REROUTE) {
239 std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
240 if (parkingarea == "") {
241 throw ProcessError(TLF("rerouter '%': parkingAreaReroute requires a parkingArea id.", getID()));
242 }
244 if (pa == nullptr) {
245 throw ProcessError(TLF("rerouter '%': parkingArea '%' is not known.", getID(), parkingarea));
246 }
247 // get the probability to reroute
248 bool ok = true;
249 const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
250 if (!ok) {
251 throw ProcessError();
252 }
253 if (prob < 0) {
254 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for parkingArea '%' is negative (must not).", getID(), parkingarea));
255 }
256 const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
257 // add
258 myParsedRerouteInterval.parkProbs.add(std::make_pair(pa, visible), prob);
259 myHaveParkProbs = true;
260 }
261
262 if (element == SUMO_TAG_VIA_PROB_REROUTE) {
263 // by giving probabilities of vias
264 std::string viaID = attrs.getStringSecure(SUMO_ATTR_ID, "");
265 if (viaID == "") {
266 throw ProcessError(TLF("rerouter '%': No via edge id given.", getID()));
267 }
268 MSEdge* const via = MSEdge::dictionary(viaID);
269 if (via == nullptr) {
270 throw ProcessError(TLF("rerouter '%': Via Edge '%' is not known.", getID(), viaID));
271 }
272 // get the probability to reroute
273 bool ok = true;
274 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
275 if (!ok) {
276 throw ProcessError();
277 }
278 if (prob < 0) {
279 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for via '%' is negative (must not).", getID(), viaID));
280 }
281 // add
284 }
285 if (element == SUMO_TAG_OVERTAKING_REROUTE) {
286 // for letting a slow train use a siding to be overtaken by a fast train
287 OvertakeLocation oloc;
288 bool ok = true;
289 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_MAIN, getID().c_str(), ok)) {
290 MSEdge* edge = MSEdge::dictionary(edgeID);
291 if (edge == nullptr) {
292 throw InvalidArgument(TLF("The main edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
293 }
294 oloc.main.push_back(edge);
295 oloc.cMain.push_back(edge);
296 }
297 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_SIDING, getID().c_str(), ok)) {
298 MSEdge* edge = MSEdge::dictionary(edgeID);
299 if (edge == nullptr) {
300 throw InvalidArgument(TLF("The siding edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
301 }
302 oloc.siding.push_back(edge);
303 oloc.cSiding.push_back(edge);
304 }
305 oloc.sidingExit = findSignal(oloc.cSiding.begin(), oloc.cSiding.end());
306 if (oloc.sidingExit == nullptr) {
307 throw InvalidArgument(TLF("The siding within rerouter '%' does not have a rail signal.", getID()));
308 }
309 for (auto it = oloc.cSiding.begin(); it != oloc.cSiding.end(); it++) {
310 oloc.sidingLength += (*it)->getLength();
311 if ((*it)->getToJunction()->getID() == oloc.sidingExit->getID()) {
312 break;
313 }
314 }
315 oloc.minSaving = attrs.getOpt<double>(SUMO_ATTR_MINSAVING, getID().c_str(), ok, 300);
316 const bool hasAlternatives = myParsedRerouteInterval.overtakeLocations.size() > 0;
317 oloc.defer = attrs.getOpt<bool>(SUMO_ATTR_DEFER, getID().c_str(), ok, hasAlternatives);
319 }
320 if (element == SUMO_TAG_STATION_REROUTE) {
321 // for letting a train switch it's stopping place in case of conflict
322 const std::string stopID = attrs.getStringSecure(SUMO_ATTR_ID, "");
323 if (stopID == "") {
324 throw ProcessError(TLF("rerouter '%': stationReroute requires a stopping place id.", getID()));
325 }
327 if (stop == nullptr) {
328 throw ProcessError(TLF("rerouter '%': stopping place '%' is not known.", getID(), stopID));
329 }
330 myParsedRerouteInterval.stopAlternatives.push_back(std::make_pair(stop, true));
331 }
332}
333
334
335void
337 if (element == SUMO_TAG_INTERVAL) {
338 // precompute permissionsAllowAll
339 bool allowAll = true;
340 for (const auto& entry : myParsedRerouteInterval.closed) {
341 allowAll = allowAll && entry.second.first == SVC_UNSPECIFIED;
342 if (!allowAll) {
343 break;
344 }
345 }
347
348 for (auto paVi : myParsedRerouteInterval.parkProbs.getVals()) {
349 dynamic_cast<MSParkingArea*>(paVi.first)->setNumAlternatives((int)myParsedRerouteInterval.parkProbs.getVals().size() - 1);
350 }
351 if (myParsedRerouteInterval.closedLanes.size() > 0) {
352 // collect edges that are affect by a closed lane
353 std::set<MSEdge*> affected;
354 for (std::pair<MSLane*, SVCPermissions> settings : myParsedRerouteInterval.closedLanes) {
355 affected.insert(&settings.first->getEdge());
356 }
358 }
359 const SUMOTime closingBegin = myParsedRerouteInterval.begin;
360 const SUMOTime simBegin = string2time(OptionsCont::getOptions().getString("begin"));
361 if (closingBegin < simBegin && myParsedRerouteInterval.end > simBegin) {
362 // interval started before simulation begin but is still active at
363 // the start of the simulation
365 }
367 myIntervals.back().id = (long long int)&myIntervals.back();
371 }
372 }
373}
374
375
376// ------------ loading end
377
378
381 bool updateVehicles = false;
382 for (const RerouteInterval& i : myIntervals) {
383 if (i.begin == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
384 for (const auto& settings : i.closed) {
385 if (settings.second.first != SVC_UNSPECIFIED) {
386 for (MSLane* lane : settings.first->getLanes()) {
387 //std::cout << SIMTIME << " closing: intervalID=" << i.id << " lane=" << lane->getID() << " prevPerm=" << getVehicleClassNames(lane->getPermissions()) << " new=" << getVehicleClassNames(settings.second.first) << "\n";
388 lane->setPermissions(settings.second.first, i.id);
389 }
390 settings.first->rebuildAllowedLanes();
391 updateVehicles = true;
392 }
393 }
394 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
395 settings.first->setPermissions(settings.second, i.id);
396 settings.first->getEdge().rebuildAllowedLanes();
397 updateVehicles = true;
398 }
401 }
402 if (i.end == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
403 for (auto settings : i.closed) {
404 if (settings.second.first != SVC_UNSPECIFIED) {
405 for (MSLane* lane : settings.first->getLanes()) {
406 lane->resetPermissions(i.id);
407 //std::cout << SIMTIME << " opening: intervalID=" << i.id << " lane=" << lane->getID() << " restore prevPerm=" << getVehicleClassNames(lane->getPermissions()) << "\n";
408 }
409 settings.first->rebuildAllowedLanes();
410 updateVehicles = true;
411 }
412 }
413 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
414 settings.first->resetPermissions(i.id);
415 settings.first->getEdge().rebuildAllowedLanes();
416 updateVehicles = true;
417 }
418 }
419 }
420 if (updateVehicles) {
422 // only vehicles on the affected lanes had their bestlanes updated so far
423 for (MSEdge* e : myEdges) {
424 // also updates vehicles
425 e->rebuildAllowedTargets();
426 }
427 }
428 return 0;
429}
430
431
434 for (const RerouteInterval& ri : myIntervals) {
435 if (ri.begin <= time && ri.end > time) {
436 if (
437 // destProbReroute
438 ri.edgeProbs.getOverallProb() > 0 ||
439 // routeProbReroute
440 ri.routeProbs.getOverallProb() > 0 ||
441 // parkingZoneReroute
442 ri.parkProbs.getOverallProb() > 0 ||
443 // stationReroute
444 ri.stopAlternatives.size() > 0) {
445 return &ri;
446 }
447 if (!ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.overtakeLocations.empty()) {
448 const std::set<SUMOTrafficObject::NumericalID>& edgeIndices = obj.getUpcomingEdgeIDs();
449 if (affected(edgeIndices, ri.getClosedEdges())
450 || affected(edgeIndices, ri.closedLanesAffected)) {
451 return &ri;
452 }
453 for (const OvertakeLocation& oloc : ri.overtakeLocations) {
454 if (affected(edgeIndices, oloc.main)) {
455 return &ri;
456 }
457 }
458
459 }
460 }
461 }
462 return nullptr;
463}
464
465
468 for (const RerouteInterval& ri : myIntervals) {
469 if (ri.begin <= time && ri.end > time) {
470 if (ri.edgeProbs.getOverallProb() != 0 || ri.routeProbs.getOverallProb() != 0 || ri.parkProbs.getOverallProb() != 0
471 || !ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.overtakeLocations.empty()) {
472 return &ri;
473 }
474 }
475 }
476 return nullptr;
477}
478
479
480bool
482 if (myAmOptional || myRadius != std::numeric_limits<double>::max()) {
483 return true;
484 }
485 return triggerRouting(tObject, reason);
486}
487
488
489bool
491 double /*newPos*/, double /*newSpeed*/) {
493}
494
495
496bool
498 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
499 return reason == NOTIFICATION_LANE_CHANGE;
500}
501
502
503bool
505 if (!applies(tObject)) {
506 return false;
507 }
508 if (myRadius != std::numeric_limits<double>::max() && tObject.getPosition().distanceTo(myPosition) > myRadius) {
509 return true;
510 }
511 // check whether the vehicle shall be rerouted
513 const MSTriggeredRerouter::RerouteInterval* const rerouteDef = getCurrentReroute(now, tObject);
514 if (rerouteDef == nullptr) {
515 return true; // an active interval could appear later
516 }
517 const double prob = myAmInUserMode ? myUserProbability : myProbability;
518 if (prob < 1 && RandHelper::rand(tObject.getRNG()) > prob) {
519 return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
520 }
521 if (myTimeThreshold > 0 && MAX2(tObject.getWaitingTime(), tObject.getWaitingTime(true)) < myTimeThreshold) {
522 return true; // waiting time may be reached later
523 }
524 if (reason == NOTIFICATION_LANE_CHANGE) {
525 return false;
526 }
527 // if we have a closingLaneReroute it may still affect the network topology (i.e. by closing a turning lane).
528 // Even if the topology stays unchanged, vehicles with a rerouting device could reroute around jams that form due to capacity reduction
529 const bool hasReroutingDevice = tObject.getDevice(typeid(MSDevice_Routing)) != nullptr;
530 const MSEdge* lastEdge = tObject.getRerouteDestination();
531#ifdef DEBUG_REROUTER
532 if (DEBUGCOND(tObject)) {
533 std::cout << SIMTIME << " veh=" << tObject.getID() << " check rerouter " << getID() << " lane=" << Named::getIDSecure(tObject.getLane()) << " edge=" << tObject.getEdge()->getID() << " finalEdge=" << lastEdge->getID() /*<< " arrivalPos=" << tObject.getArrivalPos()*/ << "\n";
534 }
535#endif
536
537 if (rerouteDef->parkProbs.getOverallProb() > 0) {
538#ifdef HAVE_FOX
539 ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
540#endif
541 if (!tObject.isVehicle()) {
542 return false;
543 }
544 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
545 bool newDestination = false;
546 ConstMSEdgeVector newRoute;
547 MSParkingArea* oldParkingArea = veh.getNextParkingArea();
548 MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination, newRoute);
549 if (newParkingArea != nullptr) {
550 // adapt plans of any riders
551 for (MSTransportable* p : veh.getPersons()) {
552 p->rerouteParkingArea(oldParkingArea, newParkingArea);
553 }
554
555 if (newDestination && veh.getParameter().arrivalPosProcedure != ArrivalPosDefinition::DEFAULT) {
556 // update arrival parameters
557 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
558 *newParameter = veh.getParameter();
560 newParameter->arrivalPos = newParkingArea->getEndLanePosition();
561 veh.replaceParameter(newParameter);
562 }
563
564 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
565 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
566 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
567 const double routeCost = router.recomputeCosts(newRoute, &veh, MSNet::getInstance()->getCurrentTimeStep());
568 ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
569 resetClosedEdges(hasReroutingDevice, veh);
570 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
571 const double savings = previousCost - routeCost;
572 //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
573 // << " prevEdges=" << toString(prevEdges)
574 // << " newEdges=" << toString(edges)
575 // << "\n";
576
577 std::string errorMsg;
578 if (veh.replaceParkingArea(newParkingArea, errorMsg)) {
579 veh.replaceRouteEdges(newRoute, routeCost, savings, getID() + ":" + toString(SUMO_TAG_PARKING_AREA_REROUTE), false, false, false);
580 if (oldParkingArea->isReservable()) {
581 oldParkingArea->removeSpaceReservation(&veh);
582 }
583 if (newParkingArea->isReservable()) {
584 newParkingArea->addSpaceReservation(&veh);
585 }
586 } else {
587 WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
588 + "' could not reroute to new parkingArea '" + newParkingArea->getID()
589 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
590 }
591 } else {
592 if (oldParkingArea && oldParkingArea->isReservable()) {
593 oldParkingArea->addSpaceReservation(&veh);
594 }
595 }
596 return false;
597 }
598 if (rerouteDef->overtakeLocations.size() > 0) {
599 if (!tObject.isVehicle()) {
600 return false;
601 }
602 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
603 const ConstMSEdgeVector& oldEdges = veh.getRoute().getEdges();
604 double bestSavings = -std::numeric_limits<double>::max();
605 double netSaving;
606 int bestIndex = -1;
607 MSRouteIterator bestMainStart = oldEdges.end();
608 std::pair<const SUMOVehicle*, MSRailSignal*> best_overtaker_signal(nullptr, nullptr);
609 int index = -1;
610 // sort locations by descending distance to vehicle
611 std::vector<std::pair<int, int> > sortedLocs;
612 for (const OvertakeLocation& oloc : rerouteDef->overtakeLocations) {
613 index++;
614 if (veh.getLength() > oloc.sidingLength) {
615 continue;
616 }
617 auto mainStart = std::find(veh.getCurrentRouteEdge(), oldEdges.end(), oloc.main.front());
618 if (mainStart == oldEdges.end()
619 // exit main within
620 || ConstMSEdgeVector(mainStart, mainStart + oloc.main.size()) != oloc.cMain
621 // stop in main
622 || (veh.hasStops() && veh.getNextStop().edge < (mainStart + oloc.main.size()))) {
623 //std::cout << SIMTIME << " veh=" << veh.getID() << " wrong route or stop\n";
624 continue;
625 }
626 // negated iterator distance for descending order
627 sortedLocs.push_back(std::make_pair(-(int)(mainStart - veh.getCurrentRouteEdge()), index));
628 }
629 std::sort(sortedLocs.begin(), sortedLocs.end());
630 for (const auto& item : sortedLocs) {
631 index = item.second;
632 const OvertakeLocation& oloc = rerouteDef->overtakeLocations[index];
633 auto mainStart = veh.getCurrentRouteEdge() - item.first; // subtracting negative difference
634 std::pair<const SUMOVehicle*, MSRailSignal*> overtaker_signal = overtakingTrain(veh, mainStart, oloc, netSaving);
635 if (overtaker_signal.first != nullptr && netSaving > bestSavings) {
636 bestSavings = netSaving;
637 bestIndex = index;
638 best_overtaker_signal = overtaker_signal;
639 bestMainStart = mainStart;
640#ifdef DEBUG_OVERTAKING
641 std::cout << " newBest index=" << bestIndex << " saving=" << bestSavings << "\n";
642#endif
643 }
644 }
645 if (bestIndex >= 0) {
646 const OvertakeLocation& oloc = rerouteDef->overtakeLocations[bestIndex];
647 if (oloc.defer) {
648 return false;
649 }
650 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
651 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
652 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
653 ConstMSEdgeVector newEdges(veh.getCurrentRouteEdge(), bestMainStart);
654 newEdges.insert(newEdges.end(), oloc.siding.begin(), oloc.siding.end());
655 newEdges.insert(newEdges.end(), bestMainStart + oloc.main.size(), oldEdges.end());
656 const double routeCost = router.recomputeCosts(newEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
657 const double savings = (router.recomputeCosts(oloc.cMain, &veh, MSNet::getInstance()->getCurrentTimeStep())
659 const std::string info = getID() + ":" + toString(SUMO_TAG_OVERTAKING_REROUTE) + ":" + best_overtaker_signal.first->getID();
660 veh.replaceRouteEdges(newEdges, routeCost, savings, info, false, false, false);
662 MSRailSignalConstraint::PREDECESSOR, best_overtaker_signal.second, best_overtaker_signal.first->getID(), 100, true));
663 resetClosedEdges(hasReroutingDevice, veh);
664 }
665 return false;
666 }
667 if (rerouteDef->stopAlternatives.size() > 0) {
668 // somewhat similar to parkProbs but taking into account public transport schedule
669 if (!tObject.isVehicle()) {
670 return false;
671 }
672 checkStopSwitch(static_cast<MSBaseVehicle&>(tObject), rerouteDef);
673 }
674 // get rerouting params
675 ConstMSRoutePtr newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : nullptr;
676 // we will use the route if given rather than calling our own dijsktra...
677 if (newRoute != nullptr) {
678#ifdef DEBUG_REROUTER
679 if (DEBUGCOND(tObject)) {
680 std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
681 }
682#endif
683 tObject.replaceRoute(newRoute, getID());
684 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
685 }
686 const MSEdge* newEdge = lastEdge;
687 // ok, try using a new destination
688 double newArrivalPos = -1;
689 const MSEdgeVector closed = rerouteDef->getClosedEdges();
690 const bool destUnreachable = std::find(closed.begin(), closed.end(), lastEdge) != closed.end();
691 bool keepDestination = false;
692 // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
693 // if we have a closingLaneReroute, no new destinations should be assigned
694 if (closed.empty() || destUnreachable || (rerouteDef->isVia && affected(tObject.getUpcomingEdgeIDs(), closed))) {
695 newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : lastEdge;
696 assert(newEdge != nullptr);
697 if (newEdge == &mySpecialDest_terminateRoute) {
698 keepDestination = true;
699 newEdge = tObject.getEdge();
700 newArrivalPos = tObject.getPositionOnLane(); // instant arrival
701 } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
702 if (destUnreachable && rerouteDef->permissionsAllowAll) {
703 // if permissions aren't set vehicles will simply drive through
704 // the closing unless terminated. If the permissions are specified, assume that the user wants
705 // vehicles to stand and wait until the closing ends
706 WRITE_WARNINGF(TL("Cannot keep destination edge '%' for vehicle '%' due to closed edges. Terminating route."), lastEdge->getID(), tObject.getID());
707 newEdge = tObject.getEdge();
708 } else {
709 newEdge = lastEdge;
710 }
711 }
712 }
713 ConstMSEdgeVector edges;
714 std::vector<MSTransportableRouter::TripItem> items;
715 // we have a new destination, let's replace the route (if it is affected)
716 Prohibitions prohibited = rerouteDef->getClosed();
717 if (rerouteDef->closed.empty() || destUnreachable || affected(tObject.getUpcomingEdgeIDs(), closed)) {
718 if (tObject.ignoreTransientPermissions()) {
719 // after learning about network changes, the driver must no longer forget them
720 if (!myHaveClosingUntil) {
722 } else if (hasReroutingDevice && dynamic_cast<MSDevice_Routing*>(tObject.getDevice(typeid(MSDevice_Routing)))->getPeriod() > 0) {
723 WRITE_WARNINGF(TL("Periodic rerouting and rerouting mode 8 for vehicle '%' are incompatible with closingReroute attribute 'until' in rerouter (vehicle may return to an invalid route."),
724 tObject.getID(), getID());
725 }
726 }
727 if (tObject.isVehicle()) {
728 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
729 ConstMSEdgeVector prevEdges = veh.getRoute().getEdges();
730 const bool canChangeDest = rerouteDef->edgeProbs.getOverallProb() > 0;
731 MSVehicleRouter& router = hasReroutingDevice
732 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
733 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
734 bool ok = false;
735 try {
736 ok = veh.reroute(now, getID(), router, false, false, canChangeDest, newEdge);
737 } catch (ProcessError&) {}
738 if (!ok && !keepDestination && canChangeDest) {
739 // destination unreachable due to closed intermediate edges. pick among alternative targets
740 RandomDistributor<MSEdge*> edgeProbs2 = rerouteDef->edgeProbs;
741 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
742 while (!ok && edgeProbs2.getVals().size() > 0) {
743 newEdge = edgeProbs2.get();
744 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
745 if (newEdge == &mySpecialDest_terminateRoute) {
746 newEdge = veh.getEdge();
747 newArrivalPos = veh.getPositionOnLane(); // instant arrival
748 while (veh.hasStops()) {
749 veh.abortNextStop();
750 }
751 }
752 if (newEdge == &mySpecialDest_keepDestination && !rerouteDef->permissionsAllowAll) {
753 newEdge = lastEdge;
754 break;
755 }
756 try {
757 ok = veh.reroute(now, getID(), router, false, false, true, newEdge);
758 } catch (ProcessError&) {}
759 }
760 }
761 resetClosedEdges(hasReroutingDevice, tObject);
762 if (ok) {
763 // since the old route was closed, savings would be infinite. This isn't useful
764 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
765 const double savings = previousCost - veh.getRoute().getCosts();
766 const_cast<MSRoute&>(veh.getRoute()).setSavings(savings);
767 }
768 if (!rerouteDef->isVia) {
769#ifdef DEBUG_REROUTER
770 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
771 << " newEdges=" << toString(edges)
772 << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
773 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(closed) << "\n";
774#endif
775 if (ok && newArrivalPos != -1) {
776 // must be called here because replaceRouteEdges may also set the arrivalPos
777 veh.setArrivalPos(newArrivalPos);
778 }
779
780 }
781 } else {
782 // person rerouting here
783 MSTransportableRouter& router = hasReroutingDevice
785 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
786 const bool success = router.compute(tObject.getEdge(), newEdge, tObject.getPositionOnLane(), "",
787 rerouteDef->isVia ? newEdge->getLength() / 2. : tObject.getParameter().arrivalPos, "",
788 tObject.getMaxSpeed(), nullptr, tObject.getVTypeParameter(), 0, now, items);
789 if (!rerouteDef->isVia) {
790 if (success) {
791 for (const MSTransportableRouter::TripItem& it : items) {
792 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
793 edges.pop_back();
794 }
795 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
796 if (!edges.empty()) {
797 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
798 }
799 }
800 } else {
801 // maybe the pedestrian model still finds a way (JuPedSim)
802 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge}, tObject.getPositionOnLane(), 0, 1);
803 }
804 }
805 }
806 if (!prohibited.empty()) {
807 resetClosedEdges(hasReroutingDevice, tObject);
808 }
809 }
810 // it was only a via so calculate the remaining part
811 if (rerouteDef->isVia && newEdge != lastEdge) {
812 if (tObject.isVehicle()) {
813 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
814 if (!edges.empty()) {
815 edges.pop_back();
816 }
817 MSVehicleRouter& router = hasReroutingDevice
818 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
819 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
820 router.compute(newEdge, lastEdge, &veh, now, edges);
821 const double routeCost = router.recomputeCosts(edges, &veh, now);
822 hasReroutingDevice
824 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
825 const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
826#ifdef DEBUG_REROUTER
827 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
828 << " newEdges=" << toString(edges)
829 << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
830 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(closed) << "\n";
831#endif
832 if (useNewRoute && newArrivalPos != -1) {
833 // must be called here because replaceRouteEdges may also set the arrivalPos
834 veh.setArrivalPos(newArrivalPos);
835 }
836 } else {
837 // person rerouting here
838 bool success = !items.empty();
839 if (success) {
840 MSTransportableRouter& router = hasReroutingDevice
842 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
843 success = router.compute(newEdge, lastEdge, newEdge->getLength() / 2., "",
844 tObject.getParameter().arrivalPos, "",
845 tObject.getMaxSpeed(), nullptr, tObject.getVTypeParameter(), 0, now, items);
846 }
847 if (success) {
848 for (const MSTransportableRouter::TripItem& it : items) {
849 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
850 edges.pop_back();
851 }
852 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
853 }
854 if (!edges.empty()) {
855 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
856 }
857 } else {
858 // maybe the pedestrian model still finds a way (JuPedSim)
859 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge, lastEdge}, tObject.getPositionOnLane(), 0, 1);
860 }
861 }
862 if (!prohibited.empty()) {
863 resetClosedEdges(hasReroutingDevice, tObject);
864 }
865 }
866 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
867}
868
869
870void
874
875
876void
880
881
882bool
886
887
888double
892
893
894double
898
899
900double
902 return (sp->getElement() == SUMO_TAG_PARKING_AREA
903 ? (double)dynamic_cast<MSParkingArea*>(sp)->getOccupancyIncludingRemoteReservations(veh)
904 : (double)sp->getStoppedVehicles().size());
905}
906
907
908double
914
915
916double
918 if (myBlockedStoppingPlaces.count(sp) == 0) {
919 return (double)(sp->getElement() == SUMO_TAG_PARKING_AREA
920 ? dynamic_cast<MSParkingArea*>(sp)->getCapacity()
921 // assume only one vehicle at a time (for stationReroute)
922 : 1.);
923 } else {
924 return 0.;
925 }
926}
927
928
929void
931 veh.rememberBlockedParkingArea(parkingArea, blocked);
932}
933
934
935void
937 veh.rememberParkingAreaScore(parkingArea, score);
938}
939
940
941void
945
946
949 return veh.sawBlockedParkingArea(parkingArea, local);
950}
951
952
953int
957
958
959void
963
964
967 SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute) {
968 MSStoppingPlace* destStoppingPlace = veh.getNextParkingArea();
969 if (destStoppingPlace == nullptr) {
970 // not driving towards the right type of stop
971 return nullptr;
972 }
973 std::vector<StoppingPlaceVisible> parks;
974 for (auto cand : rerouteDef->parkProbs.getVals()) {
975 if (cand.first->accepts(&veh)) {
976 parks.push_back(cand);
977 }
978 }
979 StoppingPlaceParamMap_t addInput = {};
980 return dynamic_cast<MSParkingArea*>(rerouteStoppingPlace(destStoppingPlace, parks, rerouteDef->parkProbs.getProbs(), veh, newDestination, newRoute, addInput, rerouteDef->getClosed()));
981}
982
983
984std::pair<const SUMOVehicle*, MSRailSignal*>
986 ConstMSEdgeVector::const_iterator mainStart,
987 const OvertakeLocation& oloc,
988 double& netSaving) {
989 const ConstMSEdgeVector& route = veh.getRoute().getEdges();
990 const MSEdgeVector& main = oloc.main;
991 const double vMax = veh.getMaxSpeed();
992 const double prio = veh.getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKEN, false);
994 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
995 const MSBaseVehicle* veh2 = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
996 if (veh2->isOnRoad() && veh2->getMaxSpeed() > vMax) {
997 const double arrivalDelay = veh2->getStopArrivalDelay();
998 const double delay = MAX2(veh2->getStopDelay(), arrivalDelay == INVALID_DOUBLE ? 0 : arrivalDelay);
999 if (delay > veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".maxDelay", false, DEFAULT_MAXDELAY, false)) {
1000 continue;
1001 }
1002 const ConstMSEdgeVector& route2 = veh2->getRoute().getEdges();
1003 auto itOnMain2 = route2.end();
1004 int mainIndex = 0;
1005 for (const MSEdge* m : main) {
1006 itOnMain2 = std::find(veh2->getCurrentRouteEdge(), route2.end(), m);
1007 if (itOnMain2 != route2.end()) {
1008 break;
1009 }
1010 mainIndex++;
1011 }
1012 if (itOnMain2 != route2.end() && itOnMain2 > veh2->getCurrentRouteEdge()) {
1013 auto itOnMain = mainStart + mainIndex;
1014 double timeToMain = 0;
1015 for (auto it = veh.getCurrentRouteEdge(); it != itOnMain; it++) {
1016 timeToMain += (*it)->getMinimumTravelTime(&veh);
1017 }
1018 // veh2 may be anywhere on the current edge so we have to discount
1019 double timeToMain2 = -veh2->getEdge()->getMinimumTravelTime(veh2) * veh2->getPositionOnLane() / veh2->getEdge()->getLength();
1020 double timeToLastSignal2 = timeToMain2;
1021 for (auto it = veh2->getCurrentRouteEdge(); it != itOnMain2; it++) {
1022 timeToMain2 += (*it)->getMinimumTravelTime(veh2);
1023 auto signal = getRailSignal(*it);
1024 if (signal) {
1025 timeToLastSignal2 = timeToMain2;
1026#ifdef DEBUG_OVERTAKING
1027 std::cout << " lastBeforeMain2 " << signal->getID() << "\n";
1028#endif
1029 }
1030 }
1031 double exitMainTime = timeToMain;
1032 double exitMainBlockTime2 = timeToMain2;
1033 double commonTime = 0;
1034 double commonTime2 = 0;
1035 int nCommon = 0;
1036 auto exitMain2 = itOnMain2;
1037 const MSRailSignal* firstAfterMain = nullptr;
1038 const MSEdge* common = nullptr;
1039 double vMinCommon = (*itOnMain)->getVehicleMaxSpeed(&veh);
1040 double vMinCommon2 = (*itOnMain2)->getVehicleMaxSpeed(veh2);
1041 while (itOnMain2 != route2.end()
1042 && itOnMain != route.end()
1043 && *itOnMain == *itOnMain2) {
1044 common = *itOnMain;
1045 commonTime += common->getMinimumTravelTime(&veh);
1046 commonTime2 += common->getMinimumTravelTime(veh2);
1047 vMinCommon = MIN2(vMinCommon, common->getVehicleMaxSpeed(&veh));
1048 vMinCommon2 = MIN2(vMinCommon2, common->getVehicleMaxSpeed(veh2));
1049 const bool onMain = nCommon < (int)main.size() - mainIndex;
1050 if (onMain) {
1051 exitMainTime = timeToMain + commonTime;
1052 }
1053 if (firstAfterMain == nullptr) {
1054 exitMainBlockTime2 = timeToMain2 + commonTime2;
1055 }
1056 auto signal = getRailSignal(common);
1057 if (signal) {
1058 if (!onMain && firstAfterMain == nullptr) {
1059 firstAfterMain = signal;
1060#ifdef DEBUG_OVERTAKING
1061 std::cout << " firstAfterMain " << signal->getID() << "\n";
1062#endif
1063 }
1064 }
1065 nCommon++;
1066 itOnMain++;
1067 itOnMain2++;
1068 }
1069 const double vMaxLast = common->getVehicleMaxSpeed(&veh);
1070 const double vMaxLast2 = common->getVehicleMaxSpeed(veh2);
1071 commonTime += veh.getLength() / vMaxLast;
1072 exitMainBlockTime2 += veh2->getLength() / vMaxLast2;
1073 exitMain2 += MIN2(nCommon, (int)main.size() - mainIndex);
1074 double timeLoss2 = MAX2(0.0, timeToMain + veh.getLength() / oloc.siding.front()->getVehicleMaxSpeed(&veh) - timeToLastSignal2);
1075 const double saving = timeToMain + commonTime - (timeToMain2 + commonTime2) - timeLoss2;
1076 const double loss = exitMainBlockTime2 - exitMainTime;
1077 const double prio2 = veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKER, false);
1078 // losses from acceleration after stopping at a signal
1079 const double accelTimeLoss = loss > 0 ? 0.5 * vMinCommon / veh.getVehicleType().getCarFollowModel().getMaxAccel() : 0;
1080 const double accelTimeLoss2 = timeLoss2 > 0 ? 0.5 * vMinCommon2 / veh2->getVehicleType().getCarFollowModel().getMaxAccel() : 0;
1081 netSaving = prio2 * (saving - accelTimeLoss2) - prio * (loss + accelTimeLoss);
1082#ifdef DEBUG_OVERTAKING
1083 std::cout << SIMTIME << " veh=" << veh.getID() << " veh2=" << veh2->getID()
1084 << " sidingStart=" << oloc.siding.front()->getID()
1085 << " ttm=" << timeToMain << " ttm2=" << timeToMain2
1086 << " nCommon=" << nCommon << " cT=" << commonTime << " cT2=" << commonTime2
1087 << " em=" << exitMainTime << " emb2=" << exitMainBlockTime2
1088 << " ttls2=" << timeToLastSignal2
1089 << " saving=" << saving << " loss=" << loss
1090 << " atl=" << accelTimeLoss << " atl2=" << accelTimeLoss2 << " tl2=" << timeLoss2
1091 << " prio=" << prio << " prio2=" << prio2 << " netSaving=" << netSaving << "\n";
1092#endif
1093 if (netSaving > oloc.minSaving) {
1094 MSRailSignal* s = findSignal(veh2->getCurrentRouteEdge(), exitMain2);
1095 if (s != nullptr) {
1096 return std::make_pair(veh2, s);
1097 }
1098 }
1099 }
1100 }
1101 }
1102 return std::make_pair(nullptr, nullptr);
1103}
1104
1105
1106void
1109#ifdef DEBUG_REROUTER
1110 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << "\n";
1111#endif
1112 if (!ego.hasStops()) {
1113 return;
1114 }
1115 const MSStop& stop = ego.getNextStop();
1116 if (stop.reached || stop.joinTriggered || (stop.pars.arrival < 0 && stop.pars.until < 0)) {
1117 return;
1118 }
1119 MSStoppingPlace* cur = nullptr;
1120 for (MSStoppingPlace* sp : stop.getPlaces()) {
1121 for (auto item : def->stopAlternatives) {
1122 if (sp == item.first) {
1123 cur = sp;
1124 break;
1125 }
1126 }
1127 }
1128 if (cur == nullptr) {
1129 return;
1130 }
1131 std::vector<const SUMOVehicle*> stopped = cur->getStoppedVehicles();
1132#ifdef DEBUG_REROUTER
1133 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopped=" << toString(stopped) << "\n";
1134#endif
1135 SUMOTime stoppedDuration = -1;
1136 if (stopped.empty()) {
1138 const MSLane& stopLane = cur->getLane();
1140 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
1141 const MSBaseVehicle* veh = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
1142 if (veh->isOnRoad() && veh->hasStops()) {
1143 const MSStop& vehStop = veh->getNextStop();
1144 if (vehStop.pars.lane == stopLane.getID()) {
1145 myBlockedStoppingPlaces.insert(cur);
1146 if (veh->isStopped()) {
1147 // stopped somewhere else on the same lane
1148 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, veh->getStopDuration());
1149 } else {
1150 std::pair<double, double> timeDist = veh->estimateTimeToNextStop();
1151 SUMOTime timeTo = TIME2STEPS(timeDist.first);
1152 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, timeTo + vehStop.getMinDuration(SIMSTEP + timeTo));
1153 }
1154 }
1155 }
1156 }
1157 } else {
1158 stoppedDuration = 0;
1159 for (const SUMOVehicle* veh : cur->getStoppedVehicles()) {
1160 stoppedDuration = MAX2(stoppedDuration, veh->getStopDuration());
1161 }
1162 }
1163 if (stoppedDuration < 0) {
1164 return;
1165 }
1167 const SUMOTime stopFree = SIMSTEP + stoppedDuration;
1168 const SUMOTime scheduledArrival = stop.pars.arrival >= 0 ? stop.pars.arrival : stop.pars.until - stop.pars.duration;
1169#ifdef DEBUG_REROUTER
1170 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " scheduledArrival=" << time2string(scheduledArrival) << "\n";
1171#endif
1172 if (stopFree < scheduledArrival) {
1173 // no conflict according to the schedule
1174 return;
1175 }
1176 const SUMOTime estimatedArrival = SIMSTEP + (stop.pars.arrival >= 0
1178 : TIME2STEPS(ego.getStopDelay()) - stop.pars.duration);
1179#ifdef DEBUG_REROUTER
1180 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " estimatedArrival=" << time2string(estimatedArrival) << "\n";
1181#endif
1182 if (stopFree < estimatedArrival) {
1183 // no conflict when considering current delay
1184 return;
1185 }
1186 const std::vector<double> probs(def->stopAlternatives.size(), 1.);
1187 StoppingPlaceParamMap_t scores = {};
1188 bool newDestination;
1189 ConstMSEdgeVector newRoute;
1190 // @todo: consider future conflicts caused by rerouting
1191 // @todo: reject alternatives with large detour
1192 const MSStoppingPlace* alternative = rerouteStoppingPlace(nullptr, def->stopAlternatives, probs, ego, newDestination, newRoute, scores);
1193#ifdef DEBUG_REROUTER
1194 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " alternative=" << Named::getIDSecure(alternative) << "\n";
1195#endif
1196 if (alternative != nullptr) {
1197 // @todo adapt plans of any riders
1198 //for (MSTransportable* p : ego.getPersons()) {
1199 // p->rerouteParkingArea(ego.getNextParkingArea(), newParkingArea);
1200 //}
1201
1202 if (newDestination && ego.getParameter().arrivalPosProcedure != ArrivalPosDefinition::DEFAULT) {
1203 // update arrival parameters
1204 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
1205 *newParameter = ego.getParameter();
1207 newParameter->arrivalPos = alternative->getEndLanePosition();
1208 ego.replaceParameter(newParameter);
1209 }
1210
1211 SUMOVehicleParameter::Stop newStop = stop.pars;
1212 newStop.lane = alternative->getLane().getID();
1213 newStop.startPos = alternative->getBeginLanePosition();
1214 newStop.endPos = alternative->getEndLanePosition();
1215 switch (alternative->getElement()) {
1217 newStop.parkingarea = alternative->getID();
1218 break;
1220 newStop.containerstop = alternative->getID();
1221 break;
1223 newStop.chargingStation = alternative->getID();
1224 break;
1226 newStop.overheadWireSegment = alternative->getID();
1227 break;
1228 case SUMO_TAG_BUS_STOP:
1230 default:
1231 newStop.busstop = alternative->getID();
1232 }
1233 std::string errorMsg;
1234 if (!ego.replaceStop(0, newStop, getID() + ":" + toString(SUMO_TAG_STATION_REROUTE), false, errorMsg)) {
1235 WRITE_WARNING("Vehicle '" + ego.getID() + "' at rerouter '" + getID()
1236 + "' could not perform stationReroute to '" + alternative->getID()
1237 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1238 }
1239 }
1240}
1241
1242
1244MSTriggeredRerouter::findSignal(ConstMSEdgeVector::const_iterator begin, ConstMSEdgeVector::const_iterator end) {
1245 auto it = end;
1246 do {
1247 it--;
1248 auto signal = getRailSignal(*it);
1249 if (signal != nullptr) {
1250 return signal;
1251 }
1252 } while (it != begin);
1253 return nullptr;
1254}
1255
1256
1260 for (const MSLink* link : edge->getLanes().front()->getLinkCont()) {
1261 if (link->getTLLogic() != nullptr) {
1262 return dynamic_cast<MSRailSignal*>(const_cast<MSTrafficLightLogic*>(link->getTLLogic()));
1263 }
1264 }
1265 }
1266 return nullptr;
1267}
1268
1269bool
1271 if (myVehicleTypes.empty() || myVehicleTypes.count(obj.getVehicleType().getOriginalID()) > 0) {
1272 return true;
1273 } else {
1275 for (auto vTypeDist : vTypeDists) {
1276 if (myVehicleTypes.count(vTypeDist) > 0) {
1277 return true;
1278 }
1279 }
1280 return false;
1281 }
1282}
1283
1284
1285bool
1286MSTriggeredRerouter::affected(const std::set<SUMOTrafficObject::NumericalID>& edgeIndices, const MSEdgeVector& closed) {
1287 for (const MSEdge* const e : closed) {
1288 if (edgeIndices.count(e->getNumericalID()) > 0) {
1289 return true;
1290 }
1291 }
1292 return false;
1293}
1294
1295
1296void
1298 // if a parkingArea is a rerouting target, it should generally have a
1299 // rerouter on its edge or vehicles will be stuck there once it's full.
1300 // The user should receive a Warning in this case
1301 std::set<MSEdge*> parkingRerouterEdges;
1302 std::map<MSParkingArea*, std::string, ComparatorIdLess> targetedParkingArea; // paID -> targetingRerouter
1303 for (const auto& rr : myInstances) {
1304 bool hasParkingReroute = false;
1305 for (const RerouteInterval& interval : rr.second->myIntervals) {
1306 if (interval.parkProbs.getOverallProb() > 0) {
1307 hasParkingReroute = true;
1308 for (const StoppingPlaceVisible& pav : interval.parkProbs.getVals()) {
1309 targetedParkingArea[dynamic_cast<MSParkingArea*>(pav.first)] = rr.first;
1310 }
1311 }
1312 }
1313 if (hasParkingReroute) {
1314 parkingRerouterEdges.insert(rr.second->myEdges.begin(), rr.second->myEdges.end());
1315 }
1316 }
1317 for (const auto& item : targetedParkingArea) {
1318 if (parkingRerouterEdges.count(&item.first->getLane().getEdge()) == 0) {
1319 WRITE_WARNINGF(TL("ParkingArea '%' is targeted by rerouter '%' but doesn't have its own rerouter. This may cause parking search to abort."),
1320 item.first->getID(), item.second);
1321 }
1322 }
1323}
1324
1325
1326void
1328 // getRouterTT without prohibitions removes previous prohibitions
1329 if (o.isVehicle()) {
1330 hasReroutingDevice
1333 } else {
1334 hasReroutingDevice
1337 }
1338}
1339
1340/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:73
#define DEBUGCOND(PED)
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition MSRoute.h:57
#define DEFAULT_PRIO_OVERTAKEN
#define DEFAULT_PRIO_OVERTAKER
assume that a faster train has more priority and a slower train doesn't matter
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
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:69
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:70
const SVCPermissions SVC_UNSPECIFIED
permissions not specified
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_AUTHORITY
authorities vehicles
@ GIVEN
The arrival position is given.
@ DEFAULT
No information given; use default.
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_CLOSING_REROUTE
reroute of type closing
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_PARKING_AREA_REROUTE
entry for an alternative parking zone
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_ROUTE_PROB_REROUTE
probability of route of a reroute
@ SUMO_TAG_VIA_PROB_REROUTE
probability of a via reroute
@ SUMO_TAG_TRAIN_STOP
A train stop (alias for bus stop)
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
@ SUMO_TAG_DEST_PROB_REROUTE
probability of destination of a reroute
@ SUMO_TAG_OVERTAKING_REROUTE
decision point for rerouting to be overtaken
@ SUMO_TAG_CLOSING_LANE_REROUTE
lane of a reroute of type closing
@ SUMO_TAG_STATION_REROUTE
decision point for switching trainStop/busStop within a station
@ SUMO_ATTR_DISALLOW
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_MAIN
@ SUMO_ATTR_DEFER
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_MINSAVING
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_PROB
@ SUMO_ATTR_SIDING
@ SUMO_ATTR_ID
@ SUMO_ATTR_VISIBLE
@ SUMO_ATTR_UNTIL
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
T MAX3(T a, T b, T c)
Definition StdDefs.h:100
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
int main(int argc, char *argv[])
bool compute(const E *from, const E *to, const double departPos, const std::string &originStopID, const double arrivalPos, const std::string &stopID, const double speed, const V *const vehicle, const SUMOVTypeParameter &pars, const SVCPermissions modeSet, const SUMOTime msTime, std::vector< TripItem > &into, const double externalFactor=0.)
Builds the route between the given edges using the minimum effort at the given time The definition of...
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:384
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
The base class for microscopic and mesoscopic vehicles.
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
virtual double getStopDelay() const
Returns the estimated public transport stop (departure) delay in seconds.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
double getLength() const
Returns the vehicle's length.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
virtual std::pair< double, double > estimateTimeToNextStop() const
return time (s) and distance to the next stop
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
const MSStop & getNextStop() const
virtual double getStopArrivalDelay() const
Returns the estimated public transport stop arrival delay in seconds.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
const MSRoute & getRoute() const
Returns the current route.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition MSCFModel.h:277
A device that performs vehicle rerouting based on current edge speeds.
SUMOTime getPeriod() const
A road/street connecting two junctions.
Definition MSEdge.h:77
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
const MSJunction * getToJunction() const
Definition MSEdge.h:427
double getLength() const
return the length of the edge
Definition MSEdge.h:694
double getMinimumTravelTime(const SUMOVehicle *const veh) const
returns the minimum travel time for the given vehicle
Definition MSEdge.h:485
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1105
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1235
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:149
SumoXMLNodeType getType() const
return the type of this Junction
Definition MSJunction.h:133
Representation of a lane in the micro simulation.
Definition MSLane.h:84
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2528
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_LANE_CHANGE
The vehicle changes lanes (micro only)
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:201
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:495
MSTransportableRouter & getIntermodalRouter(int rngIndex, const int routingMode=0, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1710
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1653
void setPermissionsFound()
Labels the network to contain vehicle class permissions.
Definition MSNet.h:219
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1521
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
A lane area vehicles can halt at.
int getLastStepOccupancyIncludingRemoteReservations(const SUMOVehicle *forVehicle) const
bool isReservable() const
whether vehicles may reserve a slot for this parkingArea
void addSpaceReservation(const SUMOVehicle *veh)
api for reserving spaces at this parkingArea
int getOccupancyIncludingRemoteReservations(const SUMOVehicle *forVehicle) const
void removeSpaceReservation(const SUMOVehicle *veh)
A signal for rails.
void addConstraint(const std::string &tripId, MSRailSignalConstraint *constraint)
register constraint for signal switching
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:128
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition MSRoute.cpp:79
bool containsAnyOf(const MSEdgeVector &edgelist) const
Definition MSRoute.cpp:250
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
double getCosts() const
Returns the costs of the route.
Definition MSRoute.h:178
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
static MSTransportableRouter & getIntermodalRouterTT(const int rngIndex, const Prohibitions &prohibited={})
return the person router instance
std::vector< MSStoppingPlace * > getPlaces() const
return all stoppingPlaces associated with this stop
Definition MSStop.cpp:227
bool joinTriggered
whether coupling another vehicle (train) the vehicle continue
Definition MSStop.h:73
SUMOTime getMinDuration(SUMOTime time) const
return minimum stop duration when starting stop at time
Definition MSStop.cpp:173
bool reached
Information whether the stop has been reached.
Definition MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition MSStop.h:65
A lane area vehicles can halt at.
std::vector< const SUMOVehicle * > getStoppedVehicles() const
get list of vehicles waiting at this stop
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.
std::map< std::string, double > StoppingPlaceParamMap_t
MSStoppingPlace * rerouteStoppingPlace(MSStoppingPlace *destStoppingPlace, const std::vector< StoppingPlaceVisible > &stoppingPlaceCandidates, const std::vector< double > &probs, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute, StoppingPlaceParamMap_t &scores, const Prohibitions &closedEdges={}, const int insertStopIndex=0, const bool keepCurrentStop=true)
main method to trigger the rerouting to the "best" StoppingPlace according to the custom evaluation f...
std::pair< MSStoppingPlace *, bool > StoppingPlaceVisible
The parent class for traffic light logics.
SUMOTime setPermissions(const SUMOTime currentTime)
Sets the edge permission if there are any defined in the closingEdge.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Tries to reroute the vehicle.
int getNumberStoppingPlaceReroutes(SUMOVehicle &veh)
ask how many times already the vehicle has been rerouted to another stopping place
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Triggers rerouting (once) for vehicles that are already on the edge when the rerouter activates.
static MSRailSignal * findSignal(ConstMSEdgeVector::const_iterator begin, ConstMSEdgeVector::const_iterator end)
find the last downstream signal on the given route
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Removes the reminder.
MSTriggeredRerouter(const std::string &id, const MSEdgeVector &edges, double prob, bool off, bool optional, SUMOTime timeThreshold, const std::string &vTypes, const Position &pos, const double radius)
Constructor.
double getStoppingPlaceOccupancy(MSStoppingPlace *sp, const SUMOVehicle *veh)
Return the number of occupied places of the stopping place.
double getUserProbability() const
Returns the rerouting probability given by the user.
static const double DEFAULT_MAXDELAY
MSParkingArea * rerouteParkingArea(const MSTriggeredRerouter::RerouteInterval *rerouteDef, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute)
search for an alternative ParkingArea
bool myHaveParkProbs
whether this rerouter has loaded parkingReroute definitions
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
bool myHaveClosingUntil
whether closed edges with known duration are loaded
bool myAmOptional
Information whether the rerouting will only take place on request.
static bool affected(const std::set< SUMOTrafficObject::NumericalID > &edgeIndices, const MSEdgeVector &closed)
void setUserUsageProbability(double prob)
Sets the probability with which a vehicle is rerouted given by the user.
Position myPosition
Where are we located in the network.
std::pair< const SUMOVehicle *, MSRailSignal * > overtakingTrain(const SUMOVehicle &veh, ConstMSEdgeVector::const_iterator mainStart, const OvertakeLocation &oloc, double &netSaving)
determine whether veh should switch from main to siding to be overtaken and return the overtaking veh...
void rememberStoppingPlaceScore(SUMOVehicle &veh, MSStoppingPlace *parkingArea, const std::string &score)
store the score of the ParkingArea in the vehicle
void rememberBlockedStoppingPlace(SUMOVehicle &veh, const MSStoppingPlace *parkingArea, bool blocked)
store the blocked ParkingArea in the vehicle
static MSEdge mySpecialDest_terminateRoute
virtual void myEndElement(int element)
Called when a closing tag occurs.
void checkStopSwitch(MSBaseVehicle &veh, const MSTriggeredRerouter::RerouteInterval *def)
consider switching the location of the upcoming stop
void resetClosedEdges(bool hasReroutingDevice, const SUMOTrafficObject &o)
reset router after closing edges
bool triggerRouting(SUMOTrafficObject &veh, MSMoveReminder::Notification reason)
double myRadius
At which distance are we activated.
void resetStoppingPlaceScores(SUMOVehicle &veh)
reset all stored ParkingArea scores for this vehicle
double myProbability
The probability and the user-given probability.
SUMOTime sawBlockedStoppingPlace(SUMOVehicle &veh, MSStoppingPlace *parkingArea, bool local)
get the time the ParkingArea was considered full from this vehicle
virtual ~MSTriggeredRerouter()
Destructor.
bool inUserMode() const
Returns whether the user is setting the rerouting probability.
void setNumberStoppingPlaceReroutes(SUMOVehicle &veh, int value)
update the number of reroutes for the vehicle
std::set< const MSStoppingPlace * > myBlockedStoppingPlaces
double getStoppingPlaceCapacity(MSStoppingPlace *sp)
Return the number of places the stopping place provides.
std::set< std::string > myVehicleTypes
The vehicle types to look for (empty means all)
const RerouteInterval * getCurrentReroute(SUMOTime time, SUMOTrafficObject &obj) const
Returns the rerouting definition valid for the given time and object, nullptr if none.
static void checkParkingRerouteConsistency()
issues warning for incomplete parkingReroute relationships
static std::map< std::string, MSTriggeredRerouter * > myInstances
bool applies(const SUMOTrafficObject &obj) const
Checks whether the detector measures objects of the given type.
bool myAmInUserMode
Information whether the current rerouting probability is the user-given.
static MSRailSignal * getRailSignal(const MSEdge *edge)
return railsignal at that edge or nullptr
const MSEdgeVector myEdges
edges where vehicles are notified
std::map< const MSEdge *, RouterProhibition > Prohibitions
static MSEdge mySpecialDest_keepDestination
special destination values
RerouteInterval myParsedRerouteInterval
used during loading
double getProbability() const
Returns the rerouting probability.
std::vector< RerouteInterval > myIntervals
List of rerouting definition intervals.
double getLastStepStoppingPlaceOccupancy(MSStoppingPlace *sp, const SUMOVehicle *veh)
Return the number of occupied places of the stopping place from the previous time step.
void setUserMode(bool val)
Sets whether the process is currently steered by the user.
The class responsible for building and deletion of vehicles.
std::map< std::string, SUMOVehicle * >::const_iterator constVehIt
Definition of the internal vehicles map iterator.
constVehIt loadedVehBegin() const
Returns the begin of the internal vehicle map.
constVehIt loadedVehEnd() const
Returns the end of the internal vehicle map.
const std::set< std::string > getVTypeDistributionMembership(const std::string &id) const
Return the distribution IDs the vehicle type is a member of.
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
const std::string & getOriginalID() const
Returns the id of the original vehicle type if this is a vehicle specific type, the id otherwise.
Base class for objects which have an id.
Definition Named.h:53
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:66
const std::string & getID() const
Returns the id.
Definition Named.h:73
static OptionsCont & getOptions()
Retrieves the options.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:323
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimensions
Definition Position.h:263
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Represents a generic random distribution.
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
T get(SumoRNG *which=nullptr) const
Draw a sample of the distribution.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
const std::vector< T > & getVals() const
Returns the members of the distribution.
bool remove(T val)
Removes a value with an assigned probability from the distribution.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
Representation of a vehicle, person, or container.
virtual bool ignoreTransientPermissions() const
Returns whether this object is ignoring transient permission changes (during routing)
virtual bool isVehicle() const
Whether it is a vehicle.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual const SUMOVTypeParameter & getVTypeParameter() const =0
Returns the object's "vehicle" type parameter.
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 bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true, std::string *msgReturn=nullptr)=0
Replaces the current route by the given one.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual double getMaxSpeed() const =0
Returns the object's maximum speed (minimum of technical and desired maximum speed)
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
virtual SumoRNG * getRNG() const =0
Returns the associated RNG for this object.
virtual Position getPosition(const double offset=0) const =0
Return current position (x/y, cartesian)
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 std::set< NumericalID > getUpcomingEdgeIDs() const =0
returns the numerical IDs of edges to be used (possibly of future stages)
virtual void setRoutingMode(int value)=0
Sets routing behavior.
virtual const MSEdge * getEdge() const =0
Returns the (normal) route edge the object is currently at.
virtual const MSEdge * getRerouteDestination() const =0
Returns the end point for reroutes (usually the last edge of the route)
virtual int getRoutingMode() const =0
return routing mode (configures router choice but also handling of transient permission changes)
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:63
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 SUMOTime sawBlockedParkingArea(const MSStoppingPlace *pa, bool local) const =0
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 bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)=0
Replaces a stop.
virtual bool hasStops() const =0
Returns whether the vehicle has to stop somewhere.
virtual MSParkingArea * getNextParkingArea()=0
virtual void rememberParkingAreaScore(const MSStoppingPlace *pa, const std::string &score)=0
virtual void rememberBlockedParkingArea(const MSStoppingPlace *pa, bool local)=0
virtual double getLength() const =0
Returns the vehicles's length.
virtual int getNumberParkingReroutes() const =0
virtual const std::vector< MSTransportable * > & getPersons() const =0
retrieve riding persons
virtual void replaceParameter(const SUMOVehicleParameter *newParameter)=0
Replaces the vehicle's parameter.
virtual void resetParkingAreaScores()=0
virtual const MSStop & getNextStop() const =0
virtual void setArrivalPos(double arrivalPos)=0
Sets this vehicle's desired arrivalPos for its current route.
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
virtual void setNumberParkingReroutes(int value)=0
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)
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
std::string overheadWireSegment
(Optional) overhead line segment if one is assigned to the stop
SUMOTime until
The time at which the vehicle may continue its journey.
double endPos
The stopping position end.
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
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
double arrivalPos
(optional) The position the vehicle shall arrive on
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
A scoped lock which only triggers on condition.
std::vector< std::string > getVector()
return vector of strings
A wrapper for a Command function.
TRACI_CONST int ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS
double sidingLength
The usable length of the siding.
MSEdgeVector main
The list of main edges (const and non-const for different usage)
bool defer
whether the decision to use this siding should be deferred
double minSaving
The threshold in savings for triggering reroute.
MSEdgeVector siding
The list of siding edges.
MSRailSignal * sidingExit
The rail signal at the end of the siding.
SUMOTime begin
The begin time these definitions are valid.
RandomDistributor< MSStoppingPlaceRerouter::StoppingPlaceVisible > parkProbs
The distributions of new parking areas to use as destinations.
std::vector< MSStoppingPlaceRerouter::StoppingPlaceVisible > stopAlternatives
RandomDistributor< ConstMSRoutePtr > routeProbs
The distributions of new routes to use.
SUMOTime end
The end time these definitions are valid.
RandomDistributor< MSEdge * > edgeProbs
The distributions of new destinations or vias to use.
std::map< MSLane *, SVCPermissions > closedLanes
The list of closed lanes to their permissions.
bool isVia
The edge probs are vias and not destinations.
MSEdgeVector closedLanesAffected
The list of edges that are affected by closed lanes.
bool permissionsAllowAll
The permissions are all SVCAll.
std::map< MSEdge *, std::pair< SVCPermissions, double > > closed
The map of closed edges to their permissions and expected end of closing.
std::vector< OvertakeLocation > overtakeLocations