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