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-2014 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