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