Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2007-2026 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 : /****************************************************************************/
14 : /// @file MSRoutingEngine.cpp
15 : /// @author Michael Behrisch
16 : /// @author Daniel Krajzewicz
17 : /// @author Laura Bieker
18 : /// @author Christoph Sommer
19 : /// @author Jakob Erdmann
20 : /// @date Tue, 04 Dec 2007
21 : ///
22 : // A device that performs vehicle rerouting based on current edge speeds
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include "MSRoutingEngine.h"
27 : #include <microsim/MSNet.h>
28 : #include <microsim/MSLane.h>
29 : #include <microsim/MSEdge.h>
30 : #include <microsim/MSEdgeControl.h>
31 : #include <microsim/MSEventControl.h>
32 : #include <microsim/MSGlobals.h>
33 : #include <microsim/MSVehicleControl.h>
34 : #include <microsim/MSInsertionControl.h>
35 : #include <microsim/transportables/MSTransportable.h>
36 : #include <microsim/devices/MSDevice_Taxi.h>
37 : #include <utils/options/OptionsCont.h>
38 : #include <utils/common/WrappingCommand.h>
39 : #include <utils/common/StaticCommand.h>
40 : #include <utils/common/StringUtils.h>
41 : #include <utils/xml/SUMOSAXAttributes.h>
42 : #include <utils/router/DijkstraRouter.h>
43 : #include <utils/router/AStarRouter.h>
44 : #include <utils/router/CHRouter.h>
45 : #include <utils/router/CHRouterWrapper.h>
46 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
47 :
48 : //#define DEBUG_SEPARATE_TURNS
49 : #define DEBUG_COND(obj) (obj->isSelected())
50 :
51 : // ===========================================================================
52 : // static member variables
53 : // ===========================================================================
54 : std::vector<double> MSRoutingEngine::myEdgeSpeeds;
55 : std::vector<double> MSRoutingEngine::myEdgeBikeSpeeds;
56 : std::vector<MSRoutingEngine::TimeAndCount> MSRoutingEngine::myEdgeTravelTimes;
57 : std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeSpeeds;
58 : std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeBikeSpeeds;
59 : Command* MSRoutingEngine::myEdgeWeightSettingCommand = nullptr;
60 : double MSRoutingEngine::myAdaptationWeight;
61 : int MSRoutingEngine::myAdaptationSteps;
62 : int MSRoutingEngine::myAdaptationStepsIndex = 0;
63 : SUMOTime MSRoutingEngine::myAdaptationInterval = -1;
64 : SUMOTime MSRoutingEngine::myLastAdaptation = -1;
65 : bool MSRoutingEngine::myWithTaz;
66 : bool MSRoutingEngine::myBikeSpeeds;
67 : MSRouterProvider* MSRoutingEngine::myRouterProvider = nullptr;
68 : std::map<std::pair<const MSEdge*, const MSEdge*>, ConstMSRoutePtr> MSRoutingEngine::myCachedRoutes;
69 : double MSRoutingEngine::myPriorityFactor(0);
70 : double MSRoutingEngine::myMinEdgePriority(std::numeric_limits<double>::max());
71 : double MSRoutingEngine::myEdgePriorityRange(0);
72 : bool MSRoutingEngine::myDynamicRandomness(false);
73 : bool MSRoutingEngine::myHaveExtras(false);
74 :
75 : SUMOAbstractRouter<MSEdge, SUMOVehicle>::Operation MSRoutingEngine::myEffortFunc = &MSRoutingEngine::getEffort;
76 : #ifdef HAVE_FOX
77 : FXMutex MSRoutingEngine::myRouteCacheMutex;
78 : #endif
79 :
80 :
81 : // ===========================================================================
82 : // method definitions
83 : // ===========================================================================
84 : void
85 1395953 : MSRoutingEngine::initWeightUpdate() {
86 1395953 : if (myAdaptationInterval == -1) {
87 7820 : myEdgeWeightSettingCommand = nullptr;
88 : myEdgeSpeeds.clear();
89 : myEdgeTravelTimes.clear();
90 7820 : myAdaptationSteps = -1;
91 7820 : myLastAdaptation = -1;
92 7820 : const OptionsCont& oc = OptionsCont::getOptions();
93 7820 : myWithTaz = oc.getBool("device.rerouting.with-taz");
94 7820 : myAdaptationInterval = string2time(oc.getString("device.rerouting.adaptation-interval"));
95 7820 : myAdaptationWeight = oc.getFloat("device.rerouting.adaptation-weight");
96 7820 : const SUMOTime period = string2time(oc.getString("device.rerouting.period"));
97 7820 : if (myAdaptationWeight < 1. && myAdaptationInterval > 0) {
98 7752 : myEdgeWeightSettingCommand = new StaticCommand<MSRoutingEngine>(&MSRoutingEngine::adaptEdgeEfforts);
99 7752 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myEdgeWeightSettingCommand);
100 68 : } else if (period > 0) {
101 0 : WRITE_WARNING(TL("Rerouting is useless if the edge weights do not get updated!"));
102 : }
103 15640 : OutputDevice::createDeviceByOption("device.rerouting.output", "weights", "meandata_file.xsd");
104 : }
105 1395953 : }
106 :
107 :
108 : void
109 13998686 : MSRoutingEngine::initEdgeWeights(SUMOVehicleClass svc, SUMOTime lastAdaption, int index) {
110 13998686 : if (myBikeSpeeds && svc == SVC_BICYCLE) {
111 294 : _initEdgeWeights(myEdgeBikeSpeeds, myPastEdgeBikeSpeeds);
112 : } else {
113 13998392 : _initEdgeWeights(myEdgeSpeeds, myPastEdgeSpeeds);
114 : }
115 13998686 : if (lastAdaption >= 0) {
116 176 : myLastAdaptation = lastAdaption;
117 : }
118 13998686 : if (index >= 0 && myAdaptationSteps > 0) {
119 : assert(index < myAdaptationSteps);
120 176 : myAdaptationStepsIndex = index;
121 : }
122 13998686 : }
123 :
124 :
125 : void
126 40551 : MSRoutingEngine::initWeightConstants(const OptionsCont& oc) {
127 81102 : if (oc.getFloat("weights.priority-factor") != 0) {
128 35 : myPriorityFactor = oc.getFloat("weights.priority-factor");
129 35 : if (myPriorityFactor < 0) {
130 0 : throw ProcessError(TL("weights.priority-factor cannot be negative."));
131 : }
132 35 : myMinEdgePriority = std::numeric_limits<double>::max();
133 : double maxEdgePriority = -std::numeric_limits<double>::max();
134 364 : for (const MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
135 329 : maxEdgePriority = MAX2(maxEdgePriority, (double)edge->getPriority());
136 553 : myMinEdgePriority = MIN2(myMinEdgePriority, (double)edge->getPriority());
137 : }
138 35 : myEdgePriorityRange = maxEdgePriority - myMinEdgePriority;
139 35 : if (myEdgePriorityRange == 0) {
140 0 : WRITE_WARNING(TL("Option weights.priority-factor does not take effect because all edges have the same priority"));
141 0 : myPriorityFactor = 0;
142 : }
143 : }
144 40551 : myDynamicRandomness = oc.getBool("weights.random-factor.dynamic");
145 40551 : myHaveExtras = gRoutingPreferences || myPriorityFactor != 0 || gWeightsRandomFactor != 0;
146 40551 : }
147 :
148 :
149 : void
150 13998686 : MSRoutingEngine::_initEdgeWeights(std::vector<double>& edgeSpeeds, std::vector<std::vector<double> >& pastEdgeSpeeds) {
151 13998686 : if (edgeSpeeds.empty()) {
152 7731 : const OptionsCont& oc = OptionsCont::getOptions();
153 7821 : if (myAdaptationWeight == 0 || !oc.isDefault("device.rerouting.adaptation-steps")) {
154 7641 : myAdaptationSteps = oc.getInt("device.rerouting.adaptation-steps");
155 : }
156 7731 : const bool useLoaded = oc.getBool("device.rerouting.init-with-loaded-weights");
157 7731 : const double currentSecond = SIMTIME;
158 759425 : for (const MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
159 1503388 : while (edge->getNumericalID() >= (int)edgeSpeeds.size()) {
160 751694 : edgeSpeeds.push_back(0);
161 751694 : if (myAdaptationSteps > 0) {
162 751008 : pastEdgeSpeeds.push_back(std::vector<double>());
163 : }
164 753339 : if (MSGlobals::gWeightsSeparateTurns && edgeSpeeds == myEdgeSpeeds) {
165 1645 : myEdgeTravelTimes.push_back(TimeAndCount(0, 0));
166 : }
167 : }
168 751694 : if (useLoaded) {
169 114 : edgeSpeeds[edge->getNumericalID()] = edge->getLength() / MSNet::getTravelTime(edge, nullptr, currentSecond);
170 : } else {
171 751580 : edgeSpeeds[edge->getNumericalID()] = edge->getMeanSpeed();
172 : }
173 751694 : if (myAdaptationSteps > 0) {
174 751008 : pastEdgeSpeeds[edge->getNumericalID()] = std::vector<double>(myAdaptationSteps, edgeSpeeds[edge->getNumericalID()]);
175 : }
176 : }
177 7731 : myLastAdaptation = MSNet::getInstance()->getCurrentTimeStep();
178 : }
179 13998686 : }
180 :
181 :
182 : double
183 213964344 : MSRoutingEngine::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double) {
184 : const int id = e->getNumericalID();
185 213964344 : if (id < (int)myEdgeSpeeds.size()) {
186 206266458 : return MAX2(e->getLength() / MAX2(myEdgeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
187 : }
188 7930554 : return e->getMinimumTravelTime(v);
189 : }
190 :
191 :
192 : double
193 3088 : MSRoutingEngine::getEffortBike(const MSEdge* const e, const SUMOVehicle* const v, double) {
194 : const int id = e->getNumericalID();
195 3088 : if (id < (int)myEdgeBikeSpeeds.size()) {
196 3088 : return MAX2(e->getLength() / MAX2(myEdgeBikeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
197 : }
198 0 : return e->getMinimumTravelTime(v);
199 : }
200 :
201 :
202 : double
203 72566 : MSRoutingEngine::getEffortExtra(const MSEdge* const e, const SUMOVehicle* const v, double t) {
204 5054 : double effort = (!myBikeSpeeds || v == nullptr || v->getVClass() != SVC_BICYCLE
205 76100 : ? getEffort(e, v, t)
206 1520 : : getEffortBike(e, v, t));
207 72566 : applyExtras(e, v, SIMSTEP, effort);
208 72566 : return effort;
209 : }
210 :
211 :
212 : double
213 4240 : MSRoutingEngine::getAssumedSpeed(const MSEdge* edge, const SUMOVehicle* veh) {
214 4240 : return edge->getLength() / myEffortFunc(edge, veh, 0);
215 : }
216 :
217 :
218 : SUMOTime
219 11726214 : MSRoutingEngine::adaptEdgeEfforts(SUMOTime currentTime) {
220 11726214 : initEdgeWeights(SVC_PASSENGER);
221 11726214 : if (myBikeSpeeds) {
222 224 : initEdgeWeights(SVC_BICYCLE);
223 : }
224 11726214 : if (MSNet::getInstance()->getVehicleControl().getDepartedVehicleNo() == 0) {
225 37530 : return myAdaptationInterval;
226 : }
227 : myCachedRoutes.clear();
228 11688684 : const MSEdgeVector& edges = MSNet::getInstance()->getEdgeControl().getEdges();
229 11688684 : const double newWeightFactor = (double)(1. - myAdaptationWeight);
230 762856454 : for (const MSEdge* const e : edges) {
231 8702514 : if (e->isDelayed()) {
232 : const int id = e->getNumericalID();
233 183397012 : double currSpeed = e->getMeanSpeed();
234 183397012 : if (MSGlobals::gWeightsSeparateTurns > 0 && e->getNumSuccessors() > 1) {
235 161049 : currSpeed = patchSpeedForTurns(e, currSpeed);
236 : }
237 : #ifdef DEBUG_SEPARATE_TURNS
238 : if (DEBUG_COND(e->getLanes()[0])) {
239 : std::cout << SIMTIME << " edge=" << e->getID()
240 : << " meanSpeed=" << e->getMeanSpeed()
241 : << " currSpeed=" << currSpeed
242 : << " oldestSpeed=" << myPastEdgeSpeeds[id][myAdaptationStepsIndex]
243 : << " oldAvg=" << myEdgeSpeeds[id]
244 : << "\n";
245 : }
246 : #endif
247 183397012 : if (myAdaptationSteps > 0) {
248 : // moving average
249 183333764 : myEdgeSpeeds[id] += (currSpeed - myPastEdgeSpeeds[id][myAdaptationStepsIndex]) / myAdaptationSteps;
250 183333764 : myPastEdgeSpeeds[id][myAdaptationStepsIndex] = currSpeed;
251 183333764 : if (myBikeSpeeds) {
252 0 : const double currBikeSpeed = e->getMeanSpeedBike();
253 0 : myEdgeBikeSpeeds[id] += (currBikeSpeed - myPastEdgeBikeSpeeds[id][myAdaptationStepsIndex]) / myAdaptationSteps;
254 0 : myPastEdgeBikeSpeeds[id][myAdaptationStepsIndex] = currBikeSpeed;
255 : }
256 : } else {
257 : // exponential moving average
258 63248 : if (currSpeed != myEdgeSpeeds[id]) {
259 25418 : myEdgeSpeeds[id] = myEdgeSpeeds[id] * myAdaptationWeight + currSpeed * newWeightFactor;
260 : }
261 63248 : if (myBikeSpeeds) {
262 1272 : const double currBikeSpeed = e->getMeanSpeedBike();
263 1272 : if (currBikeSpeed != myEdgeBikeSpeeds[id]) {
264 812 : myEdgeBikeSpeeds[id] = myEdgeBikeSpeeds[id] * myAdaptationWeight + currBikeSpeed * newWeightFactor;
265 : }
266 : }
267 : }
268 : }
269 : }
270 11688684 : if (myAdaptationSteps > 0) {
271 11669138 : myAdaptationStepsIndex = (myAdaptationStepsIndex + 1) % myAdaptationSteps;
272 : }
273 11688684 : myLastAdaptation = currentTime + DELTA_T; // because we run at the end of the time step
274 23377368 : if (OptionsCont::getOptions().isSet("device.rerouting.output")) {
275 11839 : OutputDevice& dev = OutputDevice::getDeviceByOption("device.rerouting.output");
276 11839 : dev.openTag(SUMO_TAG_INTERVAL);
277 11839 : dev.writeAttr(SUMO_ATTR_ID, "device.rerouting");
278 11839 : dev.writeAttr(SUMO_ATTR_BEGIN, STEPS2TIME(currentTime));
279 11839 : dev.writeAttr(SUMO_ATTR_END, STEPS2TIME(currentTime + myAdaptationInterval));
280 142395 : for (const MSEdge* e : edges) {
281 130556 : dev.openTag(SUMO_TAG_EDGE);
282 130556 : dev.writeAttr(SUMO_ATTR_ID, e->getID());
283 130556 : dev.writeAttr("traveltime", myEffortFunc(e, nullptr, STEPS2TIME(currentTime)));
284 130556 : if (myBikeSpeeds) {
285 : // @note edge-priority is not included here
286 1568 : dev.writeAttr("traveltimeBike", getEffortBike(e, nullptr, STEPS2TIME(currentTime)));
287 : }
288 261112 : dev.closeTag();
289 : }
290 23678 : dev.closeTag();
291 : }
292 11688684 : return myAdaptationInterval;
293 : }
294 :
295 :
296 : double
297 161049 : MSRoutingEngine::patchSpeedForTurns(const MSEdge* edge, double currSpeed) {
298 : const double length = edge->getLength();
299 : double maxSpeed = 0;
300 694173 : for (const auto& pair : edge->getViaSuccessors()) {
301 533124 : if (pair.second == nullptr) {
302 50119 : continue;
303 : }
304 483005 : TimeAndCount& tc = myEdgeTravelTimes[pair.second->getNumericalID()];
305 483005 : if (tc.second > 0) {
306 52850 : const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
307 : maxSpeed = MAX2(avgSpeed, maxSpeed);
308 : }
309 : }
310 161049 : if (maxSpeed > 0) {
311 : // perform correction
312 31095 : const double correctedSpeed = MSGlobals::gWeightsSeparateTurns * maxSpeed + (1 - MSGlobals::gWeightsSeparateTurns) * currSpeed;
313 138070 : for (const auto& pair : edge->getViaSuccessors()) {
314 106975 : if (pair.second == nullptr) {
315 10065 : continue;
316 : }
317 : const int iid = pair.second->getNumericalID();
318 96910 : TimeAndCount& tc = myEdgeTravelTimes[iid];
319 96910 : if (tc.second > 0) {
320 52850 : const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
321 52850 : if (avgSpeed < correctedSpeed) {
322 21530 : double internalTT = pair.second->getLength() / pair.second->getSpeedLimit();
323 21530 : internalTT += (length / avgSpeed - length / correctedSpeed) * MSGlobals::gWeightsSeparateTurns;
324 21530 : const double origInternalSpeed = myEdgeSpeeds[iid];
325 21530 : const double newInternalSpeed = pair.second->getLength() / internalTT;
326 21530 : const double origCurrSpeed = myPastEdgeSpeeds[iid][myAdaptationStepsIndex];
327 :
328 21530 : myEdgeSpeeds[iid] = newInternalSpeed;
329 : // to ensure myEdgeSpeed reverts to the speed limit
330 : // when there are no updates, we also have to patch
331 : // myPastEdgeSpeeds with a virtual value that is consistent
332 : // with the updated speed
333 : // note: internal edges were handled before the normal ones
334 21530 : const double virtualSpeed = (newInternalSpeed - (origInternalSpeed - origCurrSpeed / myAdaptationSteps)) * myAdaptationSteps;
335 21530 : myPastEdgeSpeeds[iid][myAdaptationStepsIndex] = virtualSpeed;
336 :
337 : #ifdef DEBUG_SEPARATE_TURNS
338 : if (DEBUG_COND(pair.second->getLanes()[0])) {
339 : std::cout << SIMTIME << " edge=" << edge->getID() << " to=" << pair.first->getID() << " via=" << pair.second->getID()
340 : << " origSpeed=" << currSpeed
341 : << " maxSpeed=" << maxSpeed
342 : << " correctedSpeed=" << correctedSpeed
343 : << " avgSpeed=" << avgSpeed
344 : << " internalTT=" << internalTT
345 : << " internalSpeed=" << origInternalSpeed
346 : << " newInternalSpeed=" << newInternalSpeed
347 : << " virtualSpeed=" << virtualSpeed
348 : << "\n";
349 : }
350 : #endif
351 : }
352 52850 : if (myAdaptationStepsIndex == 0) {
353 550 : tc.first = 0;
354 550 : tc.second = 0;
355 : }
356 : }
357 : }
358 : return correctedSpeed;
359 : }
360 : return currSpeed;
361 : }
362 :
363 :
364 : ConstMSRoutePtr
365 465800 : MSRoutingEngine::getCachedRoute(const std::pair<const MSEdge*, const MSEdge*>& key) {
366 : auto routeIt = myCachedRoutes.find(key);
367 465800 : if (routeIt != myCachedRoutes.end()) {
368 : return routeIt->second;
369 : }
370 : return nullptr;
371 : }
372 :
373 :
374 : void
375 7582 : MSRoutingEngine::initRouter(SUMOVehicle* vehicle) {
376 7582 : OptionsCont& oc = OptionsCont::getOptions();
377 7582 : const std::string routingAlgorithm = oc.getString("routing-algorithm");
378 7582 : const bool hasPermissions = MSNet::getInstance()->hasPermissions();
379 7582 : myBikeSpeeds = oc.getBool("device.rerouting.bike-speeds");
380 7582 : myEffortFunc = ((gWeightsRandomFactor != 1 || myPriorityFactor != 0 || myBikeSpeeds || gRoutingPreferences) ? &MSRoutingEngine::getEffortExtra : &MSRoutingEngine::getEffort);
381 :
382 : SUMOAbstractRouter<MSEdge, SUMOVehicle>* router = nullptr;
383 7582 : if (routingAlgorithm == "dijkstra") {
384 7286 : router = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, nullptr, true);
385 296 : } else if (routingAlgorithm == "astar") {
386 : typedef AStarRouter<MSEdge, SUMOVehicle, MSMapMatcher> AStar;
387 : std::shared_ptr<const AStar::LookupTable> lookup = nullptr;
388 556 : if (oc.isSet("astar.all-distances")) {
389 0 : lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)MSEdge::getAllEdges().size());
390 556 : } else if (oc.isSet("astar.landmark-distances") && vehicle != nullptr) {
391 35 : const double speedFactor = vehicle->getChosenSpeedFactor();
392 : // we need an exemplary vehicle with speedFactor 1
393 35 : vehicle->setChosenSpeedFactor(1);
394 : CHRouterWrapper<MSEdge, SUMOVehicle> chrouter(
395 35 : MSEdge::getAllEdges(), true, &MSNet::getTravelTime,
396 105 : string2time(oc.getString("begin")), string2time(oc.getString("end")), SUMOTime_MAX, hasPermissions, 1);
397 35 : lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), MSEdge::getAllEdges(), &chrouter,
398 70 : nullptr, vehicle, "", oc.getInt("device.rerouting.threads"), MSNet::getInstance()->getMapMatcher());
399 35 : vehicle->setChosenSpeedFactor(speedFactor);
400 35 : }
401 834 : router = new AStar(MSEdge::getAllEdges(), true, myEffortFunc, lookup, true);
402 18 : } else if (routingAlgorithm == "CH" && !hasPermissions) {
403 6 : const SUMOTime weightPeriod = myAdaptationInterval > 0 ? myAdaptationInterval : SUMOTime_MAX;
404 : router = new CHRouter<MSEdge, SUMOVehicle>(
405 6 : MSEdge::getAllEdges(), true, myEffortFunc, vehicle == nullptr ? SVC_PASSENGER : vehicle->getVClass(), weightPeriod, true, false);
406 12 : } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
407 : // use CHWrapper instead of CH if the net has permissions
408 12 : const SUMOTime weightPeriod = myAdaptationInterval > 0 ? myAdaptationInterval : SUMOTime_MAX;
409 : router = new CHRouterWrapper<MSEdge, SUMOVehicle>(
410 12 : MSEdge::getAllEdges(), true, myEffortFunc,
411 36 : string2time(oc.getString("begin")), string2time(oc.getString("end")), weightPeriod, hasPermissions, oc.getInt("device.rerouting.threads"));
412 : } else {
413 0 : throw ProcessError(TLF("Unknown routing algorithm '%'!", routingAlgorithm));
414 : }
415 :
416 : RailwayRouter<MSEdge, SUMOVehicle>* railRouter = nullptr;
417 7582 : if (MSNet::getInstance()->hasBidiEdges()) {
418 578 : railRouter = new RailwayRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, true, false,
419 : oc.getFloat("railway.max-train-length"),
420 1156 : oc.getFloat("weights.reversal-penalty"));
421 : }
422 8453 : const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, MSDevice_Taxi::hasFleet() || MSNet::getInstance()->getInsertionControl().hasTaxiFlow());
423 7582 : const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
424 7582 : MSTransportableRouter* transRouter = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, 0);
425 7582 : myRouterProvider = new MSRouterProvider(router, nullptr, transRouter, railRouter);
426 : #ifndef THREAD_POOL
427 : #ifdef HAVE_FOX
428 7582 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
429 7582 : if (threadPool.size() > 0) {
430 : const std::vector<MFXWorkerThread*>& threads = threadPool.getWorkers();
431 946 : if (static_cast<MSEdgeControl::WorkerThread*>(threads.front())->setRouterProvider(myRouterProvider)) {
432 3716 : for (std::vector<MFXWorkerThread*>::const_iterator t = threads.begin() + 1; t != threads.end(); ++t) {
433 2770 : static_cast<MSEdgeControl::WorkerThread*>(*t)->setRouterProvider(myRouterProvider->clone());
434 : }
435 : }
436 : }
437 : #endif
438 : #endif
439 7582 : }
440 :
441 :
442 : void
443 2270090 : MSRoutingEngine::reroute(SUMOVehicle& vehicle, const SUMOTime currentTime, const std::string& info,
444 : const bool onInit, const bool silent, const Prohibitions& prohibited) {
445 2270090 : if (myRouterProvider == nullptr) {
446 7410 : initRouter(&vehicle);
447 : }
448 2270090 : auto& router = myRouterProvider->getVehicleRouter(vehicle.getVClass());
449 : #ifndef THREAD_POOL
450 : #ifdef HAVE_FOX
451 2270090 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
452 2270090 : if (threadPool.size() > 0) {
453 189979 : threadPool.add(new RoutingTask(vehicle, currentTime, info, onInit, silent, prohibited));
454 189979 : return;
455 : }
456 : #endif
457 : #endif
458 2080111 : if (!prohibited.empty()) {
459 4 : router.prohibit(prohibited);
460 : }
461 : try {
462 2080111 : vehicle.reroute(currentTime, info, router, onInit, myWithTaz, silent);
463 95 : } catch (ProcessError&) {
464 95 : if (!silent) {
465 95 : if (!prohibited.empty()) {
466 0 : router.prohibit(Prohibitions());
467 : }
468 95 : throw;
469 : }
470 95 : }
471 2080016 : if (!prohibited.empty()) {
472 8 : router.prohibit(Prohibitions());
473 : }
474 : }
475 :
476 :
477 : void
478 118 : MSRoutingEngine::reroute(MSTransportable& t, const SUMOTime currentTime, const std::string& info,
479 : const bool onInit, const bool silent, const Prohibitions& prohibited) {
480 118 : MSTransportableRouter& router = getIntermodalRouterTT(t.getRNGIndex(), prohibited);
481 : #ifndef THREAD_POOL
482 : #ifdef HAVE_FOX
483 118 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
484 118 : if (threadPool.size() > 0) {
485 : // threadPool.add(new RoutingTask(t, currentTime, info, onInit, silent, prohibited));
486 : return;
487 : }
488 : #endif
489 : #endif
490 100 : if (!prohibited.empty()) {
491 0 : router.prohibit(prohibited);
492 : }
493 : try {
494 100 : t.reroute(currentTime, info, router, onInit, myWithTaz, silent);
495 0 : } catch (ProcessError&) {
496 0 : if (!silent) {
497 0 : if (!prohibited.empty()) {
498 0 : router.prohibit(Prohibitions());
499 : }
500 0 : throw;
501 : }
502 0 : }
503 100 : if (!prohibited.empty()) {
504 0 : router.prohibit(Prohibitions());
505 : }
506 : }
507 :
508 :
509 : void
510 9 : MSRoutingEngine::setEdgeTravelTime(const MSEdge* const edge, const double travelTime) {
511 9 : myEdgeSpeeds[edge->getNumericalID()] = edge->getLength() / travelTime;
512 9 : }
513 :
514 : void
515 11090 : MSRoutingEngine::addEdgeTravelTime(const MSEdge& edge, const SUMOTime travelTime) {
516 11090 : TimeAndCount& tc = myEdgeTravelTimes[edge.getNumericalID()];
517 11090 : tc.first += travelTime;
518 11090 : tc.second += 1;
519 11090 : }
520 :
521 :
522 : MSVehicleRouter&
523 620340 : MSRoutingEngine::getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions& prohibited) {
524 620340 : if (myRouterProvider == nullptr) {
525 172 : initWeightUpdate();
526 172 : initEdgeWeights(svc);
527 172 : initRouter();
528 : }
529 : #ifndef THREAD_POOL
530 : #ifdef HAVE_FOX
531 620340 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
532 620340 : if (threadPool.size() > 0) {
533 33447 : auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getRouter(svc);
534 33447 : router.prohibit(prohibited);
535 33447 : return router;
536 : }
537 : #else
538 : UNUSED_PARAMETER(rngIndex);
539 : #endif
540 : #endif
541 1173786 : myRouterProvider->getVehicleRouter(svc).prohibit(prohibited);
542 586893 : return myRouterProvider->getVehicleRouter(svc);
543 : }
544 :
545 :
546 : MSTransportableRouter&
547 118 : MSRoutingEngine::getIntermodalRouterTT(const int rngIndex, const Prohibitions& prohibited) {
548 118 : if (myRouterProvider == nullptr) {
549 0 : initWeightUpdate();
550 0 : initEdgeWeights(SVC_PEDESTRIAN);
551 0 : initRouter();
552 : }
553 : #ifndef THREAD_POOL
554 : #ifdef HAVE_FOX
555 118 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
556 118 : if (threadPool.size() > 0) {
557 18 : auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getIntermodalRouter();
558 18 : router.prohibit(prohibited);
559 18 : return router;
560 : }
561 : #else
562 : UNUSED_PARAMETER(rngIndex);
563 : #endif
564 : #endif
565 100 : myRouterProvider->getIntermodalRouter().prohibit(prohibited);
566 100 : return myRouterProvider->getIntermodalRouter();
567 : }
568 :
569 :
570 : void
571 41448 : MSRoutingEngine::cleanup() {
572 41448 : myAdaptationInterval = -1; // responsible for triggering initEdgeWeights
573 : myPastEdgeSpeeds.clear();
574 : myEdgeSpeeds.clear();
575 : myEdgeTravelTimes.clear();
576 : myPastEdgeBikeSpeeds.clear();
577 : myEdgeBikeSpeeds.clear();
578 : // @todo recheck. calling release crashes in parallel routing
579 : //for (auto& item : myCachedRoutes) {
580 : // item.second->release();
581 : //}
582 : myCachedRoutes.clear();
583 41448 : myAdaptationStepsIndex = 0;
584 : #ifdef HAVE_FOX
585 41448 : if (MSGlobals::gNumThreads > 1) {
586 : // router deletion is done in thread destructor
587 4446 : myRouterProvider = nullptr;
588 4446 : return;
589 : }
590 : #endif
591 37002 : delete myRouterProvider;
592 37002 : myRouterProvider = nullptr;
593 : }
594 :
595 :
596 : void
597 496 : MSRoutingEngine::saveState(OutputDevice& out) {
598 496 : if (myEdgeSpeeds.size() == 0) {
599 : return;
600 : }
601 107 : out.openTag(SUMO_TAG_ROUTINGENGINE);
602 107 : out.writeAttr(SUMO_ATTR_LAST, myLastAdaptation);
603 107 : out.writeAttr(SUMO_ATTR_INDEX, myAdaptationStepsIndex);
604 107 : const MSEdgeVector& edges = MSNet::getInstance()->getEdgeControl().getEdges();
605 8341 : for (const MSEdge* const e : edges) {
606 0 : if (e->isDelayed()) {
607 : const int id = e->getNumericalID();
608 1358 : out.openTag(SUMO_TAG_EDGE);
609 1358 : out.writeAttr(SUMO_ATTR_ID, e->getID());
610 1358 : out.writeAttr(SUMO_ATTR_SPEED, myEdgeSpeeds[id]);
611 1358 : if (myAdaptationSteps > 0) {
612 1358 : out.writeAttr(SUMO_ATTR_PASTSPEED, myPastEdgeSpeeds[id]);
613 : }
614 1358 : if (myBikeSpeeds) {
615 0 : out.writeAttr(SUMO_ATTR_BIKESPEED, myEdgeBikeSpeeds[id]);
616 0 : if (myAdaptationSteps > 0) {
617 0 : out.writeAttr(SUMO_ATTR_PASTBIKESPEED, myPastEdgeBikeSpeeds[id]);
618 : }
619 : }
620 2716 : out.closeTag();
621 : }
622 : }
623 214 : out.closeTag();
624 : }
625 :
626 :
627 : void
628 1688 : MSRoutingEngine::loadState(const SUMOSAXAttributes& attrs) {
629 3376 : const MSEdge* const e = MSEdge::dictionary(attrs.getString(SUMO_ATTR_ID));
630 : e->markDelayed();
631 : const int id = e->getNumericalID();
632 : bool checkedSteps = false;
633 : bool checkedBikeSpeeds = false;
634 1688 : bool ok = true;
635 1688 : if ((int)myEdgeSpeeds.size() > id) {
636 1688 : myEdgeSpeeds[id] = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
637 1688 : if (myBikeSpeeds) {
638 0 : if (attrs.hasAttribute(SUMO_ATTR_BIKESPEED)) {
639 0 : myEdgeBikeSpeeds[id] = attrs.get<double>(SUMO_ATTR_BIKESPEED, nullptr, ok);
640 : } else if (!checkedBikeSpeeds) {
641 : checkedBikeSpeeds = true;
642 0 : WRITE_WARNING("Bike speeds missing in loaded state");
643 : }
644 : }
645 1688 : if (myAdaptationSteps > 0) {
646 1688 : const std::vector<double> speeds = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PASTSPEED, nullptr, ok);
647 1688 : if ((int)speeds.size() == myAdaptationSteps) {
648 1688 : myPastEdgeSpeeds[id] = speeds;
649 1688 : if (myBikeSpeeds && attrs.hasAttribute(SUMO_ATTR_PASTBIKESPEED)) {
650 0 : myPastEdgeBikeSpeeds[id] = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PASTBIKESPEED, nullptr, ok);
651 : }
652 : } else if (!checkedSteps) {
653 : checkedSteps = true;
654 0 : WRITE_WARNING("Number of adaptation speeds in loaded state doesn't match option --device.rerouting.adaptation-steps");
655 : }
656 1688 : }
657 : }
658 1688 : }
659 :
660 :
661 : #ifdef HAVE_FOX
662 : void
663 112272785 : MSRoutingEngine::waitForAll() {
664 : #ifndef THREAD_POOL
665 112272785 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
666 112272785 : if (threadPool.size() > 0) {
667 12635356 : threadPool.waitAll();
668 : }
669 : #endif
670 112272761 : }
671 :
672 :
673 : // ---------------------------------------------------------------------------
674 : // MSRoutingEngine::RoutingTask-methods
675 : // ---------------------------------------------------------------------------
676 : void
677 189979 : MSRoutingEngine::RoutingTask::run(MFXWorkerThread* context) {
678 189979 : SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = static_cast<MSEdgeControl::WorkerThread*>(context)->getRouter(myVehicle.getVClass());
679 189979 : if (!myProhibited.empty()) {
680 2 : router.prohibit(myProhibited);
681 : }
682 : try {
683 189979 : myVehicle.reroute(myTime, myInfo, router, myOnInit, myWithTaz, mySilent);
684 24 : } catch (ProcessError&) {
685 24 : if (!mySilent) {
686 24 : if (!myProhibited.empty()) {
687 0 : router.prohibit(Prohibitions());
688 : }
689 24 : throw;
690 : }
691 24 : }
692 189955 : if (!myProhibited.empty()) {
693 4 : router.prohibit(Prohibitions());
694 : }
695 189955 : const MSEdge* source = *myVehicle.getRoute().begin();
696 189955 : const MSEdge* dest = myVehicle.getRoute().getLastEdge();
697 189955 : if (source->isTazConnector() && dest->isTazConnector()) {
698 4 : const std::pair<const MSEdge*, const MSEdge*> key = std::make_pair(source, dest);
699 : FXMutexLock lock(myRouteCacheMutex);
700 4 : if (MSRoutingEngine::myCachedRoutes.find(key) == MSRoutingEngine::myCachedRoutes.end()) {
701 6 : MSRoutingEngine::myCachedRoutes[key] = myVehicle.getRoutePtr();
702 : }
703 : }
704 189955 : }
705 :
706 :
707 : #endif
708 :
709 :
710 : /****************************************************************************/
|