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-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
22// Reroutes vehicles passing an edge
23/****************************************************************************/
24#include <config.h>
25
26#include <string>
27#include <algorithm>
28#ifdef HAVE_FOX
30#endif
43#include <microsim/MSLane.h>
44#include <microsim/MSLink.h>
45#include <microsim/MSVehicle.h>
47#include <microsim/MSRoute.h>
48#include <microsim/MSEdge.h>
50#include <microsim/MSNet.h>
52#include <microsim/MSGlobals.h>
54#include <microsim/MSStop.h>
60#include "MSTriggeredRerouter.h"
61
62#include <mesosim/MELoop.h>
63#include <mesosim/MESegment.h>
64
65//#define DEBUG_REROUTER
66#define DEBUGCOND(veh) (veh.isSelected())
67//#define DEBUGCOND(veh) (true)
68//#define DEBUGCOND(veh) (veh.getID() == "")
69
71#define DEFAULT_PRIO_OVERTAKER 1
72#define DEFAULT_PRIO_OVERTAKEN 0
73
74// ===========================================================================
75// static member definition
76// ===========================================================================
77MSEdge MSTriggeredRerouter::mySpecialDest_keepDestination("MSTriggeredRerouter_keepDestination", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
78MSEdge MSTriggeredRerouter::mySpecialDest_terminateRoute("MSTriggeredRerouter_terminateRoute", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
80std::map<std::string, MSTriggeredRerouter*> MSTriggeredRerouter::myInstances;
81
82
83// ===========================================================================
84// method definitions
85// ===========================================================================
87 const MSEdgeVector& edges, double prob, bool off, bool optional,
88 SUMOTime timeThreshold, const std::string& vTypes, const Position& pos, const double radius) :
89 Named(id),
91 MSStoppingPlaceRerouter("parking"),
92 myEdges(edges),
93 myProbability(prob),
94 myUserProbability(prob),
95 myAmInUserMode(false),
96 myAmOptional(optional),
97 myPosition(pos),
98 myRadius(radius),
99 myTimeThreshold(timeThreshold),
100 myHaveParkProbs(false) {
101 myInstances[id] = this;
102 // build actors
103 for (const MSEdge* const e : edges) {
106 }
107 for (MSLane* const lane : e->getLanes()) {
108 lane->addMoveReminder(this);
109 }
110 }
111 if (off) {
112 setUserMode(true);
114 }
115 const std::vector<std::string> vt = StringTokenizer(vTypes).getVector();
116 myVehicleTypes.insert(vt.begin(), vt.end());
118 myPosition = edges.front()->getLanes()[0]->getShape()[0];
119 }
120}
121
122
126
127
128// ------------ loading begin
129void
131 const SUMOSAXAttributes& attrs) {
132 if (element == SUMO_TAG_INTERVAL) {
133 bool ok = true;
138 throw ProcessError(TLF("rerouter '%': interval end % is not after begin %.", getID(),
141 }
142 }
143 if (element == SUMO_TAG_DEST_PROB_REROUTE) {
144 // by giving probabilities of new destinations
145 // get the destination edge
146 std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
147 if (dest == "") {
148 throw ProcessError(TLF("rerouter '%': destProbReroute has no destination edge id.", getID()));
149 }
150 MSEdge* to = MSEdge::dictionary(dest);
151 if (to == nullptr) {
152 if (dest == "keepDestination") {
154 } else if (dest == "terminateRoute") {
156 } else {
157 throw ProcessError(TLF("rerouter '%': Destination edge '%' is not known.", getID(), dest));
158 }
159 }
160 // get the probability to reroute
161 bool ok = true;
162 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
163 if (!ok) {
164 throw ProcessError();
165 }
166 if (prob < 0) {
167 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for destination '%' is negative (must not).", getID(), dest));
168 }
169 // add
171 }
172
173 if (element == SUMO_TAG_CLOSING_REROUTE) {
174 // by closing edge
175 const std::string& closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
176 MSEdge* const closedEdge = MSEdge::dictionary(closed_id);
177 if (closedEdge == nullptr) {
178 throw ProcessError(TLF("rerouter '%': Edge '%' to close is not known.", getID(), closed_id));
179 }
180 bool ok;
181 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
182 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
183 const SUMOTime until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, -1);
184 SVCPermissions permissions = parseVehicleClasses(allow, disallow);
185 myParsedRerouteInterval.closed[closedEdge] = std::make_pair(permissions, STEPS2TIME(until));
186 }
187
188 if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
189 // by closing lane
190 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
191 MSLane* closedLane = MSLane::dictionary(closed_id);
192 if (closedLane == nullptr) {
193 throw ProcessError(TLF("rerouter '%': Lane '%' to close is not known.", getID(), closed_id));
194 }
195 bool ok;
196 SVCPermissions permissions = SVC_AUTHORITY;
198 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
199 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
200 permissions = parseVehicleClasses(allow, disallow);
201 }
202 myParsedRerouteInterval.closedLanes[closedLane] = permissions;
203 }
204
205 if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
206 // by explicit rerouting using routes
207 // check if route exists
208 std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
209 if (routeStr == "") {
210 throw ProcessError(TLF("rerouter '%': routeProbReroute has no alternative route id.", getID()));
211 }
212 ConstMSRoutePtr route = MSRoute::dictionary(routeStr);
213 if (route == nullptr) {
214 throw ProcessError(TLF("rerouter '%': Alternative route '%' does not exist.", getID(), routeStr));
215 }
216
217 // get the probability to reroute
218 bool ok = true;
219 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
220 if (!ok) {
221 throw ProcessError();
222 }
223 if (prob < 0) {
224 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for alternative route '%' is negative (must not).", getID(), routeStr));
225 }
226 // add
228 }
229
230 if (element == SUMO_TAG_PARKING_AREA_REROUTE) {
231 std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
232 if (parkingarea == "") {
233 throw ProcessError(TLF("rerouter '%': parkingAreaReroute requires a parkingArea id.", getID()));
234 }
236 if (pa == nullptr) {
237 throw ProcessError(TLF("rerouter '%': parkingArea '%' is not known.", getID(), parkingarea));
238 }
239 // get the probability to reroute
240 bool ok = true;
241 const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
242 if (!ok) {
243 throw ProcessError();
244 }
245 if (prob < 0) {
246 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for parkingArea '%' is negative (must not).", getID(), parkingarea));
247 }
248 const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
249 // add
250 myParsedRerouteInterval.parkProbs.add(std::make_pair(pa, visible), prob);
251 myHaveParkProbs = true;
252 }
253
254 if (element == SUMO_TAG_VIA_PROB_REROUTE) {
255 // by giving probabilities of vias
256 std::string viaID = attrs.getStringSecure(SUMO_ATTR_ID, "");
257 if (viaID == "") {
258 throw ProcessError(TLF("rerouter '%': No via edge id given.", getID()));
259 }
260 MSEdge* const via = MSEdge::dictionary(viaID);
261 if (via == nullptr) {
262 throw ProcessError(TLF("rerouter '%': Via Edge '%' is not known.", getID(), viaID));
263 }
264 // get the probability to reroute
265 bool ok = true;
266 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
267 if (!ok) {
268 throw ProcessError();
269 }
270 if (prob < 0) {
271 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for via '%' is negative (must not).", getID(), viaID));
272 }
273 // add
276 }
277 if (element == SUMO_TAG_OVERTAKING_REROUTE) {
278 // for letting a slow train use a siding to be overtaken by a fast train
279 bool ok = true;
280 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_MAIN, getID().c_str(), ok)) {
281 MSEdge* edge = MSEdge::dictionary(edgeID);
282 if (edge == nullptr) {
283 throw InvalidArgument(TLF("The main edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
284 }
285 myParsedRerouteInterval.main.push_back(edge);
286 myParsedRerouteInterval.cMain.push_back(edge);
287 }
288 for (const std::string& edgeID : attrs.get<std::vector<std::string> >(SUMO_ATTR_SIDING, getID().c_str(), ok)) {
289 MSEdge* edge = MSEdge::dictionary(edgeID);
290 if (edge == nullptr) {
291 throw InvalidArgument(TLF("The siding edge '%' to use within rerouter '%' is not known.", edgeID, getID()));
292 }
293 myParsedRerouteInterval.siding.push_back(edge);
294 myParsedRerouteInterval.cSiding.push_back(edge);
295 }
297 if (myParsedRerouteInterval.sidingExit == nullptr) {
298 throw InvalidArgument(TLF("The siding within rerouter '%' does not have a rail signal.", getID()));
299 }
300 for (auto it = myParsedRerouteInterval.cSiding.begin(); it != myParsedRerouteInterval.cSiding.end(); it++) {
301 myParsedRerouteInterval.sidingLength += (*it)->getLength();
302 if ((*it)->getToJunction()->getID() == myParsedRerouteInterval.sidingExit->getID()) {
303 break;
304 }
305 }
306 myParsedRerouteInterval.minSaving = attrs.getOpt<double>(SUMO_ATTR_MINSAVING, getID().c_str(), ok, 300);
307 }
308 if (element == SUMO_TAG_STATION_REROUTE) {
309 // for letting a train switch it's stopping place in case of conflict
310 const std::string stopID = attrs.getStringSecure(SUMO_ATTR_ID, "");
311 if (stopID == "") {
312 throw ProcessError(TLF("rerouter '%': stationReroute requires a stopping place id.", getID()));
313 }
315 if (stop == nullptr) {
316 throw ProcessError(TLF("rerouter '%': stopping place '%' is not known.", getID(), stopID));
317 }
318 myParsedRerouteInterval.stopAlternatives.push_back(std::make_pair(stop, true));
319 }
320}
321
322
323void
325 if (element == SUMO_TAG_INTERVAL) {
326 // precompute permissionsAllowAll
327 bool allowAll = true;
328 for (const auto& entry : myParsedRerouteInterval.closed) {
329 allowAll = allowAll && entry.second.first == SVCAll;
330 if (!allowAll) {
331 break;
332 }
333 }
335
336 for (auto paVi : myParsedRerouteInterval.parkProbs.getVals()) {
337 dynamic_cast<MSParkingArea*>(paVi.first)->setNumAlternatives((int)myParsedRerouteInterval.parkProbs.getVals().size() - 1);
338 }
339 if (myParsedRerouteInterval.closedLanes.size() > 0) {
340 // collect edges that are affect by a closed lane
341 std::set<MSEdge*> affected;
342 for (std::pair<MSLane*, SVCPermissions> settings : myParsedRerouteInterval.closedLanes) {
343 affected.insert(&settings.first->getEdge());
344 }
346 }
347 const SUMOTime closingBegin = myParsedRerouteInterval.begin;
348 const SUMOTime simBegin = string2time(OptionsCont::getOptions().getString("begin"));
349 if (closingBegin < simBegin && myParsedRerouteInterval.end > simBegin) {
350 // interval started before simulation begin but is still active at
351 // the start of the simulation
353 }
355 myIntervals.back().id = (long long int)&myIntervals.back();
359 }
360 }
361}
362
363
364// ------------ loading end
365
366
369 bool updateVehicles = false;
370 for (const RerouteInterval& i : myIntervals) {
371 if (i.begin == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
372 for (const auto& settings : i.closed) {
373 for (MSLane* lane : settings.first->getLanes()) {
374 //std::cout << SIMTIME << " closing: intervalID=" << i.id << " lane=" << lane->getID() << " prevPerm=" << getVehicleClassNames(lane->getPermissions()) << " new=" << getVehicleClassNames(i.permissions) << "\n";
375 lane->setPermissions(settings.second.first, i.id);
376 }
377 settings.first->rebuildAllowedLanes();
378 updateVehicles = true;
379 }
380 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
381 settings.first->setPermissions(settings.second, i.id);
382 settings.first->getEdge().rebuildAllowedLanes();
383 updateVehicles = true;
384 }
387 }
388 if (i.end == currentTime && !(i.closed.empty() && i.closedLanes.empty()) /*&& i.permissions != SVCAll*/) {
389 for (auto settings : i.closed) {
390 for (MSLane* lane : settings.first->getLanes()) {
391 lane->resetPermissions(i.id);
392 //std::cout << SIMTIME << " opening: intervalID=" << i.id << " lane=" << lane->getID() << " restore prevPerm=" << getVehicleClassNames(lane->getPermissions()) << "\n";
393 }
394 settings.first->rebuildAllowedLanes();
395 updateVehicles = true;
396 }
397 for (std::pair<MSLane*, SVCPermissions> settings : i.closedLanes) {
398 settings.first->resetPermissions(i.id);
399 settings.first->getEdge().rebuildAllowedLanes();
400 updateVehicles = true;
401 }
402 }
403 }
404 if (updateVehicles) {
405 // only vehicles on the affected lanes had their bestlanes updated so far
406 for (MSEdge* e : myEdges) {
407 // also updates vehicles
408 e->rebuildAllowedTargets();
409 }
410 }
411 return 0;
412}
413
414
417 for (const RerouteInterval& ri : myIntervals) {
418 if (ri.begin <= time && ri.end > time) {
419 if (
420 // destProbReroute
421 ri.edgeProbs.getOverallProb() > 0 ||
422 // routeProbReroute
423 ri.routeProbs.getOverallProb() > 0 ||
424 // parkingZoneReroute
425 ri.parkProbs.getOverallProb() > 0 ||
426 // stationReroute
427 ri.stopAlternatives.size() > 0) {
428 return &ri;
429 }
430 if (!ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.main.empty()) {
431 const std::set<SUMOTrafficObject::NumericalID>& edgeIndices = obj.getUpcomingEdgeIDs();
432 if (affected(edgeIndices, ri.getClosedEdges())
433 || affected(edgeIndices, ri.closedLanesAffected)
434 || affected(edgeIndices, ri.main)) {
435 return &ri;
436 }
437 }
438 }
439 }
440 return nullptr;
441}
442
443
446 for (const RerouteInterval& ri : myIntervals) {
447 if (ri.begin <= time && ri.end > time) {
448 if (ri.edgeProbs.getOverallProb() != 0 || ri.routeProbs.getOverallProb() != 0 || ri.parkProbs.getOverallProb() != 0
449 || !ri.closed.empty() || !ri.closedLanesAffected.empty() || !ri.main.empty()) {
450 return &ri;
451 }
452 }
453 }
454 return nullptr;
455}
456
457
458bool
460 if (myAmOptional || myRadius != std::numeric_limits<double>::max()) {
461 return true;
462 }
463 return triggerRouting(tObject, reason);
464}
465
466
467bool
469 double /*newPos*/, double /*newSpeed*/) {
471}
472
473
474bool
476 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
477 return reason == NOTIFICATION_LANE_CHANGE;
478}
479
480
481bool
483 if (!applies(tObject)) {
484 return false;
485 }
486 if (myRadius != std::numeric_limits<double>::max() && tObject.getPosition().distanceTo(myPosition) > myRadius) {
487 return true;
488 }
489 // check whether the vehicle shall be rerouted
491 const MSTriggeredRerouter::RerouteInterval* const rerouteDef = getCurrentReroute(now, tObject);
492 if (rerouteDef == nullptr) {
493 return true; // an active interval could appear later
494 }
495 const double prob = myAmInUserMode ? myUserProbability : myProbability;
496 if (prob < 1 && RandHelper::rand(tObject.getRNG()) > prob) {
497 return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
498 }
499 if (myTimeThreshold > 0 && MAX2(tObject.getWaitingTime(), tObject.getWaitingTime(true)) < myTimeThreshold) {
500 return true; // waiting time may be reached later
501 }
502 if (reason == NOTIFICATION_LANE_CHANGE) {
503 return false;
504 }
505 // if we have a closingLaneReroute, only vehicles with a rerouting device can profit from rerouting (otherwise, edge weights will not reflect local jamming)
506 const bool hasReroutingDevice = tObject.getDevice(typeid(MSDevice_Routing)) != nullptr;
507 if (rerouteDef->closedLanes.size() > 0 && !hasReroutingDevice) {
508 return true; // an active interval could appear later
509 }
510 const MSEdge* lastEdge = tObject.getRerouteDestination();
511#ifdef DEBUG_REROUTER
512 if (DEBUGCOND(tObject)) {
513 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";
514 }
515#endif
516
517 if (rerouteDef->parkProbs.getOverallProb() > 0) {
518#ifdef HAVE_FOX
519 ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
520#endif
521 if (!tObject.isVehicle()) {
522 return false;
523 }
524 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
525 bool newDestination = false;
526 ConstMSEdgeVector newRoute;
527 MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination, newRoute);
528 if (newParkingArea != nullptr) {
529 // adapt plans of any riders
530 for (MSTransportable* p : veh.getPersons()) {
531 p->rerouteParkingArea(veh.getNextParkingArea(), newParkingArea);
532 }
533
534 if (newDestination) {
535 // update arrival parameters
536 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
537 *newParameter = veh.getParameter();
539 newParameter->arrivalPos = newParkingArea->getEndLanePosition();
540 veh.replaceParameter(newParameter);
541 }
542
543 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
544 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
545 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
546 const double routeCost = router.recomputeCosts(newRoute, &veh, MSNet::getInstance()->getCurrentTimeStep());
547 ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
548 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
549 const double savings = previousCost - routeCost;
550 resetClosedEdges(hasReroutingDevice, veh);
551 //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
552 // << " prevEdges=" << toString(prevEdges)
553 // << " newEdges=" << toString(edges)
554 // << "\n";
555
556 std::string errorMsg;
557 if (veh.replaceParkingArea(newParkingArea, errorMsg)) {
558 veh.replaceRouteEdges(newRoute, routeCost, savings, getID() + ":" + toString(SUMO_TAG_PARKING_AREA_REROUTE), false, false, false);
559 } else {
560 WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
561 + "' could not reroute to new parkingArea '" + newParkingArea->getID()
562 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
563 }
564 }
565 return false;
566 }
567 if (rerouteDef->main.size() > 0) {
568 if (!tObject.isVehicle()) {
569 return false;
570 }
571 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
572 if (veh.getLength() > rerouteDef->sidingLength) {
573 return false;
574 }
575 const ConstMSEdgeVector& oldEdges = veh.getRoute().getEdges();
576 auto mainStart = std::find(veh.getCurrentRouteEdge(), oldEdges.end(), rerouteDef->main.front());
577 if (mainStart == oldEdges.end()
578 // exit main within
579 || ConstMSEdgeVector(mainStart, mainStart + rerouteDef->main.size()) != rerouteDef->cMain
580 // stop in main
581 || (veh.hasStops() && veh.getNextStop().edge < (mainStart + rerouteDef->main.size()))) {
582 //std::cout << SIMTIME << " veh=" << veh.getID() << " wrong route or stop\n";
583 return false;
584 }
585 std::pair<const SUMOVehicle*, MSRailSignal*> overtaker_signal = overtakingTrain(veh, mainStart, rerouteDef);
586 if (overtaker_signal.first != nullptr) {
587 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
588 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->getClosed())
589 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->getClosed());
590 ConstMSEdgeVector newEdges(veh.getCurrentRouteEdge(), mainStart);
591 newEdges.insert(newEdges.end(), rerouteDef->siding.begin(), rerouteDef->siding.end());
592 newEdges.insert(newEdges.end(), mainStart + rerouteDef->main.size(), oldEdges.end());
593 const double routeCost = router.recomputeCosts(newEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
594 const double savings = (router.recomputeCosts(rerouteDef->cMain, &veh, MSNet::getInstance()->getCurrentTimeStep())
595 - router.recomputeCosts(rerouteDef->cSiding, &veh, MSNet::getInstance()->getCurrentTimeStep()));
596 const std::string info = getID() + ":" + toString(SUMO_TAG_OVERTAKING_REROUTE) + ":" + overtaker_signal.first->getID();
597 veh.replaceRouteEdges(newEdges, routeCost, savings, info, false, false, false);
599 MSRailSignalConstraint::PREDECESSOR, overtaker_signal.second, overtaker_signal.first->getID(), 100, true));
600 resetClosedEdges(hasReroutingDevice, veh);
601 }
602 return false;
603 }
604 if (rerouteDef->stopAlternatives.size() > 0) {
605 // somewhat similar to parkProbs but taking into account public transport schedule
606 if (!tObject.isVehicle()) {
607 return false;
608 }
609 checkStopSwitch(static_cast<MSBaseVehicle&>(tObject), rerouteDef);
610 }
611 // get rerouting params
612 ConstMSRoutePtr newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : nullptr;
613 // we will use the route if given rather than calling our own dijsktra...
614 if (newRoute != nullptr) {
615#ifdef DEBUG_REROUTER
616 if (DEBUGCOND(tObject)) {
617 std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
618 }
619#endif
620 tObject.replaceRoute(newRoute, getID());
621 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
622 }
623 const MSEdge* newEdge = lastEdge;
624 // ok, try using a new destination
625 double newArrivalPos = -1;
626 const MSEdgeVector closedEdges = rerouteDef->getClosedEdges();
627 const bool destUnreachable = std::find(closedEdges.begin(), closedEdges.end(), lastEdge) != closedEdges.end();
628 bool keepDestination = false;
629 // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
630 // if we have a closingLaneReroute, no new destinations should be assigned
631 if (closedEdges.empty() || destUnreachable || rerouteDef->isVia) {
632 newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : lastEdge;
633 assert(newEdge != nullptr);
634 if (newEdge == &mySpecialDest_terminateRoute) {
635 keepDestination = true;
636 newEdge = tObject.getEdge();
637 newArrivalPos = tObject.getPositionOnLane(); // instant arrival
638 } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
639 if (destUnreachable && rerouteDef->permissionsAllowAll) {
640 // if permissions aren't set vehicles will simply drive through
641 // the closing unless terminated. If the permissions are specified, assume that the user wants
642 // vehicles to stand and wait until the closing ends
643 WRITE_WARNINGF(TL("Cannot keep destination edge '%' for vehicle '%' due to closed edges. Terminating route."), lastEdge->getID(), tObject.getID());
644 newEdge = tObject.getEdge();
645 } else {
646 newEdge = lastEdge;
647 }
648 }
649 }
650 ConstMSEdgeVector edges;
651 std::vector<MSTransportableRouter::TripItem> items;
652 // we have a new destination, let's replace the route (if it is affected)
653 MSEdgeVector closed = rerouteDef->getClosedEdges();
654 Prohibitions prohibited = rerouteDef->getClosed();
655 if (rerouteDef->closed.empty() || destUnreachable || rerouteDef->isVia || affected(tObject.getUpcomingEdgeIDs(), closed)) {
656 if (tObject.isVehicle()) {
657 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
658 const bool canChangeDest = rerouteDef->edgeProbs.getOverallProb() > 0;
659 MSVehicleRouter& router = hasReroutingDevice
660 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
661 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
662 bool ok = veh.reroute(now, getID(), router, false, false, canChangeDest, newEdge);
663 if (!ok && !keepDestination && canChangeDest) {
664 // destination unreachable due to closed intermediate edges. pick among alternative targets
665 RandomDistributor<MSEdge*> edgeProbs2 = rerouteDef->edgeProbs;
666 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
667 while (!ok && edgeProbs2.getVals().size() > 0) {
668 newEdge = edgeProbs2.get();
669 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
670 if (newEdge == &mySpecialDest_terminateRoute) {
671 newEdge = veh.getEdge();
672 newArrivalPos = veh.getPositionOnLane(); // instant arrival
673 }
674 if (newEdge == &mySpecialDest_keepDestination && !rerouteDef->permissionsAllowAll) {
675 newEdge = lastEdge;
676 break;
677 }
678 ok = veh.reroute(now, getID(), router, false, false, true, newEdge);
679 }
680
681 }
682 if (!rerouteDef->isVia) {
683#ifdef DEBUG_REROUTER
684 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
685 << " newEdges=" << toString(edges)
686 << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
687 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->getClosed()) << "\n";
688#endif
689 if (ok && newArrivalPos != -1) {
690 // must be called here because replaceRouteEdges may also set the arrivalPos
691 veh.setArrivalPos(newArrivalPos);
692 }
693
694 }
695 } else {
696 // person rerouting here
697 MSTransportableRouter& router = hasReroutingDevice
699 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
700 const bool success = router.compute(tObject.getEdge(), newEdge, tObject.getPositionOnLane(), "",
701 rerouteDef->isVia ? newEdge->getLength() / 2. : tObject.getParameter().arrivalPos, "",
702 tObject.getMaxSpeed(), nullptr, 0, now, items);
703 if (!rerouteDef->isVia) {
704 if (success) {
705 for (const MSTransportableRouter::TripItem& it : items) {
706 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
707 edges.pop_back();
708 }
709 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
710 if (!edges.empty()) {
711 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
712 }
713 }
714 } else {
715 // maybe the pedestrian model still finds a way (JuPedSim)
716 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge}, tObject.getPositionOnLane(), 0, 1);
717 }
718 }
719 }
720 if (!prohibited.empty()) {
721 resetClosedEdges(hasReroutingDevice, tObject);
722 }
723 }
724 // it was only a via so calculate the remaining part
725 if (rerouteDef->isVia) {
726 if (tObject.isVehicle()) {
727 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
728 if (!edges.empty()) {
729 edges.pop_back();
730 }
731 MSVehicleRouter& router = hasReroutingDevice
732 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), prohibited)
733 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), prohibited);
734 router.compute(newEdge, lastEdge, &veh, now, edges);
735 const double routeCost = router.recomputeCosts(edges, &veh, now);
736 hasReroutingDevice
738 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
739 const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
740#ifdef DEBUG_REROUTER
741 if (DEBUGCOND(tObject)) std::cout << " rerouting: newDest=" << newEdge->getID()
742 << " newEdges=" << toString(edges)
743 << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
744 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->getClosed()) << "\n";
745#endif
746 if (useNewRoute && newArrivalPos != -1) {
747 // must be called here because replaceRouteEdges may also set the arrivalPos
748 veh.setArrivalPos(newArrivalPos);
749 }
750 } else {
751 // person rerouting here
752 bool success = !items.empty();
753 if (success) {
754 MSTransportableRouter& router = hasReroutingDevice
756 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, prohibited);
757 success = router.compute(newEdge, lastEdge, newEdge->getLength() / 2., "",
758 tObject.getParameter().arrivalPos, "",
759 tObject.getMaxSpeed(), nullptr, 0, now, items);
760 }
761 if (success) {
762 for (const MSTransportableRouter::TripItem& it : items) {
763 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
764 edges.pop_back();
765 }
766 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
767 }
768 if (!edges.empty()) {
769 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
770 }
771 } else {
772 // maybe the pedestrian model still finds a way (JuPedSim)
773 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge, lastEdge}, tObject.getPositionOnLane(), 0, 1);
774 }
775 }
776 if (!prohibited.empty()) {
777 resetClosedEdges(hasReroutingDevice, tObject);
778 }
779 }
780 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
781}
782
783
784void
788
789
790void
794
795
796bool
800
801
802double
806
807
808double
812
813
814double
816 return (double)(sp->getElement() == SUMO_TAG_PARKING_AREA
817 ? dynamic_cast<MSParkingArea*>(sp)->getOccupancy()
818 : sp->getStoppedVehicles().size());
819}
820
821
822double
824 return (double)(sp->getElement() == SUMO_TAG_PARKING_AREA
825 ? dynamic_cast<MSParkingArea*>(sp)->getLastStepOccupancy()
826 : sp->getStoppedVehicles().size());
827}
828
829
830double
832 if (myBlockedStoppingPlaces.count(sp) == 0) {
833 return (double)(sp->getElement() == SUMO_TAG_PARKING_AREA
834 ? dynamic_cast<MSParkingArea*>(sp)->getCapacity()
835 // assume only one vehicle at a time (for stationReroute)
836 : 1.);
837 } else {
838 return 0.;
839 }
840}
841
842
843void
845 veh.rememberBlockedParkingArea(parkingArea, blocked);
846}
847
848
849void
851 veh.rememberParkingAreaScore(parkingArea, score);
852}
853
854
855void
859
860
863 return veh.sawBlockedParkingArea(parkingArea, local);
864}
865
866
867int
871
872
873void
877
878
881 SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute) {
882 MSStoppingPlace* destStoppingPlace = veh.getNextParkingArea();
883 if (destStoppingPlace == nullptr) {
884 // not driving towards the right type of stop
885 return nullptr;
886 }
887 std::vector<StoppingPlaceVisible> parks;
888 for (auto cand : rerouteDef->parkProbs.getVals()) {
889 if (cand.first->accepts(&veh)) {
890 parks.push_back(cand);
891 }
892 }
893 StoppingPlaceParamMap_t addInput = {};
894 return dynamic_cast<MSParkingArea*>(rerouteStoppingPlace(destStoppingPlace, parks, rerouteDef->parkProbs.getProbs(), veh, newDestination, newRoute, addInput, rerouteDef->getClosed()));
895}
896
897
898std::pair<const SUMOVehicle*, MSRailSignal*>
899MSTriggeredRerouter::overtakingTrain(const SUMOVehicle& veh, ConstMSEdgeVector::const_iterator mainStart, const MSTriggeredRerouter::RerouteInterval* def) {
900 const MSEdgeVector& main = def->main;
901 const double vMax = veh.getMaxSpeed();
902 const double prio = veh.getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKEN, false);
904 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
905 const MSBaseVehicle* veh2 = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
906 if (veh2->isOnRoad() && veh2->getMaxSpeed() > vMax) {
907 const double arrivalDelay = veh2->getStopArrivalDelay();
908 const double delay = MAX2(veh2->getStopDelay(), arrivalDelay == INVALID_DOUBLE ? 0 : arrivalDelay);
909 if (delay > veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".maxDelay", false, DEFAULT_MAXDELAY, false)) {
910 continue;
911 }
912 const ConstMSEdgeVector& route2 = veh2->getRoute().getEdges();
913 auto itOnMain2 = route2.end();
914 int mainIndex = 0;
915 for (const MSEdge* m : main) {
916 itOnMain2 = std::find(veh2->getCurrentRouteEdge(), route2.end(), m);
917 if (itOnMain2 != route2.end()) {
918 break;
919 }
920 mainIndex++;
921 }
922 if (itOnMain2 != route2.end() && itOnMain2 > veh2->getCurrentRouteEdge()) {
923 auto itOnMain = mainStart + mainIndex;
924 double timeToMain = 0;
925 // veh2 may be anywhere on the current edge so we have to discount
926 double timeToMain2 = -veh2->getEdge()->getMinimumTravelTime(veh2) * veh2->getPositionOnLane() / veh2->getEdge()->getLength();
927 for (auto it = veh.getCurrentRouteEdge(); it != itOnMain; it++) {
928 timeToMain += (*it)->getMinimumTravelTime(&veh);
929 }
930 for (auto it = veh2->getCurrentRouteEdge(); it != itOnMain2; it++) {
931 timeToMain2 += (*it)->getMinimumTravelTime(veh2);
932 }
933 double exitMain2Time = timeToMain2;
934 double commonTime = 0;
935 double commonTime2 = 0;
936 int nCommon = 0;
937 auto exitMain2 = itOnMain2;
938 while (itOnMain2 != route2.end() && *itOnMain == *itOnMain2) {
939 const MSEdge* common = *itOnMain;
940 commonTime += common->getMinimumTravelTime(&veh);
941 commonTime2 += common->getMinimumTravelTime(veh2);
942 if (nCommon < (int)main.size() - mainIndex) {
943 exitMain2Time = timeToMain2 + commonTime2;
944 }
945 nCommon++;
946 itOnMain++;
947 itOnMain2++;
948 }
949 exitMain2 += MIN2(nCommon, (int)main.size() - mainIndex);
950 const double saving = timeToMain + commonTime - (timeToMain2 + commonTime2);
951 const double loss = exitMain2Time; // lower bound because veh2 also has to exit the block
952 const double prio2 = veh2->getFloatParam(toString(SUMO_TAG_OVERTAKING_REROUTE) + ".prio", false, DEFAULT_PRIO_OVERTAKER, false);
953 const double netSaving = prio2 * saving - prio * loss;
954 //std::cout << " veh=" << veh.getID() << " veh2=" << veh2->getID()
955 // << " nCommon=" << nCommon << " cT=" << commonTime << " cT2=" << commonTime2 << " ttm=" << timeToMain << " ttm2=" << timeToMain2
956 // << " saving=" << saving << " loss=" << loss << " prio=" << prio << " prio2=" << prio2 << " netSaving=" << netSaving << "\n";
957 if (netSaving > def->minSaving) {
958 MSRailSignal* s = findSignal(veh2->getCurrentRouteEdge(), exitMain2);
959 if (s != nullptr) {
960 return std::make_pair(veh2, s);
961 }
962 }
963 }
964 }
965 }
966 return std::make_pair(nullptr, nullptr);
967}
968
969
970void
973#ifdef DEBUG_REROUTER
974 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << "\n";
975#endif
976 if (!ego.hasStops()) {
977 return;
978 }
979 const MSStop& stop = ego.getNextStop();
980 if (stop.reached || stop.joinTriggered || (stop.pars.arrival < 0 && stop.pars.until < 0)) {
981 return;
982 }
983 MSStoppingPlace* cur = nullptr;
984 for (MSStoppingPlace* sp : stop.getPlaces()) {
985 for (auto item : def->stopAlternatives) {
986 if (sp == item.first) {
987 cur = sp;
988 break;
989 }
990 }
991 }
992 if (cur == nullptr) {
993 return;
994 }
995 std::vector<const SUMOVehicle*> stopped = cur->getStoppedVehicles();
996#ifdef DEBUG_REROUTER
997 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopped=" << toString(stopped) << "\n";
998#endif
999 SUMOTime stoppedDuration = -1;
1000 if (stopped.empty()) {
1002 const MSLane& stopLane = cur->getLane();
1004 for (MSVehicleControl::constVehIt it_veh = c.loadedVehBegin(); it_veh != c.loadedVehEnd(); ++it_veh) {
1005 const MSBaseVehicle* veh = dynamic_cast<const MSBaseVehicle*>((*it_veh).second);
1006 if (veh->isOnRoad() && veh->hasStops()) {
1007 const MSStop& vehStop = veh->getNextStop();
1008 if (vehStop.pars.lane == stopLane.getID()) {
1009 myBlockedStoppingPlaces.insert(cur);
1010 if (veh->isStopped()) {
1011 // stopped somewhere else on the same lane
1012 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, veh->getStopDuration());
1013 } else {
1014 std::pair<double, double> timeDist = veh->estimateTimeToNextStop();
1015 SUMOTime timeTo = TIME2STEPS(timeDist.first);
1016 stoppedDuration = MAX3((SUMOTime)0, stoppedDuration, timeTo + vehStop.getMinDuration(SIMSTEP + timeTo));
1017 }
1018 }
1019 }
1020 }
1021 } else {
1022 stoppedDuration = 0;
1023 for (const SUMOVehicle* veh : cur->getStoppedVehicles()) {
1024 stoppedDuration = MAX2(stoppedDuration, veh->getStopDuration());
1025 }
1026 }
1027 if (stoppedDuration < 0) {
1028 return;
1029 }
1031 const SUMOTime stopFree = SIMSTEP + stoppedDuration;
1032 const SUMOTime scheduledArrival = stop.pars.arrival >= 0 ? stop.pars.arrival : stop.pars.until - stop.pars.duration;
1033#ifdef DEBUG_REROUTER
1034 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " scheduledArrival=" << time2string(scheduledArrival) << "\n";
1035#endif
1036 if (stopFree < scheduledArrival) {
1037 // no conflict according to the schedule
1038 return;
1039 }
1040 const SUMOTime estimatedArrival = SIMSTEP + (stop.pars.arrival >= 0
1042 : TIME2STEPS(ego.getStopDelay()) - stop.pars.duration);
1043#ifdef DEBUG_REROUTER
1044 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " stopFree=" << stopFree << " estimatedArrival=" << time2string(estimatedArrival) << "\n";
1045#endif
1046 if (stopFree < estimatedArrival) {
1047 // no conflict when considering current delay
1048 return;
1049 }
1050 const std::vector<double> probs(def->stopAlternatives.size(), 1.);
1051 StoppingPlaceParamMap_t scores = {};
1052 bool newDestination;
1053 ConstMSEdgeVector newRoute;
1054 // @todo: consider future conflicts caused by rerouting
1055 // @todo: reject alternatives with large detour
1056 const MSStoppingPlace* alternative = rerouteStoppingPlace(nullptr, def->stopAlternatives, probs, ego, newDestination, newRoute, scores);
1057#ifdef DEBUG_REROUTER
1058 std::cout << SIMTIME << " " << getID() << " ego=" << ego.getID() << " alternative=" << Named::getIDSecure(alternative) << "\n";
1059#endif
1060 if (alternative != nullptr) {
1061 // @todo adapt plans of any riders
1062 //for (MSTransportable* p : ego.getPersons()) {
1063 // p->rerouteParkingArea(ego.getNextParkingArea(), newParkingArea);
1064 //}
1065
1066 if (newDestination) {
1067 // update arrival parameters
1068 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
1069 *newParameter = ego.getParameter();
1071 newParameter->arrivalPos = alternative->getEndLanePosition();
1072 ego.replaceParameter(newParameter);
1073 }
1074
1075 SUMOVehicleParameter::Stop newStop = stop.pars;
1076 newStop.lane = alternative->getLane().getID();
1077 newStop.startPos = alternative->getBeginLanePosition();
1078 newStop.endPos = alternative->getEndLanePosition();
1079 switch (alternative->getElement()) {
1081 newStop.parkingarea = alternative->getID();
1082 break;
1084 newStop.containerstop = alternative->getID();
1085 break;
1087 newStop.chargingStation = alternative->getID();
1088 break;
1090 newStop.overheadWireSegment = alternative->getID();
1091 break;
1092 case SUMO_TAG_BUS_STOP:
1094 default:
1095 newStop.busstop = alternative->getID();
1096 }
1097 std::string errorMsg;
1098 if (!ego.replaceStop(0, newStop, getID() + ":" + toString(SUMO_TAG_STATION_REROUTE), false, errorMsg)) {
1099 WRITE_WARNING("Vehicle '" + ego.getID() + "' at rerouter '" + getID()
1100 + "' could not perform stationReroute to '" + alternative->getID()
1101 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1102 }
1103 }
1104}
1105
1106
1108MSTriggeredRerouter::findSignal(ConstMSEdgeVector::const_iterator begin, ConstMSEdgeVector::const_iterator end) {
1109 auto it = end;
1110 do {
1111 it--;
1112 const MSEdge* edge = *it;
1114 for (const MSLink* link : edge->getLanes().front()->getLinkCont()) {
1115 if (link->getTLLogic() != nullptr) {
1116 return dynamic_cast<MSRailSignal*>(const_cast<MSTrafficLightLogic*>(link->getTLLogic()));
1117 }
1118 }
1119 }
1120 } while (it != begin);
1121 return nullptr;
1122}
1123
1124bool
1126 if (myVehicleTypes.empty() || myVehicleTypes.count(obj.getVehicleType().getOriginalID()) > 0) {
1127 return true;
1128 } else {
1130 for (auto vTypeDist : vTypeDists) {
1131 if (myVehicleTypes.count(vTypeDist) > 0) {
1132 return true;
1133 }
1134 }
1135 return false;
1136 }
1137}
1138
1139
1140bool
1141MSTriggeredRerouter::affected(const std::set<SUMOTrafficObject::NumericalID>& edgeIndices, const MSEdgeVector& closed) {
1142 for (const MSEdge* const e : closed) {
1143 if (edgeIndices.count(e->getNumericalID()) > 0) {
1144 return true;
1145 }
1146 }
1147 return false;
1148}
1149
1150
1151void
1153 // if a parkingArea is a rerouting target, it should generally have a
1154 // rerouter on its edge or vehicles will be stuck there once it's full.
1155 // The user should receive a Warning in this case
1156 std::set<MSEdge*> parkingRerouterEdges;
1157 std::map<MSParkingArea*, std::string, ComparatorIdLess> targetedParkingArea; // paID -> targetingRerouter
1158 for (const auto& rr : myInstances) {
1159 bool hasParkingReroute = false;
1160 for (const RerouteInterval& interval : rr.second->myIntervals) {
1161 if (interval.parkProbs.getOverallProb() > 0) {
1162 hasParkingReroute = true;
1163 for (const StoppingPlaceVisible& pav : interval.parkProbs.getVals()) {
1164 targetedParkingArea[dynamic_cast<MSParkingArea*>(pav.first)] = rr.first;
1165 }
1166 }
1167 }
1168 if (hasParkingReroute) {
1169 parkingRerouterEdges.insert(rr.second->myEdges.begin(), rr.second->myEdges.end());
1170 }
1171 }
1172 for (const auto& item : targetedParkingArea) {
1173 if (parkingRerouterEdges.count(&item.first->getLane().getEdge()) == 0) {
1174 WRITE_WARNINGF(TL("ParkingArea '%' is targeted by rerouter '%' but doesn't have its own rerouter. This may cause parking search to abort."),
1175 item.first->getID(), item.second);
1176 }
1177 }
1178}
1179
1180
1181void
1183 // getRouterTT without prohibitions removes previous prohibitions
1184 if (o.isVehicle()) {
1185 hasReroutingDevice
1188 } else {
1189 hasReroutingDevice
1192 }
1193}
1194
1195/****************************************************************************/
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)
#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:288
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
#define TLF(string,...)
Definition MsgHandler.h:307
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:55
#define SIMSTEP
Definition SUMOTime.h:61
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
const SVCPermissions SVCAll
all VClasses are allowed
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.
@ 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_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:46
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 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:340
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.
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)
bool isStopped() const
Returns whether the vehicle is at a stop.
A device that performs vehicle rerouting based on current edge speeds.
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:418
double getLength() const
return the length of the edge
Definition MSEdge.h:685
double getMinimumTravelTime(const SUMOVehicle *const veh) const
returns the minimum travel time for the given vehicle
Definition MSEdge.h:476
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:1053
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:112
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:146
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:2478
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:186
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:477
MSTransportableRouter & getIntermodalRouter(int rngIndex, const int routingMode=0, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1577
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1530
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:326
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1403
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:384
A lane area vehicles can halt at.
A signal for rails.
void addConstraint(const std::string &tripId, MSRailSignalConstraint *constraint)
register constraint for signal switching
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:125
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:243
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:109
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:188
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:134
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.
MSRailSignal * findSignal(ConstMSEdgeVector::const_iterator begin, ConstMSEdgeVector::const_iterator end)
find the last downstream signal on the given route
std::map< const MSEdge *, double > Prohibitions
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 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 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 MSTriggeredRerouter::RerouteInterval *)
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
double getStoppingPlaceOccupancy(MSStoppingPlace *sp)
Return the number of occupied places of the stopping place.
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
double getLastStepStoppingPlaceOccupancy(MSStoppingPlace *sp)
Return the number of occupied places of the stopping place from the previous time step.
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.
const MSEdgeVector myEdges
edges where vehicles are notified
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.
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 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:54
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:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
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 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 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 const MSEdge * getEdge() const =0
Returns the 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 double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:62
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.
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.
SUMOTime begin
The begin time these definitions are valid.
RandomDistributor< MSStoppingPlaceRerouter::StoppingPlaceVisible > parkProbs
The distributions of new parking areas to use as destinations.
MSEdgeVector siding
The list of siding edges.
std::vector< MSStoppingPlaceRerouter::StoppingPlaceVisible > stopAlternatives
RandomDistributor< ConstMSRoutePtr > routeProbs
The distributions of new routes to use.
SUMOTime end
The end time these definitions are valid.
double sidingLength
The usable length of the siding.
MSRailSignal * sidingExit
The rail signal at the end of the siding.
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.
double minSaving
The threshold in savings for triggering reroute.