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.sourceforge.net/
12 // Copyright (C) 2001-2012 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), MSMoveReminder(), SUMOSAXHandler(file),
77  myProbability(prob), myUserProbability(prob), myAmInUserMode(false) {
78  // read in the trigger description
79  if (file != "" && !XMLSubSys::runParser(*this, file)) {
80  throw ProcessError();
81  }
82  // build actors
83  for (std::vector<MSEdge*>::const_iterator j = edges.begin(); j != edges.end(); ++j) {
84 #ifdef HAVE_INTERNAL
86  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(**j);
87  s->addDetector(this);
88  continue;
89  }
90 #endif
91  const std::vector<MSLane*>& destLanes = (*j)->getLanes();
92  for (std::vector<MSLane*>::const_iterator i = destLanes.begin(); i != destLanes.end(); ++i) {
93  (*i)->addMoveReminder(this);
94  }
95  }
96  if (off) {
97  setUserMode(true);
99  }
100 }
101 
102 
104 }
105 
106 // ------------ loading begin
107 void
109  const SUMOSAXAttributes& attrs) {
110  if (element == SUMO_TAG_INTERVAL) {
111  bool ok = true;
114  }
115  if (element == SUMO_TAG_DEST_PROB_REROUTE) {
116  // by giving probabilities of new destinations
117  // get the destination edge
118  std::string dest = attrs.getStringSecure(SUMO_ATTR_ID, "");
119  if (dest == "") {
120  throw ProcessError("MSTriggeredRerouter " + getID() + ": No destination edge id given.");
121  }
122  MSEdge* to = MSEdge::dictionary(dest);
123  if (to == 0) {
124  if (dest == "keepDestination") {
126  } else if (dest == "terminateRoute") {
128  } else {
129  throw ProcessError("MSTriggeredRerouter " + getID() + ": Destination edge '" + dest + "' is not known.");
130  }
131  }
132  // get the probability to reroute
133  bool ok = true;
134  SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
135  if (!ok) {
136  throw ProcessError();
137  }
138  if (prob < 0) {
139  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for destination '" + dest + "' is negative (must not).");
140  }
141  // add
142  myCurrentEdgeProb.add(prob, to);
143  }
144 
145  if (element == SUMO_TAG_CLOSING_REROUTE) {
146  // by closing
147  std::string closed_id = attrs.getStringSecure(SUMO_ATTR_ID, "");
148  if (closed_id == "") {
149  throw ProcessError("MSTriggeredRerouter " + getID() + ": closed edge id given.");
150  }
151  MSEdge* closed = MSEdge::dictionary(closed_id);
152  if (closed == 0) {
153  throw ProcessError("MSTriggeredRerouter " + getID() + ": Edge '" + closed_id + "' to close is not known.");
154  }
155  myCurrentClosed.push_back(closed);
156  }
157 
158  if (element == SUMO_TAG_ROUTE_PROB_REROUTE) {
159  // by explicit rerouting using routes
160  // check if route exists
161  std::string routeStr = attrs.getStringSecure(SUMO_ATTR_ID, "");
162  if (routeStr == "") {
163  throw ProcessError("MSTriggeredRerouter " + getID() + ": No route id given.");
164  }
165  const MSRoute* route = MSRoute::dictionary(routeStr);
166  if (route == 0) {
167  throw ProcessError("MSTriggeredRerouter " + getID() + ": Route '" + routeStr + "' does not exist.");
168  }
169 
170  // get the probability to reroute
171  bool ok = true;
172  SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, getID().c_str(), ok, 1.);
173  if (!ok) {
174  throw ProcessError();
175  }
176  if (prob < 0) {
177  throw ProcessError("MSTriggeredRerouter " + getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
178  }
179  // add
180  myCurrentRouteProb.add(prob, route);
181  }
182 }
183 
184 
185 void
187  if (element == SUMO_TAG_INTERVAL) {
188  RerouteInterval ri;
191  ri.closed = myCurrentClosed;
194  myCurrentClosed.clear();
197  myIntervals.push_back(ri);
198  }
199 }
200 
201 
202 // ------------ loading end
203 
204 
205 bool
207  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
208  const MSRoute& route = veh.getRoute();
209  while (i != myIntervals.end()) {
210  if ((*i).begin <= time && (*i).end >= time) {
211  if (
212  // affected by closingReroute, possibly combined with destProbReroute (route prob makes no sense)
213  route.containsAnyOf((*i).closed) ||
214  // no closingReroute but destProbReroute or routeProbReroute
215  ((*i).closed.size() == 0 && (*i).edgeProbs.getOverallProb() + (*i).routeProbs.getOverallProb() > 0)) {
216  return true;
217  }
218  }
219  i++;
220  }
221  return false;
222 }
223 
224 
225 bool
227  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
228  while (i != myIntervals.end()) {
229  if ((*i).begin <= time && (*i).end >= time) {
230  if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || (*i).closed.size() != 0) {
231  return true;
232  }
233  }
234  i++;
235  }
236  return false;
237 }
238 
239 
242  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
243  const MSRoute& route = veh.getRoute();
244  while (i != myIntervals.end()) {
245  if ((*i).begin <= time && (*i).end >= time) {
246  if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || route.containsAnyOf((*i).closed)) {
247  return *i;
248  }
249  }
250  i++;
251  }
252  throw 1;
253 }
254 
255 
258  std::vector<RerouteInterval>::const_iterator i = myIntervals.begin();
259  while (i != myIntervals.end()) {
260  if ((*i).edgeProbs.getOverallProb() != 0 || (*i).routeProbs.getOverallProb() != 0 || (*i).closed.size() != 0) {
261  return *i;
262  }
263  i++;
264  }
265  throw 1;
266 }
267 
268 
269 
270 bool
273  return false;
274  }
275  // check whether the vehicle shall be rerouted
277  if (!hasCurrentReroute(time, veh)) {
278  return false;
279  }
280 
282  if (RandHelper::rand() > prob) {
283  return false;
284  }
285 
286  // get vehicle params
287  const MSRoute& route = veh.getRoute();
288  const MSEdge* lastEdge = route.getLastEdge();
289  // get rerouting params
290  const MSTriggeredRerouter::RerouteInterval& rerouteDef = getCurrentReroute(time, veh);
291  const MSRoute* newRoute = rerouteDef.routeProbs.getOverallProb() > 0 ? rerouteDef.routeProbs.get() : 0;
292  // we will use the route if given rather than calling our own dijsktra...
293  if (newRoute != 0) {
294  veh.replaceRoute(newRoute);
295  return false;
296  }
297  const MSEdge* newEdge = lastEdge;
298  // ok, try using a new destination
299  const bool destUnreachable = std::find(rerouteDef.closed.begin(), rerouteDef.closed.end(), lastEdge) != rerouteDef.closed.end();
300  // if we have a closingReroute, only assign new destinations to vehicles which cannot reach their original destination
301  if (rerouteDef.closed.size() == 0 || destUnreachable) {
302  newEdge = rerouteDef.edgeProbs.getOverallProb() > 0 ? rerouteDef.edgeProbs.get() : route.getLastEdge();
303  if (newEdge == &mySpecialDest_terminateRoute) {
304  newEdge = veh.getEdge();
305  } else if (newEdge == &mySpecialDest_keepDestination || newEdge == lastEdge) {
306  if (destUnreachable) {
307  WRITE_WARNING("Cannot keep destination for vehicle '" + veh.getID() + "' due to closed edges. Terminating route.");
308  newEdge = veh.getEdge();
309  } else {
310  newEdge = lastEdge;
311  }
312  } else if (newEdge == 0) {
313  assert(false); // this should never happen
314  newEdge = veh.getEdge();
315  }
316  }
317  // we have a new destination, let's replace the vehicle route
318  std::vector<const MSEdge*> edges;
320  veh.getEdge(), newEdge, &veh, MSNet::getInstance()->getCurrentTimeStep(), edges);
321  veh.replaceRouteEdges(edges);
322  return false;
323 }
324 
325 
326 void
328  myAmInUserMode = val;
329 }
330 
331 
332 void
334  myUserProbability = prob;
335 }
336 
337 
338 bool
340  return myAmInUserMode;
341 }
342 
343 
344 SUMOReal
347 }
348 
349 
350 SUMOReal
352  return myUserProbability;
353 }
354 
355 
356 
357 /****************************************************************************/
358