Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSDevice_Routing.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2007-2023 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
22// A device that performs vehicle rerouting based on current edge speeds
23/****************************************************************************/
24#include <config.h>
25
26#include <microsim/MSNet.h>
27#include <microsim/MSLane.h>
28#include <microsim/MSEdge.h>
31#include <microsim/MSGlobals.h>
38#include "MSRoutingEngine.h"
39#include "MSDevice_Routing.h"
40
41
42// ===========================================================================
43// method definitions
44// ===========================================================================
45// ---------------------------------------------------------------------------
46// static initialisation methods
47// ---------------------------------------------------------------------------
48void
50 insertDefaultAssignmentOptions("rerouting", "Routing", oc);
51
52 oc.doRegister("device.rerouting.period", new Option_String("0", "TIME"));
53 oc.addSynonyme("device.rerouting.period", "device.routing.period", true);
54 oc.addDescription("device.rerouting.period", "Routing", TL("The period with which the vehicle shall be rerouted"));
55
56 oc.doRegister("device.rerouting.pre-period", new Option_String("60", "TIME"));
57 oc.addSynonyme("device.rerouting.pre-period", "device.routing.pre-period", true);
58 oc.addDescription("device.rerouting.pre-period", "Routing", TL("The rerouting period before depart"));
59
60 oc.doRegister("device.rerouting.adaptation-weight", new Option_Float(0));
61 oc.addSynonyme("device.rerouting.adaptation-weight", "device.routing.adaptation-weight", true);
62 oc.addDescription("device.rerouting.adaptation-weight", "Routing", TL("The weight of prior edge weights for exponential moving average"));
63
64 oc.doRegister("device.rerouting.adaptation-steps", new Option_Integer(180));
65 oc.addSynonyme("device.rerouting.adaptation-steps", "device.routing.adaptation-steps", true);
66 oc.addDescription("device.rerouting.adaptation-steps", "Routing", TL("The number of steps for moving average weight of prior edge weights"));
67
68 oc.doRegister("device.rerouting.adaptation-interval", new Option_String("1", "TIME"));
69 oc.addSynonyme("device.rerouting.adaptation-interval", "device.routing.adaptation-interval", true);
70 oc.addDescription("device.rerouting.adaptation-interval", "Routing", TL("The interval for updating the edge weights"));
71
72 oc.doRegister("device.rerouting.with-taz", new Option_Bool(false));
73 oc.addSynonyme("device.rerouting.with-taz", "device.routing.with-taz", true);
74 oc.addSynonyme("device.rerouting.with-taz", "with-taz");
75 oc.addDescription("device.rerouting.with-taz", "Routing", TL("Use zones (districts) as routing start- and endpoints"));
76
77 oc.doRegister("device.rerouting.init-with-loaded-weights", new Option_Bool(false));
78 oc.addDescription("device.rerouting.init-with-loaded-weights", "Routing", TL("Use weight files given with option --weight-files for initializing edge weights"));
79
80 oc.doRegister("device.rerouting.threads", new Option_Integer(0));
81 oc.addSynonyme("device.rerouting.threads", "routing-threads");
82 oc.addDescription("device.rerouting.threads", "Routing", TL("The number of parallel execution threads used for rerouting"));
83
84 oc.doRegister("device.rerouting.synchronize", new Option_Bool(false));
85 oc.addDescription("device.rerouting.synchronize", "Routing", TL("Let rerouting happen at the same time for all vehicles"));
86
87 oc.doRegister("device.rerouting.railsignal", new Option_Bool(true));
88 oc.addDescription("device.rerouting.railsignal", "Routing", TL("Allow rerouting triggered by rail signals."));
89
90 oc.doRegister("device.rerouting.bike-speeds", new Option_Bool(false));
91 oc.addDescription("device.rerouting.bike-speeds", "Routing", TL("Compute separate average speeds for bicycles"));
92
93 oc.doRegister("device.rerouting.output", new Option_FileName());
94 oc.addDescription("device.rerouting.output", "Routing", TL("Save adapting weights to FILE"));
95}
96
97
98bool
100 bool ok = true;
101 if (!oc.isDefault("device.rerouting.adaptation-steps") && !oc.isDefault("device.rerouting.adaptation-weight")) {
102 WRITE_ERROR(TL("Only one of the options 'device.rerouting.adaptation-steps' or 'device.rerouting.adaptation-weight' may be given."));
103 ok = false;
104 }
105 if (oc.getFloat("weights.random-factor") < 1) {
106 WRITE_ERROR(TL("weights.random-factor cannot be less than 1"));
107 ok = false;
108 }
109 if (string2time(oc.getString("device.rerouting.adaptation-interval")) < 0) {
110 WRITE_ERROR(TL("Negative value for device.rerouting.adaptation-interval!"));
111 ok = false;
112 }
113 if (oc.getFloat("device.rerouting.adaptation-weight") < 0. ||
114 oc.getFloat("device.rerouting.adaptation-weight") > 1.) {
115 WRITE_ERROR(TL("The value for device.rerouting.adaptation-weight must be between 0 and 1!"));
116 ok = false;
117 }
118#ifndef HAVE_FOX
119 if (oc.getInt("device.rerouting.threads") > 1) {
120 WRITE_ERROR(TL("Parallel routing is only possible when compiled with Fox."));
121 ok = false;
122 }
123#endif
124 if (oc.getInt("threads") > 1 && oc.getInt("device.rerouting.threads") > 1 && oc.getInt("threads") != oc.getInt("device.rerouting.threads")) {
125 WRITE_WARNING(TL("Adapting number of routing threads to number of simulation threads."));
126 }
127 return ok;
128}
129
130
131void
132MSDevice_Routing::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
134 const bool equip = equippedByDefaultAssignmentOptions(oc, "rerouting", v, false);
135 if (v.getParameter().wasSet(VEHPARS_FORCE_REROUTE) || equip) {
136 // route computation is enabled
137 // for implicitly equipped vehicles (trips, flows), option probability
138 // can still be used to disable periodic rerouting after insertion for
139 // parts of the fleet
140 const SUMOTime period = equip || oc.isDefault("device.rerouting.probability") ? getTimeParam(v, oc, "rerouting.period", 0, false) : 0;
141 const SUMOTime prePeriod = MAX2((SUMOTime)0, getTimeParam(v, oc, "rerouting.pre-period", string2time(oc.getString("device.rerouting.pre-period")), false));
143 // build the device
144 into.push_back(new MSDevice_Routing(v, "routing_" + v.getID(), period, prePeriod));
145 }
146}
147
148
149// ---------------------------------------------------------------------------
150// MSDevice_Routing-methods
151// ---------------------------------------------------------------------------
152MSDevice_Routing::MSDevice_Routing(SUMOVehicle& holder, const std::string& id,
153 SUMOTime period, SUMOTime preInsertionPeriod) :
154 MSVehicleDevice(holder, id),
155 myPeriod(period),
156 myPreInsertionPeriod(preInsertionPeriod),
157 myLastRouting(-1),
158 mySkipRouting(-1),
159 myRerouteCommand(nullptr),
160 myRerouteRailSignal(getBoolParam(holder, OptionsCont::getOptions(), "rerouting.railsignal", true, true)),
161 myLastLaneEntryTime(-1),
162 myRerouteAfterStop(false),
163 myActive(true) {
165 // 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")
167 // if we don't update the edge weights, we might as well reroute now and hopefully use our threads better
168 const SUMOTime execTime = MSRoutingEngine::hasEdgeUpdates() ? holder.getParameter().depart : -1;
170 }
171}
172
173
175 // make the rerouting command invalid if there is one
176 if (myRerouteCommand != nullptr) {
178 }
179}
180
181
182bool
186 // pre-insertion rerouting was disabled. Reroute once if insertion was delayed
187 // this is happening in the run thread (not inbeginOfTimestepEvents) so we cannot safely use the threadPool
188 myHolder.reroute(MSNet::getInstance()->getCurrentTimeStep(), "device.rerouting",
190 false, MSRoutingEngine::withTaz(), false);
191 }
192 // build repetition trigger if routing shall be done more often
194 }
197 const SUMOTime t = SIMSTEP;
198 if (myLastLaneEntryTime >= 0 && enteredLane->isInternal()) {
199 // record travel time on the previous edge but store on the internal ledge
201 }
203 }
204 return true;
205 } else {
206 return false;
207 }
208}
209
210
211void
218
219
220void
222 if (myRerouteCommand != nullptr) {
224 myRerouteCommand = nullptr;
225 }
226 if (myPeriod > 0) {
229 if (OptionsCont::getOptions().getBool("device.rerouting.synchronize")) {
230 start -= start % myPeriod;
231 }
233 }
234}
235
236
239 if (mySkipRouting == currentTime) {
240 return DELTA_T;
241 }
242 if (myPreInsertionPeriod == 0) {
243 // the event will deschedule and destroy itself so it does not need to be stored
244 myRerouteCommand = nullptr;
245 }
246 const MSEdge* source = *myHolder.getRoute().begin();
247 const MSEdge* dest = myHolder.getRoute().getLastEdge();
248 if (source->isTazConnector() && dest->isTazConnector()) {
249 ConstMSRoutePtr cached = MSRoutingEngine::getCachedRoute(std::make_pair(source, dest));
250 if (cached != nullptr && cached->size() > 2) {
251 myHolder.replaceRoute(cached, "device.rerouting", true);
253 }
254 }
255 try {
256 std::string msg;
257 if (myHolder.hasValidRouteStart(msg)) {
258 reroute(currentTime, true);
259 }
260 } catch (ProcessError&) {
261 myRerouteCommand = nullptr;
262 throw;
263 }
264 // avoid repeated pre-insertion rerouting when the departure edge is fix and
265 // the departure lane does not depend on the route
267 myRerouteCommand = nullptr;
268 return 0;
269 }
271}
272
273
276 if (myHolder.isStopped()) {
277 myRerouteAfterStop = true;
278 } else {
279 reroute(currentTime);
280 }
281 return myPeriod;
282}
283
284
285void
286MSDevice_Routing::reroute(const SUMOTime currentTime, const bool onInit) {
288 //check whether the weights did change since the last reroute
290 return;
291 }
292 myLastRouting = currentTime;
293 MSRoutingEngine::reroute(myHolder, currentTime, "device.rerouting", onInit);
294}
295
296
297std::string
298MSDevice_Routing::getParameter(const std::string& key) const {
299 if (StringUtils::startsWith(key, "edge:")) {
300 const std::string edgeID = key.substr(5);
301 const MSEdge* edge = MSEdge::dictionary(edgeID);
302 if (edge == nullptr) {
303 throw InvalidArgument("Edge '" + edgeID + "' is invalid for parameter retrieval of '" + deviceName() + "'");
304 }
306 } else if (key == "period") {
307 return time2string(myPeriod);
308 }
309 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
310}
311
312
313void
314MSDevice_Routing::setParameter(const std::string& key, const std::string& value) {
315 double doubleValue;
316 try {
317 doubleValue = StringUtils::toDouble(value);
318 } catch (NumberFormatException&) {
319 throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
320 }
321 if (StringUtils::startsWith(key, "edge:")) {
322 const std::string edgeID = key.substr(5);
323 const MSEdge* edge = MSEdge::dictionary(edgeID);
324 if (edge == nullptr) {
325 throw InvalidArgument("Edge '" + edgeID + "' is invalid for parameter setting of '" + deviceName() + "'");
326 }
327 MSRoutingEngine::setEdgeTravelTime(edge, doubleValue);
328 } else if (key == "period") {
329 myPeriod = TIME2STEPS(doubleValue);
330 // re-schedule routing command
332 } else {
333 throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
334 }
335}
336
337
338void
342 std::vector<std::string> internals;
343 internals.push_back(toString(myPeriod));
344 out.writeAttr(SUMO_ATTR_STATE, toString(internals));
345 out.closeTag();
346}
347
348
349void
351 std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
352 bis >> myPeriod;
353}
354
355
356/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_ERROR(msg)
Definition MsgHandler.h:279
#define WRITE_WARNING(msg)
Definition MsgHandler.h:270
#define TL(string)
Definition MsgHandler.h:287
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:69
#define SIMSTEP
Definition SUMOTime.h:61
#define TIME2STEPS(x)
Definition SUMOTime.h:57
@ BEST_FREE
The least occupied lane from best lanes.
const int VEHPARS_FORCE_REROUTE
@ SUMO_TAG_DEVICE
@ SUMO_ATTR_ID
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A device that performs vehicle rerouting based on current edge speeds.
const std::string deviceName() const
return the name for this type of device
void rebuildRerouteCommand()
rebuild reroute command according to period
void saveState(OutputDevice &out) const
Saves the state of the device.
SUMOTime wrappedRerouteCommandExecute(SUMOTime currentTime)
Performs rerouting after a period.
SUMOTime mySkipRouting
The time for which routing may be skipped because we cannot be inserted.
static void insertOptions(OptionsCont &oc)
Inserts MSDevice_Routing-options.
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key
bool myActive
Whether the equipped vehicle may perform rerouting.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
SUMOTime myPreInsertionPeriod
The period with which a vehicle shall be rerouted before insertion.
SUMOTime myPeriod
The period with which a vehicle shall be rerouted.
void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the device from the given description.
void reroute(const SUMOTime currentTime, const bool onInit=false)
initiate the rerouting, create router / thread pool on first use
static bool checkOptions(OptionsCont &oc)
checks MSDevice_Routing-options
MSDevice_Routing(SUMOVehicle &holder, const std::string &id, SUMOTime period, SUMOTime preInsertionPeriod)
Constructor.
WrappingCommand< MSDevice_Routing > * myRerouteCommand
The (optional) command responsible for rerouting.
~MSDevice_Routing()
Destructor.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
SUMOTime myLastLaneEntryTime
the previous time that a vehicle entered a lane
SUMOTime myLastRouting
The last time a routing took place.
void notifyStopEnded()
called to do the rerouting we missed whuile stopping
bool myRerouteAfterStop
Whether the equipped vehicle missed a reroute while stopping and should do so after the stop has ende...
void setParameter(const std::string &key, const std::string &value)
try to set the given parameter for this device. Throw exception for unsupported key
SUMOTime preInsertionReroute(const SUMOTime currentTime)
Performs rerouting before insertion into the network.
static SUMOTime getTimeParam(const SUMOVehicle &v, const OptionsCont &oc, std::string paramName, SUMOTime deflt, bool required=false)
Definition MSDevice.cpp:225
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:148
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:202
A road/street connecting two junctions.
Definition MSEdge.h:77
bool isTazConnector() const
Definition MSEdge.h:288
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:945
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static double gWeightsSeparateTurns
Whether turning specific weights are estimated (and how much)
Definition MSGlobals.h:172
Representation of a lane in the micro simulation.
Definition MSLane.h:84
bool isInternal() const
Definition MSLane.cpp:2456
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:745
Notification
Definition of a vehicle state.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:183
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:473
MSEventControl * getInsertionEvents()
Returns the event control for insertion events.
Definition MSNet.h:493
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:322
const MSEdge * getLastEdge() const
returns the destination edge
Definition MSRoute.cpp:91
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition MSRoute.cpp:73
static void setEdgeTravelTime(const MSEdge *const edge, const double travelTime)
adapt the known travel time for an edge
static void reroute(SUMOVehicle &vehicle, const SUMOTime currentTime, const std::string &info, const bool onInit=false, const bool silent=false, const MSEdgeVector &prohibited=MSEdgeVector())
initiate the rerouting, create router / thread pool on first use
static SUMOTime getLastAdaptation()
Information when the last edge weight adaptation occurred.
static bool withTaz()
whether taz-routing is enabled
static bool hasEdgeUpdates()
returns whether any edge weight updates will take place
static void addEdgeTravelTime(const MSEdge &edge, const SUMOTime travelTime)
record actual travel time for an edge
static void initWeightUpdate()
intialize period edge weight update
static void initEdgeWeights(SUMOVehicleClass svc)
initialize the edge weights if not done before
static ConstMSRoutePtr getCachedRoute(const std::pair< const MSEdge *, const MSEdge * > &key)
return the cached route or nullptr on miss
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
static double getEffort(const MSEdge *const e, const SUMOVehicle *const v, double t)
Returns the effort to pass an edge.
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
void doRegister(const std::string &name, Option *o)
Adds an option under the given name.
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
Representation of a vehicle, person, or container.
virtual bool isStopped() const =0
Returns whether the object is at a stop.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual void reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false)=0
Performs a rerouting using the given router.
virtual int getRNGIndex() const =0
virtual bool hasValidRouteStart(std::string &msg)=0
checks wether the vehicle can depart on the first edge
virtual SUMOTime getDepartDelay() const =0
virtual bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true, std::string *msgReturn=nullptr)=0
Replaces the current route by the given one.
virtual const MSRoute & getRoute() const =0
Returns the current route.
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
bool wasSet(int what) const
Returns whether the given parameter was set.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
A wrapper for a Command function.
void deschedule()
Marks this Command as being descheduled.