Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2007-2024 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/transportables/MSTransportable.h>
35 : #include <utils/options/OptionsCont.h>
36 : #include <utils/common/WrappingCommand.h>
37 : #include <utils/common/StaticCommand.h>
38 : #include <utils/common/StringUtils.h>
39 : #include <utils/router/DijkstraRouter.h>
40 : #include <utils/router/AStarRouter.h>
41 : #include <utils/router/CHRouter.h>
42 : #include <utils/router/CHRouterWrapper.h>
43 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
44 :
45 : //#define DEBUG_SEPARATE_TURNS
46 : #define DEBUG_COND(obj) (obj->isSelected())
47 :
48 : // ===========================================================================
49 : // static member variables
50 : // ===========================================================================
51 : std::vector<double> MSRoutingEngine::myEdgeSpeeds;
52 : std::vector<double> MSRoutingEngine::myEdgeBikeSpeeds;
53 : std::vector<MSRoutingEngine::TimeAndCount> MSRoutingEngine::myEdgeTravelTimes;
54 : std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeSpeeds;
55 : std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeBikeSpeeds;
56 : Command* MSRoutingEngine::myEdgeWeightSettingCommand = nullptr;
57 : double MSRoutingEngine::myAdaptationWeight;
58 : int MSRoutingEngine::myAdaptationSteps;
59 : int MSRoutingEngine::myAdaptationStepsIndex = 0;
60 : SUMOTime MSRoutingEngine::myAdaptationInterval = -1;
61 : SUMOTime MSRoutingEngine::myLastAdaptation = -1;
62 : bool MSRoutingEngine::myWithTaz;
63 : bool MSRoutingEngine::myBikeSpeeds;
64 : MSRouterProvider* MSRoutingEngine::myRouterProvider = nullptr;
65 : std::map<std::pair<const MSEdge*, const MSEdge*>, ConstMSRoutePtr> MSRoutingEngine::myCachedRoutes;
66 : double MSRoutingEngine::myPriorityFactor(0);
67 : double MSRoutingEngine::myMinEdgePriority(std::numeric_limits<double>::max());
68 : double MSRoutingEngine::myEdgePriorityRange(0);
69 : std::map<std::thread::id, SumoRNG*> MSRoutingEngine::myThreadRNGs;
70 : bool MSRoutingEngine::myHaveRoutingThreads(false);
71 :
72 : SUMOAbstractRouter<MSEdge, SUMOVehicle>::Operation MSRoutingEngine::myEffortFunc = &MSRoutingEngine::getEffort;
73 : #ifdef HAVE_FOX
74 : FXMutex MSRoutingEngine::myRouteCacheMutex;
75 : #endif
76 :
77 :
78 : // ===========================================================================
79 : // method definitions
80 : // ===========================================================================
81 : void
82 1514757 : MSRoutingEngine::initWeightUpdate() {
83 1514757 : if (myAdaptationInterval == -1) {
84 8049 : myEdgeWeightSettingCommand = nullptr;
85 : myEdgeSpeeds.clear();
86 : myEdgeTravelTimes.clear();
87 8049 : myAdaptationSteps = -1;
88 8049 : myLastAdaptation = -1;
89 8049 : const OptionsCont& oc = OptionsCont::getOptions();
90 8049 : myWithTaz = oc.getBool("device.rerouting.with-taz");
91 8049 : myAdaptationInterval = string2time(oc.getString("device.rerouting.adaptation-interval"));
92 8049 : myAdaptationWeight = oc.getFloat("device.rerouting.adaptation-weight");
93 8049 : const SUMOTime period = string2time(oc.getString("device.rerouting.period"));
94 8049 : if (myAdaptationWeight < 1. && myAdaptationInterval > 0) {
95 7986 : myEdgeWeightSettingCommand = new StaticCommand<MSRoutingEngine>(&MSRoutingEngine::adaptEdgeEfforts);
96 7986 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myEdgeWeightSettingCommand);
97 63 : } else if (period > 0) {
98 0 : WRITE_WARNING(TL("Rerouting is useless if the edge weights do not get updated!"));
99 : }
100 16098 : OutputDevice::createDeviceByOption("device.rerouting.output", "weights", "meandata_file.xsd");
101 : }
102 1514757 : }
103 :
104 :
105 : void
106 12239715 : MSRoutingEngine::initEdgeWeights(SUMOVehicleClass svc) {
107 12239715 : if (myBikeSpeeds && svc == SVC_BICYCLE) {
108 252 : _initEdgeWeights(myEdgeBikeSpeeds, myPastEdgeBikeSpeeds);
109 : } else {
110 12239463 : _initEdgeWeights(myEdgeSpeeds, myPastEdgeSpeeds);
111 : }
112 12239715 : }
113 :
114 :
115 : void
116 12239715 : MSRoutingEngine::_initEdgeWeights(std::vector<double>& edgeSpeeds, std::vector<std::vector<double> >& pastEdgeSpeeds) {
117 12239715 : if (edgeSpeeds.empty()) {
118 7964 : const OptionsCont& oc = OptionsCont::getOptions();
119 8052 : if (myAdaptationWeight == 0 || !oc.isDefault("device.rerouting.adaptation-steps")) {
120 7876 : myAdaptationSteps = oc.getInt("device.rerouting.adaptation-steps");
121 : }
122 7964 : const bool useLoaded = oc.getBool("device.rerouting.init-with-loaded-weights");
123 7964 : const double currentSecond = SIMTIME;
124 : double maxEdgePriority = -std::numeric_limits<double>::max();
125 673782 : for (const MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
126 1331636 : while (edge->getNumericalID() >= (int)edgeSpeeds.size()) {
127 665818 : edgeSpeeds.push_back(0);
128 665818 : if (myAdaptationSteps > 0) {
129 665146 : pastEdgeSpeeds.push_back(std::vector<double>());
130 : }
131 666993 : if (MSGlobals::gWeightsSeparateTurns && edgeSpeeds == myEdgeSpeeds) {
132 1175 : myEdgeTravelTimes.push_back(TimeAndCount(0, 0));
133 : }
134 : }
135 665818 : if (useLoaded) {
136 114 : edgeSpeeds[edge->getNumericalID()] = edge->getLength() / MSNet::getTravelTime(edge, nullptr, currentSecond);
137 : } else {
138 665704 : edgeSpeeds[edge->getNumericalID()] = edge->getMeanSpeed();
139 : }
140 665818 : if (myAdaptationSteps > 0) {
141 665146 : pastEdgeSpeeds[edge->getNumericalID()] = std::vector<double>(myAdaptationSteps, edgeSpeeds[edge->getNumericalID()]);
142 : }
143 665818 : maxEdgePriority = MAX2(maxEdgePriority, (double)edge->getPriority());
144 1290773 : myMinEdgePriority = MIN2(myMinEdgePriority, (double)edge->getPriority());
145 : }
146 7964 : myEdgePriorityRange = maxEdgePriority - myMinEdgePriority;
147 7964 : myLastAdaptation = MSNet::getInstance()->getCurrentTimeStep();
148 7964 : myPriorityFactor = oc.getFloat("weights.priority-factor");
149 7964 : if (myPriorityFactor < 0) {
150 0 : throw ProcessError(TL("weights.priority-factor cannot be negative."));
151 : }
152 7964 : if (myPriorityFactor > 0) {
153 7 : if (myEdgePriorityRange == 0) {
154 0 : WRITE_WARNING(TL("Option weights.priority-factor does not take effect because all edges have the same priority"));
155 0 : myPriorityFactor = 0;
156 : }
157 : }
158 : }
159 12239715 : }
160 :
161 :
162 : double
163 99497202 : MSRoutingEngine::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double) {
164 : const int id = e->getNumericalID();
165 99497202 : if (id < (int)myEdgeSpeeds.size()) {
166 91008536 : return MAX2(e->getLength() / MAX2(myEdgeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
167 : }
168 8534218 : return e->getMinimumTravelTime(v);
169 : }
170 :
171 :
172 : double
173 1924 : MSRoutingEngine::getEffortBike(const MSEdge* const e, const SUMOVehicle* const v, double) {
174 : const int id = e->getNumericalID();
175 1924 : if (id < (int)myEdgeBikeSpeeds.size()) {
176 1924 : return MAX2(e->getLength() / MAX2(myEdgeBikeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
177 : }
178 0 : return e->getMinimumTravelTime(v);
179 : }
180 :
181 : SumoRNG*
182 22677 : MSRoutingEngine::getThreadRNG() {
183 22677 : if (myHaveRoutingThreads) {
184 : auto it = myThreadRNGs.find(std::this_thread::get_id());
185 5254 : if (it != myThreadRNGs.end()) {
186 5236 : return it->second;
187 : } else {
188 36 : SumoRNG* rng = new SumoRNG("routing_" + toString(myThreadRNGs.size()));
189 18 : myThreadRNGs[std::this_thread::get_id()] = rng;
190 18 : return rng;
191 : }
192 : }
193 : return nullptr;
194 : }
195 :
196 :
197 : double
198 27908 : MSRoutingEngine::getEffortExtra(const MSEdge* const e, const SUMOVehicle* const v, double t) {
199 2636 : double effort = (!myBikeSpeeds || v == nullptr || v->getVClass() != SVC_BICYCLE
200 29964 : ? getEffort(e, v, t)
201 580 : : getEffortBike(e, v, t));
202 27908 : if (gWeightsRandomFactor != 1.) {
203 22677 : effort *= RandHelper::rand(1., gWeightsRandomFactor, getThreadRNG());
204 : }
205 27908 : if (myPriorityFactor != 0) {
206 : // lower priority should result in higher effort (and the edge with
207 : // minimum priority receives a factor of 1 + myPriorityFactor
208 840 : const double relativeInversePrio = 1 - ((e->getPriority() - myMinEdgePriority) / myEdgePriorityRange);
209 840 : effort *= 1 + relativeInversePrio * myPriorityFactor;
210 : }
211 27908 : return effort;
212 : }
213 :
214 :
215 : double
216 4240 : MSRoutingEngine::getAssumedSpeed(const MSEdge* edge, const SUMOVehicle* veh) {
217 4240 : return edge->getLength() / myEffortFunc(edge, veh, 0);
218 : }
219 :
220 :
221 : SUMOTime
222 10037052 : MSRoutingEngine::adaptEdgeEfforts(SUMOTime currentTime) {
223 10037052 : initEdgeWeights(SVC_PASSENGER);
224 10037052 : if (myBikeSpeeds) {
225 192 : initEdgeWeights(SVC_BICYCLE);
226 : }
227 10037052 : if (MSNet::getInstance()->getVehicleControl().getDepartedVehicleNo() == 0) {
228 94728 : return myAdaptationInterval;
229 : }
230 : myCachedRoutes.clear();
231 9942324 : const MSEdgeVector& edges = MSNet::getInstance()->getEdgeControl().getEdges();
232 9942324 : const double newWeightFactor = (double)(1. - myAdaptationWeight);
233 573106934 : for (const MSEdge* const e : edges) {
234 8152945 : if (e->isDelayed()) {
235 : const int id = e->getNumericalID();
236 122524470 : double currSpeed = e->getMeanSpeed();
237 122524470 : if (MSGlobals::gWeightsSeparateTurns > 0 && e->getNumSuccessors() > 1) {
238 129475 : currSpeed = patchSpeedForTurns(e, currSpeed);
239 : }
240 : #ifdef DEBUG_SEPARATE_TURNS
241 : if (DEBUG_COND(e->getLanes()[0])) {
242 : std::cout << SIMTIME << " edge=" << e->getID()
243 : << " meanSpeed=" << e->getMeanSpeed()
244 : << " currSpeed=" << currSpeed
245 : << " oldestSpeed=" << myPastEdgeSpeeds[id][myAdaptationStepsIndex]
246 : << " oldAvg=" << myEdgeSpeeds[id]
247 : << "\n";
248 : }
249 : #endif
250 122524470 : if (myAdaptationSteps > 0) {
251 : // moving average
252 122461404 : myEdgeSpeeds[id] += (currSpeed - myPastEdgeSpeeds[id][myAdaptationStepsIndex]) / myAdaptationSteps;
253 122461404 : myPastEdgeSpeeds[id][myAdaptationStepsIndex] = currSpeed;
254 122461404 : if (myBikeSpeeds) {
255 0 : const double currBikeSpeed = e->getMeanSpeedBike();
256 0 : myEdgeBikeSpeeds[id] += (currBikeSpeed - myPastEdgeBikeSpeeds[id][myAdaptationStepsIndex]) / myAdaptationSteps;
257 0 : myPastEdgeBikeSpeeds[id][myAdaptationStepsIndex] = currBikeSpeed;
258 : }
259 : } else {
260 : // exponential moving average
261 63066 : if (currSpeed != myEdgeSpeeds[id]) {
262 25322 : myEdgeSpeeds[id] = myEdgeSpeeds[id] * myAdaptationWeight + currSpeed * newWeightFactor;
263 : }
264 63066 : if (myBikeSpeeds) {
265 1090 : const double currBikeSpeed = e->getMeanSpeedBike();
266 1090 : if (currBikeSpeed != myEdgeBikeSpeeds[id]) {
267 722 : myEdgeBikeSpeeds[id] = myEdgeBikeSpeeds[id] * myAdaptationWeight + currBikeSpeed * newWeightFactor;
268 : }
269 : }
270 : }
271 : }
272 : }
273 9942324 : if (myAdaptationSteps > 0) {
274 9922810 : myAdaptationStepsIndex = (myAdaptationStepsIndex + 1) % myAdaptationSteps;
275 : }
276 9942324 : myLastAdaptation = currentTime + DELTA_T; // because we run at the end of the time step
277 19884648 : if (OptionsCont::getOptions().isSet("device.rerouting.output")) {
278 11807 : OutputDevice& dev = OutputDevice::getDeviceByOption("device.rerouting.output");
279 11807 : dev.openTag(SUMO_TAG_INTERVAL);
280 : dev.writeAttr(SUMO_ATTR_ID, "device.rerouting");
281 11807 : dev.writeAttr(SUMO_ATTR_BEGIN, STEPS2TIME(currentTime));
282 23614 : dev.writeAttr(SUMO_ATTR_END, STEPS2TIME(currentTime + myAdaptationInterval));
283 142139 : for (const MSEdge* e : edges) {
284 130332 : dev.openTag(SUMO_TAG_EDGE);
285 : dev.writeAttr(SUMO_ATTR_ID, e->getID());
286 130332 : dev.writeAttr("traveltime", myEffortFunc(e, nullptr, STEPS2TIME(currentTime)));
287 130332 : if (myBikeSpeeds) {
288 : // @note edge-priority is not included here
289 2688 : dev.writeAttr("traveltimeBike", getEffortBike(e, nullptr, STEPS2TIME(currentTime)));
290 : }
291 260664 : dev.closeTag();
292 : }
293 23614 : dev.closeTag();
294 : }
295 9942324 : return myAdaptationInterval;
296 : }
297 :
298 :
299 : double
300 129475 : MSRoutingEngine::patchSpeedForTurns(const MSEdge* edge, double currSpeed) {
301 : const double length = edge->getLength();
302 : double maxSpeed = 0;
303 558215 : for (const auto& pair : edge->getViaSuccessors()) {
304 428740 : if (pair.second == nullptr) {
305 40545 : continue;
306 : }
307 : TimeAndCount& tc = myEdgeTravelTimes[pair.second->getNumericalID()];
308 388195 : if (tc.second > 0) {
309 52035 : const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
310 : maxSpeed = MAX2(avgSpeed, maxSpeed);
311 : }
312 : }
313 129475 : if (maxSpeed > 0) {
314 : // perform correction
315 30670 : const double correctedSpeed = MSGlobals::gWeightsSeparateTurns * maxSpeed + (1 - MSGlobals::gWeightsSeparateTurns) * currSpeed;
316 135600 : for (const auto& pair : edge->getViaSuccessors()) {
317 104930 : if (pair.second == nullptr) {
318 9640 : continue;
319 : }
320 : const int iid = pair.second->getNumericalID();
321 95290 : TimeAndCount& tc = myEdgeTravelTimes[iid];
322 95290 : if (tc.second > 0) {
323 52035 : const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
324 52035 : if (avgSpeed < correctedSpeed) {
325 21140 : double internalTT = pair.second->getLength() / pair.second->getSpeedLimit();
326 21140 : internalTT += (length / avgSpeed - length / correctedSpeed) * MSGlobals::gWeightsSeparateTurns;
327 21140 : const double origInternalSpeed = myEdgeSpeeds[iid];
328 21140 : const double newInternalSpeed = pair.second->getLength() / internalTT;
329 21140 : const double origCurrSpeed = myPastEdgeSpeeds[iid][myAdaptationStepsIndex];
330 :
331 21140 : myEdgeSpeeds[iid] = newInternalSpeed;
332 : // to ensure myEdgeSpeed reverts to the speed limit
333 : // when there are no updates, we also have to patch
334 : // myPastEdgeSpeeds with a virtual value that is consistent
335 : // with the updated speed
336 : // note: internal edges were handled before the normal ones
337 21140 : const double virtualSpeed = (newInternalSpeed - (origInternalSpeed - origCurrSpeed / myAdaptationSteps)) * myAdaptationSteps;
338 21140 : myPastEdgeSpeeds[iid][myAdaptationStepsIndex] = virtualSpeed;
339 :
340 : #ifdef DEBUG_SEPARATE_TURNS
341 : if (DEBUG_COND(pair.second->getLanes()[0])) {
342 : std::cout << SIMTIME << " edge=" << edge->getID() << " to=" << pair.first->getID() << " via=" << pair.second->getID()
343 : << " origSpeed=" << currSpeed
344 : << " maxSpeed=" << maxSpeed
345 : << " correctedSpeed=" << correctedSpeed
346 : << " avgSpeed=" << avgSpeed
347 : << " internalTT=" << internalTT
348 : << " internalSpeed=" << origInternalSpeed
349 : << " newInternalSpeed=" << newInternalSpeed
350 : << " virtualSpeed=" << virtualSpeed
351 : << "\n";
352 : }
353 : #endif
354 : }
355 52035 : if (myAdaptationStepsIndex == 0) {
356 550 : tc.first = 0;
357 550 : tc.second = 0;
358 : }
359 : }
360 : }
361 : return correctedSpeed;
362 : }
363 : return currSpeed;
364 : }
365 :
366 :
367 : ConstMSRoutePtr
368 566045 : MSRoutingEngine::getCachedRoute(const std::pair<const MSEdge*, const MSEdge*>& key) {
369 : auto routeIt = myCachedRoutes.find(key);
370 566045 : if (routeIt != myCachedRoutes.end()) {
371 : return routeIt->second;
372 : }
373 : return nullptr;
374 : }
375 :
376 :
377 : void
378 7863 : MSRoutingEngine::initRouter(SUMOVehicle* vehicle) {
379 7863 : OptionsCont& oc = OptionsCont::getOptions();
380 7863 : const std::string routingAlgorithm = oc.getString("routing-algorithm");
381 7863 : const bool hasPermissions = MSNet::getInstance()->hasPermissions();
382 7863 : myBikeSpeeds = oc.getBool("device.rerouting.bike-speeds");
383 7863 : myEffortFunc = ((gWeightsRandomFactor != 1 || myPriorityFactor != 0 || myBikeSpeeds) ? &MSRoutingEngine::getEffortExtra : &MSRoutingEngine::getEffort);
384 :
385 : SUMOAbstractRouter<MSEdge, SUMOVehicle>* router = nullptr;
386 7863 : if (routingAlgorithm == "dijkstra") {
387 7605 : router = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, nullptr, true);
388 258 : } else if (routingAlgorithm == "astar") {
389 : typedef AStarRouter<MSEdge, SUMOVehicle> AStar;
390 : std::shared_ptr<const AStar::LookupTable> lookup = nullptr;
391 480 : if (oc.isSet("astar.all-distances")) {
392 0 : lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)MSEdge::getAllEdges().size());
393 480 : } else if (oc.isSet("astar.landmark-distances") && vehicle != nullptr) {
394 28 : const double speedFactor = vehicle->getChosenSpeedFactor();
395 : // we need an exemplary vehicle with speedFactor 1
396 28 : vehicle->setChosenSpeedFactor(1);
397 : CHRouterWrapper<MSEdge, SUMOVehicle> chrouter(
398 28 : MSEdge::getAllEdges(), true, &MSNet::getTravelTime,
399 84 : string2time(oc.getString("begin")), string2time(oc.getString("end")), SUMOTime_MAX, hasPermissions, 1);
400 28 : lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), MSEdge::getAllEdges(), &chrouter,
401 56 : nullptr, vehicle, "", oc.getInt("device.rerouting.threads"));
402 28 : vehicle->setChosenSpeedFactor(speedFactor);
403 28 : }
404 720 : router = new AStar(MSEdge::getAllEdges(), true, myEffortFunc, lookup, true);
405 18 : } else if (routingAlgorithm == "CH" && !hasPermissions) {
406 6 : const SUMOTime weightPeriod = myAdaptationInterval > 0 ? myAdaptationInterval : SUMOTime_MAX;
407 : router = new CHRouter<MSEdge, SUMOVehicle>(
408 6 : MSEdge::getAllEdges(), true, myEffortFunc, vehicle == nullptr ? SVC_PASSENGER : vehicle->getVClass(), weightPeriod, true, false);
409 12 : } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
410 : // use CHWrapper instead of CH if the net has permissions
411 12 : const SUMOTime weightPeriod = myAdaptationInterval > 0 ? myAdaptationInterval : SUMOTime_MAX;
412 : router = new CHRouterWrapper<MSEdge, SUMOVehicle>(
413 12 : MSEdge::getAllEdges(), true, myEffortFunc,
414 36 : string2time(oc.getString("begin")), string2time(oc.getString("end")), weightPeriod, hasPermissions, oc.getInt("device.rerouting.threads"));
415 : } else {
416 0 : throw ProcessError(TLF("Unknown routing algorithm '%'!", routingAlgorithm));
417 : }
418 :
419 : RailwayRouter<MSEdge, SUMOVehicle>* railRouter = nullptr;
420 7863 : if (MSNet::getInstance()->hasBidiEdges()) {
421 894 : railRouter = new RailwayRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, true, false, oc.getFloat("railway.max-train-length"));
422 : }
423 7863 : const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc);
424 7863 : const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
425 7863 : MSTransportableRouter* transRouter = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, 0);
426 7863 : myRouterProvider = new MSRouterProvider(router, nullptr, transRouter, railRouter);
427 : #ifndef THREAD_POOL
428 : #ifdef HAVE_FOX
429 7863 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
430 7863 : if (threadPool.size() > 0) {
431 : const std::vector<MFXWorkerThread*>& threads = threadPool.getWorkers();
432 804 : if (static_cast<MSEdgeControl::WorkerThread*>(threads.front())->setRouterProvider(myRouterProvider)) {
433 3124 : for (std::vector<MFXWorkerThread*>::const_iterator t = threads.begin() + 1; t != threads.end(); ++t) {
434 2320 : static_cast<MSEdgeControl::WorkerThread*>(*t)->setRouterProvider(myRouterProvider->clone());
435 : }
436 : }
437 804 : myHaveRoutingThreads = true;
438 : }
439 : #endif
440 : #endif
441 7863 : }
442 :
443 :
444 : void
445 2200639 : MSRoutingEngine::reroute(SUMOVehicle& vehicle, const SUMOTime currentTime, const std::string& info,
446 : const bool onInit, const bool silent, const MSEdgeVector& prohibited) {
447 2200639 : if (myRouterProvider == nullptr) {
448 7766 : initRouter(&vehicle);
449 : }
450 2200639 : auto& router = myRouterProvider->getVehicleRouter(vehicle.getVClass());
451 : #ifndef THREAD_POOL
452 : #ifdef HAVE_FOX
453 2200639 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
454 2200639 : if (threadPool.size() > 0) {
455 176487 : threadPool.add(new RoutingTask(vehicle, currentTime, info, onInit, silent, prohibited));
456 176487 : return;
457 : }
458 : #endif
459 : #endif
460 2024152 : if (!prohibited.empty()) {
461 4 : router.prohibit(prohibited);
462 : }
463 : try {
464 2024152 : vehicle.reroute(currentTime, info, router, onInit, myWithTaz, silent);
465 97 : } catch (ProcessError&) {
466 97 : if (!silent) {
467 97 : if (!prohibited.empty()) {
468 0 : router.prohibit(MSEdgeVector());
469 : }
470 97 : throw;
471 : }
472 97 : }
473 2024055 : if (!prohibited.empty()) {
474 4 : router.prohibit(MSEdgeVector());
475 : }
476 : }
477 :
478 :
479 : void
480 111 : MSRoutingEngine::reroute(MSTransportable& t, const SUMOTime currentTime, const std::string& info,
481 : const bool onInit, const bool silent, const MSEdgeVector& prohibited) {
482 111 : MSTransportableRouter& router = getIntermodalRouterTT(t.getRNGIndex(), prohibited);
483 : #ifndef THREAD_POOL
484 : #ifdef HAVE_FOX
485 111 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
486 111 : 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(MSEdgeVector());
501 : }
502 0 : throw;
503 : }
504 0 : }
505 100 : if (!prohibited.empty()) {
506 0 : router.prohibit(MSEdgeVector());
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 465856 : MSRoutingEngine::getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector& prohibited) {
526 465856 : if (myRouterProvider == nullptr) {
527 97 : initWeightUpdate();
528 97 : initEdgeWeights(svc);
529 97 : initRouter();
530 : }
531 : #ifndef THREAD_POOL
532 : #ifdef HAVE_FOX
533 465856 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
534 465856 : if (threadPool.size() > 0) {
535 34850 : auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getRouter(svc);
536 34850 : router.prohibit(prohibited);
537 34850 : return router;
538 : }
539 : #else
540 : UNUSED_PARAMETER(rngIndex);
541 : #endif
542 : #endif
543 862012 : myRouterProvider->getVehicleRouter(svc).prohibit(prohibited);
544 431006 : return myRouterProvider->getVehicleRouter(svc);
545 : }
546 :
547 :
548 : MSTransportableRouter&
549 111 : MSRoutingEngine::getIntermodalRouterTT(const int rngIndex, const MSEdgeVector& prohibited) {
550 111 : if (myRouterProvider == nullptr) {
551 0 : initWeightUpdate();
552 0 : initEdgeWeights(SVC_PEDESTRIAN);
553 0 : initRouter();
554 : }
555 : #ifndef THREAD_POOL
556 : #ifdef HAVE_FOX
557 111 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
558 111 : if (threadPool.size() > 0) {
559 11 : auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getIntermodalRouter();
560 11 : router.prohibit(prohibited);
561 11 : 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 40275 : MSRoutingEngine::cleanup() {
574 40275 : 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 40275 : myAdaptationStepsIndex = 0;
586 : #ifdef HAVE_FOX
587 40275 : if (MSGlobals::gNumThreads > 1) {
588 : // router deletion is done in thread destructor
589 4020 : myRouterProvider = nullptr;
590 4020 : return;
591 : }
592 : #endif
593 36255 : delete myRouterProvider;
594 36255 : myRouterProvider = nullptr;
595 : }
596 :
597 :
598 : #ifdef HAVE_FOX
599 : void
600 183543816 : MSRoutingEngine::waitForAll() {
601 : #ifndef THREAD_POOL
602 183543816 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
603 183543816 : if (threadPool.size() > 0) {
604 7362985 : threadPool.waitAll();
605 : }
606 : #endif
607 183543792 : }
608 :
609 :
610 : // ---------------------------------------------------------------------------
611 : // MSRoutingEngine::RoutingTask-methods
612 : // ---------------------------------------------------------------------------
613 : void
614 176487 : MSRoutingEngine::RoutingTask::run(MFXWorkerThread* context) {
615 176487 : SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = static_cast<MSEdgeControl::WorkerThread*>(context)->getRouter(myVehicle.getVClass());
616 176487 : if (!myProhibited.empty()) {
617 2 : router.prohibit(myProhibited);
618 : }
619 : try {
620 176487 : myVehicle.reroute(myTime, myInfo, router, myOnInit, myWithTaz, mySilent);
621 24 : } catch (ProcessError&) {
622 24 : if (!mySilent) {
623 24 : if (!myProhibited.empty()) {
624 0 : router.prohibit(MSEdgeVector());
625 : }
626 24 : throw;
627 : }
628 24 : }
629 176463 : if (!myProhibited.empty()) {
630 2 : router.prohibit(MSEdgeVector());
631 : }
632 176463 : const MSEdge* source = *myVehicle.getRoute().begin();
633 176463 : const MSEdge* dest = myVehicle.getRoute().getLastEdge();
634 176463 : if (source->isTazConnector() && dest->isTazConnector()) {
635 4 : const std::pair<const MSEdge*, const MSEdge*> key = std::make_pair(source, dest);
636 : FXMutexLock lock(myRouteCacheMutex);
637 4 : if (MSRoutingEngine::myCachedRoutes.find(key) == MSRoutingEngine::myCachedRoutes.end()) {
638 6 : MSRoutingEngine::myCachedRoutes[key] = myVehicle.getRoutePtr();
639 : }
640 : }
641 176463 : }
642 : #endif
643 :
644 :
645 : /****************************************************************************/
|