SUMO - Simulation of Urban MObility
RORouteDef.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Base class for a vehicle's route definition
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2002-2015 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 <iterator>
35 #include <algorithm>
37 #include <utils/common/ToString.h>
38 #include <utils/common/Named.h>
44 #include "ROEdge.h"
45 #include "RORoute.h"
48 #include "RORouteDef.h"
49 #include "ROVehicle.h"
50 
51 #ifdef CHECK_MEMORY_LEAKS
52 #include <foreign/nvwa/debug_new.h>
53 #endif // CHECK_MEMORY_LEAKS
54 
55 // ===========================================================================
56 // static members
57 // ===========================================================================
58 bool RORouteDef::myUsingJTRR(false);
59 
60 // ===========================================================================
61 // method definitions
62 // ===========================================================================
63 RORouteDef::RORouteDef(const std::string& id, const unsigned int lastUsed,
64  const bool tryRepair, const bool mayBeDisconnected) :
65  Named(StringUtils::convertUmlaute(id)),
66  myPrecomputed(0), myLastUsed(lastUsed), myTryRepair(tryRepair), myMayBeDisconnected(mayBeDisconnected)
67 {}
68 
69 
71  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
72  if (myRouteRefs.count(*i) == 0) {
73  delete *i;
74  }
75  }
76 }
77 
78 
79 void
81  myAlternatives.push_back(alt);
82 }
83 
84 
85 void
87  std::copy(alt->myAlternatives.begin(), alt->myAlternatives.end(),
88  back_inserter(myAlternatives));
89  std::copy(alt->myAlternatives.begin(), alt->myAlternatives.end(),
90  std::inserter(myRouteRefs, myRouteRefs.end()));
91 }
92 
93 
94 RORoute*
96  SUMOTime begin, const ROVehicle& veh) const {
97  if (myPrecomputed == 0) {
98  preComputeCurrentRoute(router, begin, veh);
99  }
100  return myPrecomputed;
101 }
102 
103 
104 void
106  SUMOTime begin, const ROVehicle& veh) const {
107  myNewRoute = false;
108  assert(myAlternatives[0]->getEdgeVector().size() > 0);
109  MsgHandler* mh = (OptionsCont::getOptions().getBool("ignore-errors") ?
111  if (myAlternatives[0]->getFirst()->prohibits(&veh)) {
113  mh->inform("Vehicle '" + veh.getID() + "' is not allowed to depart on edge '" +
114  myAlternatives[0]->getFirst()->getID() + "'.");
115  return;
116  } else if (myAlternatives[0]->getLast()->prohibits(&veh)) {
117  // this check is not strictly necessary unless myTryRepair is set.
118  // However, the error message is more helpful than "no connection found"
119  mh->inform("Vehicle '" + veh.getID() + "' is not allowed to arrive on edge '" +
120  myAlternatives[0]->getLast()->getID() + "'.");
121  return;
122  }
123  if (myTryRepair) {
124  repairCurrentRoute(router, begin, veh);
125  return;
126  }
128  || OptionsCont::getOptions().getBool("remove-loops")) {
130  } else {
131  // build a new route to test whether it is better
132  ConstROEdgeVector edges;
133  router.compute(myAlternatives[0]->getFirst(), myAlternatives[0]->getLast(), &veh, begin, edges);
134  // check whether the same route was already used
135  int cheapest = -1;
136  for (unsigned int i = 0; i < myAlternatives.size(); i++) {
137  if (edges == myAlternatives[i]->getEdgeVector()) {
138  cheapest = i;
139  break;
140  }
141  }
142  if (cheapest >= 0) {
143  myPrecomputed = myAlternatives[cheapest];
144  } else {
145  RGBColor* col = myAlternatives[0]->getColor() != 0 ? new RGBColor(*myAlternatives[0]->getColor()) : 0;
146  myPrecomputed = new RORoute(myID, 0, 1, edges, col, myAlternatives[0]->getStops());
147  myNewRoute = true;
148  }
149  }
150 }
151 
152 
153 void
155  SUMOTime begin, const ROVehicle& veh) const {
156  MsgHandler* mh = (OptionsCont::getOptions().getBool("ignore-errors") ?
158  ConstROEdgeVector oldEdges = myAlternatives[0]->getEdgeVector();
159  ConstROEdgeVector newEdges;
160  ConstROEdgeVector mandatory;
161  if (oldEdges.size() == 1) {
162  if (myUsingJTRR) {
164  router.compute(oldEdges.front(), 0, &veh, begin, newEdges);
165  } else {
166  newEdges = oldEdges;
167  }
168  } else {
169  // prepare mandatory edges
170  mandatory.push_back(oldEdges.front());
171  ConstROEdgeVector stops = veh.getStopEdges();
172  for (ConstROEdgeVector::const_iterator i = stops.begin(); i != stops.end(); ++i) {
173  if (*i != mandatory.back()) {
174  mandatory.push_back(*i);
175  }
176  }
177  if (mandatory.size() < 2 || oldEdges.back() != mandatory.back()) {
178  mandatory.push_back(oldEdges.back());
179  }
180  assert(mandatory.size() >= 2);
181  // removed prohibited
182  for (ConstROEdgeVector::iterator i = oldEdges.begin(); i != oldEdges.end();) {
183  if ((*i)->prohibits(&veh)) {
184  if (std::find(mandatory.begin(), mandatory.end(), *i) != mandatory.end()) {
185  mh->inform("Mandatory edge '" + (*i)->getID() + "' does not allow vehicle '" + veh.getID() + "'.");
186  return;
187  }
188  i = oldEdges.erase(i);
189  } else {
190  ++i;
191  }
192  }
193  // reconnect remaining edges
194  newEdges.push_back(*(oldEdges.begin()));
195  ConstROEdgeVector::iterator nextMandatory = mandatory.begin() + 1;
196  size_t lastMandatory = 0;
197  for (ConstROEdgeVector::iterator i = oldEdges.begin() + 1;
198  i != oldEdges.end() && nextMandatory != mandatory.end(); ++i) {
199  if ((*(i - 1))->isConnectedTo(*i, &veh)) {
200  newEdges.push_back(*i);
201  } else {
202  ConstROEdgeVector edges;
203  router.compute(newEdges.back(), *i, &veh, begin, edges);
204  if (edges.size() == 0) {
205  // backtrack: try to route from last mandatory edge to next mandatory edge
206  // XXX add option for backtracking in smaller increments
207  // (i.e. previous edge to edge after *i)
208  // we would then need to decide whether we have found a good
209  // tradeoff between faithfulness to the input data and detour-length
210  if (newEdges.back() != newEdges[lastMandatory]) {
211  router.compute(newEdges[lastMandatory], *nextMandatory, &veh, begin, edges);
212  }
213  if (edges.size() == 0) {
214  mh->inform("Mandatory edge '" + (*i)->getID() + "' not reachable by vehicle '" + veh.getID() + "'.");
215  return;
216  } else {
217  while (*i != *nextMandatory) {
218  ++i;
219  }
220  newEdges.erase(newEdges.begin() + lastMandatory + 1, newEdges.end());
221  }
222  }
223  std::copy(edges.begin() + 1, edges.end(), back_inserter(newEdges));
224  }
225  if (*i == *nextMandatory) {
226  nextMandatory++;
227  lastMandatory = newEdges.size() - 1;
228  }
229  }
230  }
231  if (myAlternatives[0]->getEdgeVector() != newEdges) {
232  if (!myMayBeDisconnected) {
233  WRITE_WARNING("Repaired route of vehicle '" + veh.getID() + "'.");
234  }
235  myNewRoute = true;
236  RGBColor* col = myAlternatives[0]->getColor() != 0 ? new RGBColor(*myAlternatives[0]->getColor()) : 0;
237  myPrecomputed = new RORoute(myID, 0, myAlternatives[0]->getProbability(), newEdges, col, myAlternatives[0]->getStops());
238  } else {
240  }
241 }
242 
243 
244 void
246  const ROVehicle* const veh, RORoute* current, SUMOTime begin) {
247  if (myTryRepair) {
248  if (myNewRoute) {
249  delete myAlternatives[0];
250  myAlternatives.pop_back();
251  myAlternatives.push_back(current);
252  }
253  const SUMOReal costs = router.recomputeCosts(current->getEdgeVector(), veh, begin);
254  if (costs < 0) {
255  throw ProcessError("Route '" + getID() + "' (vehicle '" + veh->getID() + "') is not valid.");
256  }
257  current->setCosts(costs);
258  return;
259  }
260  // add the route when it's new
261  if (myNewRoute) {
262  myAlternatives.push_back(current);
263  }
264  // recompute the costs and (when a new route was added) scale the probabilities
265  const SUMOReal scale = SUMOReal(myAlternatives.size() - 1) / SUMOReal(myAlternatives.size());
266  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
267  RORoute* alt = *i;
268  // recompute the costs for all routes
269  const SUMOReal newCosts = router.recomputeCosts(alt->getEdgeVector(), veh, begin);
270  if (newCosts < 0.) {
271  throw ProcessError("Route '" + current->getID() + "' (vehicle '" + veh->getID() + "') is not valid.");
272  }
273  assert(myAlternatives.size() != 0);
274  if (myNewRoute) {
275  if (*i == current) {
276  // set initial probability and costs
277  alt->setProbability((SUMOReal)(1.0 / (SUMOReal) myAlternatives.size()));
278  alt->setCosts(newCosts);
279  } else {
280  // rescale probs for all others
281  alt->setProbability(alt->getProbability() * scale);
282  }
283  }
285  }
286  assert(myAlternatives.size() != 0);
289  // remove with probability of 0 (not mentioned in Gawron)
290  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end();) {
291  if ((*i)->getProbability() == 0) {
292  delete *i;
293  i = myAlternatives.erase(i);
294  } else {
295  i++;
296  }
297  }
298  }
300  // only keep the routes with highest probability
301  sort(myAlternatives.begin(), myAlternatives.end(), ComparatorProbability());
302  for (std::vector<RORoute*>::iterator i = myAlternatives.begin() + RouteCostCalculator<RORoute, ROEdge, ROVehicle>::getCalculator().getMaxRouteNumber(); i != myAlternatives.end(); i++) {
303  delete *i;
304  }
306  // rescale probabilities
307  SUMOReal newSum = 0;
308  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
309  newSum += (*i)->getProbability();
310  }
311  assert(newSum > 0);
312  // @note newSum may be larger than 1 for numerical reasons
313  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
314  (*i)->setProbability((*i)->getProbability() / newSum);
315  }
316  }
317 
318  // find the route to use
319  SUMOReal chosen = RandHelper::rand();
320  int pos = 0;
321  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end() - 1; i++, pos++) {
322  chosen -= (*i)->getProbability();
323  if (chosen <= 0) {
324  myLastUsed = pos;
325  return;
326  }
327  }
328  myLastUsed = pos;
329 }
330 
331 
332 const ROEdge*
334  return myAlternatives[0]->getLast();
335 }
336 
337 
340  bool asAlternatives, bool withExitTimes) const {
341  if (asAlternatives) {
343  for (size_t i = 0; i != myAlternatives.size(); i++) {
344  myAlternatives[i]->writeXMLDefinition(dev, veh, true, withExitTimes);
345  }
346  dev.closeTag();
347  return dev;
348  } else {
349  return myAlternatives[myLastUsed]->writeXMLDefinition(dev, veh, false, withExitTimes);
350  }
351 }
352 
353 
354 RORouteDef*
355 RORouteDef::copyOrigDest(const std::string& id) const {
356  RORouteDef* result = new RORouteDef(id, 0, true, true);
357  RORoute* route = myAlternatives[0];
358  RGBColor* col = route->getColor() != 0 ? new RGBColor(*route->getColor()) : 0;
359  ConstROEdgeVector edges;
360  edges.push_back(route->getFirst());
361  edges.push_back(route->getLast());
362  result->addLoadedAlternative(new RORoute(id, 0, 1, edges, col, route->getStops()));
363  return result;
364 }
365 
366 
367 RORouteDef*
368 RORouteDef::copy(const std::string& id) const {
369  RORouteDef* result = new RORouteDef(id, 0, myTryRepair, myMayBeDisconnected);
370  for (std::vector<RORoute*>::const_iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
371  RORoute* route = *i;
372  RGBColor* col = route->getColor() != 0 ? new RGBColor(*route->getColor()) : 0;
373  result->addLoadedAlternative(new RORoute(id, 0, 1, route->getEdgeVector(), col, route->getStops()));
374  }
375  return result;
376 }
377 
378 
379 SUMOReal
381  SUMOReal sum = 0.;
382  for (std::vector<RORoute*>::const_iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
383  sum += (*i)->getProbability();
384  }
385  return sum;
386 }
387 
388 
389 /****************************************************************************/
SUMOTime getDepartureTime() const
Returns the time the vehicle starts at, 0 for triggered vehicles.
Definition: ROVehicle.h:112
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:71
const std::string & getID() const
Returns the id of the vehicle.
Definition: ROVehicle.h:103
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:257
bool myNewRoute
Information whether a new route was generated.
Definition: RORouteDef.h:164
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
RORouteDef * copyOrigDest(const std::string &id) const
Returns a origin-destination copy of the route definition.
Definition: RORouteDef.cpp:355
const bool myTryRepair
Definition: RORouteDef.h:166
Some static methods for string processing.
Definition: StringUtils.h:45
void addAlternative(SUMOAbstractRouter< ROEdge, ROVehicle > &router, const ROVehicle *const, RORoute *current, SUMOTime begin)
Adds an alternative to the list of routes.
Definition: RORouteDef.cpp:245
RORoute * buildCurrentRoute(SUMOAbstractRouter< ROEdge, ROVehicle > &router, SUMOTime begin, const ROVehicle &veh) const
Triggers building of the complete route (via preComputeCurrentRoute) or returns precomputed route...
Definition: RORouteDef.cpp:95
void addAlternativeDef(const RORouteDef *alternative)
Adds an alternative loaded from the file.
Definition: RORouteDef.cpp:86
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
const ConstROEdgeVector & getEdgeVector() const
Returns the list of edges this route consists of.
Definition: RORoute.h:155
void setProbability(SUMOReal prob)
Sets the probability of the route.
Definition: RORoute.cpp:80
void preComputeCurrentRoute(SUMOAbstractRouter< ROEdge, ROVehicle > &router, SUMOTime begin, const ROVehicle &veh) const
Builds the complete route (or chooses her from the list of alternatives, when existing) ...
Definition: RORouteDef.cpp:105
void repairCurrentRoute(SUMOAbstractRouter< ROEdge, ROVehicle > &router, SUMOTime begin, const ROVehicle &veh) const
Builds the complete route (or chooses her from the list of alternatives, when existing) ...
Definition: RORouteDef.cpp:154
std::vector< const ROEdge * > ConstROEdgeVector
Definition: ROEdge.h:59
static bool myUsingJTRR
Definition: RORouteDef.h:169
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
RORoute * myPrecomputed
precomputed route for out-of-order computation
Definition: RORouteDef.h:152
const std::string & getID() const
Returns the id.
Definition: Named.h:60
const bool myMayBeDisconnected
Definition: RORouteDef.h:167
A vehicle as used by router.
Definition: ROVehicle.h:60
const ROEdge * getLast() const
Returns the last edge in the route.
Definition: RORoute.h:103
std::set< RORoute * > myRouteRefs
Routes which are deleted someplace else.
Definition: RORouteDef.h:161
OutputDevice & writeXMLDefinition(OutputDevice &dev, const ROVehicle *const veh, bool asAlternatives, bool withExitTimes) const
Saves the built route / route alternatives.
Definition: RORouteDef.cpp:339
const RGBColor * getColor() const
Returns this route's color.
Definition: RORoute.h:163
SUMOReal getProbability() const
Returns the probability the driver will take this route with.
Definition: RORoute.h:123
void setCosts(SUMOReal costs)
Sets the costs of the route.
Definition: RORoute.cpp:74
Abstract base class providing static factory method.
const ROEdge * getDestination() const
Definition: RORouteDef.cpp:333
const ROEdge * getFirst() const
Returns the first edge in the route.
Definition: RORoute.h:94
A basic edge for routing applications.
Definition: ROEdge.h:73
Base class for objects which have an id.
Definition: Named.h:45
virtual ~RORouteDef()
Destructor.
Definition: RORouteDef.cpp:70
unsigned int myLastUsed
Index of the route used within the last step.
Definition: RORouteDef.h:155
std::string myID
The name of the object.
Definition: Named.h:128
const ConstROEdgeVector & getStopEdges() const
Definition: ROVehicle.h:124
RORouteDef * copy(const std::string &id) const
Returns a deep copy of the route definition.
Definition: RORouteDef.cpp:368
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:89
Base class for a vehicle's route definition.
Definition: RORouteDef.h:63
int SUMOTime
Definition: SUMOTime.h:43
void addLoadedAlternative(RORoute *alternative)
Adds a single alternative loaded from the file An alternative may also be generated during DUA...
Definition: RORouteDef.cpp:80
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
virtual SUMOReal recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime) const =0
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:218
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...
static RouteCostCalculator< R, E, V > & getCalculator()
RORouteDef(const std::string &id, const unsigned int lastUsed, const bool tryRepair, const bool mayBeDisconnected)
Constructor.
Definition: RORouteDef.cpp:63
std::vector< RORoute * > myAlternatives
The alternatives.
Definition: RORouteDef.h:158
SUMOReal getOverallProb() const
Returns the sum of the probablities of the contained routes.
Definition: RORouteDef.cpp:380
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the list of stops this route contains.
Definition: RORoute.h:184
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
A complete router's route.
Definition: RORoute.h:62