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-2023 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/****************************************************************************/
21// Reroutes vehicles passing an edge
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
26#include <algorithm>
27#ifdef HAVE_FOX
29#endif
42#include <microsim/MSLane.h>
43#include <microsim/MSVehicle.h>
44#include <microsim/MSRoute.h>
45#include <microsim/MSEdge.h>
47#include <microsim/MSNet.h>
49#include <microsim/MSGlobals.h>
51#include <microsim/MSStop.h>
55#include "MSTriggeredRerouter.h"
56
57#include <mesosim/MELoop.h>
58#include <mesosim/MESegment.h>
59
60//#define DEBUG_REROUTER
61//#define DEBUG_PARKING
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// method definitions
75// ===========================================================================
77 const MSEdgeVector& edges, double prob, bool off,
78 SUMOTime timeThreshold, const std::string& vTypes) :
79 Named(id),
81 myEdges(edges),
82 myProbability(prob),
83 myUserProbability(prob),
84 myAmInUserMode(false),
85 myTimeThreshold(timeThreshold),
86 myHaveParkProbs(false)
87{
88 myInstances[id] = this;
89 // build actors
90 for (MSEdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
93 s->addDetector(this);
94 continue;
95 }
96 const std::vector<MSLane*>& destLanes = (*j)->getLanes();
97 for (std::vector<MSLane*>::const_iterator i = destLanes.begin(); i != destLanes.end(); ++i) {
98 (*i)->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;
123 }
124 if (element == SUMO_TAG_DEST_PROB_REROUTE) {
125 // by giving probabilities of new destinations
126 // get the destination edge
127 std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
128 if (dest == "") {
129 throw ProcessError(TLF("MSTriggeredRerouter %: No destination edge id given.", getID()));
130 }
131 MSEdge* to = MSEdge::dictionary(dest);
132 if (to == nullptr) {
133 if (dest == "keepDestination") {
135 } else if (dest == "terminateRoute") {
137 } else {
138 throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
139 }
140 }
141 // get the probability to reroute
142 bool ok = true;
143 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
144 if (!ok) {
145 throw ProcessError();
146 }
147 if (prob < 0) {
148 throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
149 }
150 // add
151 myCurrentEdgeProb.add(to, prob);
152 }
153
154
155 if (element == SUMO_TAG_CLOSING_REROUTE) {
156 // by closing
157 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
158 MSEdge* closed = MSEdge::dictionary(closed_id);
159 if (closed == nullptr) {
160 throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
161 }
162 myCurrentClosed.push_back(closed);
163 bool ok;
164 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
165 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
166 myCurrentPermissions = parseVehicleClasses(allow, disallow);
167 }
168
169 if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
170 // by closing lane
171 std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
172 MSLane* closed = MSLane::dictionary(closed_id);
173 if (closed == nullptr) {
174 throw ProcessError("MSTriggeredRerouter " + getID() + ": Lane '" + closed_id + "' to close is not known.");
175 }
176 myCurrentClosedLanes.push_back(closed);
177 bool ok;
179 const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
180 const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
181 myCurrentPermissions = parseVehicleClasses(allow, disallow);
182 } else {
183 // lane closing only makes sense if the lane really receives reduced
184 // permissions
186 }
187 }
188
189 if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
190 // by explicit rerouting using routes
191 // check if route exists
192 std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
193 if (routeStr == "") {
194 throw ProcessError(TLF("MSTriggeredRerouter %: No route id given.", getID()));
195 }
196 ConstMSRoutePtr route = MSRoute::dictionary(routeStr);
197 if (route == nullptr) {
198 throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
199 }
200
201 // get the probability to reroute
202 bool ok = true;
203 double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
204 if (!ok) {
205 throw ProcessError();
206 }
207 if (prob < 0) {
208 throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
209 }
210 // add
211 myCurrentRouteProb.add(route, prob);
212 }
213
214 if (element == SUMO_TAG_PARKING_AREA_REROUTE) {
215 // by giving probabilities of new destinations
216 // get the destination edge
217 std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
218 if (parkingarea == "") {
219 throw ProcessError(TLF("MSTriggeredRerouter %: No parking area id given.", getID()));
220 }
222 if (pa == nullptr) {
223 throw ProcessError("MSTriggeredRerouter " + getID() + ": Parking area '" + parkingarea + "' is not known.");
224 }
225 // get the probability to reroute
226 bool ok = true;
227 const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
228 if (!ok) {
229 throw ProcessError();
230 }
231 if (prob < 0) {
232 throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + parkingarea + "' is negative (must not).");
233 }
234 const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
235 // add
236 myCurrentParkProb.add(std::make_pair(pa, visible), prob);
237 myHaveParkProbs = true;
238 //MSEdge* to = &(pa->getLane().getEdge());
239 //myCurrentEdgeProb.add(prob, to);
240 }
241}
242
243
244void
246 if (element == SUMO_TAG_INTERVAL) {
256 for (auto paVi : ri.parkProbs.getVals()) {
257 paVi.first->setNumAlternatives((int)ri.parkProbs.getVals().size() - 1);
258 }
259 if (ri.closedLanes.size() > 0) {
260 // collect edges that are affect by a closed lane
261 std::set<MSEdge*> affected;
262 for (const MSLane* const l : ri.closedLanes) {
263 affected.insert(&l->getEdge());
264 }
265 ri.closedLanesAffected.insert(ri.closedLanesAffected.begin(), affected.begin(), affected.end());
266 }
267 SUMOTime closingBegin = ri.begin;
268 SUMOTime simBegin = string2time(OptionsCont::getOptions().getString("begin"));
269 if (closingBegin < simBegin && ri.end > simBegin) {
270 // interval started before simulation begin but is still active at
271 // the start of the simulation
272 ri.begin = simBegin;
273 }
274 myCurrentClosed.clear();
275 myCurrentClosedLanes.clear();
279 myIntervals.push_back(ri);
280 myIntervals.back().id = (long long)&myIntervals.back();
281 if (!(ri.closed.empty() && ri.closedLanes.empty()) && ri.permissions != SVCAll) {
284 }
285 }
286}
287
288
289// ------------ loading end
290
291
294 bool updateVehicles = false;
295 for (const RerouteInterval& i : myIntervals) {
296 if (i.begin == currentTime && !(i.closed.empty() && i.closedLanes.empty()) && i.permissions != SVCAll) {
297 for (MSEdge* e : i.closed) {
298 for (MSLane* lane : e->getLanes()) {
299 //std::cout << SIMTIME << " closing: intervalID=" << i.id << " lane=" << (*l)->getID() << " prevPerm=" << getVehicleClassNames((*l)->getPermissions()) << " new=" << getVehicleClassNames(i.permissions) << "\n";
300 lane->setPermissions(i.permissions, i.id);
301 }
302 e->rebuildAllowedLanes();
303 updateVehicles = true;
304 }
305 for (MSLane* lane : i.closedLanes) {
306 lane->setPermissions(i.permissions, i.id);
307 lane->getEdge().rebuildAllowedLanes();
308 updateVehicles = true;
309 }
312 }
313 if (i.end == currentTime && !(i.closed.empty() && i.closedLanes.empty()) && i.permissions != SVCAll) {
314 for (MSEdge* e : i.closed) {
315 for (MSLane* lane : e->getLanes()) {
316 lane->resetPermissions(i.id);
317 //std::cout << SIMTIME << " opening: intervalID=" << i.id << " lane=" << (*l)->getID() << " restore prevPerm=" << getVehicleClassNames((*l)->getPermissions()) << "\n";
318 }
319 e->rebuildAllowedLanes();
320 updateVehicles = true;
321 }
322 for (MSLane* lane : i.closedLanes) {
323 lane->resetPermissions(i.id);
324 lane->getEdge().rebuildAllowedLanes();
325 updateVehicles = true;
326 }
327 }
328 }
329 if (updateVehicles) {
330 // only vehicles on the affected lanes had their bestlanes updated so far
331 for (MSEdge* e : myEdges) {
332 // also updates vehicles
333 e->rebuildAllowedTargets();
334 }
335 }
336 return 0;
337}
338
339
342 for (std::vector<RerouteInterval>::const_iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
343 if (i->begin <= time && i->end > time) {
344 if (
345 // destProbReroute
346 i->edgeProbs.getOverallProb() > 0 ||
347 // routeProbReroute
348 i->routeProbs.getOverallProb() > 0 ||
349 // parkingZoneReroute
350 i->parkProbs.getOverallProb() > 0 ||
351 // affected by closingReroute
352 veh.getRoute().containsAnyOf(i->closed) ||
353 // affected by closingLaneReroute
354 veh.getRoute().containsAnyOf(i->closedLanesAffected)) {
355 return &*i;
356 }
357 }
358 }
359 return nullptr;
360}
361
362
365 for (std::vector<RerouteInterval>::const_iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
366 if (i->begin <= time && i->end > time) {
367 if (i->parkProbs.getOverallProb() != 0 || i->edgeProbs.getOverallProb() != 0 || i->routeProbs.getOverallProb() != 0 || !i->closed.empty()) {
368 return &*i;
369 }
370 }
371 }
372 return nullptr;
373}
374
375
376bool
378 double /*newPos*/, double /*newSpeed*/) {
380}
381
382
383bool
385 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
386 return reason == NOTIFICATION_LANE_CHANGE;
387}
388
389
390bool
392 if (!tObject.isVehicle()) {
393 return false;
394 }
395 SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
396 if (!vehicleApplies(veh)) {
397 return false;
398 }
399 // check whether the vehicle shall be rerouted
401 const MSTriggeredRerouter::RerouteInterval* rerouteDef = getCurrentReroute(time, veh);
402 if (rerouteDef == nullptr) {
403 return true; // an active interval could appear later
404 }
405 const double prob = myAmInUserMode ? myUserProbability : myProbability;
406 if (prob < 1 && RandHelper::rand(veh.getRNG()) > prob) {
407 return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
408 }
410 return true; // waiting time may be reached later
411 }
412 if (reason == NOTIFICATION_LANE_CHANGE) {
413 return false;
414 }
415 // if we have a closingLaneReroute, only vehicles with a rerouting device can profit from rerouting (otherwise, edge weights will not reflect local jamming)
416 const bool hasReroutingDevice = veh.getDevice(typeid(MSDevice_Routing)) != nullptr;
417 if (rerouteDef->closedLanes.size() > 0 && !hasReroutingDevice) {
418 return true; // an active interval could appear later
419 }
420 // get vehicle params
421 const MSRoute& route = veh.getRoute();
422 const MSEdge* lastEdge = route.getLastEdge();
423#ifdef DEBUG_REROUTER
424 if (DEBUGCOND) {
425 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";
426 }
427#endif
428
429 if (rerouteDef->parkProbs.getOverallProb() > 0) {
430#ifdef HAVE_FOX
431 ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
432#endif
433 bool newDestination = false;
434 ConstMSEdgeVector newRoute;
435 MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination, newRoute);
436 if (newParkingArea != nullptr) {
437 // adapt plans of any riders
438 for (MSTransportable* p : veh.getPersons()) {
439 p->rerouteParkingArea(veh.getNextParkingArea(), newParkingArea);
440 }
441
442 if (newDestination) {
443 // update arrival parameters
444 SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
445 *newParameter = veh.getParameter();
447 newParameter->arrivalPos = newParkingArea->getEndLanePosition();
448 veh.replaceParameter(newParameter);
449 }
450
451 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
452 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
453 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
454 const double routeCost = router.recomputeCosts(newRoute, &veh, MSNet::getInstance()->getCurrentTimeStep());
455 ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
456 const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
457 const double savings = previousCost - routeCost;
458 hasReroutingDevice
460 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
461 //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
462 // << " prevEdges=" << toString(prevEdges)
463 // << " newEdges=" << toString(edges)
464 // << "\n";
465
466 std::string errorMsg;
467 if (veh.replaceParkingArea(newParkingArea, errorMsg)) {
468 veh.replaceRouteEdges(newRoute, routeCost, savings, getID() + ":" + toString(SUMO_TAG_PARKING_AREA_REROUTE), false, false, false);
469 } else {
470 WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
471 + "' could not reroute to new parkingArea '" + newParkingArea->getID()
472 + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
473 }
474 }
475 return false;
476 }
477
478 // get rerouting params
479 ConstMSRoutePtr newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : 0;
480 // we will use the route if given rather than calling our own dijsktra...
481 if (newRoute != nullptr) {
482#ifdef DEBUG_REROUTER
483 if (DEBUGCOND) {
484 std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
485 }
486#endif
487 veh.replaceRoute(newRoute, getID());
488 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
489 }
490 const MSEdge* newEdge = lastEdge;
491 // ok, try using a new destination
492 double newArrivalPos = -1;
493 const bool destUnreachable = std::find(rerouteDef->closed.begin(), rerouteDef->closed.end(), lastEdge) != rerouteDef->closed.end();
494 bool keepDestination = false;
495 // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
496 // if we have a closingLaneReroute, no new destinations should be assigned
497 if (rerouteDef->closed.size() == 0 || destUnreachable) {
498 newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : route.getLastEdge();
499 if (newEdge == &mySpecialDest_terminateRoute) {
500 keepDestination = true;
501 newEdge = veh.getEdge();
502 newArrivalPos = veh.getPositionOnLane(); // instant arrival
503 } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
504 if (destUnreachable && rerouteDef->permissions == SVCAll) {
505 // if permissions aren't set vehicles will simply drive through
506 // the closing unless terminated. If the permissions are specified, assume that the user wants
507 // vehicles to stand and wait until the closing ends
508 WRITE_WARNINGF(TL("Cannot keep destination edge '%' for vehicle '%' due to closed edges. Terminating route."), lastEdge->getID(), veh.getID());
509 newEdge = veh.getEdge();
510 } else {
511 newEdge = lastEdge;
512 }
513 } else if (newEdge == nullptr) {
514#ifdef DEBUG_REROUTER
515 if (DEBUGCOND) {
516 std::cout << " could not find new edge!\n";
517 }
518#endif
519 assert(false); // this should never happen
520 newEdge = veh.getEdge();
521 }
522 }
523 // we have a new destination, let's replace the vehicle route (if it is affected)
524 if (rerouteDef->closed.size() == 0 || destUnreachable || veh.getRoute().containsAnyOf(rerouteDef->closed)) {
525 ConstMSEdgeVector edges;
526 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
527 ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
528 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
529 router.compute(veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
530 if (edges.size() == 0 && !keepDestination && rerouteDef->edgeProbs.getOverallProb() > 0) {
531 // destination unreachable due to closed intermediate edges. pick among alternative targets
532 RandomDistributor<MSEdge*> edgeProbs2 = rerouteDef->edgeProbs;
533 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
534 while (edges.size() == 0 && edgeProbs2.getVals().size() > 0) {
535 newEdge = edgeProbs2.get();
536 edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
537 if (newEdge == &mySpecialDest_terminateRoute) {
538 newEdge = veh.getEdge();
539 newArrivalPos = veh.getPositionOnLane(); // instant arrival
540 }
541 if (newEdge == &mySpecialDest_keepDestination && rerouteDef->permissions != SVCAll) {
542 newEdge = lastEdge;
543 break;
544 }
545 router.compute(
546 veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
547 }
548
549 }
550 const double routeCost = router.recomputeCosts(edges, &veh, MSNet::getInstance()->getCurrentTimeStep());
551 hasReroutingDevice
553 : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
554 const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
555#ifdef DEBUG_REROUTER
556 if (DEBUGCOND) std::cout << " rerouting: newDest=" << newEdge->getID()
557 << " newEdges=" << toString(edges)
558 << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
559 << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->closed) << "\n";
560#endif
561 if (useNewRoute && newArrivalPos != -1) {
562 // must be called here because replaceRouteEdges may also set the arrivalPos
563 veh.setArrivalPos(newArrivalPos);
564 }
565 }
566 return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
567}
568
569
570void
574
575
576void
580
581
582bool
586
587
588double
592
593
594double
598
599
600double
601MSTriggeredRerouter::getWeight(SUMOVehicle& veh, const std::string param, const double defaultWeight) {
602 // get custom vehicle parameter
603 if (veh.getParameter().knowsParameter(param)) {
604 try {
605 return StringUtils::toDouble(veh.getParameter().getParameter(param, "-1"));
606 } catch (...) {
607 WRITE_WARNINGF(TL("Invalid value '%' for vehicle parameter '%'"), veh.getParameter().getParameter(param, "-1"), param);
608 }
609 } else {
610 // get custom vType parameter
611 if (veh.getVehicleType().getParameter().knowsParameter(param)) {
612 try {
614 } catch (...) {
615 WRITE_WARNINGF(TL("Invalid value '%' for vType parameter '%'"), veh.getVehicleType().getParameter().getParameter(param, "-1"), param);
616 }
617 }
618 }
619 //WRITE_MESSAGE("Vehicle '" +veh.getID() + "' does not supply vehicle parameter '" + param + "'. Using default of " + toString(defaultWeight) + "\n";
620 return defaultWeight;
621}
622
623
626 SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute) {
627 // Reroute destination from initial parking area to an alternative parking area
628 // if the following conditions are met:
629 // - next stop target is a parking area
630 // - target is included in the current alternative set
631 // - target is visibly full
632 // Any parking areas that are visibly full at the current location are
633 // committed to parking memory
634
635 MSParkingArea* nearParkArea = nullptr;
636 std::vector<ParkingAreaVisible> parks = rerouteDef->parkProbs.getVals();
637
638 // get vehicle params
639 MSParkingArea* destParkArea = veh.getNextParkingArea();
640 const MSRoute& route = veh.getRoute();
641
642 if (destParkArea == nullptr) {
643 // not driving towards a parkingArea
644 return nullptr;
645 }
646 // if the vehicle is on the destParkArea edge it is always visible
647 bool destVisible = (&destParkArea->getLane().getEdge() == veh.getEdge());
648
649 for (auto paVis : parks) {
650 if (paVis.first == destParkArea && paVis.second) {
651 destVisible = true;
652 break;
653 }
654 }
655
656 MSParkingArea* onTheWay = nullptr;
657 const int parkAnywhere = (int)getWeight(veh, "parking.anywhere", -1);
658
659 // check whether we are ready to accept any free parkingArea along the
660 // way to our destination
661 if (parkAnywhere < 0 || parkAnywhere > veh.getNumberParkingReroutes()) {
662 if (!destVisible) {
663 // cannot determine destination occupancy, only register visibly full
664 for (const ParkingAreaVisible& pav : parks) {
665 if (pav.second && pav.first->getLastStepOccupancy() == pav.first->getCapacity()) {
666 veh.rememberBlockedParkingArea(pav.first, &pav.first->getLane().getEdge() == veh.getEdge());
667 }
668 }
669#ifdef DEBUG_PARKING
670 if (DEBUGCOND) {
671 //std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID()
672 // << " dest=" << destParkArea->getID() << " parkAnywhere=" << parkAnywhere << " parkingReroutes=" << veh.getNumberParkingReroutes() << " stay on original route\n";
673 }
674#endif
675 }
676
677 } else {
678 double bestDist = std::numeric_limits<double>::max();
679 const double brakeGap = veh.getBrakeGap(true);
680 for (ParkingAreaVisible& item : parks) {
681 if (item.second) {
682 MSParkingArea* pa = item.first;
683 if (&pa->getLane().getEdge() == veh.getEdge()
684 && pa->getLastStepOccupancy() < pa->getCapacity()) {
685 const double distToStart = pa->getBeginLanePosition() - veh.getPositionOnLane();
686 const double distToEnd = pa->getEndLanePosition() - veh.getPositionOnLane();
687 if (distToEnd > brakeGap) {
688 veh.rememberParkingAreaScore(pa, "dist=" + toString(distToStart));
689 if (distToStart < bestDist) {
690 bestDist = distToStart;
691 onTheWay = pa;
692 }
693 } else {
694 veh.rememberParkingAreaScore(pa, "tooClose");
695 }
696 }
697 }
698 }
699#ifdef DEBUG_PARKING
700 if (DEBUGCOND) {
701 std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID()
702 << " dest=" << destParkArea->getID() << " parkAnywhere=" << parkAnywhere << " parkingReroutes=" << veh.getNumberParkingReroutes() << " alongTheWay=" << Named::getIDSecure(onTheWay) << "\n";
703 }
704#endif
705 }
706 if (!destVisible && onTheWay == nullptr) {
707 return nullptr;
708 }
709
710 if (destParkArea->getLastStepOccupancy() == destParkArea->getCapacity() || onTheWay != nullptr) {
711
712 // if the current route ends at the parking area, the new route will
713 // also and at the new area
714 newDestination = (&destParkArea->getLane().getEdge() == route.getLastEdge()
715 && veh.getArrivalPos() >= destParkArea->getBeginLanePosition()
716 && veh.getArrivalPos() <= destParkArea->getEndLanePosition());
717
718#ifdef DEBUG_PARKING
719 if (DEBUGCOND) {
720 std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID()
721 << " rerouteParkingArea dest=" << destParkArea->getID()
722 << " onDestEdge=" << (&(destParkArea->getLane().getEdge()) == veh.getEdge())
723 << " newDest=" << newDestination
724 << " onTheWay=" << Named::getIDSecure(onTheWay)
725 << "\n";
726 }
727#endif
728
729 ParkingParamMap_t weights;
730 std::map<MSParkingArea*, ConstMSEdgeVector> newRoutes;
731 std::map<MSParkingArea*, ConstMSEdgeVector> parkApproaches;
732
733 // The probability of choosing this area inside the zone
734 weights["probability"] = getWeight(veh, "parking.probability.weight", 0.0);
735
736 // The capacity of this area
737 weights["capacity"] = getWeight(veh, "parking.capacity.weight", 0.0);
738
739 // The absolute number of free spaces
740 weights["absfreespace"] = getWeight(veh, "parking.absfreespace.weight", 0.0);
741
742 // The relative number of free spaces
743 weights["relfreespace"] = getWeight(veh, "parking.relfreespace.weight", 0.0);
744
745 // The distance to the new parking area
746 weights["distanceto"] = getWeight(veh, "parking.distanceto.weight", getWeight(veh, "parking.distance.weight", 1.0));
747
748 // The time to reach this area
749 weights["timeto"] = getWeight(veh, "parking.timeto.weight", 0.0);
750
751 // The distance from the new parking area
752 weights["distancefrom"] = getWeight(veh, "parking.distancefrom.weight", 0.0);
753
754 // The time to reach the end from this area
755 weights["timefrom"] = getWeight(veh, "parking.timefrom.weight", 0.0);
756
757 // a map stores maximum values to normalize parking values
758 ParkingParamMap_t maxValues;
759
760 maxValues["probability"] = 0.0;
761 maxValues["capacity"] = 0.0;
762 maxValues["absfreespace"] = 0.0;
763 maxValues["relfreespace"] = 0.0;
764 maxValues["distanceto"] = 0.0;
765 maxValues["timeto"] = 0.0;
766 maxValues["distancefrom"] = 0.0;
767 maxValues["timefrom"] = 0.0;
768
769 // a map stores elegible parking areas
770 MSParkingAreaMap_t parkAreas;
771
773
774 const std::vector<double>& probs = rerouteDef->parkProbs.getProbs();
775
776 const double brakeGap = veh.getBrakeGap(true);
777
778 if (onTheWay != nullptr) {
779 // compute new route
780 if (newDestination) {
781 newRoute.push_back(veh.getEdge());
782 } else {
783 bool valid = addParkValues(veh, brakeGap, newDestination, onTheWay, onTheWay->getLastStepOccupancy(), 1, router, parkAreas, newRoutes, parkApproaches, maxValues);
784 if (!valid) {
785 WRITE_WARNINGF(TL("Parkingarea '%' along the way cannot be used by vehicle '%' for unknown reason"), onTheWay->getID(), veh.getID());
786 return nullptr;
787 }
788 newRoute = newRoutes[onTheWay];
789 }
790 return onTheWay;
791 }
792
793 int numAlternatives = 0;
794 std::vector<std::tuple<SUMOTime, MSParkingArea*, int> > blockedTimes;
796 veh.rememberParkingAreaScore(destParkArea, "occupied");
797 veh.rememberBlockedParkingArea(destParkArea, &destParkArea->getLane().getEdge() == veh.getEdge());
798
799 const SUMOTime parkingMemory = TIME2STEPS(getWeight(veh, "parking.memory", 600));
800 const double parkingFrustration = getWeight(veh, "parking.frustration", 100);
801 const double parkingKnowledge = getWeight(veh, "parking.knowledge", 0);
802
803 for (int i = 0; i < (int)parks.size(); ++i) {
804 MSParkingArea* pa = parks[i].first;
805 // alternative occupancy is randomized (but never full) if invisible
806 // current destination must be visible at this point
807 const bool visible = parks[i].second || (pa == destParkArea && destVisible);
808 double paOccupancy = pa->getOccupancy();
809 if (!visible && (parkingKnowledge == 0 || parkingKnowledge < RandHelper::rand(veh.getRNG()))) {
810 const double minOccupancy = MIN2((double)pa->getCapacity() - NUMERICAL_EPS, (veh.getNumberParkingReroutes() * pa->getCapacity() / parkingFrustration));
811 paOccupancy = RandHelper::rand(minOccupancy, (double)pa->getCapacity());
812 // previously visited?
813 SUMOTime blockedTime = veh.sawBlockedParkingArea(pa, false);
814 if (blockedTime >= 0 && SIMSTEP - blockedTime < parkingMemory) {
815 // assume it's still occupied
816 paOccupancy = pa->getCapacity();
817 blockedTimes.push_back(std::make_tuple(blockedTime, pa, i));
818#ifdef DEBUG_PARKING
819 if (DEBUGCOND) {
820 std::cout << " altPA=" << pa->getID() << " was blocked at " << time2string(blockedTime) << "\n";
821 }
822#endif
823 }
824 }
825 if (paOccupancy < pa->getCapacity()) {
826 if (addParkValues(veh, brakeGap, newDestination, pa, paOccupancy, probs[i], router, parkAreas, newRoutes, parkApproaches, maxValues)) {
827 numAlternatives++;
828 }
829 } else if (visible) {
830 // might only be visible now (i.e. because it's on the other
831 // side of the street), so we should remember this for later.
832 veh.rememberBlockedParkingArea(pa, &pa->getLane().getEdge() == veh.getEdge());
833 }
834 }
835 if (numAlternatives == 0) {
836 // use parkingArea with lowest blockedTime
837 std::sort(blockedTimes.begin(), blockedTimes.end(),
838 [](std::tuple<SUMOTime, MSParkingArea*, int> const & t1, std::tuple<SUMOTime, MSParkingArea*, int> const & t2) {
839 if (std::get<0>(t1) < std::get<0>(t2)) {
840 return true;
841 }
842 if (std::get<0>(t1) == std::get<0>(t2)) {
843 if (std::get<1>(t1)->getID() < std::get<1>(t2)->getID()) {
844 return true;
845 }
846 if (std::get<1>(t1)->getID() == std::get<1>(t2)->getID()) {
847 return std::get<2>(t1) < std::get<2>(t2);
848 }
849 }
850 return false;
851 }
852 );
853 for (auto item : blockedTimes) {
854 MSParkingArea* pa = std::get<1>(item);
855 double prob = probs[std::get<2>(item)];
856 // all parking areas are occupied. We have no good basis for
857 // prefering one or the other based on estimated occupancy
858 double paOccupancy = RandHelper::rand((double)pa->getCapacity());
859 if (addParkValues(veh, brakeGap, newDestination, pa, paOccupancy, prob, router, parkAreas, newRoutes, parkApproaches, maxValues)) {
860#ifdef DEBUG_PARKING
861 if (DEBUGCOND) {
862 std::cout << " altPA=" << pa->getID() << " targeting occupied pa based on blockTime " << STEPS2TIME(std::get<0>(item)) << " among " << blockedTimes.size() << " alternatives\n";
863 }
864#endif
865 numAlternatives = 1;
866 break;
867 }
868 //std::cout << " candidate=" << item.second->getID() << " observed=" << time2string(item.first) << "\n";
869 }
870 if (numAlternatives == 0) {
871 // take any random target but prefer that that haven't been visited yet
872 std::vector<std::pair<SUMOTime, MSParkingArea*> > candidates;
873 for (const ParkingAreaVisible& pav : parks) {
874 if (pav.first == destParkArea) {
875 continue;
876 }
877 SUMOTime dummy = veh.sawBlockedParkingArea(pav.first, true);
878 if (dummy < 0) {
879 // randomize among the unvisited
880 dummy = -RandHelper::rand(1000000);
881 }
882 candidates.push_back(std::make_pair(dummy, pav.first));
883 }
884 std::sort(candidates.begin(), candidates.end(),
885 [](std::tuple<SUMOTime, MSParkingArea*> const & t1, std::tuple<SUMOTime, MSParkingArea*> const & t2) {
886 return std::get<0>(t1) < std::get<0>(t2) || (std::get<0>(t1) == std::get<0>(t2) && std::get<1>(t1)->getID() < std::get<1>(t2)->getID());
887 }
888 );
889 for (auto item : candidates) {
890 MSParkingArea* pa = item.second;
891 if (addParkValues(veh, brakeGap, newDestination, pa, 0, 1, router, parkAreas, newRoutes, parkApproaches, maxValues)) {
892#ifdef DEBUG_PARKING
893 if (DEBUGCOND) {
894 std::cout << " altPA=" << pa->getID() << " targeting occupied pa (based on pure randomness) among " << candidates.size() << " alternatives\n";
895 }
896#endif
897 numAlternatives = 1;
898 break;
899 }
900 }
901 }
902 }
903
904 MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
905
906#ifdef DEBUG_PARKING
907 if (DEBUGCOND) {
908 std::cout << " maxValues=" << joinToString(maxValues, " ", ":") << "\n";
909 }
910#endif
911
912 // minimum cost to get the parking area
913 double minParkingCost = 0.0;
914
915 for (MSParkingAreaMap_t::iterator it = parkAreas.begin(); it != parkAreas.end(); ++it) {
916 // get the parking values
917 ParkingParamMap_t parkValues = it->second;
918
919 if (weights["probability"] > 0 && maxValues["probability"] > 0.0) {
920 // random search should not drive past a usable parking area
921 bool dominated = false;
922 double endPos = it->first->getEndLanePosition();
923 const ConstMSEdgeVector& to1 = parkApproaches[it->first];
924 assert(to1.size() > 0);
925 for (auto altPa : parkAreas) {
926 if (altPa.first == it->first) {
927 continue;
928 }
929 const ConstMSEdgeVector& to2 = parkApproaches[altPa.first];
930 assert(to2.size() > 0);
931 if (to1.size() > to2.size()) {
932 if (std::equal(to2.begin(), to2.end(), to1.begin())) {
933 // other target lies on the route to the current candidate
934 dominated = true;
935 //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " onTheWay=" << altPa.first->getID() << "\n";
936 break;
937 }
938 } else if (to1 == to2 && endPos > altPa.first->getEndLanePosition()) {
939 // other target is on the same edge but ahead of the current candidate
940 dominated = true;
941 //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " sameEdge=" << altPa.first->getID() << "\n";
942 break;
943 }
944 }
945 double prob = 0;
946 if (!dominated) {
947 prob = RandHelper::rand(parkValues["probability"], veh.getRNG());
948 parkValues["probability"] = 1.0 - prob / maxValues["probability"];
949 } else {
950 // worst probability score
951 parkValues["probability"] = 1.0;
952 }
953 } else {
954 // value takes no effect due to weight=0
955 parkValues["probability"] = 0;
956 }
957 // normalizing with maximum values (we want to maximize some parameters then we reverse the value)
958 parkValues["capacity"] = maxValues["capacity"] > 0.0 ? 1.0 - parkValues["capacity"] / maxValues["capacity"] : 0.0;
959 parkValues["absfreespace"] = maxValues["absfreespace"] > 0.0 ? 1.0 - parkValues["absfreespace"] / maxValues["absfreespace"] : 0.0;
960 parkValues["relfreespace"] = maxValues["relfreespace"] > 0.0 ? 1.0 - parkValues["relfreespace"] / maxValues["relfreespace"] : 0.0;
961
962 parkValues["distanceto"] = maxValues["distanceto"] > 0.0 ? parkValues["distanceto"] / maxValues["distanceto"] : 0.0;
963 parkValues["timeto"] = maxValues["timeto"] > 0.0 ? parkValues["timeto"] / maxValues["timeto"] : 0.0;
964
965 parkValues["distancefrom"] = maxValues["distancefrom"] > 0.0 ? parkValues["distancefrom"] / maxValues["distancefrom"] : 0.0;
966 parkValues["timefrom"] = maxValues["timefrom"] > 0.0 ? parkValues["timefrom"] / maxValues["timefrom"] : 0.0;
967
968 // get the parking area cost
969 double parkingCost = 0.0;
970
971 // sum every index with its weight
972 for (ParkingParamMap_t::iterator pc = parkValues.begin(); pc != parkValues.end(); ++pc) {
973 parkingCost += weights[pc->first] * pc->second;
974 }
975 veh.rememberParkingAreaScore(it->first, toString(parkingCost)
976 //+ " rfs=" + toString(parkValues["relfreespace"])
977 //+ " dt=" + toString(parkValues["distanceto"])
978 //+ " p=" + toString(parkValues["probability"])
979 );
980
981 // get the parking area with minimum cost
982 if (nearParkArea == nullptr || parkingCost < minParkingCost) {
983 minParkingCost = parkingCost;
984 nearParkArea = it->first;
985 newRoute = newRoutes[nearParkArea];
986 }
987
988#ifdef DEBUG_PARKING
989 if (DEBUGCOND) {
990 std::cout << " altPA=" << it->first->getID() << " score=" << parkingCost << " vals=" << joinToString(parkValues, " ", ":") << "\n";
991 }
992#endif
993 }
995 } else {
996#ifdef DEBUG_PARKING
997 if (DEBUGCOND) {
998 std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID() << " rerouteParkingArea dest=" << destParkArea->getID() << " sufficient space\n";
999 }
1000#endif
1001 }
1002
1003#ifdef DEBUG_PARKING
1004 if (DEBUGCOND) {
1005 std::cout << " parkingResult=" << Named::getIDSecure(nearParkArea) << "\n";
1006 }
1007#endif
1008
1009 return nearParkArea;
1010}
1011
1012
1013bool
1014MSTriggeredRerouter::addParkValues(SUMOVehicle& veh, double brakeGap, bool newDestination,
1015 MSParkingArea* pa, double paOccupancy, double prob,
1017 MSParkingAreaMap_t& parkAreas,
1018 std::map<MSParkingArea*, ConstMSEdgeVector>& newRoutes,
1019 std::map<MSParkingArea*, ConstMSEdgeVector>& parkApproaches,
1020 ParkingParamMap_t& maxValues) {
1021 // a map stores the parking values
1022 ParkingParamMap_t parkValues;
1023
1024 const MSRoute& route = veh.getRoute();
1025 const RGBColor& c = route.getColor();
1026 const MSEdge* parkEdge = &(pa->getLane().getEdge());
1027
1028 const bool includeInternalLengths = MSGlobals::gUsingInternalLanes && MSNet::getInstance()->hasInternalLinks();
1029
1030 // Compute the route from the current edge to the parking area edge
1031 ConstMSEdgeVector edgesToPark;
1032 const double parkPos = pa->getLastFreePos(veh);
1033 const MSEdge* rerouteOrigin = *veh.getRerouteOrigin();
1034 router.compute(rerouteOrigin, veh.getPositionOnLane(), parkEdge, parkPos, &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesToPark, true);
1035
1036#ifdef DEBUG_PARKING
1037 if (DEBUGCOND) {
1038 std::cout << " altPA=" << pa->getID() << " vehEdge=" << veh.getEdge()->getID() << " parkEdge " << parkEdge->getID() << " edgesToPark=" << edgesToPark.size() << "\n";
1039 }
1040#endif
1041
1042 if (edgesToPark.size() > 0) {
1043 // Compute the route from the parking area edge to the end of the route
1044 if (rerouteOrigin != veh.getEdge()) {
1045 edgesToPark.insert(edgesToPark.begin(), veh.getEdge());
1046 }
1047 ConstMSEdgeVector edgesFromPark;
1048 parkApproaches[pa] = edgesToPark;
1049
1050 const MSEdge* nextDestination = route.getLastEdge();
1051 double nextPos = veh.getArrivalPos();
1052 int nextDestinationIndex = route.size() - 1;
1053 if (!newDestination) {
1054 std::vector<std::pair<int, double> > stopIndices = veh.getStopIndices();
1055 if (stopIndices.size() > 1) {
1056 nextDestinationIndex = stopIndices[1].first;
1057 nextDestination = route.getEdges()[nextDestinationIndex];
1058 nextPos = stopIndices[1].second;
1059
1060 }
1061 router.compute(parkEdge, parkPos, nextDestination, nextPos, &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesFromPark, true);
1062 }
1063#ifdef DEBUG_PARKING
1064 if (DEBUGCOND) {
1065 //std::cout << " altPA=" << pa->getID() << " parkEdge=" << parkEdge->getID() << " nextDest=" << nextDestination->getID() << " edgesFromPark=" << edgesFromPark.size() << "\n";
1066 }
1067#endif
1068
1069 if (edgesFromPark.size() > 0 || newDestination) {
1070
1071 parkValues["probability"] = prob;
1072
1073 if (parkValues["probability"] > maxValues["probability"]) {
1074 maxValues["probability"] = parkValues["probability"];
1075 }
1076
1077 parkValues["capacity"] = (double)(pa->getCapacity());
1078 parkValues["absfreespace"] = (double)(pa->getCapacity() - paOccupancy);
1079 // if capacity = 0 then absfreespace and relfreespace are also 0
1080 parkValues["relfreespace"] = parkValues["absfreespace"] / MAX2(1.0, parkValues["capacity"]);
1081
1082 if (parkValues["capacity"] > maxValues["capacity"]) {
1083 maxValues["capacity"] = parkValues["capacity"];
1084 }
1085
1086 if (parkValues["absfreespace"] > maxValues["absfreespace"]) {
1087 maxValues["absfreespace"] = parkValues["absfreespace"];
1088 }
1089
1090 if (parkValues["relfreespace"] > maxValues["relfreespace"]) {
1091 maxValues["relfreespace"] = parkValues["relfreespace"];
1092 }
1093
1094 MSRoute routeToPark(route.getID() + "!topark#1", edgesToPark, false,
1095 &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
1096
1097 // The distance from the current edge to the new parking area
1098 double toPos = pa->getBeginLanePosition();
1099 if (&pa->getLane().getEdge() == veh.getEdge()) {
1100 toPos = MAX2(veh.getPositionOnLane(), toPos);
1101 }
1102 parkValues["distanceto"] = routeToPark.getDistanceBetween(veh.getPositionOnLane(), toPos,
1103 routeToPark.begin(), routeToPark.end() - 1, includeInternalLengths);
1104
1105 if (parkValues["distanceto"] == std::numeric_limits<double>::max()) {
1106 WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' to parkingArea '%' at time=%."),
1107 veh.getID(), pa->getID(), time2string(SIMSTEP));
1108 }
1109 const double endPos = pa->getOccupancy() == pa->getCapacity()
1110 ? pa->getLastFreePos(veh, veh.getPositionOnLane() + brakeGap)
1111 : pa->getEndLanePosition();
1112 const double distToEnd = parkValues["distanceto"] - toPos + endPos;
1113#ifdef DEBUG_PARKING
1114 if (DEBUGCOND) {
1115 std::cout << " " << veh.getID() << " candidate=" << pa->getID()
1116 << " distanceTo=" << parkValues["distanceto"]
1117 << " brakeGap=" << brakeGap
1118 << " routeToPark=" << toString(edgesToPark)
1119 << " vehPos=" << veh.getPositionOnLane()
1120 << " begPos=" << pa->getBeginLanePosition()
1121 << " toPos=" << toPos
1122 << " endPos=" << pa->getEndLanePosition()
1123 << " distToEnd=" << distToEnd
1124 << "\n";
1125 }
1126#endif
1127
1128 if (distToEnd < brakeGap) {
1129 veh.rememberParkingAreaScore(pa, "tooClose");
1130#ifdef DEBUG_PARKING
1131 if (DEBUGCOND) {
1132 std::cout << " altPA=" << pa->getID() << " too close to brake (dist=" << distToEnd << " brakeGap=" << brakeGap << "\n";
1133 }
1134#endif
1135 return false;
1136 }
1137
1138 // The time to reach the new parking area
1139 parkValues["timeto"] = router.recomputeCosts(edgesToPark, &veh, MSNet::getInstance()->getCurrentTimeStep());
1140
1141 if (parkValues["distanceto"] > maxValues["distanceto"]) {
1142 maxValues["distanceto"] = parkValues["distanceto"];
1143 }
1144
1145 if (parkValues["timeto"] > maxValues["timeto"]) {
1146 maxValues["timeto"] = parkValues["timeto"];
1147 }
1148
1149 ConstMSEdgeVector newEdges = edgesToPark;
1150
1151 if (newDestination) {
1152 parkValues["distancefrom"] = 0;
1153 parkValues["timefrom"] = 0;
1154 } else {
1155 MSRoute routeFromPark(route.getID() + "!frompark#1", edgesFromPark, false,
1156 &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
1157 // The distance from the new parking area to the end of the route
1158 parkValues["distancefrom"] = routeFromPark.getDistanceBetween(pa->getBeginLanePosition(), routeFromPark.getLastEdge()->getLength(),
1159 routeFromPark.begin(), routeFromPark.end() - 1, includeInternalLengths);
1160 if (parkValues["distancefrom"] == std::numeric_limits<double>::max()) {
1161 WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' from parkingArea '%' at time=%."),
1162 veh.getID(), pa->getID(), time2string(SIMSTEP));
1163 }
1164 // The time to reach this area
1165 parkValues["timefrom"] = router.recomputeCosts(edgesFromPark, &veh, SIMSTEP);
1166 newEdges.insert(newEdges.end(), edgesFromPark.begin() + 1, edgesFromPark.end());
1167 newEdges.insert(newEdges.end(), route.begin() + nextDestinationIndex + 1, route.end());
1168 }
1169
1170 if (parkValues["distancefrom"] > maxValues["distancefrom"]) {
1171 maxValues["distancefrom"] = parkValues["distancefrom"];
1172 }
1173
1174 if (parkValues["timefrom"] > maxValues["timefrom"]) {
1175 maxValues["timefrom"] = parkValues["timefrom"];
1176 }
1177
1178 parkAreas[pa] = parkValues;
1179 newRoutes[pa] = newEdges;
1180
1181 return true;
1182 } else {
1183 veh.rememberParkingAreaScore(pa, "destUnreachable");
1184 }
1185 } else {
1186 veh.rememberParkingAreaScore(pa, "unreachable");
1187 }
1188#ifdef DEBUG_PARKING
1189 if (DEBUGCOND) {
1190 std::cout << " altPA=" << pa->getID() << " disconnected\n";
1191 }
1192#endif
1193 // unreachable
1194 return false;
1195}
1196
1197
1198bool
1200 if (myVehicleTypes.empty() || myVehicleTypes.count(veh.getVehicleType().getOriginalID()) > 0) {
1201 return true;
1202 } else {
1204 for (auto vTypeDist : vTypeDists) {
1205 if (myVehicleTypes.count(vTypeDist) > 0) {
1206 return true;
1207 }
1208 }
1209 return false;
1210 }
1211}
1212
1213
1214void
1216 // if a parkingArea is a rerouting target, it should generally have a
1217 // rerouter on it's edge or vehicles will be stuck there once it's full.
1218 // The user should receive a Warning in this case
1219 std::set<MSEdge*> parkingRerouterEdges;
1220 std::map<MSParkingArea*, std::string, ComparatorIdLess> targetedParkingArea; // paID -> targetingRerouter
1221 for (const auto& rr : myInstances) {
1222 bool hasParkingReroute = false;
1223 for (const RerouteInterval& interval : rr.second->myIntervals) {
1224 if (interval.parkProbs.getOverallProb() > 0) {
1225 hasParkingReroute = true;
1226 for (const ParkingAreaVisible& pav : interval.parkProbs.getVals()) {
1227 targetedParkingArea[pav.first] = rr.first;
1228 }
1229 }
1230 }
1231 if (hasParkingReroute) {
1232 parkingRerouterEdges.insert(rr.second->myEdges.begin(), rr.second->myEdges.end());
1233 }
1234 }
1235 for (const auto& item : targetedParkingArea) {
1236 if (parkingRerouterEdges.count(&item.first->getLane().getEdge()) == 0) {
1237 WRITE_WARNINGF(TL("ParkingArea '%' is targeted by rerouter '%' but doesn't have it's own rerouter. This may cause parking search to abort."),
1238 item.first->getID(), item.second);
1239 }
1240 }
1241}
1242/****************************************************************************/
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(PEDID)
#define DEBUGCOND
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:271
#define WRITE_WARNING(msg)
Definition MsgHandler.h:270
#define TL(string)
Definition MsgHandler.h:287
#define TLF(string,...)
Definition MsgHandler.h:288
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 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...
@ 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_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 MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:325
A single mesoscopic segment (cell)
Definition MESegment.h:49
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
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:945
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:103
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:109
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:143
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:78
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:2325
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:745
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:183
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:473
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition MSNet.cpp:1465
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:322
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1363
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:380
bool hasInternalLinks() const
return whether the network contains internal links
Definition MSNet.h:778
A lane area vehicles can halt at.
int getCapacity() const
Returns the area capacity.
double getLastFreePos(const SUMOVehicle &forVehicle, double brakePos=0) const
Returns the last free position on this stop.
int getLastStepOccupancy() const
Returns the area occupancy at the end of the last simulation step.
int getOccupancy() const
Returns the area occupancy.
int size() const
Returns the number of edges to pass.
Definition MSRoute.cpp:85
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:124
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition MSRoute.cpp:410
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition MSRoute.cpp:79
const MSEdge * getLastEdge() const
returns the destination edge
Definition MSRoute.cpp:91
double getDistanceBetween(double fromPos, double toPos, const MSEdge *fromEdge, const MSEdge *toEdge, bool includeInternal=true, int routePosition=0) const
Compute the distance between 2 given edges on this route, including the length of internal lanes....
Definition MSRoute.cpp:311
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
const RGBColor & getColor() const
Returns the color.
Definition MSRoute.cpp:401
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition MSRoute.cpp:73
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
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.
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.
RandomDistributor< ParkingAreaVisible > myCurrentParkProb
new destinations with probabilities
RandomDistributor< ConstMSRoutePtr > myCurrentRouteProb
new routes with probabilities
double getUserProbability() const
Returns the rerouting probability given by the user.
static MSParkingArea * rerouteParkingArea(const MSTriggeredRerouter::RerouteInterval *rerouteDef, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute)
std::vector< MSLane * > myCurrentClosedLanes
List of closed lanes.
bool myHaveParkProbs
whether this rerouter has loaded parkingReroute definitions
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
MSTriggeredRerouter(const std::string &id, const MSEdgeVector &edges, double prob, bool off, SUMOTime timeThreshold, const std::string &vTypes)
Constructor.
void setUserUsageProbability(double prob)
Sets the probability with which a vehicle is rerouted given by the user.
SVCPermissions myCurrentPermissions
List of permissions for closed edges.
static bool addParkValues(SUMOVehicle &veh, double brakeGap, bool newDestination, MSParkingArea *pa, double paOccupancy, double prob, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, MSParkingAreaMap_t &parkAreas, std::map< MSParkingArea *, ConstMSEdgeVector > &newRoutes, std::map< MSParkingArea *, ConstMSEdgeVector > &parkApproaches, ParkingParamMap_t &maxValues)
determine attributes of candiate parking area for scoring
static MSEdge mySpecialDest_terminateRoute
virtual void myEndElement(int element)
Called when a closing tag occurs.
const RerouteInterval * getCurrentReroute(SUMOTime time, SUMOVehicle &veh) const
Returns the rerouting definition valid for the given time and vehicle, 0 if none.
std::pair< MSParkingArea *, bool > ParkingAreaVisible
double myProbability
The probability and the user-given probability.
virtual ~MSTriggeredRerouter()
Destructor.
bool inUserMode() const
Returns whether the user is setting the rerouting probability.
std::map< std::string, double > ParkingParamMap_t
std::set< std::string > myVehicleTypes
The vehicle types to look for (empty means all)
MSEdgeVector myCurrentClosed
List of closed edges.
static void checkParkingRerouteConsistency()
issues warning for incomplete parkingReroute relationships
RandomDistributor< MSEdge * > myCurrentEdgeProb
new destinations with probabilities
static std::map< std::string, MSTriggeredRerouter * > myInstances
bool vehicleApplies(const SUMOVehicle &veh) const
Checks whether the detector measures vehicles of the given type.
SUMOTime myCurrentIntervalBegin
The first and the last time steps of the interval.
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
double getProbability() const
Returns the rerouting probability.
std::map< MSParkingArea *, ParkingParamMap_t, ComparatorIdLess > MSParkingAreaMap_t
std::vector< RerouteInterval > myIntervals
List of rerouting definition intervals.
void setUserMode(bool val)
Sets whether the process is currently steered by the user.
static double getWeight(SUMOVehicle &veh, const std::string param, const double defaultWeight)
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.
const SUMOVTypeParameter & getParameter() const
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.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition RGBColor.h:199
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.
void clear()
Clears 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 SUMOTime getWaitingTime() const =0
virtual bool isVehicle() const
Whether it is a vehicle.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
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 MSEdge * getEdge() const =0
Returns the edge the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const =0
Returns the starting point for reroutes (usually the current edge)
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 void rememberParkingAreaScore(const MSParkingArea *pa, const std::string &score)=0
virtual bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)=0
Replaces a stop.
virtual MSParkingArea * getNextParkingArea()=0
virtual SUMOTime getAccumulatedWaitingTime() const =0
virtual int getRNGIndex() const =0
virtual int getNumberParkingReroutes() const =0
virtual const std::vector< MSTransportable * > & getPersons() const =0
retrieve riding persons
virtual double getArrivalPos() const =0
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
virtual void replaceParameter(const SUMOVehicleParameter *newParameter)=0
Replaces the vehicle's parameter.
virtual void rememberBlockedParkingArea(const MSParkingArea *pa, bool local)=0
virtual SUMOTime sawBlockedParkingArea(const MSParkingArea *pa, bool local) const =0
virtual void resetParkingAreaScores()=0
virtual MSVehicleDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
virtual std::vector< std::pair< int, double > > getStopIndices() const =0
return list of route indices and stop positions for the remaining stops
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 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 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
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
A wrapper for a Command function.
SUMOTime begin
The begin time these definitions are valid.
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 to use.
MSEdgeVector closedLanesAffected
The list of edges that are affect by closed lanes.
RandomDistributor< ParkingAreaVisible > parkProbs
The distributions of new parking areas to use as destinations.
SVCPermissions permissions
The permissions to use.
MSEdgeVector closed
The list of closed edges.
std::vector< MSLane * > closedLanes
The list of closed lanes.