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-2024 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/MSVehicle.h>
45#include <microsim/MSRoute.h>
46#include <microsim/MSEdge.h>
48#include <microsim/MSNet.h>
50#include <microsim/MSGlobals.h>
52#include <microsim/MSStop.h>
56#include "MSTriggeredRerouter.h"
57
58#include <mesosim/MELoop.h>
59#include <mesosim/MESegment.h>
60
61//#define DEBUG_REROUTER
62#define DEBUGCOND (veh.isSelected())
63//#define DEBUGCOND (true)
64//#define DEBUGCOND (veh.getID() == "")
65
66// ===========================================================================
67// static member definition
68// ===========================================================================
69MSEdge MSTriggeredRerouter::mySpecialDest_keepDestination("MSTriggeredRerouter_keepDestination", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
70MSEdge MSTriggeredRerouter::mySpecialDest_terminateRoute("MSTriggeredRerouter_terminateRoute", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
71std::map<std::string, MSTriggeredRerouter*> MSTriggeredRerouter::myInstances;
72
73
74// ===========================================================================
75// method definitions
76// ===========================================================================
78 const MSEdgeVector& edges, double prob, bool off, bool optional,
79 SUMOTime timeThreshold, const std::string& vTypes, const Position& pos) :
80 Named(id),
83 myEdges(edges),
84 myProbability(prob),
85 myUserProbability(prob),
86 myAmInUserMode(false),
87 myAmOptional(optional),
88 myPosition(pos),
89 myTimeThreshold(timeThreshold),
90 myHaveParkProbs(false) {
91 myInstances[id] = this;
92 // build actors
93 for (const MSEdge* const e : edges) {
96 }
97 for (MSLane* const lane : e->getLanes()) {
98 lane->addMoveReminder(this);
99 }
100 }
101 if (off) {
102 setUserMode(true);
104 }
105 const std::vector<std::string> vt = StringTokenizer(vTypes).getVector();
106 myVehicleTypes.insert(vt.begin(), vt.end());
107}
108
109
113
114
115// ------------ loading begin
116void
118 const SUMOSAXAttributes& attrs) {
119 if (element == SUMO_TAG_INTERVAL) {
120 bool ok = true;
125 throw ProcessError(TLF("rerouter '%': interval end % is not after begin %.", getID(),
128 }
129 }
130 if (element == SUMO_TAG_DEST_PROB_REROUTE) {
131 // by giving probabilities of new destinations
132 // get the destination edge
133 std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
134 if (dest == "") {
135 throw ProcessError(TLF("rerouter '%': destProbReroute has no destination edge id.", getID()));
136 }
137 MSEdge* to = MSEdge::dictionary(dest);
138 if (to == nullptr) {
139 if (dest == "keepDestination") {
141 } else if (dest == "terminateRoute") {
143 } else {
144 throw ProcessError(TLF("rerouter '%': Destination edge '%' is not known.", getID(), dest));
145 }
146 }
147 // get the probability to reroute
148 bool ok = true;
149 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
150 if (!ok) {
151 throw ProcessError();
152 }
153 if (prob < 0) {
154 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for destination '%' is negative (must not).", getID(), dest));
155 }
156 // add
158 }
159
160 if (element == SUMO_TAG_CLOSING_REROUTE) {
161 // by closing edge
162 const std::string& closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
163 MSEdge* const closed = MSEdge::dictionary(closed_id);
164 if (closed == nullptr) {
165 throw ProcessError(TLF("rerouter '%': Edge '%' to close is not known.", getID(), closed_id));
166 }
167 myParsedRerouteInterval.closed.push_back(closed);
168 bool ok;
169 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
170 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
172 }
173
174 if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
175 // by closing lane
176 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
177 MSLane* closed = MSLane::dictionary(closed_id);
178 if (closed == nullptr) {
179 throw ProcessError(TLF("rerouter '%': Lane '%' to close is not known.", getID(), closed_id));
180 }
181 myParsedRerouteInterval.closedLanes.push_back(closed);
182 bool ok;
184 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
185 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
187 } else {
188 // lane closing only makes sense if the lane really receives reduced permissions
190 }
191 }
192
193 if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
194 // by explicit rerouting using routes
195 // check if route exists
196 std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
197 if (routeStr == "") {
198 throw ProcessError(TLF("rerouter '%': routeProbReroute has no alternative route id.", getID()));
199 }
200 ConstMSRoutePtr route = MSRoute::dictionary(routeStr);
201 if (route == nullptr) {
202 throw ProcessError(TLF("rerouter '%': Alternative route '%' does not exist.", getID(), routeStr));
203 }
204
205 // get the probability to reroute
206 bool ok = true;
207 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
208 if (!ok) {
209 throw ProcessError();
210 }
211 if (prob < 0) {
212 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for alternative route '%' is negative (must not).", getID(), routeStr));
213 }
214 // add
216 }
217
218 if (element == SUMO_TAG_PARKING_AREA_REROUTE) {
219 std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
220 if (parkingarea == "") {
221 throw ProcessError(TLF("rerouter '%': parkingAreaReroute requires a parkingArea id.", getID()));
222 }
224 if (pa == nullptr) {
225 throw ProcessError(TLF("rerouter '%': parkingArea '%' is not known.", getID(), parkingarea));
226 }
227 // get the probability to reroute
228 bool ok = true;
229 const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
230 if (!ok) {
231 throw ProcessError();
232 }
233 if (prob < 0) {
234 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for parkingArea '%' is negative (must not).", getID(), parkingarea));
235 }
236 const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
237 // add
238 myParsedRerouteInterval.parkProbs.add(std::make_pair(pa, visible), prob);
239 myHaveParkProbs = true;
240 }
241
242 if (element == SUMO_TAG_VIA_PROB_REROUTE) {
243 // by giving probabilities of vias
244 std::string viaID = attrs.getStringSecure(SUMO_ATTR_ID, "");
245 if (viaID == "") {
246 throw ProcessError(TLF("rerouter '%': No via edge id given.", getID()));
247 }
248 MSEdge* const via = MSEdge::dictionary(viaID);
249 if (via == nullptr) {
250 throw ProcessError(TLF("rerouter '%': Via Edge '%' is not known.", getID(), viaID));
251 }
252 // get the probability to reroute
253 bool ok = true;
254 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
255 if (!ok) {
256 throw ProcessError();
257 }
258 if (prob < 0) {
259 throw ProcessError(TLF("rerouter '%': Attribute 'probability' for via '%' is negative (must not).", getID(), viaID));
260 }
261 // add
264 }
265}
266
267
268void
270 if (element == SUMO_TAG_INTERVAL) {
271 for (auto paVi : myParsedRerouteInterval.parkProbs.getVals()) {
272 dynamic_cast<MSParkingArea*>(paVi.first)->setNumAlternatives((int)myParsedRerouteInterval.parkProbs.getVals().size() - 1);
273 }
274 if (myParsedRerouteInterval.closedLanes.size() > 0) {
275 // collect edges that are affect by a closed lane
276 std::set<MSEdge*> affected;
277 for (const MSLane* const l : myParsedRerouteInterval.closedLanes) {
278 affected.insert(&l->getEdge());
279 }
281 }
282 const SUMOTime closingBegin = myParsedRerouteInterval.begin;
283 const SUMOTime simBegin = string2time(OptionsCont::getOptions().getString("begin"));
284 if (closingBegin < simBegin && myParsedRerouteInterval.end > simBegin) {
285 // interval started before simulation begin but is still active at
286 // the start of the simulation
288 }
290 myIntervals.back().id = (long long int)&myIntervals.back();
294 }
295 }
296}
297
298
299// ------------ loading end
300
301
304 bool updateVehicles = false;
305 for (const RerouteInterval& i : myIntervals) {
306 if (i.begin == currentTime && !(i.closed.empty() && i.closedLanes.empty()) && i.permissions != SVCAll) {
307 for (MSEdge* const e : i.closed) {
308 for (MSLane* lane : e->getLanes()) {
309 //std::cout << SIMTIME << " closing: intervalID=" << i.id << " lane=" << lane->getID() << " prevPerm=" << getVehicleClassNames(lane->getPermissions()) << " new=" << getVehicleClassNames(i.permissions) << "\n";
310 lane->setPermissions(i.permissions, i.id);
311 }
312 e->rebuildAllowedLanes();
313 updateVehicles = true;
314 }
315 for (MSLane* const lane : i.closedLanes) {
316 lane->setPermissions(i.permissions, i.id);
317 lane->getEdge().rebuildAllowedLanes();
318 updateVehicles = true;
319 }
322 }
323 if (i.end == currentTime && !(i.closed.empty() && i.closedLanes.empty()) && i.permissions != SVCAll) {
324 for (MSEdge* const e : i.closed) {
325 for (MSLane* lane : e->getLanes()) {
326 lane->resetPermissions(i.id);
327 //std::cout << SIMTIME << " opening: intervalID=" << i.id << " lane=" << lane->getID() << " restore prevPerm=" << getVehicleClassNames(lane->getPermissions()) << "\n";
328 }
329 e->rebuildAllowedLanes();
330 updateVehicles = true;
331 }
332 for (MSLane* lane : i.closedLanes) {
333 lane->resetPermissions(i.id);
334 lane->getEdge().rebuildAllowedLanes();
335 updateVehicles = true;
336 }
337 }
338 }
339 if (updateVehicles) {
340 // only vehicles on the affected lanes had their bestlanes updated so far
341 for (MSEdge* e : myEdges) {
342 // also updates vehicles
343 e->rebuildAllowedTargets();
344 }
345 }
346 return 0;
347}
348
349
352 for (const RerouteInterval& ri : myIntervals) {
353 if (ri.begin <= time && ri.end > time) {
354 if (
355 // destProbReroute
356 ri.edgeProbs.getOverallProb() > 0 ||
357 // routeProbReroute
358 ri.routeProbs.getOverallProb() > 0 ||
359 // parkingZoneReroute
360 ri.parkProbs.getOverallProb() > 0) {
361 return &ri;
362 }
363 if (!ri.closed.empty() || !ri.closedLanesAffected.empty()) {
364 const std::set<SUMOTrafficObject::NumericalID>& edgeIndices = obj.getUpcomingEdgeIDs();
365 if (affected(edgeIndices, ri.closed) || affected(edgeIndices, ri.closedLanesAffected)) {
366 return &ri;
367 }
368 }
369 }
370 }
371 return nullptr;
372}
373
374
377 for (const RerouteInterval& ri : myIntervals) {
378 if (ri.begin <= time && ri.end > time) {
379 if (ri.edgeProbs.getOverallProb() != 0 || ri.routeProbs.getOverallProb() != 0 || ri.parkProbs.getOverallProb() != 0
380 || !ri.closed.empty() || !ri.closedLanesAffected.empty()) {
381 return &ri;
382 }
383 }
384 }
385 return nullptr;
386}
387
388
389bool
391 if (myAmOptional) {
392 return true;
393 }
394 return triggerRouting(tObject, reason);
395}
396
397
398bool
400 double /*newPos*/, double /*newSpeed*/) {
402}
403
404
405bool
407 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
408 return reason == NOTIFICATION_LANE_CHANGE;
409}
410
411
412bool
414 if (!applies(tObject)) {
415 return false;
416 }
417 // check whether the vehicle shall be rerouted
419 const MSTriggeredRerouter::RerouteInterval* const rerouteDef = getCurrentReroute(now, tObject);
420 if (rerouteDef == nullptr) {
421 return true; // an active interval could appear later
422 }
423 const double prob = myAmInUserMode ? myUserProbability : myProbability;
424 if (prob < 1 && RandHelper::rand(tObject.getRNG()) > prob) {
425 return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
426 }
427 if (myTimeThreshold > 0 && MAX2(tObject.getWaitingTime(), tObject.getWaitingTime(true)) < myTimeThreshold) {
428 return true; // waiting time may be reached later
429 }
430 if (reason == NOTIFICATION_LANE_CHANGE) {
431 return false;
432 }
433 // if we have a closingLaneReroute, only vehicles with a rerouting device can profit from rerouting (otherwise, edge weights will not reflect local jamming)
434 const bool hasReroutingDevice = tObject.getDevice(typeid(MSDevice_Routing)) != nullptr;
435 if (rerouteDef->closedLanes.size() > 0 && !hasReroutingDevice) {
436 return true; // an active interval could appear later
437 }
438 const MSEdge* lastEdge = tObject.getRerouteDestination();
439#ifdef DEBUG_REROUTER
440 if (DEBUGCOND) {
441 std::cout << SIMTIME << " veh=" << veh.getID() << " check rerouter " << getID() << " lane=" << Named::getIDSecure(veh.getLane()) << " edge=" << veh.getEdge()->getID() << " finalEdge=" << lastEdge->getID() << " arrivalPos=" << veh.getArrivalPos() << "\n";
442 }
443#endif
444
445 if (rerouteDef->parkProbs.getOverallProb() > 0) {
446#ifdef HAVE_FOX
447 ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
448#endif
449 if (!tObject.isVehicle()) {
450 return false;
451 }
452 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
453 bool newDestination = false;
454 ConstMSEdgeVector newRoute;
455 MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination, newRoute);
456 if (newParkingArea != nullptr) {
457 // adapt plans of any riders
458 for (MSTransportable* p : veh.getPersons()) {
459 p->rerouteParkingArea(veh.getNextParkingArea(), newParkingArea);
460 }
461
462 if (newDestination) {
463 // update arrival parameters
464 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
465 *newParameter = veh.getParameter();
467 newParameter->arrivalPos = newParkingArea->getEndLanePosition();
468 veh.replaceParameter(newParameter);
469 }
470
471 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
472 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
473 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
474 const double routeCost = router.recomputeCosts(newRoute, &veh, MSNet::getInstance()->getCurrentTimeStep());
475 ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
476 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
477 const double savings = previousCost - routeCost;
478 hasReroutingDevice
480 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
481 //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
482 // << " prevEdges=" << toString(prevEdges)
483 // << " newEdges=" << toString(edges)
484 // << "\n";
485
486 std::string errorMsg;
487 if (veh.replaceParkingArea(newParkingArea, errorMsg)) {
488 veh.replaceRouteEdges(newRoute, routeCost, savings, getID() + ":" + toString(SUMO_TAG_PARKING_AREA_REROUTE), false, false, false);
489 } else {
490 WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
491 + "' could not reroute to new parkingArea '" + newParkingArea->getID()
492 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
493 }
494 }
495 return false;
496 }
497
498 // get rerouting params
499 ConstMSRoutePtr newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : nullptr;
500 // we will use the route if given rather than calling our own dijsktra...
501 if (newRoute != nullptr) {
502#ifdef DEBUG_REROUTER
503 if (DEBUGCOND) {
504 std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
505 }
506#endif
507 tObject.replaceRoute(newRoute, getID());
508 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
509 }
510 const MSEdge* newEdge = lastEdge;
511 // ok, try using a new destination
512 double newArrivalPos = -1;
513 const bool destUnreachable = std::find(rerouteDef->closed.begin(), rerouteDef->closed.end(), lastEdge) != rerouteDef->closed.end();
514 bool keepDestination = false;
515 // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
516 // if we have a closingLaneReroute, no new destinations should be assigned
517 if (rerouteDef->closed.empty() || destUnreachable || rerouteDef->isVia) {
518 newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : lastEdge;
519 assert(newEdge != nullptr);
520 if (newEdge == &mySpecialDest_terminateRoute) {
521 keepDestination = true;
522 newEdge = tObject.getEdge();
523 newArrivalPos = tObject.getPositionOnLane(); // instant arrival
524 } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
525 if (destUnreachable && rerouteDef->permissions == SVCAll) {
526 // if permissions aren't set vehicles will simply drive through
527 // the closing unless terminated. If the permissions are specified, assume that the user wants
528 // vehicles to stand and wait until the closing ends
529 WRITE_WARNINGF(TL("Cannot keep destination edge '%' for vehicle '%' due to closed edges. Terminating route."), lastEdge->getID(), tObject.getID());
530 newEdge = tObject.getEdge();
531 } else {
532 newEdge = lastEdge;
533 }
534 }
535 }
536 ConstMSEdgeVector edges;
537 std::vector<MSTransportableRouter::TripItem> items;
538 // we have a new destination, let's replace the route (if it is affected)
539 if (rerouteDef->closed.empty() || destUnreachable || rerouteDef->isVia || affected(tObject.getUpcomingEdgeIDs(), rerouteDef->closed)) {
540 if (tObject.isVehicle()) {
541 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
542 const bool canChangeDest = rerouteDef->edgeProbs.getOverallProb() > 0;
543 MSVehicleRouter& router = hasReroutingDevice
544 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
545 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
546 bool ok = veh.reroute(now, getID(), router, false, false, canChangeDest, newEdge);
547 if (!ok && !keepDestination && canChangeDest) {
548 // destination unreachable due to closed intermediate edges. pick among alternative targets
549 RandomDistributor<MSEdge*> edgeProbs2 = rerouteDef->edgeProbs;
550 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
551 while (!ok && edgeProbs2.getVals().size() > 0) {
552 newEdge = edgeProbs2.get();
553 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
554 if (newEdge == &mySpecialDest_terminateRoute) {
555 newEdge = veh.getEdge();
556 newArrivalPos = veh.getPositionOnLane(); // instant arrival
557 }
558 if (newEdge == &mySpecialDest_keepDestination && rerouteDef->permissions != SVCAll) {
559 newEdge = lastEdge;
560 break;
561 }
562 ok = veh.reroute(now, getID(), router, false, false, true, newEdge);
563 }
564
565 }
566 if (!rerouteDef->isVia) {
567#ifdef DEBUG_REROUTER
568 if (DEBUGCOND) std::cout << " rerouting: newDest=" << newEdge->getID()
569 << " newEdges=" << toString(edges)
570 << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
571 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->closed) << "\n";
572#endif
573 if (ok && newArrivalPos != -1) {
574 // must be called here because replaceRouteEdges may also set the arrivalPos
575 veh.setArrivalPos(newArrivalPos);
576 }
577
578 }
579 } else {
580 // person rerouting here
581 MSTransportableRouter& router = hasReroutingDevice
583 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, rerouteDef->closed);
584 const bool success = router.compute(tObject.getEdge(), newEdge, tObject.getPositionOnLane(), "",
585 rerouteDef->isVia ? newEdge->getLength() / 2. : tObject.getParameter().arrivalPos, "",
586 tObject.getMaxSpeed(), nullptr, 0, now, items);
587 if (!rerouteDef->isVia) {
588 if (success) {
589 for (const MSTransportableRouter::TripItem& it : items) {
590 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
591 edges.pop_back();
592 }
593 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
594 if (!edges.empty()) {
595 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
596 }
597 }
598 } else {
599 // maybe the pedestrian model still finds a way (JuPedSim)
600 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge}, tObject.getPositionOnLane(), 0, 1);
601 }
602 }
603 }
604 }
605 // it was only a via so calculate the remaining part
606 if (rerouteDef->isVia) {
607 if (tObject.isVehicle()) {
608 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
609 if (!edges.empty()) {
610 edges.pop_back();
611 }
612 MSVehicleRouter& router = hasReroutingDevice
613 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
614 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
615 router.compute(newEdge, lastEdge, &veh, now, edges);
616 const double routeCost = router.recomputeCosts(edges, &veh, now);
617 hasReroutingDevice
619 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
620 const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
621#ifdef DEBUG_REROUTER
622 if (DEBUGCOND) std::cout << " rerouting: newDest=" << newEdge->getID()
623 << " newEdges=" << toString(edges)
624 << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
625 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->closed) << "\n";
626#endif
627 if (useNewRoute && newArrivalPos != -1) {
628 // must be called here because replaceRouteEdges may also set the arrivalPos
629 veh.setArrivalPos(newArrivalPos);
630 }
631 } else {
632 // person rerouting here
633 bool success = !items.empty();
634 if (success) {
635 MSTransportableRouter& router = hasReroutingDevice
637 : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, rerouteDef->closed);
638 success = router.compute(newEdge, lastEdge, newEdge->getLength() / 2., "",
639 tObject.getParameter().arrivalPos, "",
640 tObject.getMaxSpeed(), nullptr, 0, now, items);
641 }
642 if (success) {
643 for (const MSTransportableRouter::TripItem& it : items) {
644 if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
645 edges.pop_back();
646 }
647 edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
648 }
649 if (!edges.empty()) {
650 static_cast<MSPerson&>(tObject).replaceWalk(edges, tObject.getPositionOnLane(), 0, 1);
651 }
652 } else {
653 // maybe the pedestrian model still finds a way (JuPedSim)
654 static_cast<MSPerson&>(tObject).replaceWalk({tObject.getEdge(), newEdge, lastEdge}, tObject.getPositionOnLane(), 0, 1);
655 }
656 }
657 }
658 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
659}
660
661
662void
666
667
668void
672
673
674bool
678
679
680double
684
685
686double
690
691
692double
694 return dynamic_cast<MSParkingArea*>(parkingArea)->getOccupancy();
695}
696
697
698double
700 return dynamic_cast<MSParkingArea*>(parkingArea)->getLastStepOccupancy();
701}
702
703
704double
706 MSParkingArea* pa = dynamic_cast<MSParkingArea*>(parkingArea);
707 return pa->getCapacity();
708}
709
710
711void
713 veh.rememberBlockedParkingArea(parkingArea, blocked);
714}
715
716
717void
719 veh.rememberParkingAreaScore(parkingArea, score);
720}
721
722
723void
727
728
731 return veh.sawBlockedParkingArea(parkingArea, local);
732}
733
734
735int
739
740
741void
745
746
749 SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute) {
750 std::vector<StoppingPlaceVisible> parks = rerouteDef->parkProbs.getVals();
751 StoppingPlaceParamMap_t addInput = {};
752 return dynamic_cast<MSParkingArea*>(reroute(parks, rerouteDef->parkProbs.getProbs(), veh, newDestination, newRoute, addInput, rerouteDef->closed));
753}
754
755
756bool
758 if (myVehicleTypes.empty() || myVehicleTypes.count(obj.getVehicleType().getOriginalID()) > 0) {
759 return true;
760 } else {
762 for (auto vTypeDist : vTypeDists) {
763 if (myVehicleTypes.count(vTypeDist) > 0) {
764 return true;
765 }
766 }
767 return false;
768 }
769}
770
771
772bool
773MSTriggeredRerouter::affected(const std::set<SUMOTrafficObject::NumericalID>& edgeIndices, const MSEdgeVector& closed) {
774 for (const MSEdge* const e : closed) {
775 if (edgeIndices.count(e->getNumericalID()) > 0) {
776 return true;
777 }
778 }
779 return false;
780}
781
782
783void
785 // if a parkingArea is a rerouting target, it should generally have a
786 // rerouter on its edge or vehicles will be stuck there once it's full.
787 // The user should receive a Warning in this case
788 std::set<MSEdge*> parkingRerouterEdges;
789 std::map<MSParkingArea*, std::string, ComparatorIdLess> targetedParkingArea; // paID -> targetingRerouter
790 for (const auto& rr : myInstances) {
791 bool hasParkingReroute = false;
792 for (const RerouteInterval& interval : rr.second->myIntervals) {
793 if (interval.parkProbs.getOverallProb() > 0) {
794 hasParkingReroute = true;
795 for (const StoppingPlaceVisible& pav : interval.parkProbs.getVals()) {
796 targetedParkingArea[dynamic_cast<MSParkingArea*>(pav.first)] = rr.first;
797 }
798 }
799 }
800 if (hasParkingReroute) {
801 parkingRerouterEdges.insert(rr.second->myEdges.begin(), rr.second->myEdges.end());
802 }
803 }
804 for (const auto& item : targetedParkingArea) {
805 if (parkingRerouterEdges.count(&item.first->getLane().getEdge()) == 0) {
806 WRITE_WARNINGF(TL("ParkingArea '%' is targeted by rerouter '%' but doesn't have its own rerouter. This may cause parking search to abort."),
807 item.first->getID(), item.second);
808 }
809 }
810}
811
812
813/****************************************************************************/
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 WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
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:69
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:62
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...
@ 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_PARKING_AREA_REROUTE
entry for an alternative parking zone
@ 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 fora reroute
@ SUMO_TAG_DEST_PROB_REROUTE
probability of destination of a reroute
@ SUMO_TAG_CLOSING_LANE_REROUTE
lane of a reroute of type closing
@ SUMO_ATTR_DISALLOW
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_PROB
@ SUMO_ATTR_ID
@ SUMO_ATTR_VISIBLE
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
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:333
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
A device that performs vehicle rerouting based on current edge speeds.
A road/street connecting two junctions.
Definition MSEdge.h:77
double getLength() const
return the length of the edge
Definition MSEdge.h:685
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:1047
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
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:2414
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:185
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:471
MSTransportableRouter & getIntermodalRouter(const int rngIndex, const int routingMode=0, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition MSNet.cpp:1545
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:320
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1380
MSVehicleRouter & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition MSNet.cpp:1507
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:378
A lane area vehicles can halt at.
int getCapacity() const
Returns the area capacity.
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 MSEdgeVector &prohibited=MSEdgeVector())
return the vehicle router instance
static MSTransportableRouter & getIntermodalRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector())
return the person router instance
A lane area vehicles can halt at.
double getEndLanePosition() const
Returns the end position of this stop.
MSStoppingPlace * reroute(std::vector< StoppingPlaceVisible > &stoppingPlaceCandidates, const std::vector< double > &probs, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute, StoppingPlaceParamMap_t &scores, const MSEdgeVector &closedEdges={})
main method to trigger the rerouting to the "best" StoppingPlace according to the custom evaluation f...
std::map< std::string, double > StoppingPlaceParamMap_t
std::pair< MSStoppingPlace *, bool > StoppingPlaceVisible
SUMOTime setPermissions(const SUMOTime currentTime)
Sets the edge permission if there are any defined in the closingEdge.
double getStoppingPlaceCapacity(MSStoppingPlace *parkingArea)
Return the number of places the ParkingArea provides.
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.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Removes the reminder.
double getUserProbability() const
Returns the rerouting probability given by the user.
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.
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.
MSTriggeredRerouter(const std::string &id, const MSEdgeVector &edges, double prob, bool off, bool optional, SUMOTime timeThreshold, const std::string &vTypes, const Position &pos)
Constructor.
bool triggerRouting(SUMOTrafficObject &veh, MSMoveReminder::Notification reason)
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< 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.
const MSEdgeVector myEdges
edges where vehicles are notified
double getLastStepStoppingPlaceOccupancy(MSStoppingPlace *parkingArea)
Return the number of occupied places of the StoppingPlace from the previous time step.
static MSEdge mySpecialDest_keepDestination
special destination values
RerouteInterval myParsedRerouteInterval
used during loading
double getStoppingPlaceOccupancy(MSStoppingPlace *parkingArea)
Return the number of occupied places of the ParkingArea.
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.
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 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.
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 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 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 MSParkingArea * getNextParkingArea()=0
virtual void rememberParkingAreaScore(const MSStoppingPlace *pa, const std::string &score)=0
virtual void rememberBlockedParkingArea(const MSStoppingPlace *pa, bool local)=0
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 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.
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.
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.
bool isVia
The edge probs are vias and not destinations.
MSEdgeVector closedLanesAffected
The list of edges that are affect by closed lanes.
SVCPermissions permissions
The permissions to use.
MSEdgeVector closed
The list of closed edges.
std::vector< MSLane * > closedLanes
The list of closed lanes.