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 /****************************************************************************/
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 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),
82  myEdges(edges),
83  myProbability(prob),
84  myUserProbability(prob),
85  myAmInUserMode(false),
86  myAmOptional(optional),
87  myPosition(pos),
88  myTimeThreshold(timeThreshold),
89  myHaveParkProbs(false) {
90  myInstances[id] = this;
91  // build actors
92  for (const MSEdge* const e : edges) {
95  }
96  for (MSLane* const lane : e->getLanes()) {
97  lane->addMoveReminder(this);
98  }
99  }
100  if (off) {
101  setUserMode(true);
103  }
104  const std::vector<std::string> vt = StringTokenizer(vTypes).getVector();
105  myVehicleTypes.insert(vt.begin(), vt.end());
106 }
107 
108 
110  myInstances.erase(getID());
111 }
112 
113 
114 // ------------ loading begin
115 void
117  const SUMOSAXAttributes& attrs) {
118  if (element == SUMO_TAG_INTERVAL) {
119  bool ok = true;
123  }
124  if (element == SUMO_TAG_DEST_PROB_REROUTE) {
125  // by giving probabilities of new destinations
126  // get the destination edge
127  std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
128  if (dest == "") {
129  throw ProcessError(TLF("MSTriggeredRerouter %: No destination edge id given.", getID()));
130  }
131  MSEdge* to = MSEdge::dictionary(dest);
132  if (to == nullptr) {
133  if (dest == "keepDestination") {
135  } else if (dest == "terminateRoute") {
137  } else {
138  throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
139  }
140  }
141  // get the probability to reroute
142  bool ok = true;
143  double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
144  if (!ok) {
145  throw ProcessError();
146  }
147  if (prob < 0) {
148  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
149  }
150  // add
152  }
153 
154  if (element == SUMO_TAG_CLOSING_REROUTE) {
155  // by closing edge
156  const std::string& closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
157  MSEdge* const closed = MSEdge::dictionary(closed_id);
158  if (closed == nullptr) {
159  throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
160  }
161  myParsedRerouteInterval.closed.push_back(closed);
162  bool ok;
163  const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
164  const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
166  }
167 
168  if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
169  // by closing lane
170  std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
171  MSLane* closed = MSLane::dictionary(closed_id);
172  if (closed == nullptr) {
173  throw ProcessError("MSTriggeredRerouter " + getID() + ": Lane '" + closed_id + "' to close is not known.");
174  }
175  myParsedRerouteInterval.closedLanes.push_back(closed);
176  bool ok;
178  const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
179  const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
181  } else {
182  // lane closing only makes sense if the lane really receives reduced permissions
184  }
185  }
186 
187  if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
188  // by explicit rerouting using routes
189  // check if route exists
190  std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
191  if (routeStr == "") {
192  throw ProcessError(TLF("MSTriggeredRerouter %: No route id given.", getID()));
193  }
194  ConstMSRoutePtr route = MSRoute::dictionary(routeStr);
195  if (route == nullptr) {
196  throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
197  }
198 
199  // get the probability to reroute
200  bool ok = true;
201  double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
202  if (!ok) {
203  throw ProcessError();
204  }
205  if (prob < 0) {
206  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
207  }
208  // add
210  }
211 
212  if (element == SUMO_TAG_PARKING_AREA_REROUTE) {
213  std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
214  if (parkingarea == "") {
215  throw ProcessError(TLF("MSTriggeredRerouter %: No parking area id given.", getID()));
216  }
218  if (pa == nullptr) {
219  throw ProcessError("MSTriggeredRerouter " + getID() + ": Parking area '" + parkingarea + "' is not known.");
220  }
221  // get the probability to reroute
222  bool ok = true;
223  const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
224  if (!ok) {
225  throw ProcessError();
226  }
227  if (prob < 0) {
228  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + parkingarea + "' is negative (must not).");
229  }
230  const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
231  // add
232  myParsedRerouteInterval.parkProbs.add(std::make_pair(pa, visible), prob);
233  myHaveParkProbs = true;
234  }
235 
236  if (element == SUMO_TAG_VIA_PROB_REROUTE) {
237  // by giving probabilities of vias
238  std::string viaID = attrs.getStringSecure(SUMO_ATTR_ID, "");
239  if (viaID == "") {
240  throw ProcessError(TLF("MSTriggeredRerouter %: No via edge id given.", getID()));
241  }
242  MSEdge* const via = MSEdge::dictionary(viaID);
243  if (via == nullptr) {
244  throw ProcessError("MSTriggeredRerouter " + getID() + ": Via edge '" + viaID + "' is not known.");
245  }
246  // get the probability to reroute
247  bool ok = true;
248  double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
249  if (!ok) {
250  throw ProcessError();
251  }
252  if (prob < 0) {
253  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for via '" + viaID + "' is negative (must not).");
254  }
255  // add
258  }
259 }
260 
261 
262 void
264  if (element == SUMO_TAG_INTERVAL) {
265  for (auto paVi : myParsedRerouteInterval.parkProbs.getVals()) {
266  paVi.first->setNumAlternatives((int)myParsedRerouteInterval.parkProbs.getVals().size() - 1);
267  }
268  if (myParsedRerouteInterval.closedLanes.size() > 0) {
269  // collect edges that are affect by a closed lane
270  std::set<MSEdge*> affected;
271  for (const MSLane* const l : myParsedRerouteInterval.closedLanes) {
272  affected.insert(&l->getEdge());
273  }
275  }
276  const SUMOTime closingBegin = myParsedRerouteInterval.begin;
277  const SUMOTime simBegin = string2time(OptionsCont::getOptions().getString("begin"));
278  if (closingBegin < simBegin && myParsedRerouteInterval.end > simBegin) {
279  // interval started before simulation begin but is still active at
280  // the start of the simulation
281  myParsedRerouteInterval.begin = simBegin;
282  }
284  myIntervals.back().id = (long long int)&myIntervals.back();
288  }
289  }
290 }
291 
292 
293 // ------------ loading end
294 
295 
296 SUMOTime
298  bool updateVehicles = false;
299  for (const RerouteInterval& i : myIntervals) {
300  if (i.begin == currentTime && !(i.closed.empty() && i.closedLanes.empty()) && i.permissions != SVCAll) {
301  for (MSEdge* const e : i.closed) {
302  for (MSLane* lane : e->getLanes()) {
303  //std::cout << SIMTIME << " closing: intervalID=" << i.id << " lane=" << (*l)->getID() << " prevPerm=" << getVehicleClassNames((*l)->getPermissions()) << " new=" << getVehicleClassNames(i.permissions) << "\n";
304  lane->setPermissions(i.permissions, i.id);
305  }
306  e->rebuildAllowedLanes();
307  updateVehicles = true;
308  }
309  for (MSLane* const lane : i.closedLanes) {
310  lane->setPermissions(i.permissions, i.id);
311  lane->getEdge().rebuildAllowedLanes();
312  updateVehicles = true;
313  }
316  }
317  if (i.end == currentTime && !(i.closed.empty() && i.closedLanes.empty()) && i.permissions != SVCAll) {
318  for (MSEdge* const e : i.closed) {
319  for (MSLane* lane : e->getLanes()) {
320  lane->resetPermissions(i.id);
321  //std::cout << SIMTIME << " opening: intervalID=" << i.id << " lane=" << (*l)->getID() << " restore prevPerm=" << getVehicleClassNames((*l)->getPermissions()) << "\n";
322  }
323  e->rebuildAllowedLanes();
324  updateVehicles = true;
325  }
326  for (MSLane* lane : i.closedLanes) {
327  lane->resetPermissions(i.id);
328  lane->getEdge().rebuildAllowedLanes();
329  updateVehicles = true;
330  }
331  }
332  }
333  if (updateVehicles) {
334  // only vehicles on the affected lanes had their bestlanes updated so far
335  for (MSEdge* e : myEdges) {
336  // also updates vehicles
337  e->rebuildAllowedTargets();
338  }
339  }
340  return 0;
341 }
342 
343 
346  for (const RerouteInterval& ri : myIntervals) {
347  if (ri.begin <= time && ri.end > time) {
348  if (
349  // destProbReroute
350  ri.edgeProbs.getOverallProb() > 0 ||
351  // routeProbReroute
352  ri.routeProbs.getOverallProb() > 0 ||
353  // parkingZoneReroute
354  ri.parkProbs.getOverallProb() > 0) {
355  return &ri;
356  }
357  if (!ri.closed.empty() || !ri.closedLanesAffected.empty()) {
358  const std::set<SUMOTrafficObject::NumericalID>& edgeIndices = obj.getUpcomingEdgeIDs();
359  if (affected(edgeIndices, ri.closed) || affected(edgeIndices, ri.closedLanesAffected)) {
360  return &ri;
361  }
362  }
363  }
364  }
365  return nullptr;
366 }
367 
368 
371  for (const RerouteInterval& ri : myIntervals) {
372  if (ri.begin <= time && ri.end > time) {
373  if (ri.edgeProbs.getOverallProb() != 0 || ri.routeProbs.getOverallProb() != 0 || ri.parkProbs.getOverallProb() != 0
374  || !ri.closed.empty() || !ri.closedLanesAffected.empty()) {
375  return &ri;
376  }
377  }
378  }
379  return nullptr;
380 }
381 
382 
383 bool
385  if (myAmOptional) {
386  return true;
387  }
388  return triggerRouting(tObject, reason);
389 }
390 
391 
392 bool
394  double /*newPos*/, double /*newSpeed*/) {
396 }
397 
398 
399 bool
401  MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
402  return reason == NOTIFICATION_LANE_CHANGE;
403 }
404 
405 
406 bool
408  if (!applies(tObject)) {
409  return false;
410  }
411  // check whether the vehicle shall be rerouted
413  const MSTriggeredRerouter::RerouteInterval* const rerouteDef = getCurrentReroute(now, tObject);
414  if (rerouteDef == nullptr) {
415  return true; // an active interval could appear later
416  }
417  const double prob = myAmInUserMode ? myUserProbability : myProbability;
418  if (prob < 1 && RandHelper::rand(tObject.getRNG()) > prob) {
419  return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
420  }
421  if (myTimeThreshold > 0 && MAX2(tObject.getWaitingTime(), tObject.getWaitingTime(true)) < myTimeThreshold) {
422  return true; // waiting time may be reached later
423  }
424  if (reason == NOTIFICATION_LANE_CHANGE) {
425  return false;
426  }
427  // if we have a closingLaneReroute, only vehicles with a rerouting device can profit from rerouting (otherwise, edge weights will not reflect local jamming)
428  const bool hasReroutingDevice = tObject.getDevice(typeid(MSDevice_Routing)) != nullptr;
429  if (rerouteDef->closedLanes.size() > 0 && !hasReroutingDevice) {
430  return true; // an active interval could appear later
431  }
432  const MSEdge* lastEdge = tObject.getRerouteDestination();
433 #ifdef DEBUG_REROUTER
434  if (DEBUGCOND) {
435  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";
436  }
437 #endif
438 
439  if (rerouteDef->parkProbs.getOverallProb() > 0) {
440 #ifdef HAVE_FOX
441  ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
442 #endif
443  if (!tObject.isVehicle()) {
444  return false;
445  }
446  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
447  bool newDestination = false;
448  ConstMSEdgeVector newRoute;
449  MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination, newRoute);
450  if (newParkingArea != nullptr) {
451  // adapt plans of any riders
452  for (MSTransportable* p : veh.getPersons()) {
453  p->rerouteParkingArea(veh.getNextParkingArea(), newParkingArea);
454  }
455 
456  if (newDestination) {
457  // update arrival parameters
458  SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
459  *newParameter = veh.getParameter();
461  newParameter->arrivalPos = newParkingArea->getEndLanePosition();
462  veh.replaceParameter(newParameter);
463  }
464 
465  SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
466  ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
467  : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
468  const double routeCost = router.recomputeCosts(newRoute, &veh, MSNet::getInstance()->getCurrentTimeStep());
469  ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
470  const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
471  const double savings = previousCost - routeCost;
472  hasReroutingDevice
474  : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
475  //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
476  // << " prevEdges=" << toString(prevEdges)
477  // << " newEdges=" << toString(edges)
478  // << "\n";
479 
480  std::string errorMsg;
481  if (veh.replaceParkingArea(newParkingArea, errorMsg)) {
482  veh.replaceRouteEdges(newRoute, routeCost, savings, getID() + ":" + toString(SUMO_TAG_PARKING_AREA_REROUTE), false, false, false);
483  } else {
484  WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
485  + "' could not reroute to new parkingArea '" + newParkingArea->getID()
486  + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
487  }
488  }
489  return false;
490  }
491 
492  // get rerouting params
493  ConstMSRoutePtr newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : nullptr;
494  // we will use the route if given rather than calling our own dijsktra...
495  if (newRoute != nullptr) {
496 #ifdef DEBUG_REROUTER
497  if (DEBUGCOND) {
498  std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
499  }
500 #endif
501  tObject.replaceRoute(newRoute, getID());
502  return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
503  }
504  const MSEdge* newEdge = lastEdge;
505  // ok, try using a new destination
506  double newArrivalPos = -1;
507  const bool destUnreachable = std::find(rerouteDef->closed.begin(), rerouteDef->closed.end(), lastEdge) != rerouteDef->closed.end();
508  bool keepDestination = false;
509  // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
510  // if we have a closingLaneReroute, no new destinations should be assigned
511  if (rerouteDef->closed.empty() || destUnreachable || rerouteDef->isVia) {
512  newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : lastEdge;
513  assert(newEdge != nullptr);
514  if (newEdge == &mySpecialDest_terminateRoute) {
515  keepDestination = true;
516  newEdge = tObject.getEdge();
517  newArrivalPos = tObject.getPositionOnLane(); // instant arrival
518  } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
519  if (destUnreachable && rerouteDef->permissions == SVCAll) {
520  // if permissions aren't set vehicles will simply drive through
521  // the closing unless terminated. If the permissions are specified, assume that the user wants
522  // vehicles to stand and wait until the closing ends
523  WRITE_WARNINGF(TL("Cannot keep destination edge '%' for vehicle '%' due to closed edges. Terminating route."), lastEdge->getID(), tObject.getID());
524  newEdge = tObject.getEdge();
525  } else {
526  newEdge = lastEdge;
527  }
528  }
529  }
530  ConstMSEdgeVector edges;
531  std::vector<MSTransportableRouter::TripItem> items;
532  // we have a new destination, let's replace the route (if it is affected)
533  if (rerouteDef->closed.empty() || destUnreachable || rerouteDef->isVia || affected(tObject.getUpcomingEdgeIDs(), rerouteDef->closed)) {
534  if (tObject.isVehicle()) {
535  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
536  MSVehicleRouter& router = hasReroutingDevice
537  ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
538  : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
539  router.compute(veh.getEdge(), newEdge, &veh, now, edges);
540  if (edges.size() == 0 && !keepDestination && rerouteDef->edgeProbs.getOverallProb() > 0) {
541  // destination unreachable due to closed intermediate edges. pick among alternative targets
542  RandomDistributor<MSEdge*> edgeProbs2 = rerouteDef->edgeProbs;
543  edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
544  while (edges.size() == 0 && edgeProbs2.getVals().size() > 0) {
545  newEdge = edgeProbs2.get();
546  edgeProbs2.remove(const_cast<MSEdge*>(newEdge));
547  if (newEdge == &mySpecialDest_terminateRoute) {
548  newEdge = veh.getEdge();
549  newArrivalPos = veh.getPositionOnLane(); // instant arrival
550  }
551  if (newEdge == &mySpecialDest_keepDestination && rerouteDef->permissions != SVCAll) {
552  newEdge = lastEdge;
553  break;
554  }
555  router.compute(veh.getEdge(), newEdge, &veh, now, edges);
556  }
557 
558  }
559  if (!rerouteDef->isVia) {
560  const double routeCost = router.recomputeCosts(edges, &veh, now);
561  hasReroutingDevice
563  : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
564  const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
565 #ifdef DEBUG_REROUTER
566  if (DEBUGCOND) std::cout << " rerouting: newDest=" << newEdge->getID()
567  << " newEdges=" << toString(edges)
568  << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
569  << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->closed) << "\n";
570 #endif
571  if (useNewRoute && newArrivalPos != -1) {
572  // must be called here because replaceRouteEdges may also set the arrivalPos
573  veh.setArrivalPos(newArrivalPos);
574  }
575 
576  }
577  } else {
578  // person rerouting here
579  MSTransportableRouter& router = hasReroutingDevice
581  : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, rerouteDef->closed);
582  const bool success = router.compute(tObject.getEdge(), newEdge, tObject.getPositionOnLane(), "",
583  rerouteDef->isVia ? newEdge->getLength() / 2. : tObject.getParameter().arrivalPos, "",
584  tObject.getMaxSpeed(), nullptr, 0, now, items);
585  if (!rerouteDef->isVia) {
586  if (success) {
587  for (const MSTransportableRouter::TripItem& it : items) {
588  if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
589  edges.pop_back();
590  }
591  edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
592  if (!edges.empty()) {
593  static_cast<MSPerson&>(tObject).reroute(edges, tObject.getPositionOnLane(), 0, 1);
594  }
595  }
596  } else {
597  // maybe the pedestrian model still finds a way (JuPedSim)
598  static_cast<MSPerson&>(tObject).reroute({tObject.getEdge(), newEdge}, tObject.getPositionOnLane(), 0, 1);
599  }
600  }
601  }
602  }
603  // it was only a via so calculate the remaining part
604  if (rerouteDef->isVia) {
605  if (tObject.isVehicle()) {
606  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
607  if (!edges.empty()) {
608  edges.pop_back();
609  }
610  MSVehicleRouter& router = hasReroutingDevice
611  ? MSRoutingEngine::getRouterTT(veh.getRNGIndex(), veh.getVClass(), rerouteDef->closed)
612  : MSNet::getInstance()->getRouterTT(veh.getRNGIndex(), rerouteDef->closed);
613  router.compute(newEdge, lastEdge, &veh, now, edges);
614  const double routeCost = router.recomputeCosts(edges, &veh, now);
615  hasReroutingDevice
617  : MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
618  const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
619 #ifdef DEBUG_REROUTER
620  if (DEBUGCOND) std::cout << " rerouting: newDest=" << newEdge->getID()
621  << " newEdges=" << toString(edges)
622  << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
623  << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->closed) << "\n";
624 #endif
625  if (useNewRoute && newArrivalPos != -1) {
626  // must be called here because replaceRouteEdges may also set the arrivalPos
627  veh.setArrivalPos(newArrivalPos);
628  }
629  } else {
630  // person rerouting here
631  bool success = !items.empty();
632  if (success) {
633  MSTransportableRouter& router = hasReroutingDevice
635  : MSNet::getInstance()->getIntermodalRouter(tObject.getRNGIndex(), 0, rerouteDef->closed);
636  success = router.compute(newEdge, lastEdge, newEdge->getLength() / 2., "",
637  tObject.getParameter().arrivalPos, "",
638  tObject.getMaxSpeed(), nullptr, 0, now, items);
639  }
640  if (success) {
641  for (const MSTransportableRouter::TripItem& it : items) {
642  if (!it.edges.empty() && !edges.empty() && edges.back() == it.edges.front()) {
643  edges.pop_back();
644  }
645  edges.insert(edges.end(), std::make_move_iterator(it.edges.begin()), std::make_move_iterator(it.edges.end()));
646  }
647  if (!edges.empty()) {
648  static_cast<MSPerson&>(tObject).reroute(edges, tObject.getPositionOnLane(), 0, 1);
649  }
650  } else {
651  // maybe the pedestrian model still finds a way (JuPedSim)
652  static_cast<MSPerson&>(tObject).reroute({tObject.getEdge(), newEdge, lastEdge}, tObject.getPositionOnLane(), 0, 1);
653  }
654  }
655  }
656  return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
657 }
658 
659 
660 void
662  myAmInUserMode = val;
663 }
664 
665 
666 void
668  myUserProbability = prob;
669 }
670 
671 
672 bool
674  return myAmInUserMode;
675 }
676 
677 
678 double
681 }
682 
683 
684 double
686  return myUserProbability;
687 }
688 
689 
690 double
691 MSTriggeredRerouter::getWeight(SUMOVehicle& veh, const std::string param, const double defaultWeight) {
692  // get custom vehicle parameter
693  if (veh.getParameter().hasParameter(param)) {
694  try {
695  return StringUtils::toDouble(veh.getParameter().getParameter(param, "-1"));
696  } catch (...) {
697  WRITE_WARNINGF(TL("Invalid value '%' for vehicle parameter '%'"), veh.getParameter().getParameter(param, "-1"), param);
698  }
699  } else {
700  // get custom vType parameter
701  if (veh.getVehicleType().getParameter().hasParameter(param)) {
702  try {
703  return StringUtils::toDouble(veh.getVehicleType().getParameter().getParameter(param, "-1"));
704  } catch (...) {
705  WRITE_WARNINGF(TL("Invalid value '%' for vType parameter '%'"), veh.getVehicleType().getParameter().getParameter(param, "-1"), param);
706  }
707  }
708  }
709  //WRITE_MESSAGE("Vehicle '" +veh.getID() + "' does not supply vehicle parameter '" + param + "'. Using default of " + toString(defaultWeight) + "\n";
710  return defaultWeight;
711 }
712 
713 
716  SUMOVehicle& veh, bool& newDestination, ConstMSEdgeVector& newRoute) {
717  // Reroute destination from initial parking area to an alternative parking area
718  // if the following conditions are met:
719  // - next stop target is a parking area
720  // - target is included in the current alternative set
721  // - target is visibly full
722  // Any parking areas that are visibly full at the current location are
723  // committed to parking memory
724 
725  MSParkingArea* nearParkArea = nullptr;
726  std::vector<ParkingAreaVisible> parks = rerouteDef->parkProbs.getVals();
727 
728  // get vehicle params
729  MSParkingArea* destParkArea = veh.getNextParkingArea();
730  const MSRoute& route = veh.getRoute();
731 
732  if (destParkArea == nullptr) {
733  // not driving towards a parkingArea
734  return nullptr;
735  }
736  // if the vehicle is on the destParkArea edge it is always visible
737  bool destVisible = (&destParkArea->getLane().getEdge() == veh.getEdge());
738 
739  for (auto paVis : parks) {
740  if (paVis.first == destParkArea && paVis.second) {
741  destVisible = true;
742  break;
743  }
744  }
745 
746  MSParkingArea* onTheWay = nullptr;
747  const int parkAnywhere = (int)getWeight(veh, "parking.anywhere", -1);
748 
749  // check whether we are ready to accept any free parkingArea along the
750  // way to our destination
751  if (parkAnywhere < 0 || parkAnywhere > veh.getNumberParkingReroutes()) {
752  if (!destVisible) {
753  // cannot determine destination occupancy, only register visibly full
754  for (const ParkingAreaVisible& pav : parks) {
755  if (pav.second && pav.first->getLastStepOccupancy() == pav.first->getCapacity()) {
756  veh.rememberBlockedParkingArea(pav.first, &pav.first->getLane().getEdge() == veh.getEdge());
757  }
758  }
759 #ifdef DEBUG_PARKING
760  if (DEBUGCOND) {
761  //std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID()
762  // << " dest=" << destParkArea->getID() << " parkAnywhere=" << parkAnywhere << " parkingReroutes=" << veh.getNumberParkingReroutes() << " stay on original route\n";
763  }
764 #endif
765  }
766 
767  } else {
768  double bestDist = std::numeric_limits<double>::max();
769  const double brakeGap = veh.getBrakeGap(true);
770  for (ParkingAreaVisible& item : parks) {
771  if (item.second) {
772  MSParkingArea* pa = item.first;
773  if (&pa->getLane().getEdge() == veh.getEdge()
774  && pa->getLastStepOccupancy() < pa->getCapacity()) {
775  const double distToStart = pa->getBeginLanePosition() - veh.getPositionOnLane();
776  const double distToEnd = pa->getEndLanePosition() - veh.getPositionOnLane();
777  if (distToEnd > brakeGap) {
778  veh.rememberParkingAreaScore(pa, "dist=" + toString(distToStart));
779  if (distToStart < bestDist) {
780  bestDist = distToStart;
781  onTheWay = pa;
782  }
783  } else {
784  veh.rememberParkingAreaScore(pa, "tooClose");
785  }
786  }
787  }
788  }
789 #ifdef DEBUG_PARKING
790  if (DEBUGCOND) {
791  std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID()
792  << " dest=" << destParkArea->getID() << " parkAnywhere=" << parkAnywhere << " parkingReroutes=" << veh.getNumberParkingReroutes() << " alongTheWay=" << Named::getIDSecure(onTheWay) << "\n";
793  }
794 #endif
795  }
796  if (!destVisible && onTheWay == nullptr) {
797  return nullptr;
798  }
799 
800  if (destParkArea->getLastStepOccupancy() == destParkArea->getCapacity() || onTheWay != nullptr) {
801 
802  // if the current route ends at the parking area, the new route will
803  // also and at the new area
804  newDestination = (&destParkArea->getLane().getEdge() == route.getLastEdge()
805  && veh.getArrivalPos() >= destParkArea->getBeginLanePosition()
806  && veh.getArrivalPos() <= destParkArea->getEndLanePosition());
807 
808 #ifdef DEBUG_PARKING
809  if (DEBUGCOND) {
810  std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID()
811  << " rerouteParkingArea dest=" << destParkArea->getID()
812  << " onDestEdge=" << (&(destParkArea->getLane().getEdge()) == veh.getEdge())
813  << " newDest=" << newDestination
814  << " onTheWay=" << Named::getIDSecure(onTheWay)
815  << "\n";
816  }
817 #endif
818 
819  ParkingParamMap_t weights;
820  std::map<MSParkingArea*, ConstMSEdgeVector> newRoutes;
821  std::map<MSParkingArea*, ConstMSEdgeVector> parkApproaches;
822 
823  // The probability of choosing this area inside the zone
824  weights["probability"] = getWeight(veh, "parking.probability.weight", 0.0);
825 
826  // The capacity of this area
827  weights["capacity"] = getWeight(veh, "parking.capacity.weight", 0.0);
828 
829  // The absolute number of free spaces
830  weights["absfreespace"] = getWeight(veh, "parking.absfreespace.weight", 0.0);
831 
832  // The relative number of free spaces
833  weights["relfreespace"] = getWeight(veh, "parking.relfreespace.weight", 0.0);
834 
835  // The distance to the new parking area
836  weights["distanceto"] = getWeight(veh, "parking.distanceto.weight", getWeight(veh, "parking.distance.weight", 1.0));
837 
838  // The time to reach this area
839  weights["timeto"] = getWeight(veh, "parking.timeto.weight", 0.0);
840 
841  // The distance from the new parking area
842  weights["distancefrom"] = getWeight(veh, "parking.distancefrom.weight", 0.0);
843 
844  // The time to reach the end from this area
845  weights["timefrom"] = getWeight(veh, "parking.timefrom.weight", 0.0);
846 
847  // a map stores maximum values to normalize parking values
848  ParkingParamMap_t maxValues;
849 
850  maxValues["probability"] = 0.0;
851  maxValues["capacity"] = 0.0;
852  maxValues["absfreespace"] = 0.0;
853  maxValues["relfreespace"] = 0.0;
854  maxValues["distanceto"] = 0.0;
855  maxValues["timeto"] = 0.0;
856  maxValues["distancefrom"] = 0.0;
857  maxValues["timefrom"] = 0.0;
858 
859  // a map stores elegible parking areas
860  MSParkingAreaMap_t parkAreas;
861 
863 
864  const std::vector<double>& probs = rerouteDef->parkProbs.getProbs();
865 
866  const double brakeGap = veh.getBrakeGap(true);
867 
868  if (onTheWay != nullptr) {
869  // compute new route
870  if (newDestination) {
871  newRoute.push_back(veh.getEdge());
872  } else {
873  bool valid = addParkValues(veh, brakeGap, newDestination, onTheWay, onTheWay->getLastStepOccupancy(), 1, router, parkAreas, newRoutes, parkApproaches, maxValues);
874  if (!valid) {
875  WRITE_WARNINGF(TL("Parkingarea '%' along the way cannot be used by vehicle '%' for unknown reason"), onTheWay->getID(), veh.getID());
876  return nullptr;
877  }
878  newRoute = newRoutes[onTheWay];
879  }
880  return onTheWay;
881  }
882 
883  int numAlternatives = 0;
884  std::vector<std::tuple<SUMOTime, MSParkingArea*, int> > blockedTimes;
886  veh.rememberParkingAreaScore(destParkArea, "occupied");
887  veh.rememberBlockedParkingArea(destParkArea, &destParkArea->getLane().getEdge() == veh.getEdge());
888 
889  const SUMOTime parkingMemory = TIME2STEPS(getWeight(veh, "parking.memory", 600));
890  const double parkingFrustration = getWeight(veh, "parking.frustration", 100);
891  const double parkingKnowledge = getWeight(veh, "parking.knowledge", 0);
892 
893  for (int i = 0; i < (int)parks.size(); ++i) {
894  MSParkingArea* pa = parks[i].first;
895  // alternative occupancy is randomized (but never full) if invisible
896  // current destination must be visible at this point
897  const bool visible = parks[i].second || (pa == destParkArea && destVisible);
898  double paOccupancy = pa->getOccupancy();
899  if (!visible && (parkingKnowledge == 0 || parkingKnowledge < RandHelper::rand(veh.getRNG()))) {
900  const double minOccupancy = MIN2((double)pa->getCapacity() - NUMERICAL_EPS, (veh.getNumberParkingReroutes() * pa->getCapacity() / parkingFrustration));
901  paOccupancy = RandHelper::rand(minOccupancy, (double)pa->getCapacity());
902  // previously visited?
903  SUMOTime blockedTime = veh.sawBlockedParkingArea(pa, false);
904  if (blockedTime >= 0 && SIMSTEP - blockedTime < parkingMemory) {
905  // assume it's still occupied
906  paOccupancy = pa->getCapacity();
907  blockedTimes.push_back(std::make_tuple(blockedTime, pa, i));
908 #ifdef DEBUG_PARKING
909  if (DEBUGCOND) {
910  std::cout << " altPA=" << pa->getID() << " was blocked at " << time2string(blockedTime) << "\n";
911  }
912 #endif
913  }
914  }
915  if (paOccupancy < pa->getCapacity()) {
916  if (addParkValues(veh, brakeGap, newDestination, pa, paOccupancy, probs[i], router, parkAreas, newRoutes, parkApproaches, maxValues)) {
917  numAlternatives++;
918  }
919  } else if (visible) {
920  // might only be visible now (i.e. because it's on the other
921  // side of the street), so we should remember this for later.
922  veh.rememberBlockedParkingArea(pa, &pa->getLane().getEdge() == veh.getEdge());
923  }
924  }
925  if (numAlternatives == 0) {
926  // use parkingArea with lowest blockedTime
927  std::sort(blockedTimes.begin(), blockedTimes.end(),
928  [](std::tuple<SUMOTime, MSParkingArea*, int> const & t1, std::tuple<SUMOTime, MSParkingArea*, int> const & t2) {
929  if (std::get<0>(t1) < std::get<0>(t2)) {
930  return true;
931  }
932  if (std::get<0>(t1) == std::get<0>(t2)) {
933  if (std::get<1>(t1)->getID() < std::get<1>(t2)->getID()) {
934  return true;
935  }
936  if (std::get<1>(t1)->getID() == std::get<1>(t2)->getID()) {
937  return std::get<2>(t1) < std::get<2>(t2);
938  }
939  }
940  return false;
941  }
942  );
943  for (auto item : blockedTimes) {
944  MSParkingArea* pa = std::get<1>(item);
945  double prob = probs[std::get<2>(item)];
946  // all parking areas are occupied. We have no good basis for
947  // prefering one or the other based on estimated occupancy
948  double paOccupancy = RandHelper::rand((double)pa->getCapacity());
949  if (addParkValues(veh, brakeGap, newDestination, pa, paOccupancy, prob, router, parkAreas, newRoutes, parkApproaches, maxValues)) {
950 #ifdef DEBUG_PARKING
951  if (DEBUGCOND) {
952  std::cout << " altPA=" << pa->getID() << " targeting occupied pa based on blockTime " << STEPS2TIME(std::get<0>(item)) << " among " << blockedTimes.size() << " alternatives\n";
953  }
954 #endif
955  numAlternatives = 1;
956  break;
957  }
958  //std::cout << " candidate=" << item.second->getID() << " observed=" << time2string(item.first) << "\n";
959  }
960  if (numAlternatives == 0) {
961  // take any random target but prefer that that haven't been visited yet
962  std::vector<std::pair<SUMOTime, MSParkingArea*> > candidates;
963  for (const ParkingAreaVisible& pav : parks) {
964  if (pav.first == destParkArea) {
965  continue;
966  }
967  SUMOTime dummy = veh.sawBlockedParkingArea(pav.first, true);
968  if (dummy < 0) {
969  // randomize among the unvisited
970  dummy = -RandHelper::rand(1000000);
971  }
972  candidates.push_back(std::make_pair(dummy, pav.first));
973  }
974  std::sort(candidates.begin(), candidates.end(),
975  [](std::tuple<SUMOTime, MSParkingArea*> const & t1, std::tuple<SUMOTime, MSParkingArea*> const & t2) {
976  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());
977  }
978  );
979  for (auto item : candidates) {
980  MSParkingArea* pa = item.second;
981  if (addParkValues(veh, brakeGap, newDestination, pa, 0, 1, router, parkAreas, newRoutes, parkApproaches, maxValues)) {
982 #ifdef DEBUG_PARKING
983  if (DEBUGCOND) {
984  std::cout << " altPA=" << pa->getID() << " targeting occupied pa (based on pure randomness) among " << candidates.size() << " alternatives\n";
985  }
986 #endif
987  numAlternatives = 1;
988  break;
989  }
990  }
991  }
992  }
993 
994  MSNet::getInstance()->getRouterTT(veh.getRNGIndex()); // reset closed edges
995 
996 #ifdef DEBUG_PARKING
997  if (DEBUGCOND) {
998  std::cout << " maxValues=" << joinToString(maxValues, " ", ":") << "\n";
999  }
1000 #endif
1001 
1002  // minimum cost to get the parking area
1003  double minParkingCost = 0.0;
1004 
1005  for (MSParkingAreaMap_t::iterator it = parkAreas.begin(); it != parkAreas.end(); ++it) {
1006  // get the parking values
1007  ParkingParamMap_t parkValues = it->second;
1008 
1009  if (weights["probability"] > 0 && maxValues["probability"] > 0.0) {
1010  // random search should not drive past a usable parking area
1011  bool dominated = false;
1012  double endPos = it->first->getEndLanePosition();
1013  const ConstMSEdgeVector& to1 = parkApproaches[it->first];
1014  assert(to1.size() > 0);
1015  for (auto altPa : parkAreas) {
1016  if (altPa.first == it->first) {
1017  continue;
1018  }
1019  const ConstMSEdgeVector& to2 = parkApproaches[altPa.first];
1020  assert(to2.size() > 0);
1021  if (to1.size() > to2.size()) {
1022  if (std::equal(to2.begin(), to2.end(), to1.begin())) {
1023  // other target lies on the route to the current candidate
1024  dominated = true;
1025  //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " onTheWay=" << altPa.first->getID() << "\n";
1026  break;
1027  }
1028  } else if (to1 == to2 && endPos > altPa.first->getEndLanePosition()) {
1029  // other target is on the same edge but ahead of the current candidate
1030  dominated = true;
1031  //std::cout << SIMTIME << " rrP veh=" << veh.getID() << " full=" << destParkArea->getID() << " cand=" << it->first->getID() << " sameEdge=" << altPa.first->getID() << "\n";
1032  break;
1033  }
1034  }
1035  double prob = 0;
1036  if (!dominated) {
1037  prob = RandHelper::rand(parkValues["probability"], veh.getRNG());
1038  parkValues["probability"] = 1.0 - prob / maxValues["probability"];
1039  } else {
1040  // worst probability score
1041  parkValues["probability"] = 1.0;
1042  }
1043  } else {
1044  // value takes no effect due to weight=0
1045  parkValues["probability"] = 0;
1046  }
1047  // normalizing with maximum values (we want to maximize some parameters then we reverse the value)
1048  parkValues["capacity"] = maxValues["capacity"] > 0.0 ? 1.0 - parkValues["capacity"] / maxValues["capacity"] : 0.0;
1049  parkValues["absfreespace"] = maxValues["absfreespace"] > 0.0 ? 1.0 - parkValues["absfreespace"] / maxValues["absfreespace"] : 0.0;
1050  parkValues["relfreespace"] = maxValues["relfreespace"] > 0.0 ? 1.0 - parkValues["relfreespace"] / maxValues["relfreespace"] : 0.0;
1051 
1052  parkValues["distanceto"] = maxValues["distanceto"] > 0.0 ? parkValues["distanceto"] / maxValues["distanceto"] : 0.0;
1053  parkValues["timeto"] = maxValues["timeto"] > 0.0 ? parkValues["timeto"] / maxValues["timeto"] : 0.0;
1054 
1055  parkValues["distancefrom"] = maxValues["distancefrom"] > 0.0 ? parkValues["distancefrom"] / maxValues["distancefrom"] : 0.0;
1056  parkValues["timefrom"] = maxValues["timefrom"] > 0.0 ? parkValues["timefrom"] / maxValues["timefrom"] : 0.0;
1057 
1058  // get the parking area cost
1059  double parkingCost = 0.0;
1060 
1061  // sum every index with its weight
1062  for (ParkingParamMap_t::iterator pc = parkValues.begin(); pc != parkValues.end(); ++pc) {
1063  parkingCost += weights[pc->first] * pc->second;
1064  }
1065  veh.rememberParkingAreaScore(it->first, toString(parkingCost)
1066  //+ " rfs=" + toString(parkValues["relfreespace"])
1067  //+ " dt=" + toString(parkValues["distanceto"])
1068  //+ " p=" + toString(parkValues["probability"])
1069  );
1070 
1071  // get the parking area with minimum cost
1072  if (nearParkArea == nullptr || parkingCost < minParkingCost) {
1073  minParkingCost = parkingCost;
1074  nearParkArea = it->first;
1075  newRoute = newRoutes[nearParkArea];
1076  }
1077 
1078 #ifdef DEBUG_PARKING
1079  if (DEBUGCOND) {
1080  std::cout << " altPA=" << it->first->getID() << " score=" << parkingCost << " vals=" << joinToString(parkValues, " ", ":") << "\n";
1081  }
1082 #endif
1083  }
1085  } else {
1086 #ifdef DEBUG_PARKING
1087  if (DEBUGCOND) {
1088  std::cout << SIMTIME << " rerouter=" << getID() << " veh=" << veh.getID() << " rerouteParkingArea dest=" << destParkArea->getID() << " sufficient space\n";
1089  }
1090 #endif
1091  }
1092 
1093 #ifdef DEBUG_PARKING
1094  if (DEBUGCOND) {
1095  std::cout << " parkingResult=" << Named::getIDSecure(nearParkArea) << "\n";
1096  }
1097 #endif
1098 
1099  return nearParkArea;
1100 }
1101 
1102 
1103 bool
1104 MSTriggeredRerouter::addParkValues(SUMOVehicle& veh, double brakeGap, bool newDestination,
1105  MSParkingArea* pa, double paOccupancy, double prob,
1107  MSParkingAreaMap_t& parkAreas,
1108  std::map<MSParkingArea*, ConstMSEdgeVector>& newRoutes,
1109  std::map<MSParkingArea*, ConstMSEdgeVector>& parkApproaches,
1110  ParkingParamMap_t& maxValues) {
1111  // a map stores the parking values
1112  ParkingParamMap_t parkValues;
1113 
1114  const MSRoute& route = veh.getRoute();
1115  const RGBColor& c = route.getColor();
1116  const MSEdge* parkEdge = &(pa->getLane().getEdge());
1117 
1118  const bool includeInternalLengths = MSGlobals::gUsingInternalLanes && MSNet::getInstance()->hasInternalLinks();
1119 
1120  // Compute the route from the current edge to the parking area edge
1121  ConstMSEdgeVector edgesToPark;
1122  const double parkPos = pa->getLastFreePos(veh);
1123  const MSEdge* rerouteOrigin = *veh.getRerouteOrigin();
1124  router.compute(rerouteOrigin, veh.getPositionOnLane(), parkEdge, parkPos, &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesToPark, true);
1125 
1126 #ifdef DEBUG_PARKING
1127  if (DEBUGCOND) {
1128  std::cout << " altPA=" << pa->getID() << " vehEdge=" << veh.getEdge()->getID() << " parkEdge " << parkEdge->getID() << " edgesToPark=" << edgesToPark.size() << "\n";
1129  }
1130 #endif
1131 
1132  if (edgesToPark.size() > 0) {
1133  // Compute the route from the parking area edge to the end of the route
1134  if (rerouteOrigin != veh.getEdge()) {
1135  edgesToPark.insert(edgesToPark.begin(), veh.getEdge());
1136  }
1137  ConstMSEdgeVector edgesFromPark;
1138  parkApproaches[pa] = edgesToPark;
1139 
1140  const MSEdge* nextDestination = route.getLastEdge();
1141  double nextPos = veh.getArrivalPos();
1142  int nextDestinationIndex = route.size() - 1;
1143  if (!newDestination) {
1144  std::vector<std::pair<int, double> > stopIndices = veh.getStopIndices();
1145  if (stopIndices.size() > 1) {
1146  nextDestinationIndex = stopIndices[1].first;
1147  nextDestination = route.getEdges()[nextDestinationIndex];
1148  nextPos = stopIndices[1].second;
1149 
1150  }
1151  router.compute(parkEdge, parkPos, nextDestination, nextPos, &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesFromPark, true);
1152  }
1153 #ifdef DEBUG_PARKING
1154  if (DEBUGCOND) {
1155  //std::cout << " altPA=" << pa->getID() << " parkEdge=" << parkEdge->getID() << " nextDest=" << nextDestination->getID() << " edgesFromPark=" << edgesFromPark.size() << "\n";
1156  }
1157 #endif
1158 
1159  if (edgesFromPark.size() > 0 || newDestination) {
1160 
1161  parkValues["probability"] = prob;
1162 
1163  if (parkValues["probability"] > maxValues["probability"]) {
1164  maxValues["probability"] = parkValues["probability"];
1165  }
1166 
1167  parkValues["capacity"] = (double)(pa->getCapacity());
1168  parkValues["absfreespace"] = (double)(pa->getCapacity() - paOccupancy);
1169  // if capacity = 0 then absfreespace and relfreespace are also 0
1170  parkValues["relfreespace"] = parkValues["absfreespace"] / MAX2(1.0, parkValues["capacity"]);
1171 
1172  if (parkValues["capacity"] > maxValues["capacity"]) {
1173  maxValues["capacity"] = parkValues["capacity"];
1174  }
1175 
1176  if (parkValues["absfreespace"] > maxValues["absfreespace"]) {
1177  maxValues["absfreespace"] = parkValues["absfreespace"];
1178  }
1179 
1180  if (parkValues["relfreespace"] > maxValues["relfreespace"]) {
1181  maxValues["relfreespace"] = parkValues["relfreespace"];
1182  }
1183 
1184  MSRoute routeToPark(route.getID() + "!topark#1", edgesToPark, false,
1185  &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
1186 
1187  // The distance from the current edge to the new parking area
1188  double toPos = pa->getBeginLanePosition();
1189  if (&pa->getLane().getEdge() == veh.getEdge()) {
1190  toPos = MAX2(veh.getPositionOnLane(), toPos);
1191  }
1192  parkValues["distanceto"] = routeToPark.getDistanceBetween(veh.getPositionOnLane(), toPos,
1193  routeToPark.begin(), routeToPark.end() - 1, includeInternalLengths);
1194 
1195  if (parkValues["distanceto"] == std::numeric_limits<double>::max()) {
1196  WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' to parkingArea '%' at time=%."),
1197  veh.getID(), pa->getID(), time2string(SIMSTEP));
1198  }
1199  const double endPos = pa->getOccupancy() == pa->getCapacity()
1200  ? pa->getLastFreePos(veh, veh.getPositionOnLane() + brakeGap)
1201  : pa->getEndLanePosition();
1202  const double distToEnd = parkValues["distanceto"] - toPos + endPos;
1203 #ifdef DEBUG_PARKING
1204  if (DEBUGCOND) {
1205  std::cout << " " << veh.getID() << " candidate=" << pa->getID()
1206  << " distanceTo=" << parkValues["distanceto"]
1207  << " brakeGap=" << brakeGap
1208  << " routeToPark=" << toString(edgesToPark)
1209  << " vehPos=" << veh.getPositionOnLane()
1210  << " begPos=" << pa->getBeginLanePosition()
1211  << " toPos=" << toPos
1212  << " endPos=" << pa->getEndLanePosition()
1213  << " distToEnd=" << distToEnd
1214  << "\n";
1215  }
1216 #endif
1217 
1218  if (distToEnd < brakeGap) {
1219  veh.rememberParkingAreaScore(pa, "tooClose");
1220 #ifdef DEBUG_PARKING
1221  if (DEBUGCOND) {
1222  std::cout << " altPA=" << pa->getID() << " too close to brake (dist=" << distToEnd << " brakeGap=" << brakeGap << "\n";
1223  }
1224 #endif
1225  return false;
1226  }
1227 
1228  // The time to reach the new parking area
1229  parkValues["timeto"] = router.recomputeCosts(edgesToPark, &veh, MSNet::getInstance()->getCurrentTimeStep());
1230 
1231  if (parkValues["distanceto"] > maxValues["distanceto"]) {
1232  maxValues["distanceto"] = parkValues["distanceto"];
1233  }
1234 
1235  if (parkValues["timeto"] > maxValues["timeto"]) {
1236  maxValues["timeto"] = parkValues["timeto"];
1237  }
1238 
1239  ConstMSEdgeVector newEdges = edgesToPark;
1240 
1241  if (newDestination) {
1242  parkValues["distancefrom"] = 0;
1243  parkValues["timefrom"] = 0;
1244  } else {
1245  MSRoute routeFromPark(route.getID() + "!frompark#1", edgesFromPark, false,
1246  &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
1247  // The distance from the new parking area to the end of the route
1248  parkValues["distancefrom"] = routeFromPark.getDistanceBetween(pa->getBeginLanePosition(), routeFromPark.getLastEdge()->getLength(),
1249  routeFromPark.begin(), routeFromPark.end() - 1, includeInternalLengths);
1250  if (parkValues["distancefrom"] == std::numeric_limits<double>::max()) {
1251  WRITE_WARNINGF(TL("Invalid distance computation for vehicle '%' from parkingArea '%' at time=%."),
1252  veh.getID(), pa->getID(), time2string(SIMSTEP));
1253  }
1254  // The time to reach this area
1255  parkValues["timefrom"] = router.recomputeCosts(edgesFromPark, &veh, SIMSTEP);
1256  newEdges.insert(newEdges.end(), edgesFromPark.begin() + 1, edgesFromPark.end());
1257  newEdges.insert(newEdges.end(), route.begin() + nextDestinationIndex + 1, route.end());
1258  }
1259 
1260  if (parkValues["distancefrom"] > maxValues["distancefrom"]) {
1261  maxValues["distancefrom"] = parkValues["distancefrom"];
1262  }
1263 
1264  if (parkValues["timefrom"] > maxValues["timefrom"]) {
1265  maxValues["timefrom"] = parkValues["timefrom"];
1266  }
1267 
1268  parkAreas[pa] = parkValues;
1269  newRoutes[pa] = newEdges;
1270 
1271  return true;
1272  } else {
1273  veh.rememberParkingAreaScore(pa, "destUnreachable");
1274  }
1275  } else {
1276  veh.rememberParkingAreaScore(pa, "unreachable");
1277  }
1278 #ifdef DEBUG_PARKING
1279  if (DEBUGCOND) {
1280  std::cout << " altPA=" << pa->getID() << " disconnected\n";
1281  }
1282 #endif
1283  // unreachable
1284  return false;
1285 }
1286 
1287 
1288 bool
1290  if (myVehicleTypes.empty() || myVehicleTypes.count(obj.getVehicleType().getOriginalID()) > 0) {
1291  return true;
1292  } else {
1293  std::set<std::string> vTypeDists = MSNet::getInstance()->getVehicleControl().getVTypeDistributionMembership(obj.getVehicleType().getOriginalID());
1294  for (auto vTypeDist : vTypeDists) {
1295  if (myVehicleTypes.count(vTypeDist) > 0) {
1296  return true;
1297  }
1298  }
1299  return false;
1300  }
1301 }
1302 
1303 
1304 bool
1305 MSTriggeredRerouter::affected(const std::set<SUMOTrafficObject::NumericalID>& edgeIndices, const MSEdgeVector& closed) {
1306  for (const MSEdge* const e : closed) {
1307  if (edgeIndices.count(e->getNumericalID()) > 0) {
1308  return true;
1309  }
1310  }
1311  return false;
1312 }
1313 
1314 
1315 void
1317  // if a parkingArea is a rerouting target, it should generally have a
1318  // rerouter on its edge or vehicles will be stuck there once it's full.
1319  // The user should receive a Warning in this case
1320  std::set<MSEdge*> parkingRerouterEdges;
1321  std::map<MSParkingArea*, std::string, ComparatorIdLess> targetedParkingArea; // paID -> targetingRerouter
1322  for (const auto& rr : myInstances) {
1323  bool hasParkingReroute = false;
1324  for (const RerouteInterval& interval : rr.second->myIntervals) {
1325  if (interval.parkProbs.getOverallProb() > 0) {
1326  hasParkingReroute = true;
1327  for (const ParkingAreaVisible& pav : interval.parkProbs.getVals()) {
1328  targetedParkingArea[pav.first] = rr.first;
1329  }
1330  }
1331  }
1332  if (hasParkingReroute) {
1333  parkingRerouterEdges.insert(rr.second->myEdges.begin(), rr.second->myEdges.end());
1334  }
1335  }
1336  for (const auto& item : targetedParkingArea) {
1337  if (parkingRerouterEdges.count(&item.first->getLane().getEdge()) == 0) {
1338  WRITE_WARNINGF(TL("ParkingArea '%' is targeted by rerouter '%' but doesn't have its own rerouter. This may cause parking search to abort."),
1339  item.first->getID(), item.second);
1340  }
1341  }
1342 }
1343 
1344 
1345 /****************************************************************************/
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 STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SIMSTEP
Definition: SUMOTime.h:61
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
const SVCPermissions SVCAll
all VClasses are allowed
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
@ SVC_AUTHORITY
authorities vehicles
@ GIVEN
The arrival position is given.
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_CLOSING_REROUTE
reroute of type closing
@ SUMO_TAG_PARKING_AREA_REROUTE
entry for an alternative parking zone
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_ROUTE_PROB_REROUTE
probability of route of a reroute
@ SUMO_TAG_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 MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
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:325
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:317
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:662
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:983
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition: MSGlobals.h:103
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:109
static int gNumSimThreads
how many threads to use for simulation
Definition: MSGlobals.h:143
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:78
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
void resetPermissions(long long transientID)
Definition: MSLane.cpp:4410
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:4398
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2385
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:182
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:1504
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:1364
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:1466
bool hasInternalLinks() const
return whether the network contains internal links
Definition: MSNet.h:774
A lane area vehicles can halt at.
Definition: MSParkingArea.h:60
int getCapacity() const
Returns the area capacity.
double getLastFreePos(const SUMOVehicle &forVehicle, double brakePos=0) const
Returns the last free position on this stop.
int getLastStepOccupancy() const
Returns the area occupancy at the end of the last simulation step.
int getOccupancy() const
Returns the area occupancy.
int size() const
Returns the number of edges to pass.
Definition: MSRoute.cpp:85
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:404
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:79
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:91
bool containsAnyOf(const MSEdgeVector &edgelist) const
Definition: MSRoute.cpp:243
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:109
const RGBColor & getColor() const
Returns the color.
Definition: MSRoute.cpp:395
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:73
double getDistanceBetween(double fromPos, double toPos, const MSLane *fromLane, const MSLane *toLane, int routePosition=0) const
Compute the distance between 2 given edges on this route, optionally including the length of internal...
Definition: MSRoute.cpp:311
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
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
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
SUMOTime setPermissions(const SUMOTime currentTime)
Sets the edge permission if there are any defined in the closingEdge.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Tries to reroute the vehicle.
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Triggers rerouting (once) for vehicles that are already on the edge when the rerouter activates.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Removes the reminder.
double getUserProbability() const
Returns the rerouting probability given by the user.
static MSParkingArea * rerouteParkingArea(const MSTriggeredRerouter::RerouteInterval *rerouteDef, SUMOVehicle &veh, bool &newDestination, ConstMSEdgeVector &newRoute)
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.
static bool addParkValues(SUMOVehicle &veh, double brakeGap, bool newDestination, MSParkingArea *pa, double paOccupancy, double prob, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, MSParkingAreaMap_t &parkAreas, std::map< MSParkingArea *, ConstMSEdgeVector > &newRoutes, std::map< MSParkingArea *, ConstMSEdgeVector > &parkApproaches, ParkingParamMap_t &maxValues)
determine attributes of candiate parking area for scoring
static MSEdge mySpecialDest_terminateRoute
virtual void myEndElement(int element)
Called when a closing tag occurs.
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)
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)
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
static MSEdge mySpecialDest_keepDestination
special destination values
RerouteInterval myParsedRerouteInterval
used during loading
double getProbability() const
Returns the rerouting probability.
std::map< MSParkingArea *, ParkingParamMap_t, ComparatorIdLess > MSParkingAreaMap_t
std::vector< RerouteInterval > myIntervals
List of rerouting definition intervals.
void setUserMode(bool val)
Sets whether the process is currently steered by the user.
static double getWeight(SUMOVehicle &veh, const std::string param, const double defaultWeight)
const std::set< std::string > getVTypeDistributionMembership(const std::string &id) const
Return the distribution IDs the vehicle type is a member of.
const std::string & getOriginalID() const
Returns the id of the original vehicle type if this is a vehicle specific type, the id otherwise.
const SUMOVTypeParameter & getParameter() const
Base class for objects which have an id.
Definition: Named.h:54
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
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.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:60
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const =0
Returns the starting point for reroutes (usually the current edge)
virtual bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)=0
Replaces the current route by the given edges.
virtual 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 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 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.
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.
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.