SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RORouteDef.cpp
Go to the documentation of this file.
1 /****************************************************************************/
8 // Base class for a vehicle's route definition
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
11 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
12 /****************************************************************************/
13 //
14 // This file is part of SUMO.
15 // SUMO is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <string>
33 #include <iterator>
34 #include <algorithm>
36 #include <utils/common/ToString.h>
37 #include <utils/common/Named.h>
43 #include "ROEdge.h"
44 #include "RORoute.h"
46 #include "ReferencedItem.h"
47 #include "RORouteDef.h"
48 #include "ROVehicle.h"
49 #include "ROCostCalculator.h"
50 
51 #ifdef CHECK_MEMORY_LEAKS
52 #include <foreign/nvwa/debug_new.h>
53 #endif // CHECK_MEMORY_LEAKS
54 
55 
56 // ===========================================================================
57 // method definitions
58 // ===========================================================================
59 RORouteDef::RORouteDef(const std::string& id, const unsigned int lastUsed,
60  const bool tryRepair) :
61  ReferencedItem(), Named(StringUtils::convertUmlaute(id)),
62  myPrecomputed(0), myLastUsed(lastUsed), myTryRepair(tryRepair)
63 {}
64 
65 
67  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
68  delete *i;
69  }
70 }
71 
72 
73 void
75  myAlternatives.push_back(alt);
76 }
77 
78 
79 void
81  std::copy(alt->myAlternatives.begin(), alt->myAlternatives.end(),
82  back_inserter(myAlternatives));
83 }
84 
85 
86 RORoute*
88  SUMOTime begin, const ROVehicle& veh) const {
89  if (myPrecomputed == 0) {
90  preComputeCurrentRoute(router, begin, veh);
91  }
92  return myPrecomputed;
93 }
94 
95 
96 void
98  SUMOTime begin, const ROVehicle& veh) const {
99  myNewRoute = false;
100  assert(myAlternatives[0]->getEdgeVector().size() > 0);
101  MsgHandler* mh = (OptionsCont::getOptions().getBool("ignore-errors") ?
103  if (myAlternatives[0]->getFirst()->prohibits(&veh)) {
105  mh->inform("Vehicle '" + veh.getID() + "' is not allowed to depart on edge '" +
106  myAlternatives[0]->getFirst()->getID() + "'.");
107  return;
108  } else if (myAlternatives[0]->getLast()->prohibits(&veh)) {
109  // this check is not strictly necessary unless myTryRepair is set.
110  // However, the error message is more helpful than "no connection found"
111  mh->inform("Vehicle '" + veh.getID() + "' is not allowed to arrive on edge '" +
112  myAlternatives[0]->getLast()->getID() + "'.");
113  return;
114  }
115  if (myTryRepair) {
116  repairCurrentRoute(router, begin, veh);
117  return;
118  }
119  if (ROCostCalculator::getCalculator().skipRouteCalculation()) {
121  } else {
122  // build a new route to test whether it is better
123  std::vector<const ROEdge*> edges;
124  router.compute(myAlternatives[0]->getFirst(), myAlternatives[0]->getLast(), &veh, begin, edges);
125  // check whether the same route was already used
126  int cheapest = -1;
127  for (unsigned int i = 0; i < myAlternatives.size(); i++) {
128  if (edges == myAlternatives[i]->getEdgeVector()) {
129  cheapest = i;
130  break;
131  }
132  }
133  if (cheapest >= 0) {
134  myPrecomputed = myAlternatives[cheapest];
135  } else {
136  RGBColor* col = myAlternatives[0]->getColor() != 0 ? new RGBColor(*myAlternatives[0]->getColor()) : 0;
137  myPrecomputed = new RORoute(myID, 0, 1, edges, col);
138  myNewRoute = true;
139  }
140  }
141 }
142 
143 
144 void
146  SUMOTime begin, const ROVehicle& veh) const {
147  MsgHandler* mh = (OptionsCont::getOptions().getBool("ignore-errors") ?
149  std::vector<const ROEdge*> oldEdges = myAlternatives[0]->getEdgeVector();
150  std::vector<const ROEdge*> newEdges;
151  std::vector<const ROEdge*> mandatory;
152  if (oldEdges.size() == 1) {
154  router.compute(oldEdges.front(), oldEdges.front(), &veh, begin, newEdges);
155  } else {
156  // prepare mandatory edges
157  mandatory.push_back(oldEdges.front());
158  /*XXX add stop edges to the list of mandatory edges (ticket #988)
159  std::vector<const ROEdge*> stops = veh.getStopEdges();
160  for (std::vector<const ROEdge*>::const_iterator i = stops.begin(); i != stops.end(); ++i) {
161  if (*i != mandatory.back()) {
162  mandatory.push_back(*i);
163  }
164  }
165  */
166  if (mandatory.size() < 2 || oldEdges.back() != mandatory.back()) {
167  mandatory.push_back(oldEdges.back());
168  }
169  assert(mandatory.size() >= 2);
170  // removed prohibited
171  for (std::vector<const ROEdge*>::iterator i = oldEdges.begin(); i != oldEdges.end();) {
172  if ((*i)->prohibits(&veh)) {
173  if (std::find(mandatory.begin(), mandatory.end(), *i) != mandatory.end()) {
174  mh->inform("Stop edge '" + (*i)->getID() + "' does not allow vehicle '" + veh.getID() + "'.");
175  return;
176  }
177  i = oldEdges.erase(i);
178  } else {
179  ++i;
180  }
181  }
182  // reconnect remaining edges
183  newEdges.push_back(*(oldEdges.begin()));
184  std::vector<const ROEdge*>::iterator nextMandatory = mandatory.begin() + 1;
185  std::vector<const ROEdge*>::iterator lastMandatory = newEdges.begin();
186  for (std::vector<const ROEdge*>::iterator i = oldEdges.begin() + 1; i != oldEdges.end(); ++i) {
187  if ((*(i - 1))->isConnectedTo(*i)) {
189  newEdges.push_back(*i);
190  } else {
191  std::vector<const ROEdge*> edges;
192  router.compute(newEdges.back(), *i, &veh, begin, edges);
193  if (edges.size() == 0) {
194  if (*i == *nextMandatory) {
195  // fallback: try to route from last mandatory edge
196  if (newEdges.back() != *lastMandatory) {
197  router.compute(*lastMandatory, *nextMandatory, &veh, begin, edges);
198  }
199  if (edges.size() == 0) {
200  mh->inform("Mandatory edge '" + (*i)->getID() + "' not reachable by vehicle '" + veh.getID() + "'.");
201  return;
202  } else {
203  newEdges.erase(lastMandatory + 1, newEdges.end());
204  std::copy(edges.begin() + 1, edges.end(), back_inserter(newEdges));
205  }
206  }
207  } else {
208  std::copy(edges.begin() + 1, edges.end(), back_inserter(newEdges));
209  }
210  if (*i == *nextMandatory) {
211  nextMandatory++;
212  lastMandatory = i;
213  }
214  }
215  }
216  }
217  if (myAlternatives[0]->getEdgeVector() != newEdges) {
218  WRITE_MESSAGE("Repaired route of vehicle '" + veh.getID() + "'.");
219  myNewRoute = true;
220  RGBColor* col = myAlternatives[0]->getColor() != 0 ? new RGBColor(*myAlternatives[0]->getColor()) : 0;
221  myPrecomputed = new RORoute(myID, 0, 1, newEdges, col);
222  } else {
224  }
225 }
226 
227 
228 void
230  const ROVehicle* const veh, RORoute* current, SUMOTime begin) {
231  if (myTryRepair) {
232  if (myNewRoute) {
233  delete myAlternatives[0];
234  myAlternatives.pop_back();
235  myAlternatives.push_back(current);
236  }
237  const SUMOReal costs = router.recomputeCosts(current->getEdgeVector(), veh, begin);
238  if (costs < 0) {
239  throw ProcessError("Route '" + getID() + "' (vehicle '" + veh->getID() + "') is not valid.");
240  }
241  current->setCosts(costs);
242  return;
243  }
244  // add the route when it's new
245  if (myNewRoute) {
246  myAlternatives.push_back(current);
247  }
248  // recompute the costs and (when a new route was added) scale the probabilities
249  const SUMOReal scale = SUMOReal(myAlternatives.size() - 1) / SUMOReal(myAlternatives.size());
250  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
251  RORoute* alt = *i;
252  // recompute the costs for all routes
253  const SUMOReal newCosts = router.recomputeCosts(alt->getEdgeVector(), veh, begin);
254  if (newCosts < 0.) {
255  throw ProcessError("Route '" + current->getID() + "' (vehicle '" + veh->getID() + "') is not valid.");
256  }
257  assert(myAlternatives.size() != 0);
258  if (myNewRoute) {
259  if (*i == current) {
260  // set initial probability and costs
261  alt->setProbability((SUMOReal)(1.0 / (SUMOReal) myAlternatives.size()));
262  alt->setCosts(newCosts);
263  } else {
264  // rescale probs for all others
265  alt->setProbability(alt->getProbability() * scale);
266  }
267  }
269  }
270  assert(myAlternatives.size() != 0);
272  if (!ROCostCalculator::getCalculator().keepRoutes()) {
273  // remove with probability of 0 (not mentioned in Gawron)
274  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end();) {
275  if ((*i)->getProbability() == 0) {
276  delete *i;
277  i = myAlternatives.erase(i);
278  } else {
279  i++;
280  }
281  }
282  }
284  // only keep the routes with highest probability
285  sort(myAlternatives.begin(), myAlternatives.end(), ComparatorProbability());
286  for (std::vector<RORoute*>::iterator i = myAlternatives.begin() + ROCostCalculator::getCalculator().getMaxRouteNumber(); i != myAlternatives.end(); i++) {
287  delete *i;
288  }
290  // rescale probabilities
291  SUMOReal newSum = 0;
292  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
293  newSum += (*i)->getProbability();
294  }
295  assert(newSum > 0);
296  // @note newSum may be larger than 1 for numerical reasons
297  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
298  (*i)->setProbability((*i)->getProbability() / newSum);
299  }
300  }
301 
302  // find the route to use
303  SUMOReal chosen = RandHelper::rand();
304  int pos = 0;
305  for (std::vector<RORoute*>::iterator i = myAlternatives.begin(); i != myAlternatives.end() - 1; i++, pos++) {
306  chosen -= (*i)->getProbability();
307  if (chosen <= 0) {
308  myLastUsed = pos;
309  return;
310  }
311  }
312  myLastUsed = pos;
313 }
314 
315 
316 const ROEdge*
318  return myAlternatives[0]->getLast();
319 }
320 
321 
324  bool asAlternatives, bool withExitTimes) const {
325  if (asAlternatives) {
327  for (size_t i = 0; i != myAlternatives.size(); i++) {
328  myAlternatives[i]->writeXMLDefinition(dev, veh, true, withExitTimes);
329  }
330  dev.closeTag();
331  return dev;
332  } else {
333  return myAlternatives[myLastUsed]->writeXMLDefinition(dev, veh, false, withExitTimes);
334  }
335 }
336 
337 
338 RORouteDef*
339 RORouteDef::copyOrigDest(const std::string& id) const {
340  RORouteDef* result = new RORouteDef(id, 0, true);
341  RORoute* route = myAlternatives[0];
342  RGBColor* col = route->getColor() != 0 ? new RGBColor(*route->getColor()) : 0;
343  std::vector<const ROEdge*> edges;
344  edges.push_back(route->getFirst());
345  edges.push_back(route->getLast());
346  result->addLoadedAlternative(new RORoute(id, 0, 1, edges, col));
347  return result;
348 }
349 
350 
351 RORouteDef*
352 RORouteDef::copy(const std::string& id) const {
353  RORouteDef* result = new RORouteDef(id, 0, myTryRepair);
354  for (std::vector<RORoute*>::const_iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
355  RORoute* route = *i;
356  RGBColor* col = route->getColor() != 0 ? new RGBColor(*route->getColor()) : 0;
357  result->addLoadedAlternative(new RORoute(id, 0, 1, route->getEdgeVector(), col));
358  }
359  return result;
360 }
361 
362 
363 SUMOReal
365  SUMOReal sum = 0.;
366  for (std::vector<RORoute*>::const_iterator i = myAlternatives.begin(); i != myAlternatives.end(); i++) {
367  sum += (*i)->getProbability();
368  }
369  return sum;
370 }
371 
372 
373 /****************************************************************************/