SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-sim.org/
12 // Copyright (C) 2001-2013 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>
40 #include <utils/xml/XMLSubSys.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>
52 #include "MSTriggeredRerouter.h"
53 
54 #ifdef HAVE_INTERNAL
55 #include <mesosim/MELoop.h>
56 #include <mesosim/MESegment.h>
57 #endif
58 
59 #ifdef CHECK_MEMORY_LEAKS
60 #include <foreign/nvwa/debug_new.h>
61 #endif // CHECK_MEMORY_LEAKS
62 
63 
64 // ===========================================================================
65 // static member defintion
66 // ===========================================================================
69 
70 // ===========================================================================
71 // method definitions
72 // ===========================================================================
74  const std::vector<MSEdge*>& edges,
75  SUMOReal prob, const std::string& file, bool off) :
76  MSTrigger(id),
77  MSMoveReminder(id),
78  SUMOSAXHandler(file),
79  myProbability(prob), myUserProbability(prob), myAmInUserMode(false) {
80  // read in the trigger description
81  if (file != "" && !XMLSubSys::runParser(*this, file)) {
82  throw ProcessError();
83  }
84  // build actors
85  for (std::vector<MSEdge*>::const_iterator j = edges.begin(); j != edges.end(); ++j) {
86 #ifdef HAVE_INTERNAL
88  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**j);
89  s->addDetector(this);
90  continue;
91  }
92 #endif
93  const std::vector<MSLane*>& destLanes = (*j)->getLanes();
94  for (std::vector<MSLane*>::const_iterator i = destLanes.begin(); i != destLanes.end(); ++i) {
95  (*i)->addMoveReminder(this);
96  }
97  }
98  if (off) {
99  setUserMode(true);
101  }
102 }
103 
104 
106 }
107 
108 // ------------ loading begin
109 void
111  const SUMOSAXAttributes& attrs) {
112  if (element == SUMO_TAG_INTERVAL) {
113  bool ok = true;
116  }
117  if (element == SUMO_TAG_DEST_PROB_REROUTE) {
118  // by giving probabilities of new destinations
119  // get the destination edge
120  std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
121  if (dest == "") {
122  throw ProcessError("MSTriggeredRerouter " + getID() + ": No destination edge id given.");
123  }
124  MSEdge* to = MSEdge::dictionary(dest);
125  if (to == 0) {
126  if (dest == "keepDestination") {
128  } else if (dest == "terminateRoute") {
130  } else {
131  throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
132  }
133  }
134  // get the probability to reroute
135  bool ok = true;
136  SUMOReal prob = attrs.getOpt<SUMOReal>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
137  if (!ok) {
138  throw ProcessError();
139  }
140  if (prob < 0) {
141  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
142  }
143  // add
144  myCurrentEdgeProb.add(prob, to);
145  }
146 
147  if (element == SUMO_TAG_CLOSING_REROUTE) {
148  // by closing
149  std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
150  if (closed_id == "") {
151  throw ProcessError("MSTriggeredRerouter " + getID() + ": closed edge id given.");
152  }
153  MSEdge* closed = MSEdge::dictionary(closed_id);
154  if (closed == 0) {
155  throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
156  }
157  myCurrentClosed.push_back(closed);
158  }
159 
160  if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
161  // by explicit rerouting using routes
162  // check if route exists
163  std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
164  if (routeStr == "") {
165  throw ProcessError("MSTriggeredRerouter " + getID() + ": No route id given.");
166  }
167  const MSRoute* route = MSRoute::dictionary(routeStr);
168  if (route == 0) {
169  throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
170  }
171 
172  // get the probability to reroute
173  bool ok = true;
174  SUMOReal prob = attrs.getOpt<SUMOReal>(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
175  if (!ok) {
176  throw ProcessError();
177  }
178  if (prob < 0) {
179  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
180  }
181  // add
182  myCurrentRouteProb.add(prob, route);
183  }
184 }
185 
186 
187 void
189  if (element == SUMO_TAG_INTERVAL) {
190  RerouteInterval ri;
193  ri.closed = myCurrentClosed;
196  myCurrentClosed.clear();
199  myIntervals.push_back(ri);
200  }
201 }
202 
203 
204 // ------------ loading end
205 
206 
207 bool
209  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
210  const MSRoute& route = veh.getRoute();
211  while (i != myIntervals.end()) {
212  if ((*i).begin <= time && (*i).end >= time) {
213  if (
214  // affected by closingReroute, possibly combined with destProbReroute (route prob makes no sense)
215  route.containsAnyOf((*i).closed) ||
216  // no closingReroute but destProbReroute or routeProbReroute
217  ((*i).closed.size() == 0 && (*i).edgeProbs.getOverallProb() + (*i).routeProbs.getOverallProb() > 0)) {
218  return true;
219  }
220  }
221  i++;
222  }
223  return false;
224 }
225 
226 
227 bool
229  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
230  while (i != myIntervals.end()) {
231  if ((*i).begin <= time && (*i).end >= time) {
232  if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || (*i).closed.size() != 0) {
233  return true;
234  }
235  }
236  i++;
237  }
238  return false;
239 }
240 
241 
244  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
245  const MSRoute& route = veh.getRoute();
246  while (i != myIntervals.end()) {
247  if ((*i).begin <= time && (*i).end >= time) {
248  if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || route.containsAnyOf((*i).closed)) {
249  return *i;
250  }
251  }
252  i++;
253  }
254  throw 1;
255 }
256 
257 
260  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
261  while (i != myIntervals.end()) {
262  if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || (*i).closed.size() != 0) {
263  return *i;
264  }
265  i++;
266  }
267  throw 1;
268 }
269 
270 
271 
272 bool
275  return false;
276  }
277  // check whether the vehicle shall be rerouted
279  if (!hasCurrentReroute(time, veh)) {
280  return false;
281  }
282 
284  if (RandHelper::rand() > prob) {
285  return false;
286  }
287 
288  // get vehicle params
289  const MSRoute& route = veh.getRoute();
290  const MSEdge* lastEdge = route.getLastEdge();
291  // get rerouting params
292  const MSTriggeredRerouter::RerouteInterval& rerouteDef = getCurrentReroute(time, veh);
293  const MSRoute* newRoute = rerouteDef.routeProbs.getOverallProb() > 0 ? rerouteDef.routeProbs.get() : 0;
294  // we will use the route if given rather than calling our own dijsktra...
295  if (newRoute != 0) {
296  veh.replaceRoute(newRoute);
297  return false;
298  }
299  const MSEdge* newEdge = lastEdge;
300  // ok, try using a new destination
301  const bool destUnreachable = std::find(rerouteDef.closed.begin(), rerouteDef.closed.end(), lastEdge) != rerouteDef.closed.end();
302  // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
303  if (rerouteDef.closed.size() == 0 || destUnreachable) {
304  newEdge = rerouteDef.edgeProbs.getOverallProb() > 0 ? rerouteDef.edgeProbs.get() : route.getLastEdge();
305  if (newEdge == &mySpecialDest_terminateRoute) {
306  newEdge = veh.getEdge();
307  } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
308  if (destUnreachable) {
309  WRITE_WARNING("Cannot keep destination for vehicle '" + veh.getID() + "' due to closed edges. Terminating route.");
310  newEdge = veh.getEdge();
311  } else {
312  newEdge = lastEdge;
313  }
314  } else if (newEdge == 0) {
315  assert(false); // this should never happen
316  newEdge = veh.getEdge();
317  }
318  }
319  // we have a new destination, let's replace the vehicle route
320  std::vector<const MSEdge*> edges;
322  veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
323  veh.replaceRouteEdges(edges);
324  return false;
325 }
326 
327 
328 void
330  myAmInUserMode = val;
331 }
332 
333 
334 void
336  myUserProbability = prob;
337 }
338 
339 
340 bool
342  return myAmInUserMode;
343 }
344 
345 
346 SUMOReal
349 }
350 
351 
352 SUMOReal
354  return myUserProbability;
355 }
356 
357 
358 
359 /****************************************************************************/
360 
bool hasCurrentReroute(SUMOTime time, SUMOVehicle &veh) const
Returns whether a rerouting definition is valid for the given time and vehicle.
std::vector< MSEdge * > closed
The list of closed edges.
virtual const MSRoute & getRoute() const =0
Returns the current route.
RandomDistributor< MSEdge * > edgeProbs
The distributions of new destinations to use.
virtual bool replaceRoute(const MSRoute *route, bool onInit=false)=0
Replaces the current route by the given one.
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:93
SUMOTime myCurrentIntervalBegin
The first and the last time steps of the interval.
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:61
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:150
const RerouteInterval & getCurrentReroute(SUMOTime time, SUMOVehicle &veh) const
Returns the rerouting definition valid for the given time and vehicle.
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:461
SUMOReal getUserProbability() const
Returns the rerouting probability given by the user.
void setUserMode(bool val)
Sets whether the process is currently steered by the user.
static bool runParser(GenericSAXHandler &handler, const std::string &file)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:96
SAX-handler base for SUMO-files.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step (in s)
Definition: MSNet.cpp:500
The purpose of the edge is not known.
Definition: MSEdge.h:84
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:196
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:60
A road/street connecting two junctions.
Definition: MSEdge.h:73
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:63
Encapsulated SAX-Attributes.
bool containsAnyOf(const std::vector< MSEdge * > &edgelist) const
Definition: MSRoute.cpp:206
virtual ~MSTriggeredRerouter()
Destructor.
SUMOTime begin
The begin time these definitions are valid.
T get(MTRand *which=0) const
Draw a sample of the distribution.
std::vector< MSEdge * > myCurrentClosed
List of closed edges.
RandomDistributor< const MSRoute * > myCurrentRouteProb
new routes with probabilities
static MSEdge mySpecialDest_keepDestination
special destination values
SUMOReal getProbability() const
Returns the rerouting probability.
bool notifyEnter(SUMOVehicle &veh, MSMoveReminder::Notification reason)
Tries to reroute the vehicle.
Something on a lane to be noticed about vehicle movement.
static MSEdge mySpecialDest_terminateRoute
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.
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
std::vector< RerouteInterval > myIntervals
List of rerouting definition intervals.
bool myAmInUserMode
Information whether the current rerouting probability is the user-given.
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const std::vector< MSEdge * > &prohibited=std::vector< MSEdge * >()) const
Definition: MSNet.cpp:703
#define SUMOReal
Definition: config.h:221
static const bool gUseMesoSim
Definition: MSGlobals.h:95
virtual void 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 void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
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.
void add(SUMOReal prob, T val, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
MSTriggeredRerouter(const std::string &id, const std::vector< MSEdge * > &edges, SUMOReal prob, const std::string &file, bool off)
Constructor.
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:116