SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSDevice_Routing.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A device that performs vehicle rerouting based on current edge speeds
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
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 "MSDevice_Routing.h"
34 #include <microsim/MSNet.h>
35 #include <microsim/MSLane.h>
36 #include <microsim/MSEdge.h>
37 #include <microsim/MSEdgeControl.h>
42 
43 #ifdef CHECK_MEMORY_LEAKS
44 #include <foreign/nvwa/debug_new.h>
45 #endif // CHECK_MEMORY_LEAKS
46 
47 
48 // ===========================================================================
49 // static member variables
50 // ===========================================================================
51 std::map<const MSEdge*, SUMOReal> MSDevice_Routing::myEdgeEfforts;
56 std::map<std::pair<const MSEdge*, const MSEdge*>, const MSRoute*> MSDevice_Routing::myCachedRoutes;
57 
58 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
62 // ---------------------------------------------------------------------------
63 // static initialisation methods
64 // ---------------------------------------------------------------------------
65 void
68  oc.addOptionSubTopic("Routing");
69 
70  oc.doRegister("device.rerouting.probability", new Option_Float(0.));
71  oc.addSynonyme("device.rerouting.probability", "device.routing.probability", true);
72  oc.addDescription("device.rerouting.probability", "Routing", "The probability for a vehicle to have a routing device");
73 
74  oc.doRegister("device.rerouting.explicit", new Option_String());
75  oc.addSynonyme("device.rerouting.explicit", "device.routing.knownveh", true);
76  oc.addDescription("device.rerouting.explicit", "Routing", "Assign a device to named vehicles");
77 
78  oc.doRegister("device.rerouting.deterministic", new Option_Bool(false));
79  oc.addSynonyme("device.rerouting.deterministic", "device.routing.deterministic", true);
80  oc.addDescription("device.rerouting.deterministic", "Routing", "The devices are set deterministic using a fraction of 1000");
81 
82  oc.doRegister("device.rerouting.period", new Option_String("0", "TIME"));
83  oc.addSynonyme("device.rerouting.period", "device.routing.period", true);
84  oc.addDescription("device.rerouting.period", "Routing", "The period with which the vehicle shall be rerouted");
85 
86  oc.doRegister("device.rerouting.pre-period", new Option_String("0", "TIME"));
87  oc.addSynonyme("device.rerouting.pre-period", "device.routing.pre-period", true);
88  oc.addDescription("device.rerouting.pre-period", "Routing", "The rerouting period before depart");
89 
90  oc.doRegister("device.rerouting.adaptation-weight", new Option_Float(.5));
91  oc.addSynonyme("device.rerouting.adaptation-weight", "device.routing.adaptation-weight", true);
92  oc.addDescription("device.rerouting.adaptation-weight", "Routing", "The weight of prior edge weights.");
93 
94  oc.doRegister("device.rerouting.adaptation-interval", new Option_String("1", "TIME"));
95  oc.addSynonyme("device.rerouting.adaptation-interval", "device.routing.adaptation-interval", true);
96  oc.addDescription("device.rerouting.adaptation-interval", "Routing", "The interval for updating the edge weights.");
97 
98  oc.doRegister("device.rerouting.with-taz", new Option_Bool(false));
99  oc.addSynonyme("device.rerouting.with-taz", "device.routing.with-taz", true);
100  oc.addDescription("device.rerouting.with-taz", "Routing", "Use zones (districts) as routing end points");
101 
103  myEdgeEfforts.clear();
104 }
105 
106 
107 void
108 MSDevice_Routing::buildVehicleDevices(SUMOVehicle& v, std::vector<MSDevice*> &into) {
110  bool needRerouting = v.getParameter().wasSet(VEHPARS_FORCE_REROUTE);
111  if (!needRerouting && oc.getFloat("device.rerouting.probability") == 0 && !oc.isSet("device.rerouting.explicit")) {
112  // no route computation is modelled
113  return;
114  }
115  // route computation is enabled
116  bool haveByNumber = false;
117  if (oc.getBool("device.rerouting.deterministic")) {
118  haveByNumber = MSNet::getInstance()->getVehicleControl().isInQuota(oc.getFloat("device.rerouting.probability"));
119  } else {
120  haveByNumber = RandHelper::rand() <= oc.getFloat("device.rerouting.probability");
121  }
122  bool haveByName = oc.isSet("device.rerouting.explicit") && OptionsCont::getOptions().isInStringVector("device.rerouting.explicit", v.getID());
123  myWithTaz = oc.getBool("device.rerouting.with-taz");
124  if (needRerouting || haveByNumber || haveByName) {
125  // build the device
126  MSDevice_Routing* device = new MSDevice_Routing(v, "routing_" + v.getID(),
127  string2time(oc.getString("device.rerouting.period")),
128  string2time(oc.getString("device.rerouting.pre-period")));
129  into.push_back(device);
130  // initialise edge efforts if not done before
131  if (myEdgeEfforts.size() == 0) {
132  const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges();
133  for (std::vector<MSEdge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
134  myEdgeEfforts[*i] = (*i)->getCurrentTravelTime();
135  }
136  }
137  // make the weights be updated
138  if (myEdgeWeightSettingCommand == 0) {
142  myAdaptationWeight = oc.getFloat("device.rerouting.adaptation-weight");
143  myAdaptationInterval = string2time(oc.getString("device.rerouting.adaptation-interval"));
144  }
145  if (myWithTaz) {
146  if (MSEdge::dictionary(v.getParameter().fromTaz + "-source") == 0) {
147  WRITE_ERROR("Source district '" + v.getParameter().fromTaz + "' not known when rerouting '" + v.getID() + "'!");
148  return;
149  }
150  if (MSEdge::dictionary(v.getParameter().toTaz + "-sink") == 0) {
151  WRITE_ERROR("Destination district '" + v.getParameter().toTaz + "' not known when rerouting '" + v.getID() + "'!");
152  return;
153  }
154  }
155  }
156 }
157 
158 
159 // ---------------------------------------------------------------------------
160 // MSDevice_Routing-methods
161 // ---------------------------------------------------------------------------
162 MSDevice_Routing::MSDevice_Routing(SUMOVehicle& holder, const std::string& id,
163  SUMOTime period, SUMOTime preInsertionPeriod)
164  : MSDevice(holder, id), myPeriod(period), myPreInsertionPeriod(preInsertionPeriod), myRerouteCommand(0) {
165  if (myWithTaz) {
170  }
171 }
172 
173 
175  // make the rerouting command invalid if there is one
176  if (myRerouteCommand != 0) {
178  }
179 }
180 
181 
182 bool
185  if (myRerouteCommand != 0) { // clean up pre depart rerouting
186  if (myPreInsertionPeriod > 0) {
188  }
189  myRerouteCommand = 0;
190  }
191  if (!myWithTaz) {
192  wrappedRerouteCommandExecute(MSNet::getInstance()->getCurrentTimeStep());
193  }
194  // build repetition trigger if routing shall be done more often
195  if (myPeriod > 0) {
198  myRerouteCommand, myPeriod + MSNet::getInstance()->getCurrentTimeStep(),
200  }
201  }
202  return false;
203 }
204 
205 
206 SUMOTime
208  const MSEdge* source = MSEdge::dictionary(myHolder.getParameter().fromTaz + "-source");
209  const MSEdge* dest = MSEdge::dictionary(myHolder.getParameter().toTaz + "-sink");
210  if (source && dest) {
211  const std::pair<const MSEdge*, const MSEdge*> key = std::make_pair(source, dest);
212  if (myCachedRoutes.find(key) == myCachedRoutes.end()) {
214  router(MSEdge::dictSize(), true, this, &MSDevice_Routing::getEffort);
215  myHolder.reroute(currentTime, router, true);
216  myCachedRoutes[key] = &myHolder.getRoute();
218  } else {
220  }
221  }
222  return myPreInsertionPeriod;
223 }
224 
225 
226 SUMOTime
229  router(MSEdge::dictSize(), true, this, &MSDevice_Routing::getEffort);
230  myHolder.reroute(currentTime, router);
231  return myPeriod;
232 }
233 
234 
235 SUMOReal
236 MSDevice_Routing::getEffort(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal) const {
237  if (myEdgeEfforts.find(e) != myEdgeEfforts.end()) {
238  return MAX2(myEdgeEfforts.find(e)->second, e->getLength() / v->getMaxSpeed());
239  }
240  return 0;
241 }
242 
243 
244 SUMOTime
246  std::map<std::pair<const MSEdge*, const MSEdge*>, const MSRoute*>::iterator it = myCachedRoutes.begin();
247  for (; it != myCachedRoutes.end(); ++it) {
248  it->second->release();
249  }
250  myCachedRoutes.clear();
251  SUMOReal newWeight = (SUMOReal)(1. - myAdaptationWeight);
252  const std::vector<MSEdge*> &edges = MSNet::getInstance()->getEdgeControl().getEdges();
253  for (std::vector<MSEdge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
254  myEdgeEfforts[*i] = myEdgeEfforts[*i] * myAdaptationWeight + (*i)->getCurrentTravelTime() * newWeight;
255  }
256  return myAdaptationInterval;
257 }
258 
259 
260 
261 /****************************************************************************/
262