SUMO - Simulation of Urban MObility
MSDevice_Routing.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2007-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
19 // A device that performs vehicle rerouting based on current edge speeds
20 /****************************************************************************/
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <microsim/MSNet.h>
28 #include <microsim/MSLane.h>
29 #include <microsim/MSEdge.h>
30 #include <microsim/MSEdgeControl.h>
32 #include <microsim/MSGlobals.h>
41 #include <utils/vehicle/CHRouter.h>
43 #include "MSRoutingEngine.h"
44 #include "MSDevice_Routing.h"
45 
46 
47 // ===========================================================================
48 // method definitions
49 // ===========================================================================
50 // ---------------------------------------------------------------------------
51 // static initialisation methods
52 // ---------------------------------------------------------------------------
53 void
55  insertDefaultAssignmentOptions("rerouting", "Routing", oc);
56 
57  oc.doRegister("device.rerouting.period", new Option_String("0", "TIME"));
58  oc.addSynonyme("device.rerouting.period", "device.routing.period", true);
59  oc.addDescription("device.rerouting.period", "Routing", "The period with which the vehicle shall be rerouted");
60 
61  oc.doRegister("device.rerouting.pre-period", new Option_String("60", "TIME"));
62  oc.addSynonyme("device.rerouting.pre-period", "device.routing.pre-period", true);
63  oc.addDescription("device.rerouting.pre-period", "Routing", "The rerouting period before depart");
64 
65  oc.doRegister("device.rerouting.adaptation-weight", new Option_Float(.5));
66  oc.addSynonyme("device.rerouting.adaptation-weight", "device.routing.adaptation-weight", true);
67  oc.addDescription("device.rerouting.adaptation-weight", "Routing", "The weight of prior edge weights for exponential moving average");
68 
69  oc.doRegister("device.rerouting.adaptation-steps", new Option_Integer(0));
70  oc.addSynonyme("device.rerouting.adaptation-steps", "device.routing.adaptation-steps", true);
71  oc.addDescription("device.rerouting.adaptation-steps", "Routing", "The number of steps for moving average weight of prior edge weights");
72 
73  oc.doRegister("device.rerouting.adaptation-interval", new Option_String("1", "TIME"));
74  oc.addSynonyme("device.rerouting.adaptation-interval", "device.routing.adaptation-interval", true);
75  oc.addDescription("device.rerouting.adaptation-interval", "Routing", "The interval for updating the edge weights");
76 
77  oc.doRegister("device.rerouting.with-taz", new Option_Bool(false));
78  oc.addSynonyme("device.rerouting.with-taz", "device.routing.with-taz", true);
79  oc.addSynonyme("device.rerouting.with-taz", "with-taz");
80  oc.addDescription("device.rerouting.with-taz", "Routing", "Use zones (districts) as routing start- and endpoints");
81 
82  oc.doRegister("device.rerouting.init-with-loaded-weights", new Option_Bool(false));
83  oc.addDescription("device.rerouting.init-with-loaded-weights", "Routing", "Use weight files given with option --weight-files for initializing edge weights");
84 
85  oc.doRegister("device.rerouting.threads", new Option_Integer(0));
86  oc.addDescription("device.rerouting.threads", "Routing", "The number of parallel execution threads used for rerouting");
87 
88  oc.doRegister("device.rerouting.synchronize", new Option_Bool(false));
89  oc.addDescription("device.rerouting.synchronize", "Routing", "Let rerouting happen at the same time for all vehicles");
90 
91  oc.doRegister("device.rerouting.output", new Option_FileName());
92  oc.addDescription("device.rerouting.output", "Routing", "Save adapting weights to FILE");
93 }
94 
95 
96 bool
98  bool ok = true;
99  if (oc.getInt("device.rerouting.adaptation-steps") > 0 && !oc.isDefault("device.rerouting.adaptation-weight")) {
100  WRITE_ERROR("Only one of the options 'device.rerouting.adaptation-steps' or 'device.rerouting.adaptation-weight' may be given.");
101  ok = false;
102  }
103  if (oc.getFloat("weights.random-factor") < 1) {
104  WRITE_ERROR("weights.random-factor cannot be less than 1");
105  ok = false;
106  }
107  if (string2time(oc.getString("device.rerouting.adaptation-interval")) < 0) {
108  WRITE_ERROR("Negative value for device.rerouting.adaptation-interval!");
109  ok = false;
110  }
111  if (oc.getFloat("device.rerouting.adaptation-weight") < 0. ||
112  oc.getFloat("device.rerouting.adaptation-weight") > 1.) {
113  WRITE_ERROR("The value for device.rerouting.adaptation-weight must be between 0 and 1!");
114  ok = false;
115  }
116 #ifndef HAVE_FOX
117  if (oc.getInt("device.rerouting.threads") > 1) {
118  WRITE_ERROR("Parallel routing is only possible when compiled with Fox.");
119  ok = false;
120  }
121 #endif
122  return ok;
123 }
124 
125 
126 void
127 MSDevice_Routing::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
128  const OptionsCont& oc = OptionsCont::getOptions();
129  if (v.getParameter().wasSet(VEHPARS_FORCE_REROUTE) || equippedByDefaultAssignmentOptions(oc, "rerouting", v, false)) {
130  // route computation is enabled
131  const SUMOTime period = string2time(oc.getString("device.rerouting.period"));
132  const SUMOTime prePeriod = string2time(oc.getString("device.rerouting.pre-period"));
134  // build the device
135  into.push_back(new MSDevice_Routing(v, "routing_" + v.getID(), period, prePeriod));
136  }
137 }
138 
139 
140 // ---------------------------------------------------------------------------
141 // MSDevice_Routing-methods
142 // ---------------------------------------------------------------------------
143 MSDevice_Routing::MSDevice_Routing(SUMOVehicle& holder, const std::string& id,
144  SUMOTime period, SUMOTime preInsertionPeriod)
145  : MSVehicleDevice(holder, id), myPeriod(period), myPreInsertionPeriod(preInsertionPeriod), myLastRouting(-1), mySkipRouting(-1), myRerouteCommand(nullptr) {
147  // we do always a pre insertion reroute for trips to fill the best lanes of the vehicle with somehow meaningful values (especially for deaprtLane="best")
149  // if we don't update the edge weights, we might as well reroute now and hopefully use our threads better
150  const SUMOTime execTime = MSRoutingEngine::hasEdgeUpdates() ? holder.getParameter().depart : -1;
152  if (myPreInsertionPeriod == 0) {
153  // the event will deschedule and destroy itself so it does not need to be stored
154  myRerouteCommand = nullptr;
155  }
156  }
157 }
158 
159 
161  // make the rerouting command invalid if there is one
162  if (myRerouteCommand != nullptr) {
164  }
165 }
166 
167 
168 bool
171  // clean up pre depart rerouting
172  if (myRerouteCommand != nullptr) {
174  }
175  myRerouteCommand = nullptr;
176  // build repetition trigger if routing shall be done more often
177  if (myPeriod > 0) {
180  if (OptionsCont::getOptions().getBool("device.rerouting.synchronize")) {
181  start -= start % myPeriod;
182  }
184  }
185  }
186  return false;
187 }
188 
189 
190 SUMOTime
192  if (mySkipRouting == currentTime) {
193  return DELTA_T;
194  }
195  const MSEdge* source = *myHolder.getRoute().begin();
196  const MSEdge* dest = myHolder.getRoute().getLastEdge();
197  if (source->isTazConnector() && dest->isTazConnector()) {
198  const MSRoute* cached = MSRoutingEngine::getCachedRoute(std::make_pair(source, dest));
199  if (cached != nullptr && cached->size() > 2) {
200  myHolder.replaceRoute(cached, "device.rerouting", true);
201  return myPreInsertionPeriod;
202  }
203  }
204  try {
205  reroute(currentTime, true);
206  } catch (ProcessError&) {
207  myRerouteCommand = nullptr;
208  throw;
209  }
210  return myPreInsertionPeriod;
211 }
212 
213 
214 SUMOTime
216  reroute(currentTime);
217  return myPeriod;
218 }
219 
220 
221 void
222 MSDevice_Routing::reroute(const SUMOTime currentTime, const bool onInit) {
224  //check whether the weights did change since the last reroute
226  return;
227  }
228  myLastRouting = currentTime;
229  MSRoutingEngine::reroute(myHolder, currentTime, onInit);
230 }
231 
232 
233 std::string
234 MSDevice_Routing::getParameter(const std::string& key) const {
235  if (StringUtils::startsWith(key, "edge:")) {
236  const std::string edgeID = key.substr(5);
237  const MSEdge* edge = MSEdge::dictionary(edgeID);
238  if (edge == nullptr) {
239  throw InvalidArgument("Edge '" + edgeID + "' is invalid for parameter retrieval of '" + deviceName() + "'");
240  }
241  return toString(MSRoutingEngine::getEffort(edge, &myHolder, 0));
242  } else if (key == "period") {
243  return time2string(myPeriod);
244  }
245  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
246 }
247 
248 
249 void
250 MSDevice_Routing::setParameter(const std::string& key, const std::string& value) {
251  double doubleValue;
252  try {
253  doubleValue = StringUtils::toDouble(value);
254  } catch (NumberFormatException&) {
255  throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
256  }
257  if (StringUtils::startsWith(key, "edge:")) {
258  const std::string edgeID = key.substr(5);
259  const MSEdge* edge = MSEdge::dictionary(edgeID);
260  if (edge == nullptr) {
261  throw InvalidArgument("Edge '" + edgeID + "' is invalid for parameter setting of '" + deviceName() + "'");
262  }
263  MSRoutingEngine::setEdgeTravelTime(edge, doubleValue);
264  } else if (key == "period") {
265  const SUMOTime oldPeriod = myPeriod;
266  myPeriod = TIME2STEPS(doubleValue);
267  if (myPeriod <= 0) {
269  } else if (oldPeriod <= 0) {
270  // re-schedule routing command
272  }
273  } else {
274  throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
275  }
276 }
277 
278 
279 void
282  out.writeAttr(SUMO_ATTR_ID, getID());
283  std::vector<std::string> internals;
284  internals.push_back(toString(myPeriod));
285  out.writeAttr(SUMO_ATTR_STATE, toString(internals));
286  out.closeTag();
287 }
288 
289 
290 void
292  std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
293  bis >> myPeriod;
294 }
295 
296 
297 /****************************************************************************/
SUMOTime myPeriod
The period with which a vehicle shall be rerouted.
void setParameter(const std::string &key, const std::string &value)
try to set the given parameter for this device. Throw exception for unsupported key ...
void doRegister(const std::string &name, Option *v)
Adds an option under the given name.
Definition: OptionsCont.cpp:75
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
static void setEdgeTravelTime(const MSEdge *const edge, const double travelTime)
adapt the known travel time for an edge
long long int SUMOTime
Definition: SUMOTime.h:36
const int VEHPARS_FORCE_REROUTE
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
SUMOTime mySkipRouting
The time for which routing may be skipped because we cannot be inserted.
virtual const MSRoute & getRoute() const =0
Returns the current route.
static void initWeightUpdate()
intialize period edge weight update
SUMOTime myLastRouting
The last time a routing took place.
MSDevice_Routing(SUMOVehicle &holder, const std::string &id, SUMOTime period, SUMOTime preInsertionPeriod)
Constructor.
Notification
Definition of a vehicle state.
SUMOVehicle & myHolder
The vehicle that stores the device.
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
const std::string deviceName() const
return the name for this type of device
SUMOTime myPreInsertionPeriod
The period with which a vehicle shall be rerouted before insertion.
virtual bool replaceRoute(const MSRoute *route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true)=0
Replaces the current route by the given one.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
void saveState(OutputDevice &out) const
Saves the state of the device.
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn&#39;t already in the dictionary...
Definition: MSEdge.cpp:788
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:88
SUMOTime wrappedRerouteCommandExecute(SUMOTime currentTime)
Performs rerouting after a period.
const std::string & getID() const
Returns the id.
Definition: Named.h:78
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
int size() const
Returns the number of edges to pass.
Definition: MSRoute.cpp:82
static void initEdgeWeights()
initialize the edge weights if not done before
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
virtual std::string getString(int id) const =0
Returns the string-value of the named (by its enum-value) attribute.
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
Definition: OptionsCont.cpp:96
The state of a link.
A road/street connecting two junctions.
Definition: MSEdge.h:75
static void insertOptions(OptionsCont &oc)
Inserts MSDevice_Routing-options.
void reroute(const SUMOTime currentTime, const bool onInit=false)
initiate the rerouting, create router / thread pool on first use
static bool hasEdgeUpdates()
returns whether any routing actions take place
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
static const MSRoute * getCachedRoute(const std::pair< const MSEdge *, const MSEdge *> &key)
return the cached route or nullptr on miss
Representation of a vehicle.
Definition: SUMOVehicle.h:60
Encapsulated SAX-Attributes.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter ...
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:409
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
SUMOTime depart
The vehicle&#39;s departure time.
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static void reroute(SUMOVehicle &vehicle, const SUMOTime currentTime, const bool onInit)
initiate the rerouting, create router / thread pool on first use
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:263
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:42
WrappingCommand< MSDevice_Routing > * myRerouteCommand
The (optional) command responsible for rerouting.
static void insertDefaultAssignmentOptions(const std::string &deviceName, const std::string &optionsTopic, OptionsCont &oc, const bool isPerson=false)
Adds common command options that allow to assign devices to vehicles.
Definition: MSDevice.cpp:121
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static SUMOTime getLastAdaptation()
Information when the last edge weight adaptation occurred.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:247
The vehicle has departed (was inserted into the network)
An integer-option.
Definition: Option.h:333
bool isTazConnector() const
Definition: MSEdge.h:248
void deschedule()
Marks this Command as being descheduled.
static bool equippedByDefaultAssignmentOptions(const OptionsCont &oc, const std::string &deviceName, DEVICEHOLDER &v, bool outputOptionSet, const bool isPerson=false)
Determines whether a vehicle should get a certain device.
Definition: MSDevice.h:208
static double getEffort(const MSEdge *const e, const SUMOVehicle *const v, double t)
Returns the effort to pass an edge.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle&#39;s parameter (including departure definition)
A storage for options typed value containers)
Definition: OptionsCont.h:92
Abstract in-vehicle device.
MSEventControl * getInsertionEvents()
Returns the event control for insertion events.
Definition: MSNet.h:429
bool notifyEnter(SUMOVehicle &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the device from the given description.
bool wasSet(int what) const
Returns whether the given parameter was set.
~MSDevice_Routing()
Destructor.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static bool checkOptions(OptionsCont &oc)
checks MSDevice_Routing-options
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:70
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice *> &into)
Build devices for the given vehicle, if needed.
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key ...
SUMOTime preInsertionReroute(const SUMOTime currentTime)
Performs rerouting before insertion into the network.