SUMO - Simulation of Urban MObility
MSTriggeredRerouter.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
18 // Reroutes vehicles passing an edge
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <string>
28 #include <algorithm>
31 #include <utils/common/Command.h>
34 #include <utils/common/ToString.h>
41 #include <microsim/MSLane.h>
42 #include <microsim/MSVehicle.h>
43 #include <microsim/MSRoute.h>
44 #include <microsim/MSEdge.h>
46 #include <microsim/MSNet.h>
48 #include <microsim/MSGlobals.h>
49 #include <microsim/MSParkingArea.h>
53 #include "MSTriggeredRerouter.h"
54 
55 #include <mesosim/MELoop.h>
56 #include <mesosim/MESegment.h>
57 
58 //#define DEBUG_REROUTER
59 #define DEBUG_PARKING
60 #define DEBUGCOND (veh.isSelected())
61 
62 // ===========================================================================
63 // static member defintion
64 // ===========================================================================
65 MSEdge MSTriggeredRerouter::mySpecialDest_keepDestination("MSTriggeredRerouter_keepDestination", -1, EDGEFUNC_UNKNOWN, "", "", -1);
66 MSEdge MSTriggeredRerouter::mySpecialDest_terminateRoute("MSTriggeredRerouter_terminateRoute", -1, EDGEFUNC_UNKNOWN, "", "", -1);
67 
68 // ===========================================================================
69 // method definitions
70 // ===========================================================================
72  const MSEdgeVector& edges,
73  double prob, const std::string& file, bool off,
74  SUMOTime timeThreshold,
75  const std::string& vTypes) :
76  MSTrigger(id),
77  MSMoveReminder(id),
78  SUMOSAXHandler(file),
79  myProbability(prob),
80  myUserProbability(prob),
81  myAmInUserMode(false),
82  myTimeThreshold(timeThreshold) {
83  // build actors
84  for (MSEdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
87  s->addDetector(this);
88  continue;
89  }
90  const std::vector<MSLane*>& destLanes = (*j)->getLanes();
91  for (std::vector<MSLane*>::const_iterator i = destLanes.begin(); i != destLanes.end(); ++i) {
92  (*i)->addMoveReminder(this);
93  }
94  }
95  if (off) {
96  setUserMode(true);
98  }
99  const std::vector<std::string> vt = StringTokenizer(vTypes).getVector();
100  myVehicleTypes.insert(vt.begin(), vt.end());
101 }
102 
103 
105 }
106 
107 // ------------ loading begin
108 void
110  const SUMOSAXAttributes& attrs) {
111  if (element == SUMO_TAG_INTERVAL) {
112  bool ok = true;
115  }
116  if (element == SUMO_TAG_DEST_PROB_REROUTE) {
117  // by giving probabilities of new destinations
118  // get the destination edge
119  std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
120  if (dest == "") {
121  throw ProcessError("MSTriggeredRerouter " + getID() + ": No destination edge id given.");
122  }
123  MSEdge* to = MSEdge::dictionary(dest);
124  if (to == nullptr) {
125  if (dest == "keepDestination") {
127  } else if (dest == "terminateRoute") {
129  } else {
130  throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
131  }
132  }
133  // get the probability to reroute
134  bool ok = true;
135  double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
136  if (!ok) {
137  throw ProcessError();
138  }
139  if (prob < 0) {
140  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
141  }
142  // add
143  myCurrentEdgeProb.add(to, prob);
144  }
145 
146 
147  if (element == SUMO_TAG_CLOSING_REROUTE) {
148  // by closing
149  std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
150  MSEdge* closed = MSEdge::dictionary(closed_id);
151  if (closed == nullptr) {
152  throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
153  }
154  myCurrentClosed.push_back(closed);
155  bool ok;
156  const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
157  const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
158  myCurrentPermissions = parseVehicleClasses(allow, disallow);
159  }
160 
161  if (element == SUMO_TAG_CLOSING_LANE_REROUTE) {
162  // by closing lane
163  std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
164  MSLane* closed = MSLane::dictionary(closed_id);
165  if (closed == nullptr) {
166  throw ProcessError("MSTriggeredRerouter " + getID() + ": Lane '" + closed_id + "' to close is not known.");
167  }
168  myCurrentClosedLanes.push_back(closed);
169  bool ok;
171  const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
172  const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
173  myCurrentPermissions = parseVehicleClasses(allow, disallow);
174  } else {
175  // lane closing only makes sense if the lane really receives reduced
176  // permissions
178  }
179  }
180 
181  if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
182  // by explicit rerouting using routes
183  // check if route exists
184  std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
185  if (routeStr == "") {
186  throw ProcessError("MSTriggeredRerouter " + getID() + ": No route id given.");
187  }
188  const MSRoute* route = MSRoute::dictionary(routeStr);
189  if (route == nullptr) {
190  throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
191  }
192 
193  // get the probability to reroute
194  bool ok = true;
195  double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
196  if (!ok) {
197  throw ProcessError();
198  }
199  if (prob < 0) {
200  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
201  }
202  // add
203  myCurrentRouteProb.add(route, prob);
204  }
205 
206  if (element == SUMO_TAG_PARKING_ZONE_REROUTE) {
207  // by giving probabilities of new destinations
208  // get the destination edge
209  std::string parkingarea = attrs.getStringSecure(SUMO_ATTR_ID, "");
210  if (parkingarea == "") {
211  throw ProcessError("MSTriggeredRerouter " + getID() + ": No parking area id given.");
212  }
214  if (pa == nullptr) {
215  throw ProcessError("MSTriggeredRerouter " + getID() + ": Parking area '" + parkingarea + "' is not known.");
216  }
217  // get the probability to reroute
218  bool ok = true;
219  const double prob = attrs.getOpt<double>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
220  if (!ok) {
221  throw ProcessError();
222  }
223  if (prob < 0) {
224  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + parkingarea + "' is negative (must not).");
225  }
226  const bool visible = attrs.getOpt<bool>(SUMO_ATTR_VISIBLE, getID().c_str(), ok, false);
227  // add
228  myCurrentParkProb.add(std::make_pair(pa, visible), prob);
229  //MSEdge* to = &(pa->getLane().getEdge());
230  //myCurrentEdgeProb.add(prob, to);
231  }
232 }
233 
234 
235 void
237  if (element == SUMO_TAG_INTERVAL) {
238  RerouteInterval ri;
241  ri.closed = myCurrentClosed;
247  if (ri.closedLanes.size() > 0) {
248  // collect edges that are affect by a closed lane
249  std::set<MSEdge*> affected;
250  for (std::vector<MSLane*>::iterator l = ri.closedLanes.begin(); l != ri.closedLanes.end(); ++l) {
251  affected.insert(&((*l)->getEdge()));
252  }
253  ri.closedLanesAffected.insert(ri.closedLanesAffected.begin(), affected.begin(), affected.end());
254  }
255  myCurrentClosed.clear();
256  myCurrentClosedLanes.clear();
260  myIntervals.push_back(ri);
261  myIntervals.back().id = (long long)&myIntervals.back();
262  if (!(ri.closed.empty() && ri.closedLanes.empty()) && ri.permissions != SVCAll) {
265  }
266  }
267 }
268 
269 
270 // ------------ loading end
271 
272 
273 SUMOTime
275  for (std::vector<RerouteInterval>::iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
276  if (i->begin == currentTime && !(i->closed.empty() && i->closedLanes.empty()) && i->permissions != SVCAll) {
277  for (MSEdgeVector::iterator e = i->closed.begin(); e != i->closed.end(); ++e) {
278  for (std::vector<MSLane*>::const_iterator l = (*e)->getLanes().begin(); l != (*e)->getLanes().end(); ++l) {
279  //std::cout << SIMTIME << " closing: intervalID=" << i->id << " lane=" << (*l)->getID() << " prevPerm=" << getVehicleClassNames((*l)->getPermissions()) << " new=" << getVehicleClassNames(i->permissions) << "\n";
280  (*l)->setPermissions(i->permissions, i->id);
281  }
282  (*e)->rebuildAllowedLanes();
283  }
284  for (std::vector<MSLane*>::iterator l = i->closedLanes.begin(); l != i->closedLanes.end(); ++l) {
285  (*l)->setPermissions(i->permissions, i->id);
286  (*l)->getEdge().rebuildAllowedLanes();
287  }
290  }
291  if (i->end == currentTime && !(i->closed.empty() && i->closedLanes.empty()) && i->permissions != SVCAll) {
292  for (MSEdgeVector::iterator e = i->closed.begin(); e != i->closed.end(); ++e) {
293  for (std::vector<MSLane*>::const_iterator l = (*e)->getLanes().begin(); l != (*e)->getLanes().end(); ++l) {
294  (*l)->resetPermissions(i->id);
295  //std::cout << SIMTIME << " opening: intervalID=" << i->id << " lane=" << (*l)->getID() << " restore prevPerm=" << getVehicleClassNames((*l)->getPermissions()) << "\n";
296  }
297  (*e)->rebuildAllowedLanes();
298  }
299  for (std::vector<MSLane*>::iterator l = i->closedLanes.begin(); l != i->closedLanes.end(); ++l) {
300  (*l)->resetPermissions(i->id);
301  (*l)->getEdge().rebuildAllowedLanes();
302  }
303  }
304  }
305  return 0;
306 }
307 
308 
311  for (std::vector<RerouteInterval>::const_iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
312  if (i->begin <= time && i->end > time) {
313  if (
314  // destProbReroute
315  i->edgeProbs.getOverallProb() > 0 ||
316  // routeProbReroute
317  i->routeProbs.getOverallProb() > 0 ||
318  // parkingZoneReroute
319  i->parkProbs.getOverallProb() > 0 ||
320  // affected by closingReroute
321  veh.getRoute().containsAnyOf(i->closed) ||
322  // affected by closingLaneReroute
323  veh.getRoute().containsAnyOf(i->closedLanesAffected)) {
324  return &*i;
325  }
326  }
327  }
328  return nullptr;
329 }
330 
331 
334  for (std::vector<RerouteInterval>::const_iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
335  if (i->begin <= time && i->end > time) {
336  if (i->parkProbs.getOverallProb() != 0 || i->edgeProbs.getOverallProb() != 0 || i->routeProbs.getOverallProb() != 0 || !i->closed.empty()) {
337  return &*i;
338  }
339  }
340  }
341  return nullptr;
342 }
343 
344 
345 bool
347  double /*newPos*/, double /*newSpeed*/) {
348  return notifyEnter(veh, NOTIFICATION_JUNCTION);
349 }
350 
351 
352 bool
353 MSTriggeredRerouter::notifyLeave(SUMOVehicle& /*veh*/, double /*lastPos*/,
354  MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
355  return reason == NOTIFICATION_LANE_CHANGE;
356 }
357 
358 
359 bool
361  if (!vehicleApplies(veh)) {
362  return false;
363  }
364  // check whether the vehicle shall be rerouted
366  const MSTriggeredRerouter::RerouteInterval* rerouteDef = getCurrentReroute(time, veh);
367  if (rerouteDef == nullptr) {
368  return true; // an active interval could appear later
369  }
371  if (RandHelper::rand() > prob) {
372  return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
373  }
375  return true; // waiting time may be reached later
376  }
377  // if we have a closingLaneReroute, only vehicles with a rerouting device can profit from rerouting (otherwise, edge weights will not reflect local jamming)
378  const bool hasReroutingDevice = veh.getDevice(typeid(MSDevice_Routing)) != nullptr;
379  if (rerouteDef->closedLanes.size() > 0 && !hasReroutingDevice) {
380  return true; // an active interval could appear later
381  }
382  // get vehicle params
383  const MSRoute& route = veh.getRoute();
384  const MSEdge* lastEdge = route.getLastEdge();
385 #ifdef DEBUG_REROUTER
386  if (DEBUGCOND) {
387  std::cout << SIMTIME << " veh=" << veh.getID() << " check rerouter " << getID() << " lane=" << veh.getLane()->getID() << " edge=" << veh.getEdge()->getID() << " finalEdge=" << lastEdge->getID() << " arrivalPos=" << veh.getArrivalPos() << "\n";
388  }
389 #endif
390 
391  if (rerouteDef->parkProbs.getOverallProb() > 0) {
392  bool newDestination = false;
393  MSParkingArea* newParkingArea = rerouteParkingArea(rerouteDef, veh, newDestination);
394  if (newParkingArea != nullptr) {
395  const MSEdge* newEdge = &(newParkingArea->getLane().getEdge());
396 
397  SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
398  ? MSRoutingEngine::getRouterTT(rerouteDef->closed)
399  : MSNet::getInstance()->getRouterTT(rerouteDef->closed);
400 
401  // Compute the route from the current edge to the parking area edge
402  ConstMSEdgeVector edgesToPark;
403  router.compute(veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesToPark);
404 
405  // Compute the route from the parking area edge to the end of the route
406  ConstMSEdgeVector edgesFromPark;
407  if (!newDestination) {
408  router.compute(newEdge, lastEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesFromPark);
409  } else {
410  // adapt plans of any riders
411  for (MSTransportable* p : veh.getPersons()) {
412  p->rerouteParkingArea(veh.getNextParkingArea(), newParkingArea);
413  }
414  }
415 
416  // we have a new destination, let's replace the vehicle route
417  ConstMSEdgeVector edges = edgesToPark;
418  if (edgesFromPark.size() > 0) {
419  edges.insert(edges.end(), edgesFromPark.begin() + 1, edgesFromPark.end());
420  }
421 
422  if (newDestination) {
423  SUMOVehicleParameter* newParameter = new SUMOVehicleParameter();
424  *newParameter = veh.getParameter();
425  newParameter->arrivalPosProcedure = ARRIVAL_POS_GIVEN;
426  newParameter->arrivalPos = newParkingArea->getEndLanePosition();
427  veh.replaceParameter(newParameter);
428  }
429  const double routeCost = router.recomputeCosts(edges, &veh, MSNet::getInstance()->getCurrentTimeStep());
430  ConstMSEdgeVector prevEdges(veh.getCurrentRouteEdge(), veh.getRoute().end());
431  const double previousCost = router.recomputeCosts(prevEdges, &veh, MSNet::getInstance()->getCurrentTimeStep());
432  const double savings = previousCost - routeCost;
433  //if (getID() == "ego") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
434  // << " prevEdges=" << toString(prevEdges)
435  // << " newEdges=" << toString(edges)
436  // << "\n";
437  veh.replaceRouteEdges(edges, routeCost, savings, getID(), false, false, false);
438  std::string errorMsg;
439  if (!veh.replaceParkingArea(newParkingArea, errorMsg)) {
440  WRITE_WARNING("Vehicle '" + veh.getID() + "' at rerouter '" + getID()
441  + "' could not reroute to new parkingArea '" + newParkingArea->getID()
442  + "' reason=" + errorMsg + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
443  }
444  }
445  return false;
446  }
447 
448  // get rerouting params
449  const MSRoute* newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : 0;
450  // we will use the route if given rather than calling our own dijsktra...
451  if (newRoute != nullptr) {
452 #ifdef DEBUG_REROUTER
453  if (DEBUGCOND) {
454  std::cout << " replacedRoute from routeDist " << newRoute->getID() << "\n";
455  }
456 #endif
457  veh.replaceRoute(newRoute, getID());
458  return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
459  }
460  const MSEdge* newEdge = lastEdge;
461  // ok, try using a new destination
462  double newArrivalPos = -1;
463  const bool destUnreachable = std::find(rerouteDef->closed.begin(), rerouteDef->closed.end(), lastEdge) != rerouteDef->closed.end();
464  // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
465  // if we have a closingLaneReroute, no new destinations should be assigned
466  if (rerouteDef->closed.size() == 0 || destUnreachable) {
467  newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : route.getLastEdge();
468  if (newEdge == &mySpecialDest_terminateRoute) {
469  newEdge = veh.getEdge();
470  newArrivalPos = veh.getPositionOnLane(); // instant arrival
471  } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
472  if (destUnreachable && rerouteDef->permissions == SVCAll) {
473  // if permissions aren't set vehicles will simply drive through
474  // the closing unless terminated. If the permissions are specified, assume that the user wants
475  // vehicles to stand and wait until the closing ends
476  WRITE_WARNING("Cannot keep destination edge '" + lastEdge->getID() + "' for vehicle '" + veh.getID() + "' due to closed edges. Terminating route.");
477  newEdge = veh.getEdge();
478  } else {
479  newEdge = lastEdge;
480  }
481  } else if (newEdge == nullptr) {
482 #ifdef DEBUG_REROUTER
483  if (DEBUGCOND) {
484  std::cout << " could not find new edge!\n";
485  }
486 #endif
487  assert(false); // this should never happen
488  newEdge = veh.getEdge();
489  }
490  }
491  // we have a new destination, let's replace the vehicle route (if it is affected)
492  if (rerouteDef->closed.size() == 0 || destUnreachable || veh.getRoute().containsAnyOf(rerouteDef->closed)) {
493  ConstMSEdgeVector edges;
494  SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
495  ? MSRoutingEngine::getRouterTT(rerouteDef->closed)
496  : MSNet::getInstance()->getRouterTT(rerouteDef->closed);
497  router.compute(
498  veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
499  const double routeCost = router.recomputeCosts(edges, &veh, MSNet::getInstance()->getCurrentTimeStep());
500  const bool useNewRoute = veh.replaceRouteEdges(edges, routeCost, 0, getID());
501 #ifdef DEBUG_REROUTER
502  if (DEBUGCOND) std::cout << " rerouting: newEdge=" << newEdge->getID() << " useNewRoute=" << useNewRoute << " newArrivalPos=" << newArrivalPos << " numClosed=" << rerouteDef->closed.size()
503  << " destUnreachable=" << destUnreachable << " containsClosed=" << veh.getRoute().containsAnyOf(rerouteDef->closed) << "\n";
504 #endif
505  if (useNewRoute && newArrivalPos != -1) {
506  // must be called here because replaceRouteEdges may also set the arrivalPos
507  veh.setArrivalPos(newArrivalPos);
508  }
509  }
510  return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
511 }
512 
513 
514 void
516  myAmInUserMode = val;
517 }
518 
519 
520 void
522  myUserProbability = prob;
523 }
524 
525 
526 bool
528  return myAmInUserMode;
529 }
530 
531 
532 double
535 }
536 
537 
538 double
540  return myUserProbability;
541 }
542 
543 
544 double
545 MSTriggeredRerouter::getWeight(SUMOVehicle& veh, const std::string param, const double defaultWeight) const {
546  // get custom vehicle parameter
547  if (veh.getParameter().knowsParameter(param)) {
548  try {
549  return StringUtils::toDouble(veh.getParameter().getParameter(param, "-1"));
550  } catch (...) {
551  WRITE_WARNING("Invalid value '" + veh.getParameter().getParameter(param, "-1") + "' for vehicle parameter '" + param + "'");
552  }
553  } else {
554  // get custom vType parameter
555  if (veh.getVehicleType().getParameter().knowsParameter(param)) {
556  try {
557  return StringUtils::toDouble(veh.getVehicleType().getParameter().getParameter(param, "-1"));
558  } catch (...) {
559  WRITE_WARNING("Invalid value '" + veh.getVehicleType().getParameter().getParameter(param, "-1") + "' for vType parameter '" + param + "'");
560  }
561  }
562  }
563  //WRITE_MESSAGE("Vehicle '" +veh.getID() + "' does not supply vehicle parameter '" + param + "'. Using default of " + toString(defaultWeight) + "\n";
564  return defaultWeight;
565 }
566 
567 
570  SUMOVehicle& veh, bool& newDestination) const {
571  // reroute destination from initial parking area to the near parking area
572  // if the next stop is a parking area, it is included in the current
573  // alternative set and if it can be observed to be full
574 
575  MSParkingArea* nearParkArea = nullptr;
576  std::vector<ParkingAreaVisible> parks = rerouteDef->parkProbs.getVals();
577 
578  // get vehicle params
579  MSParkingArea* destParkArea = veh.getNextParkingArea();
580  const MSRoute& route = veh.getRoute();
581 
582  if (destParkArea == nullptr) {
583  // not driving towards a parkingArea
584  return nullptr;
585  }
586 
587  bool destVisible = false;
588  for (auto paVis : parks) {
589  if (paVis.first == destParkArea
590  && (paVis.second
591  // if the vehicle is on the destParkArea edge it is always visible
592  || &(destParkArea->getLane().getEdge()) == veh.getEdge())) {
593  destVisible = true;
594  break;
595  }
596  }
597  if (!destVisible) {
598  // cannot determine destination occupancy
599  return nullptr;
600  }
601  if (destParkArea->getOccupancy() == destParkArea->getCapacity()) {
602  // if the current route ends at the parking area, the new route will
603  // also and at the new area
604  newDestination = (&destParkArea->getLane().getEdge() == route.getLastEdge()
605  && veh.getArrivalPos() >= destParkArea->getBeginLanePosition()
606  && veh.getArrivalPos() <= destParkArea->getEndLanePosition());
607 
608 #ifdef DEBUG_PARKING
609  if (DEBUGCOND) {
610  std::cout << SIMTIME << " veh=" << veh.getID()
611  << " rerouteParkingArea dest=" << destParkArea->getID()
612  << " onDestEdge=" << (&(destParkArea->getLane().getEdge()) == veh.getEdge())
613  << " newDest=" << newDestination
614  << "\n";
615  }
616 #endif
617 
618  typedef std::map<std::string, double> ParkingParamMap_t;
619  typedef std::map<MSParkingArea*, ParkingParamMap_t> MSParkingAreaMap_t;
620 
621  ParkingParamMap_t weights;
622 
623  // The probability of choosing this area inside the zone
624  weights["probability"] = getWeight(veh, "parking.probability.weight", 0.0);
625 
626  // The capacity of this area
627  weights["capacity"] = getWeight(veh, "parking.capacity.weight", 0.0);
628 
629  // The absolute number of free spaces
630  weights["absfreespace"] = getWeight(veh, "parking.absfreespace.weight", 0.0);
631 
632  // The relative number of free spaces
633  weights["relfreespace"] = getWeight(veh, "parking.relfreespace.weight", 0.0);
634 
635  // The distance to the new parking area
636  weights["distanceto"] = getWeight(veh, "parking.distanceto.weight", getWeight(veh, "parking.distance.weight", 1.0));
637 
638  // The time to reach this area
639  weights["timeto"] = getWeight(veh, "parking.timeto.weight", 0.0);
640 
641  // The distance from the new parking area
642  weights["distancefrom"] = getWeight(veh, "parking.distancefrom.weight", 0.0);
643 
644  // The time to reach the end from this area
645  weights["timefrom"] = getWeight(veh, "parking.timefrom.weight", 0.0);
646 
647  // a map stores maximum values to normalize parking values
648  ParkingParamMap_t maxValues;
649 
650  maxValues["probability"] = 0.0;
651  maxValues["capacity"] = 0.0;
652  maxValues["absfreespace"] = 0.0;
653  maxValues["relfreespace"] = 0.0;
654  maxValues["distanceto"] = 0.0;
655  maxValues["timeto"] = 0.0;
656  maxValues["distancefrom"] = 0.0;
657  maxValues["timefrom"] = 0.0;
658 
659  // a map stores elegible parking areas
660  MSParkingAreaMap_t parkAreas;
661 
663 
664  std::vector<double> probs = rerouteDef->parkProbs.getProbs();
665 
666  const double brakeGap = veh.getBrakeGap();
667 
668  for (int i = 0; i < (int)parks.size(); ++i) {
669  MSParkingArea* pa = parks[i].first;
670  const double prob = probs[i];
671  // alternative occupancy is randomized (but never full) if invisible
672  // current destination must be visible at this point
673  int paOccupancy = parks[i].second || pa == destParkArea ? pa->getOccupancy() : RandHelper::rand(pa->getCapacity());
674  if (paOccupancy < pa->getCapacity()) {
675 
676  // a map stores the parking values
677  ParkingParamMap_t parkValues;
678 
679  const RGBColor& c = route.getColor();
680  const MSEdge* parkEdge = &(pa->getLane().getEdge());
681 
682  const bool includeInternalLengths = MSGlobals::gUsingInternalLanes && MSNet::getInstance()->hasInternalLinks();
683 
684  // Compute the route from the current edge to the parking area edge
685  ConstMSEdgeVector edgesToPark;
686  router.compute(veh.getEdge(), parkEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesToPark);
687 
688  if (edgesToPark.size() > 0) {
689  // Compute the route from the parking area edge to the end of the route
690  ConstMSEdgeVector edgesFromPark;
691 
692  if (!newDestination) {
693  router.compute(parkEdge, route.getLastEdge(), &veh, MSNet::getInstance()->getCurrentTimeStep(), edgesFromPark);
694  }
695 
696  if (edgesFromPark.size() > 0 || newDestination) {
697 
698  parkValues["probability"] = prob;
699 
700  if (parkValues["probability"] > maxValues["probability"]) {
701  maxValues["probability"] = parkValues["probability"];
702  }
703 
704  parkValues["capacity"] = (double)(pa->getCapacity());
705  parkValues["absfreespace"] = (double)(pa->getCapacity() - paOccupancy);
706  parkValues["relfreespace"] = parkValues["absfreespace"] / parkValues["capacity"];
707 
708  if (parkValues["capacity"] > maxValues["capacity"]) {
709  maxValues["capacity"] = parkValues["capacity"];
710  }
711 
712  if (parkValues["absfreespace"] > maxValues["absfreespace"]) {
713  maxValues["absfreespace"] = parkValues["absfreespace"];
714  }
715 
716  if (parkValues["relfreespace"] > maxValues["relfreespace"]) {
717  maxValues["relfreespace"] = parkValues["relfreespace"];
718  }
719 
720  MSRoute routeToPark(route.getID() + "!topark#1", edgesToPark, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
721 
722  // The distance from the current edge to the new parking area
723  parkValues["distanceto"] = routeToPark.getDistanceBetween(veh.getPositionOnLane(), pa->getBeginLanePosition(),
724  routeToPark.begin(), routeToPark.end() - 1, includeInternalLengths);
725 
726  //std::cout << SIMTIME << " veh=" << veh.getID() << " candidate=" << pa->getID()
727  // << " distanceTo=" << parkValues["distanceto"]
728  // << " brakeGap=" << brakeGap
729  // << " routeToPark=" << toString(edgesToPark)
730  // << " fromPos=" << veh.getPositionOnLane()
731  // << " tPos=" << pa->getBeginLanePosition()
732  // << "\n";
733  if (parkValues["distanceto"] < brakeGap) {
734  //std::cout << " removed: pa too close\n";
735  // to close to stop for this parkingArea
736  continue;
737  }
738 
739  // The time to reach the new parking area
740  parkValues["timeto"] = router.recomputeCosts(edgesToPark, &veh, MSNet::getInstance()->getCurrentTimeStep());
741 
742  if (parkValues["distanceto"] > maxValues["distanceto"]) {
743  maxValues["distanceto"] = parkValues["distanceto"];
744  }
745 
746  if (parkValues["timeto"] > maxValues["timeto"]) {
747  maxValues["timeto"] = parkValues["timeto"];
748  }
749 
750  if (newDestination) {
751  parkValues["distancefrom"] = 0;
752  parkValues["timefrom"] = 0;
753  } else {
754  MSRoute routeFromPark(route.getID() + "!frompark#1", edgesFromPark, false,
755  &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), route.getStops());
756  // The distance from the new parking area to the end of the route
757  parkValues["distancefrom"] = routeFromPark.getDistanceBetween(pa->getBeginLanePosition(), routeFromPark.getLastEdge()->getLength(),
758  routeFromPark.begin(), routeFromPark.end() - 1, includeInternalLengths);
759  // The time to reach this area
760  parkValues["timefrom"] = router.recomputeCosts(edgesFromPark, &veh, MSNet::getInstance()->getCurrentTimeStep());
761  }
762 
763  if (parkValues["distancefrom"] > maxValues["distancefrom"]) {
764  maxValues["distancefrom"] = parkValues["distancefrom"];
765  }
766 
767  if (parkValues["timefrom"] > maxValues["timefrom"]) {
768  maxValues["timefrom"] = parkValues["timefrom"];
769  }
770 
771  parkAreas[pa] = parkValues;
772 
773 #ifdef DEBUG_PARKING
774  if (DEBUGCOND) {
775  std::cout << " altPA=" << pa->getID()
776  << " vals=" << joinToString(parkValues, " ", ":")
777  << "\n";
778  }
779 #endif
780  }
781  }
782  }
783  }
784 
785 #ifdef DEBUG_PARKING
786  if (DEBUGCOND) {
787  std::cout << " maxValues=" << joinToString(maxValues, " ", ":") << "\n";
788  }
789 #endif
790 
791  // minimum cost to get the parking area
792  double minParkingCost = 0.0;
793 
794  for (MSParkingAreaMap_t::iterator it = parkAreas.begin(); it != parkAreas.end(); ++it) {
795  // get the parking values
796  ParkingParamMap_t parkValues = it->second;
797 
798  // normalizing parking values with maximum values (we want to maximize some parameters then we reverse the value)
799  parkValues["probability"] = maxValues["probability"] > 0.0 ? 1.0 - parkValues["probability"] / maxValues["probability"] : 0.0;
800  parkValues["capacity"] = maxValues["capacity"] > 0.0 ? 1.0 - parkValues["capacity"] / maxValues["capacity"] : 0.0;
801  parkValues["absfreespace"] = maxValues["absfreespace"] > 0.0 ? 1.0 - parkValues["absfreespace"] / maxValues["absfreespace"] : 0.0;
802  parkValues["relfreespace"] = maxValues["relfreespace"] > 0.0 ? 1.0 - parkValues["relfreespace"] / maxValues["relfreespace"] : 0.0;
803 
804  parkValues["distanceto"] = maxValues["distanceto"] > 0.0 ? parkValues["distanceto"] / maxValues["distanceto"] : 0.0;
805  parkValues["timeto"] = maxValues["timeto"] > 0.0 ? parkValues["timeto"] / maxValues["timeto"] : 0.0;
806 
807  parkValues["distancefrom"] = maxValues["distancefrom"] > 0.0 ? parkValues["distancefrom"] / maxValues["distancefrom"] : 0.0;
808  parkValues["timefrom"] = maxValues["timefrom"] > 0.0 ? parkValues["timefrom"] / maxValues["timefrom"] : 0.0;
809 
810  // get the parking area cost
811  double parkingCost = 0.0;
812 
813  // sum every index with its weight
814  for (ParkingParamMap_t::iterator pc = parkValues.begin(); pc != parkValues.end(); ++pc) {
815  parkingCost += weights[pc->first] * pc->second;
816  }
817 
818  // get the parking area with minimum cost
819  if (nearParkArea == nullptr || parkingCost < minParkingCost) {
820  minParkingCost = parkingCost;
821  nearParkArea = it->first;
822  }
823 
824 #ifdef DEBUG_PARKING
825  if (DEBUGCOND) {
826  std::cout << " altPA=" << it->first->getID() << " score=" << parkingCost << "\n";
827  }
828 #endif
829  }
830  }
831 
832 #ifdef DEBUG_PARKING
833  if (DEBUGCOND) {
834  std::cout << " parkingResult=" << Named::getIDSecure(nearParkArea) << "\n";
835  }
836 #endif
837 
838  return nearParkArea;
839 }
840 
841 
842 bool
844  if (myVehicleTypes.empty() || myVehicleTypes.count(veh.getVehicleType().getID()) > 0) {
845  return true;
846  } else {
847  std::set<std::string> vTypeDists = MSNet::getInstance()->getVehicleControl().getVTypeDistributionMembership(veh.getVehicleType().getID());
848  for (auto vTypeDist : vTypeDists) {
849  if (myVehicleTypes.count(vTypeDist) > 0) {
850  return true;
851  }
852  }
853  return false;
854  }
855 }
856 /****************************************************************************/
857 
#define DEBUGCOND
A lane area vehicles can halt at.
Definition: MSParkingArea.h:59
double getProbability() const
Returns the rerouting probability.
MSEdgeVector closed
The list of closed edges.
const RerouteInterval * getCurrentReroute(SUMOTime time, SUMOVehicle &veh) const
Returns the rerouting definition valid for the given time and vehicle, 0 if none. ...
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:640
long long int SUMOTime
Definition: SUMOTime.h:36
virtual double getArrivalPos() const =0
Returns this vehicle&#39;s desired arrivalPos for its current route (may change on reroute) ...
double getBeginLanePosition() const
Returns the begin position of this stop.
double getUserProbability() const
Returns the rerouting probability given by the user.
virtual MSParkingArea * getNextParkingArea()=0
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:283
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:869
virtual MSVehicleDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
virtual const MSRoute & getRoute() const =0
Returns the current route.
SUMOTime setPermissions(const SUMOTime currentTime)
Sets the edge permission if there are any defined in the closingEdge.
SVCPermissions myCurrentPermissions
List of permissions for closed edges.
RandomDistributor< MSEdge * > edgeProbs
The distributions of new destinations to use.
The vehicle arrived at a junction.
lane of a reroute of type closing
SUMOTime myCurrentIntervalBegin
The first and the last time steps of the interval.
std::vector< MSLane * > myCurrentClosedLanes
List of closed lanes.
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:61
virtual const MSEdge * getEdge() const =0
Returns the edge the vehicle is currently at.
Notification
Definition of a vehicle state.
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
A device that performs vehicle rerouting based on current edge speeds.
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E *> &into)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual MSLane * getLane() const =0
Returns the lane the vehicle is on.
const RGBColor & getColor() const
Returns the color.
Definition: MSRoute.cpp:357
weights: time range begin
virtual double getBrakeGap() const =0
get distance for coming to a stop (used for rerouting checks)
virtual bool replaceRoute(const MSRoute *route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true)=0
Replaces the current route by the given one.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
T MAX2(T a, T b)
Definition: StdDefs.h:76
MSTriggeredRerouter(const std::string &id, const MSEdgeVector &edges, double prob, const std::string &file, bool off, SUMOTime timeThreshold, const std::string &vTypes)
Constructor.
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:71
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn&#39;t already in the dictionary...
Definition: MSEdge.cpp:788
const std::vector< T > & getVals() const
Returns the members of the distribution.
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:88
void setUserUsageProbability(double prob)
Sets the probability with which a vehicle is rerouted given by the user.
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:72
const std::string & getID() const
Returns the id.
Definition: Named.h:78
The arrival position is given.
const SVCPermissions SVCAll
all VClasses are allowed
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
void setUserMode(bool val)
Sets whether the process is currently steered by the user.
SAX-handler base for SUMO-files.
std::set< std::string > myVehicleTypes
The vehicle types to look for (empty means all)
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
double myProbability
The probability and the user-given probability.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
#define SIMTIME
Definition: SUMOTime.h:65
authorities vehicles
RandomDistributor< ParkingAreaVisible > myCurrentParkProb
new destinations with probabilities
A road/street connecting two junctions.
Definition: MSEdge.h:75
virtual void myEndElement(int element)
Called when a closing tag occurs.
double getEndLanePosition() const
Returns the end position of this stop.
The vehicle changes lanes (micro only)
std::set< std::string > getVTypeDistributionMembership(const std::string &id) const
Return the distribution IDs the vehicle type is a member of.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
An abstract device that changes the state of the micro simulation.
Definition: MSTrigger.h:41
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
double getWeight(SUMOVehicle &veh, const std::string param, const double defaultWeight) const
Representation of a vehicle.
Definition: SUMOVehicle.h:60
Encapsulated SAX-Attributes.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter ...
T get(std::mt19937 *which=0) const
Draw a sample of the distribution.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition: RGBColor.h:198
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:316
virtual ~MSTriggeredRerouter()
Destructor.
SUMOTime begin
The begin time these definitions are valid.
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:409
A wrapper for a Command function.
int getCapacity() const
Returns the area capacity.
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
virtual SUMOTime getAccumulatedWaitingTime() const =0
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:263
RandomDistributor< const MSRoute * > myCurrentRouteProb
new routes with probabilities
static MSEdge mySpecialDest_keepDestination
special destination values
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:212
bool hasInternalLinks() const
return whether the network contains internal links
Definition: MSNet.h:605
MSParkingArea * rerouteParkingArea(const MSTriggeredRerouter::RerouteInterval *rerouteDef, SUMOVehicle &veh, bool &newDestination) const
probability of route of a reroute
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:69
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
probability of destiny of a reroute
Something on a lane to be noticed about vehicle movement.
static MSEdge mySpecialDest_terminateRoute
const SUMOVTypeParameter & getParameter() const
int getOccupancy() const
Returns the area occupancy.
bool notifyEnter(SUMOVehicle &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Tries to reroute the vehicle.
bool notifyLeave(SUMOVehicle &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Removes the reminder.
double arrivalPos
(optional) The position the vehicle shall arrive on
RandomDistributor< MSEdge * > myCurrentEdgeProb
new destinations with probabilities
std::vector< std::string > getVector()
reroute of type closing
void clear()
Clears the distribution.
entry for an alternative parking zone
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1730
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, bool report=true) const
Tries to read given attribute assuming it is an int.
Structure representing possible vehicle parameter.
SUMOTime end
The end time these definitions are valid.
bool containsAnyOf(const MSEdgeVector &edgelist) const
Definition: MSRoute.cpp:239
std::vector< MSLane * > closedLanes
The list of closed lanes.
RandomDistributor< const MSRoute * > routeProbs
The distributions of new routes to use.
virtual double getPositionOnLane() const =0
Get the vehicle&#39;s position along the lane.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle&#39;s parameter (including departure definition)
weights: time range end
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.
A single mesoscopic segment (cell)
Definition: MESegment.h:50
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:94
std::vector< RerouteInterval > myIntervals
List of rerouting definition intervals.
bool inUserMode() const
Returns whether the user is setting the rerouting probability.
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
MSEdgeVector myCurrentClosed
List of closed edges.
bool myAmInUserMode
Information whether the current rerouting probability is the user-given.
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:106
virtual SUMOTime getWaitingTime() const =0
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
an aggreagated-output interval
double recomputeCosts(const std::vector< const E *> &edges, const V *const v, SUMOTime msTime) const
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:903
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:71
bool notifyMove(SUMOVehicle &veh, double oldPos, double newPos, double newSpeed)
Triggers rerouting (once) for vehicles that are already on the edge when the rerouter activates...
const MSLane & getLane() const
Returns the lane this stop is located at.
bool vehicleApplies(const SUMOVehicle &veh) const
Checks whether the detector measures vehicles of the given type.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
SVCPermissions permissions
The permissions to use.
RandomDistributor< ParkingAreaVisible > parkProbs
The distributions of new parking areas to use as destinations.
static bool gUseMesoSim
Definition: MSGlobals.h:91
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:366
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:237
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
MSEdgeVector closedLanesAffected
The list of edges that are affect by closed lanes.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:114
double getDistanceBetween(double fromPos, double toPos, const MSEdge *fromEdge, const MSEdge *toEdge, bool includeInternal=true, int routePosition=0) const
Compute the distance between 2 given edges on this route, including the length of internal lanes...
Definition: MSRoute.cpp:277