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