SUMO - Simulation of Urban MObility
MSTriggeredRerouter.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Reroutes vehicles passing an edge
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <string>
34 #include <algorithm>
36 #include <utils/common/Command.h>
39 #include <utils/common/ToString.h>
46 #include <microsim/MSLane.h>
47 #include <microsim/MSVehicle.h>
48 #include <microsim/MSRoute.h>
49 #include <microsim/MSEdge.h>
50 #include <microsim/MSNet.h>
51 #include <microsim/MSGlobals.h>
53 #include "MSTriggeredRerouter.h"
54 
55 #include <mesosim/MELoop.h>
56 #include <mesosim/MESegment.h>
57 
58 #ifdef CHECK_MEMORY_LEAKS
59 #include <foreign/nvwa/debug_new.h>
60 #endif // CHECK_MEMORY_LEAKS
61 
62 
63 // ===========================================================================
64 // static member defintion
65 // ===========================================================================
66 MSEdge MSTriggeredRerouter::mySpecialDest_keepDestination("MSTriggeredRerouter_keepDestination", -1, MSEdge::EDGEFUNCTION_UNKNOWN, "", "", -1);
67 MSEdge MSTriggeredRerouter::mySpecialDest_terminateRoute("MSTriggeredRerouter_terminateRoute", -1, MSEdge::EDGEFUNCTION_UNKNOWN, "", "", -1);
68 
69 // ===========================================================================
70 // method definitions
71 // ===========================================================================
73  const MSEdgeVector& edges,
74  SUMOReal prob, const std::string& file, bool off) :
75  MSTrigger(id),
76  MSMoveReminder(id),
77  SUMOSAXHandler(file),
78  myProbability(prob), myUserProbability(prob), myAmInUserMode(false) {
79  // build actors
80  for (MSEdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
83  s->addDetector(this);
84  continue;
85  }
86  const std::vector<MSLane*>& destLanes = (*j)->getLanes();
87  for (std::vector<MSLane*>::const_iterator i = destLanes.begin(); i != destLanes.end(); ++i) {
88  (*i)->addMoveReminder(this);
89  }
90  }
91  if (off) {
92  setUserMode(true);
94  }
95 }
96 
97 
99 }
100 
101 // ------------ loading begin
102 void
104  const SUMOSAXAttributes& attrs) {
105  if (element == SUMO_TAG_INTERVAL) {
106  bool ok = true;
109  }
110  if (element == SUMO_TAG_DEST_PROB_REROUTE) {
111  // by giving probabilities of new destinations
112  // get the destination edge
113  std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
114  if (dest == "") {
115  throw ProcessError("MSTriggeredRerouter " + getID() + ": No destination edge id given.");
116  }
117  MSEdge* to = MSEdge::dictionary(dest);
118  if (to == 0) {
119  if (dest == "keepDestination") {
121  } else if (dest == "terminateRoute") {
123  } else {
124  throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
125  }
126  }
127  // get the probability to reroute
128  bool ok = true;
129  SUMOReal prob = attrs.getOpt<SUMOReal>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
130  if (!ok) {
131  throw ProcessError();
132  }
133  if (prob < 0) {
134  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
135  }
136  // add
137  myCurrentEdgeProb.add(prob, to);
138  }
139 
140  if (element == SUMO_TAG_CLOSING_REROUTE) {
141  // by closing
142  std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
143  MSEdge* closed = MSEdge::dictionary(closed_id);
144  if (closed == 0) {
145  throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
146  }
147  myCurrentClosed.push_back(closed);
148  bool ok;
149  const std::string allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, getID().c_str(), ok, "", false);
150  const std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, getID().c_str(), ok, "");
151  myCurrentPermissions = parseVehicleClasses(allow, disallow);
152  }
153 
154  if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
155  // by explicit rerouting using routes
156  // check if route exists
157  std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
158  if (routeStr == "") {
159  throw ProcessError("MSTriggeredRerouter " + getID() + ": No route id given.");
160  }
161  const MSRoute* route = MSRoute::dictionary(routeStr);
162  if (route == 0) {
163  throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
164  }
165 
166  // get the probability to reroute
167  bool ok = true;
168  SUMOReal prob = attrs.getOpt<SUMOReal>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
169  if (!ok) {
170  throw ProcessError();
171  }
172  if (prob < 0) {
173  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
174  }
175  // add
176  myCurrentRouteProb.add(prob, route);
177  }
178 }
179 
180 
181 void
183  if (element == SUMO_TAG_INTERVAL) {
184  RerouteInterval ri;
187  ri.closed = myCurrentClosed;
191  myCurrentClosed.clear();
194  myIntervals.push_back(ri);
195  if (!ri.closed.empty() && ri.permissions != SVCAll) {
199  }
200  }
201 }
202 
203 
204 // ------------ loading end
205 
206 
207 SUMOTime
209  for (std::vector<RerouteInterval>::iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
210  if (i->begin == currentTime && !i->closed.empty() && i->permissions != SVCAll) {
211  for (MSEdgeVector::iterator e = i->closed.begin(); e != i->closed.end(); ++e) {
212  for (std::vector<MSLane*>::const_iterator l = (*e)->getLanes().begin(); l != (*e)->getLanes().end(); ++l) {
213  i->prevPermissions.push_back((*l)->getPermissions());
214  (*l)->setPermissions(i->permissions);
215  }
216  (*e)->rebuildAllowedLanes();
217  }
221  }
222  if (i->end == currentTime && !i->closed.empty() && i->permissions != SVCAll) {
223  for (MSEdgeVector::iterator e = i->closed.begin(); e != i->closed.end(); ++e) {
224  std::vector<SVCPermissions>::const_iterator p = i->prevPermissions.begin();
225  for (std::vector<MSLane*>::const_iterator l = (*e)->getLanes().begin(); l != (*e)->getLanes().end(); ++l, ++p) {
226  (*l)->setPermissions(*p);
227  }
228  (*e)->rebuildAllowedLanes();
229  }
230  }
231  }
232  return 0;
233 }
234 
235 
238  for (std::vector<RerouteInterval>::const_iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
239  if (i->begin <= time && i->end > time) {
240  if (
241  // destProbReroute
242  i->edgeProbs.getOverallProb() > 0 ||
243  // routeProbReroute
244  i->routeProbs.getOverallProb() > 0 ||
245  // affected by closingReroute
246  veh.getRoute().containsAnyOf(i->closed)) {
247  return &*i;
248  }
249  }
250  }
251  return 0;
252 }
253 
254 
257  for (std::vector<RerouteInterval>::const_iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
258  if (i->begin <= time && i->end > time) {
259  if (i->edgeProbs.getOverallProb() != 0 || i->routeProbs.getOverallProb() != 0 || !i->closed.empty()) {
260  return &*i;
261  }
262  }
263  }
264  return 0;
265 }
266 
267 
268 bool
270  SUMOReal /*newPos*/, SUMOReal /*newSpeed*/) {
271  return notifyEnter(veh, NOTIFICATION_JUNCTION);
272 }
273 
274 
275 bool
278  return reason == NOTIFICATION_LANE_CHANGE;
279 }
280 
281 
282 bool
284  // check whether the vehicle shall be rerouted
286  const MSTriggeredRerouter::RerouteInterval* rerouteDef = getCurrentReroute(time, veh);
287  if (rerouteDef == 0) {
288  return true; // an active interval could appear later
289  }
290 
292  if (RandHelper::rand() > prob) {
293  return false; // XXX another interval could appear later but we would have to track whether the current interval was already tried
294  }
295 
296  // get vehicle params
297  const MSRoute& route = veh.getRoute();
298  const MSEdge* lastEdge = route.getLastEdge();
299  // get rerouting params
300  const MSRoute* newRoute = rerouteDef->routeProbs.getOverallProb() > 0 ? rerouteDef->routeProbs.get() : 0;
301  // we will use the route if given rather than calling our own dijsktra...
302  if (newRoute != 0) {
303  veh.replaceRoute(newRoute);
304  return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
305  }
306  const MSEdge* newEdge = lastEdge;
307  // ok, try using a new destination
308  SUMOReal newArrivalPos = -1;
309  const bool destUnreachable = std::find(rerouteDef->closed.begin(), rerouteDef->closed.end(), lastEdge) != rerouteDef->closed.end();
310  // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
311  if (rerouteDef->closed.size() == 0 || destUnreachable) {
312  newEdge = rerouteDef->edgeProbs.getOverallProb() > 0 ? rerouteDef->edgeProbs.get() : route.getLastEdge();
313  if (newEdge == &mySpecialDest_terminateRoute) {
314  newEdge = veh.getEdge();
315  newArrivalPos = veh.getPositionOnLane(); // instant arrival
316  } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
317  if (destUnreachable && rerouteDef->permissions == SVCAll) {
318  // if permissions aren't set vehicles will simply drive through
319  // the closing unless terminated. If the permissions are specified, assume that the user wants
320  // vehicles to stand and wait until the closing ends
321  WRITE_WARNING("Cannot keep destination edge '" + lastEdge->getID() + "' for vehicle '" + veh.getID() + "' due to closed edges. Terminating route.");
322  newEdge = veh.getEdge();
323  } else {
324  newEdge = lastEdge;
325  }
326  } else if (newEdge == 0) {
327  assert(false); // this should never happen
328  newEdge = veh.getEdge();
329  }
330  }
331  // we have a new destination, let's replace the vehicle route (if it is affected)
332  if (rerouteDef->closed.size() == 0 || destUnreachable || veh.getRoute().containsAnyOf(rerouteDef->closed)) {
333  ConstMSEdgeVector edges;
334  const bool hasReroutingDevice = veh.getDevice(typeid(MSDevice_Routing)) != 0;
335  SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = hasReroutingDevice
337  : MSNet::getInstance()->getRouterTT(rerouteDef->closed);
338  router.compute(
339  veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
340  const bool useNewRoute = veh.replaceRouteEdges(edges);
341  if (useNewRoute && newArrivalPos != -1) {
342  // must be called here because replaceRouteEdges may also set the arrivalPos
343  veh.setArrivalPos(newArrivalPos);
344  }
345  }
346  return false; // XXX another interval could appear later but we would have to track whether the currenty interval was already used
347 }
348 
349 
350 void
352  myAmInUserMode = val;
353 }
354 
355 
356 void
358  myUserProbability = prob;
359 }
360 
361 
362 bool
364  return myAmInUserMode;
365 }
366 
367 
368 SUMOReal
371 }
372 
373 
374 SUMOReal
376  return myUserProbability;
377 }
378 
379 
380 
381 /****************************************************************************/
382 
MSEdgeVector closed
The list of closed edges.
long long int SUMOTime
Definition: SUMOTime.h:43
bool notifyMove(SUMOVehicle &veh, SUMOReal oldPos, SUMOReal newPos, SUMOReal newSpeed)
Triggers rerouting (once) for vehicles that are already on the edge when the rerouter activates...
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.
bool add(SUMOReal prob, T val, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:96
SUMOTime myCurrentIntervalBegin
The first and the last time steps of the interval.
bool notifyLeave(SUMOVehicle &veh, SUMOReal lastPos, MSMoveReminder::Notification reason)
Removes the reminder.
virtual SUMOReal getPositionOnLane() const =0
Get the vehicle&#39;s position along the lane.
virtual const MSEdge * getEdge() const =0
Returns the edge the vehicle is currently at.
Notification
Definition of a vehicle state.
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
A device that performs vehicle rerouting based on current edge speeds.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:160
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...
void setUserUsageProbability(SUMOReal prob)
Sets the probability with which a vehicle is rerouted given by the user.
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:578
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:78
SUMOReal getUserProbability() const
Returns the rerouting probability given by the user.
const SVCPermissions SVCAll
void setUserMode(bool val)
Sets whether the process is currently steered by the user.
SAX-handler base for SUMO-files.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:255
The purpose of the edge is not known.
Definition: MSEdge.h:91
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
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.
SUMOReal myProbability
The probability and the user-given probability.
const std::string & getID() const
Returns the id.
Definition: Named.h:65
A road/street connecting two junctions.
Definition: MSEdge.h:80
virtual void myEndElement(int element)
Called when a closing tag occurs.
The vehicle changes lanes (micro only)
An abstract device that changes the state of the micro simulation.
Definition: MSTrigger.h:48
Representation of a vehicle.
Definition: SUMOVehicle.h:65
Encapsulated SAX-Attributes.
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:389
T get(MTRand *which=0) const
Draw a sample of the distribution.
A wrapper for a Command function.
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:159
SUMOReal getProbability() const
Returns the rerouting probability.
bool notifyEnter(SUMOVehicle &veh, MSMoveReminder::Notification reason)
Tries to reroute the vehicle.
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
Something on a lane to be noticed about vehicle movement.
static MSEdge mySpecialDest_terminateRoute
const RerouteInterval * getCurrentReroute(SUMOTime time, SUMOVehicle &veh) const
Returns the rerouting definition valid for the given time and vehicle, 0 if none. ...
virtual SUMOTime addEvent(Command *operation, SUMOTime execTimeStep, AdaptType type)
Adds an Event.
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:847
RandomDistributor< MSEdge * > myCurrentEdgeProb
new destinations with probabilities
void clear()
Clears the distribution.
SUMOReal getOverallProb() const
Return the sum of the probabilites assigned to the members.
bool inUserMode() const
Returns whether the user is setting the rerouting probability.
SUMOTime end
The end time these definitions are valid.
RandomDistributor< const MSRoute * > routeProbs
The distributions of new routes to use.
A single mesoscopic segment (cell)
Definition: MESegment.h:57
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 replaceRoute(const MSRoute *route, bool onInit=false, int offset=0)=0
Replaces the current route by the given one.
std::vector< RerouteInterval > myIntervals
List of rerouting definition intervals.
MESegment * getSegmentForEdge(const MSEdge &e, SUMOReal pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:288
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:99
MSTriggeredRerouter(const std::string &id, const MSEdgeVector &edges, SUMOReal prob, const std::string &file, bool off)
Constructor.
Patch the time in a way that it is at least as high as the simulation begin time. ...
#define SUMOReal
Definition: config.h:213
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
virtual MSDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
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.
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:77
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
SVCPermissions permissions
The permissions to use.
static bool gUseMesoSim
Definition: MSGlobals.h:87
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:122
bool containsAnyOf(const MSEdgeVector &edgelist) const
Definition: MSRoute.cpp:247