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