Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSRoutingEngine.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-2025 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 "MSRoutingEngine.h"
27#include <microsim/MSNet.h>
28#include <microsim/MSLane.h>
29#include <microsim/MSEdge.h>
32#include <microsim/MSGlobals.h>
45
46//#define DEBUG_SEPARATE_TURNS
47#define DEBUG_COND(obj) (obj->isSelected())
48
49// ===========================================================================
50// static member variables
51// ===========================================================================
52std::vector<double> MSRoutingEngine::myEdgeSpeeds;
53std::vector<double> MSRoutingEngine::myEdgeBikeSpeeds;
54std::vector<MSRoutingEngine::TimeAndCount> MSRoutingEngine::myEdgeTravelTimes;
55std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeSpeeds;
56std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeBikeSpeeds;
66std::map<std::pair<const MSEdge*, const MSEdge*>, ConstMSRoutePtr> MSRoutingEngine::myCachedRoutes;
68double MSRoutingEngine::myMinEdgePriority(std::numeric_limits<double>::max());
70std::map<std::thread::id, SumoRNG*> MSRoutingEngine::myThreadRNGs;
72
74#ifdef HAVE_FOX
75FXMutex MSRoutingEngine::myRouteCacheMutex;
76#endif
77
78
79// ===========================================================================
80// method definitions
81// ===========================================================================
82void
84 if (myAdaptationInterval == -1) {
86 myEdgeSpeeds.clear();
87 myEdgeTravelTimes.clear();
91 myWithTaz = oc.getBool("device.rerouting.with-taz");
92 myAdaptationInterval = string2time(oc.getString("device.rerouting.adaptation-interval"));
93 myAdaptationWeight = oc.getFloat("device.rerouting.adaptation-weight");
94 const SUMOTime period = string2time(oc.getString("device.rerouting.period"));
95 if (myAdaptationWeight < 1. && myAdaptationInterval > 0) {
98 } else if (period > 0) {
99 WRITE_WARNING(TL("Rerouting is useless if the edge weights do not get updated!"));
100 }
101 OutputDevice::createDeviceByOption("device.rerouting.output", "weights", "meandata_file.xsd");
102 }
103}
104
105
106void
108 if (myBikeSpeeds && svc == SVC_BICYCLE) {
110 } else {
112 }
113 if (lastAdaption >= 0) {
114 myLastAdaptation = lastAdaption;
115 }
116 if (index >= 0) {
117 assert(index < (int)myPastEdgeSpeeds.size());
119 }
120}
121
122
123void
124MSRoutingEngine::_initEdgeWeights(std::vector<double>& edgeSpeeds, std::vector<std::vector<double> >& pastEdgeSpeeds) {
125 if (edgeSpeeds.empty()) {
127 if (myAdaptationWeight == 0 || !oc.isDefault("device.rerouting.adaptation-steps")) {
128 myAdaptationSteps = oc.getInt("device.rerouting.adaptation-steps");
129 }
130 const bool useLoaded = oc.getBool("device.rerouting.init-with-loaded-weights");
131 const double currentSecond = SIMTIME;
132 double maxEdgePriority = -std::numeric_limits<double>::max();
133 for (const MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
134 while (edge->getNumericalID() >= (int)edgeSpeeds.size()) {
135 edgeSpeeds.push_back(0);
136 if (myAdaptationSteps > 0) {
137 pastEdgeSpeeds.push_back(std::vector<double>());
138 }
139 if (MSGlobals::gWeightsSeparateTurns && edgeSpeeds == myEdgeSpeeds) {
140 myEdgeTravelTimes.push_back(TimeAndCount(0, 0));
141 }
142 }
143 if (useLoaded) {
144 edgeSpeeds[edge->getNumericalID()] = edge->getLength() / MSNet::getTravelTime(edge, nullptr, currentSecond);
145 } else {
146 edgeSpeeds[edge->getNumericalID()] = edge->getMeanSpeed();
147 }
148 if (myAdaptationSteps > 0) {
149 pastEdgeSpeeds[edge->getNumericalID()] = std::vector<double>(myAdaptationSteps, edgeSpeeds[edge->getNumericalID()]);
150 }
151 maxEdgePriority = MAX2(maxEdgePriority, (double)edge->getPriority());
152 myMinEdgePriority = MIN2(myMinEdgePriority, (double)edge->getPriority());
153 }
154 myEdgePriorityRange = maxEdgePriority - myMinEdgePriority;
156 myPriorityFactor = oc.getFloat("weights.priority-factor");
157 if (myPriorityFactor < 0) {
158 throw ProcessError(TL("weights.priority-factor cannot be negative."));
159 }
160 if (myPriorityFactor > 0) {
161 if (myEdgePriorityRange == 0) {
162 WRITE_WARNING(TL("Option weights.priority-factor does not take effect because all edges have the same priority"));
164 }
165 }
166 }
167}
168
169
170double
171MSRoutingEngine::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double) {
172 const int id = e->getNumericalID();
173 if (id < (int)myEdgeSpeeds.size()) {
174 return MAX2(e->getLength() / MAX2(myEdgeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
175 }
176 return e->getMinimumTravelTime(v);
177}
178
179
180double
181MSRoutingEngine::getEffortBike(const MSEdge* const e, const SUMOVehicle* const v, double) {
182 const int id = e->getNumericalID();
183 if (id < (int)myEdgeBikeSpeeds.size()) {
184 return MAX2(e->getLength() / MAX2(myEdgeBikeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
185 }
186 return e->getMinimumTravelTime(v);
187}
188
189SumoRNG*
192 auto it = myThreadRNGs.find(std::this_thread::get_id());
193 // created by InitTask
194 assert(it != myThreadRNGs.end());
195 return it->second;
196 }
197 return nullptr;
198}
199
200
201double
202MSRoutingEngine::getEffortExtra(const MSEdge* const e, const SUMOVehicle* const v, double t) {
203 double effort = (!myBikeSpeeds || v == nullptr || v->getVClass() != SVC_BICYCLE
204 ? getEffort(e, v, t)
205 : getEffortBike(e, v, t));
206 if (gWeightsRandomFactor != 1.) {
208 }
209 if (myPriorityFactor != 0) {
210 // lower priority should result in higher effort (and the edge with
211 // minimum priority receives a factor of 1 + myPriorityFactor
212 const double relativeInversePrio = 1 - ((e->getPriority() - myMinEdgePriority) / myEdgePriorityRange);
213 effort *= 1 + relativeInversePrio * myPriorityFactor;
214 }
215 return effort;
216}
217
218
219double
221 return edge->getLength() / myEffortFunc(edge, veh, 0);
222}
223
224
228 if (myBikeSpeeds) {
230 }
231 if (MSNet::getInstance()->getVehicleControl().getDepartedVehicleNo() == 0) {
233 }
234 myCachedRoutes.clear();
236 const double newWeightFactor = (double)(1. - myAdaptationWeight);
237 for (const MSEdge* const e : edges) {
238 if (e->isDelayed()) {
239 const int id = e->getNumericalID();
240 double currSpeed = e->getMeanSpeed();
241 if (MSGlobals::gWeightsSeparateTurns > 0 && e->getNumSuccessors() > 1) {
242 currSpeed = patchSpeedForTurns(e, currSpeed);
243 }
244#ifdef DEBUG_SEPARATE_TURNS
245 if (DEBUG_COND(e->getLanes()[0])) {
246 std::cout << SIMTIME << " edge=" << e->getID()
247 << " meanSpeed=" << e->getMeanSpeed()
248 << " currSpeed=" << currSpeed
249 << " oldestSpeed=" << myPastEdgeSpeeds[id][myAdaptationStepsIndex]
250 << " oldAvg=" << myEdgeSpeeds[id]
251 << "\n";
252 }
253#endif
254 if (myAdaptationSteps > 0) {
255 // moving average
258 if (myBikeSpeeds) {
259 const double currBikeSpeed = e->getMeanSpeedBike();
261 myPastEdgeBikeSpeeds[id][myAdaptationStepsIndex] = currBikeSpeed;
262 }
263 } else {
264 // exponential moving average
265 if (currSpeed != myEdgeSpeeds[id]) {
266 myEdgeSpeeds[id] = myEdgeSpeeds[id] * myAdaptationWeight + currSpeed * newWeightFactor;
267 }
268 if (myBikeSpeeds) {
269 const double currBikeSpeed = e->getMeanSpeedBike();
270 if (currBikeSpeed != myEdgeBikeSpeeds[id]) {
271 myEdgeBikeSpeeds[id] = myEdgeBikeSpeeds[id] * myAdaptationWeight + currBikeSpeed * newWeightFactor;
272 }
273 }
274 }
275 }
276 }
277 if (myAdaptationSteps > 0) {
279 }
280 myLastAdaptation = currentTime + DELTA_T; // because we run at the end of the time step
281 if (OptionsCont::getOptions().isSet("device.rerouting.output")) {
282 OutputDevice& dev = OutputDevice::getDeviceByOption("device.rerouting.output");
284 dev.writeAttr(SUMO_ATTR_ID, "device.rerouting");
285 dev.writeAttr(SUMO_ATTR_BEGIN, STEPS2TIME(currentTime));
287 for (const MSEdge* e : edges) {
289 dev.writeAttr(SUMO_ATTR_ID, e->getID());
290 dev.writeAttr("traveltime", myEffortFunc(e, nullptr, STEPS2TIME(currentTime)));
291 if (myBikeSpeeds) {
292 // @note edge-priority is not included here
293 dev.writeAttr("traveltimeBike", getEffortBike(e, nullptr, STEPS2TIME(currentTime)));
294 }
295 dev.closeTag();
296 }
297 dev.closeTag();
298 }
300}
301
302
303double
304MSRoutingEngine::patchSpeedForTurns(const MSEdge* edge, double currSpeed) {
305 const double length = edge->getLength();
306 double maxSpeed = 0;
307 for (const auto& pair : edge->getViaSuccessors()) {
308 if (pair.second == nullptr) {
309 continue;
310 }
311 TimeAndCount& tc = myEdgeTravelTimes[pair.second->getNumericalID()];
312 if (tc.second > 0) {
313 const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
314 maxSpeed = MAX2(avgSpeed, maxSpeed);
315 }
316 }
317 if (maxSpeed > 0) {
318 // perform correction
319 const double correctedSpeed = MSGlobals::gWeightsSeparateTurns * maxSpeed + (1 - MSGlobals::gWeightsSeparateTurns) * currSpeed;
320 for (const auto& pair : edge->getViaSuccessors()) {
321 if (pair.second == nullptr) {
322 continue;
323 }
324 const int iid = pair.second->getNumericalID();
326 if (tc.second > 0) {
327 const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
328 if (avgSpeed < correctedSpeed) {
329 double internalTT = pair.second->getLength() / pair.second->getSpeedLimit();
330 internalTT += (length / avgSpeed - length / correctedSpeed) * MSGlobals::gWeightsSeparateTurns;
331 const double origInternalSpeed = myEdgeSpeeds[iid];
332 const double newInternalSpeed = pair.second->getLength() / internalTT;
333 const double origCurrSpeed = myPastEdgeSpeeds[iid][myAdaptationStepsIndex];
334
335 myEdgeSpeeds[iid] = newInternalSpeed;
336 // to ensure myEdgeSpeed reverts to the speed limit
337 // when there are no updates, we also have to patch
338 // myPastEdgeSpeeds with a virtual value that is consistent
339 // with the updated speed
340 // note: internal edges were handled before the normal ones
341 const double virtualSpeed = (newInternalSpeed - (origInternalSpeed - origCurrSpeed / myAdaptationSteps)) * myAdaptationSteps;
342 myPastEdgeSpeeds[iid][myAdaptationStepsIndex] = virtualSpeed;
343
344#ifdef DEBUG_SEPARATE_TURNS
345 if (DEBUG_COND(pair.second->getLanes()[0])) {
346 std::cout << SIMTIME << " edge=" << edge->getID() << " to=" << pair.first->getID() << " via=" << pair.second->getID()
347 << " origSpeed=" << currSpeed
348 << " maxSpeed=" << maxSpeed
349 << " correctedSpeed=" << correctedSpeed
350 << " avgSpeed=" << avgSpeed
351 << " internalTT=" << internalTT
352 << " internalSpeed=" << origInternalSpeed
353 << " newInternalSpeed=" << newInternalSpeed
354 << " virtualSpeed=" << virtualSpeed
355 << "\n";
356 }
357#endif
358 }
359 if (myAdaptationStepsIndex == 0) {
360 tc.first = 0;
361 tc.second = 0;
362 }
363 }
364 }
365 return correctedSpeed;
366 }
367 return currSpeed;
368}
369
370
372MSRoutingEngine::getCachedRoute(const std::pair<const MSEdge*, const MSEdge*>& key) {
373 auto routeIt = myCachedRoutes.find(key);
374 if (routeIt != myCachedRoutes.end()) {
375 return routeIt->second;
376 }
377 return nullptr;
378}
379
380
381void
384 const std::string routingAlgorithm = oc.getString("routing-algorithm");
385 const bool hasPermissions = MSNet::getInstance()->hasPermissions();
386 myBikeSpeeds = oc.getBool("device.rerouting.bike-speeds");
388
390 if (routingAlgorithm == "dijkstra") {
391 router = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, nullptr, true);
392 } else if (routingAlgorithm == "astar") {
394 std::shared_ptr<const AStar::LookupTable> lookup = nullptr;
395 if (oc.isSet("astar.all-distances")) {
396 lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)MSEdge::getAllEdges().size());
397 } else if (oc.isSet("astar.landmark-distances") && vehicle != nullptr) {
398 const double speedFactor = vehicle->getChosenSpeedFactor();
399 // we need an exemplary vehicle with speedFactor 1
400 vehicle->setChosenSpeedFactor(1);
403 string2time(oc.getString("begin")), string2time(oc.getString("end")), SUMOTime_MAX, hasPermissions, 1);
404 lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), MSEdge::getAllEdges(), &chrouter,
405 nullptr, vehicle, "", oc.getInt("device.rerouting.threads"), MSNet::getInstance()->getMapMatcher());
406 vehicle->setChosenSpeedFactor(speedFactor);
407 }
408 router = new AStar(MSEdge::getAllEdges(), true, myEffortFunc, lookup, true);
409 } else if (routingAlgorithm == "CH" && !hasPermissions) {
412 MSEdge::getAllEdges(), true, myEffortFunc, vehicle == nullptr ? SVC_PASSENGER : vehicle->getVClass(), weightPeriod, true, false);
413 } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
414 // use CHWrapper instead of CH if the net has permissions
418 string2time(oc.getString("begin")), string2time(oc.getString("end")), weightPeriod, hasPermissions, oc.getInt("device.rerouting.threads"));
419 } else {
420 throw ProcessError(TLF("Unknown routing algorithm '%'!", routingAlgorithm));
421 }
422
423 RailwayRouter<MSEdge, SUMOVehicle>* railRouter = nullptr;
424 if (MSNet::getInstance()->hasBidiEdges()) {
425 railRouter = new RailwayRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, true, false, oc.getFloat("railway.max-train-length"));
426 }
427 const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc);
428 const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
429 MSTransportableRouter* transRouter = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, 0);
430 myRouterProvider = new MSRouterProvider(router, nullptr, transRouter, railRouter);
431#ifndef THREAD_POOL
432#ifdef HAVE_FOX
433 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
434 if (threadPool.size() > 0) {
435 const std::vector<MFXWorkerThread*>& threads = threadPool.getWorkers();
436 if (static_cast<MSEdgeControl::WorkerThread*>(threads.front())->setRouterProvider(myRouterProvider)) {
437 for (std::vector<MFXWorkerThread*>::const_iterator t = threads.begin() + 1; t != threads.end(); ++t) {
438 static_cast<MSEdgeControl::WorkerThread*>(*t)->setRouterProvider(myRouterProvider->clone());
439 }
440 }
442 for (int i = 0; i < threadPool.size(); i++) {
443 threadPool.add(new InitTask(), i);
444 }
445 threadPool.waitAll();
446 // to use when routing is triggered from the main thread (i.e. by a rerouter)
447 myThreadRNGs[std::this_thread::get_id()] = nullptr;
448 }
449#endif
450#endif
451}
452
453
454void
456#ifndef THREAD_POOL
457#ifdef HAVE_FOX
458 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
459 if (threadPool.size() > 0) {
460 FXMutexLock lock(myRouteCacheMutex);
461 SumoRNG* rng = new SumoRNG("routingGUI");
462 myThreadRNGs[std::this_thread::get_id()] = rng;
463 }
464#endif
465#endif
466}
467
468
469void
470MSRoutingEngine::reroute(SUMOVehicle& vehicle, const SUMOTime currentTime, const std::string& info,
471 const bool onInit, const bool silent, const Prohibitions& prohibited) {
472 if (myRouterProvider == nullptr) {
473 initRouter(&vehicle);
474 }
475 auto& router = myRouterProvider->getVehicleRouter(vehicle.getVClass());
476#ifndef THREAD_POOL
477#ifdef HAVE_FOX
478 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
479 if (threadPool.size() > 0) {
480 threadPool.add(new RoutingTask(vehicle, currentTime, info, onInit, silent, prohibited));
481 return;
482 }
483#endif
484#endif
485 if (!prohibited.empty()) {
486 router.prohibit(prohibited);
487 }
488 try {
489 vehicle.reroute(currentTime, info, router, onInit, myWithTaz, silent);
490 } catch (ProcessError&) {
491 if (!silent) {
492 if (!prohibited.empty()) {
493 router.prohibit(Prohibitions());
494 }
495 throw;
496 }
497 }
498 if (!prohibited.empty()) {
499 router.prohibit(Prohibitions());
500 }
501}
502
503
504void
505MSRoutingEngine::reroute(MSTransportable& t, const SUMOTime currentTime, const std::string& info,
506 const bool onInit, const bool silent, const Prohibitions& prohibited) {
508#ifndef THREAD_POOL
509#ifdef HAVE_FOX
510 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
511 if (threadPool.size() > 0) {
512 // threadPool.add(new RoutingTask(t, currentTime, info, onInit, silent, prohibited));
513 return;
514 }
515#endif
516#endif
517 if (!prohibited.empty()) {
518 router.prohibit(prohibited);
519 }
520 try {
521 t.reroute(currentTime, info, router, onInit, myWithTaz, silent);
522 } catch (ProcessError&) {
523 if (!silent) {
524 if (!prohibited.empty()) {
525 router.prohibit(Prohibitions());
526 }
527 throw;
528 }
529 }
530 if (!prohibited.empty()) {
531 router.prohibit(Prohibitions());
532 }
533}
534
535
536void
537MSRoutingEngine::setEdgeTravelTime(const MSEdge* const edge, const double travelTime) {
538 myEdgeSpeeds[edge->getNumericalID()] = edge->getLength() / travelTime;
539}
540
541void
542MSRoutingEngine::addEdgeTravelTime(const MSEdge& edge, const SUMOTime travelTime) {
544 tc.first += travelTime;
545 tc.second += 1;
546}
547
548
550MSRoutingEngine::getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions& prohibited) {
551 if (myRouterProvider == nullptr) {
553 initEdgeWeights(svc);
554 initRouter();
555 }
556#ifndef THREAD_POOL
557#ifdef HAVE_FOX
558 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
559 if (threadPool.size() > 0) {
560 auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getRouter(svc);
561 router.prohibit(prohibited);
562 return router;
563 }
564#else
565 UNUSED_PARAMETER(rngIndex);
566#endif
567#endif
568 myRouterProvider->getVehicleRouter(svc).prohibit(prohibited);
570}
571
572
574MSRoutingEngine::getIntermodalRouterTT(const int rngIndex, const Prohibitions& prohibited) {
575 if (myRouterProvider == nullptr) {
578 initRouter();
579 }
580#ifndef THREAD_POOL
581#ifdef HAVE_FOX
582 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
583 if (threadPool.size() > 0) {
584 auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getIntermodalRouter();
585 router.prohibit(prohibited);
586 return router;
587 }
588#else
589 UNUSED_PARAMETER(rngIndex);
590#endif
591#endif
592 myRouterProvider->getIntermodalRouter().prohibit(prohibited);
594}
595
596
597void
599 myAdaptationInterval = -1; // responsible for triggering initEdgeWeights
600 myPastEdgeSpeeds.clear();
601 myEdgeSpeeds.clear();
602 myEdgeTravelTimes.clear();
603 myPastEdgeBikeSpeeds.clear();
604 myEdgeBikeSpeeds.clear();
605 // @todo recheck. calling release crashes in parallel routing
606 //for (auto& item : myCachedRoutes) {
607 // item.second->release();
608 //}
609 myCachedRoutes.clear();
611#ifdef HAVE_FOX
612 if (MSGlobals::gNumThreads > 1) {
613 // router deletion is done in thread destructor
614 myRouterProvider = nullptr;
615 return;
616 }
617#endif
618 delete myRouterProvider;
619 myRouterProvider = nullptr;
620}
621
622
623void
625 if (myEdgeSpeeds.size() == 0) {
626 return;
627 }
632 for (const MSEdge* const e : edges) {
633 if (e->isDelayed()) {
634 const int id = e->getNumericalID();
636 out.writeAttr(SUMO_ATTR_ID, e->getID());
638 if (myAdaptationSteps > 0) {
640 }
641 if (myBikeSpeeds) {
643 if (myAdaptationSteps > 0) {
645 }
646 }
647 out.closeTag();
648 }
649 }
650 out.closeTag();
651}
652
653
654void
656 const MSEdge* const e = MSEdge::dictionary(attrs.getString(SUMO_ATTR_ID));
657 e->markDelayed();
658 const int id = e->getNumericalID();
659 bool checkedSteps = false;
660 bool checkedBikeSpeeds = false;
661 bool ok = true;
662 if ((int)myEdgeSpeeds.size() > id) {
663 myEdgeSpeeds[id] = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
664 if (myBikeSpeeds) {
666 myEdgeBikeSpeeds[id] = attrs.get<double>(SUMO_ATTR_BIKESPEED, nullptr, ok);
667 } else if (!checkedBikeSpeeds) {
668 checkedBikeSpeeds = true;
669 WRITE_WARNING("Bike speeds missing in loaded state");
670 }
671 }
672 if (myAdaptationSteps > 0) {
673 const std::vector<double> speeds = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PASTSPEED, nullptr, ok);
674 if ((int)speeds.size() == myAdaptationSteps) {
675 myPastEdgeSpeeds[id] = speeds;
677 myPastEdgeBikeSpeeds[id] = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PASTBIKESPEED, nullptr, ok);
678 }
679 } else if (!checkedSteps) {
680 checkedSteps = true;
681 WRITE_WARNING("Number of adaptation speeds in loaded state doesn't match option --device.rerouting.adaptation-steps");
682 }
683 }
684 }
685}
686
687
688#ifdef HAVE_FOX
689void
690MSRoutingEngine::waitForAll() {
691#ifndef THREAD_POOL
692 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
693 if (threadPool.size() > 0) {
694 threadPool.waitAll();
695 }
696#endif
697}
698
699
700// ---------------------------------------------------------------------------
701// MSRoutingEngine::RoutingTask-methods
702// ---------------------------------------------------------------------------
703void
704MSRoutingEngine::RoutingTask::run(MFXWorkerThread* context) {
705 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = static_cast<MSEdgeControl::WorkerThread*>(context)->getRouter(myVehicle.getVClass());
706 if (!myProhibited.empty()) {
707 router.prohibit(myProhibited);
708 }
709 try {
710 myVehicle.reroute(myTime, myInfo, router, myOnInit, myWithTaz, mySilent);
711 } catch (ProcessError&) {
712 if (!mySilent) {
713 if (!myProhibited.empty()) {
714 router.prohibit(Prohibitions());
715 }
716 throw;
717 }
718 }
719 if (!myProhibited.empty()) {
720 router.prohibit(Prohibitions());
721 }
722 const MSEdge* source = *myVehicle.getRoute().begin();
723 const MSEdge* dest = myVehicle.getRoute().getLastEdge();
724 if (source->isTazConnector() && dest->isTazConnector()) {
725 const std::pair<const MSEdge*, const MSEdge*> key = std::make_pair(source, dest);
726 FXMutexLock lock(myRouteCacheMutex);
728 MSRoutingEngine::myCachedRoutes[key] = myVehicle.getRoutePtr();
729 }
730 }
731}
732
733// ---------------------------------------------------------------------------
734// MSRoutingEngine::InitTask-methods
735// ---------------------------------------------------------------------------
736void
737MSRoutingEngine::InitTask::run(MFXWorkerThread* /*context*/) {
738 FXMutexLock lock(myRouteCacheMutex);
739 SumoRNG* rng = new SumoRNG("routing_" + toString(myThreadRNGs.size()));
740 myThreadRNGs[std::this_thread::get_id()] = rng;
741}
742
743#endif
744
745
746/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:73
RouterProvider< MSEdge, MSLane, MSJunction, SUMOVehicle > MSRouterProvider
IntermodalRouter< MSEdge, MSLane, MSJunction, SUMOVehicle > MSTransportableRouter
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
#define TLF(string,...)
Definition MsgHandler.h:307
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
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:62
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_ROUTINGENGINE
the internal state for MSRoutingEngine
@ SUMO_TAG_EDGE
begin/end of the description of an edge
@ SUMO_ATTR_LAST
@ SUMO_ATTR_PASTSPEED
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_PASTBIKESPEED
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ID
@ SUMO_ATTR_BIKESPEED
double gWeightsRandomFactor
Definition StdDefs.cpp:33
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
Computes the shortest path through a network using the A* algorithm.
Definition AStarRouter.h:76
Computes the shortest path through a contracted network.
Definition CHRouter.h:59
Computes the shortest path through a contracted network.
Base (microsim) event class.
Definition Command.h:50
Computes the shortest path through a network using the Dijkstra algorithm.
void prohibit(const std::map< const E *, double > &toProhibit)
A pool of worker threads which distributes the tasks and collects the results.
void waitAll(const bool deleteFinished=true)
waits for all tasks to be finished
void add(Task *const t, int index=-1)
Gives a number to the given task and assigns it to the worker with the given index....
const std::vector< MFXWorkerThread * > & getWorkers()
int size() const
Returns the number of threads in the pool.
A thread repeatingly calculating incoming tasks.
const MSEdgeVector & getEdges() const
Returns loaded edges.
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1092
int getPriority() const
Returns the priority of the edge.
Definition MSEdge.h:328
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition MSEdge.cpp:1294
double getLength() const
return the length of the edge
Definition MSEdge.h:685
bool isTazConnector() const
Definition MSEdge.h:291
double getMinimumTravelTime(const SUMOVehicle *const veh) const
returns the minimum travel time for the given vehicle
Definition MSEdge.h:476
int getNumericalID() const
Returns the numerical id of the edge.
Definition MSEdge.h:306
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:1053
void markDelayed() const
Definition MSEdge.h:729
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:177
static int gNumThreads
how many threads to use
Definition MSGlobals.h:149
MSMapMatcher * getMapMatcher() const
Definition MSNet.cpp:1680
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:487
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:326
static double getTravelTime(const MSEdge *const e, const SUMOVehicle *const v, double t)
Returns the travel time to pass an edge.
Definition MSNet.cpp:166
bool hasPermissions() const
Returns whether the network has specific vehicle class permissions.
Definition MSNet.h:213
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition MSNet.h:427
static void adaptIntermodalRouter(MSTransportableRouter &router)
Definition MSNet.cpp:1599
static void saveState(OutputDevice &out)
Saves the state (i.e. recorded speeds)
static SUMOTime myAdaptationInterval
At which time interval the edge weights get updated.
static void initEdgeWeights(SUMOVehicleClass svc, SUMOTime lastAdaption=-1, int index=-1)
initialize the edge weights if not done before
static double myAdaptationWeight
Information which weight prior edge efforts have.
static int myAdaptationStepsIndex
The current index in the pastEdgeSpeed ring-buffer.
static double myMinEdgePriority
Minimum priority for all edges.
static std::vector< TimeAndCount > myEdgeTravelTimes
Sum of travel times experienced by equipped vehicles for each edge.
static double getEffortBike(const MSEdge *const e, const SUMOVehicle *const v, double t)
static void setEdgeTravelTime(const MSEdge *const edge, const double travelTime)
adapt the known travel time for an edge
static double myEdgePriorityRange
the difference between maximum and minimum priority for all edges
static double myPriorityFactor
Coefficient for factoring edge priority into routing weight.
static std::map< std::pair< const MSEdge *, const MSEdge * >, ConstMSRoutePtr > myCachedRoutes
The container of pre-calculated routes.
static SUMOTime adaptEdgeEfforts(SUMOTime currentTime)
Adapt edge efforts by the current edge states.
static bool myBikeSpeeds
whether separate speeds for bicycles shall be tracked
static void _initEdgeWeights(std::vector< double > &edgeSpeeds, std::vector< std::vector< double > > &pastEdgeSpeeds)
initialized edge speed storage into the given containers
static SumoRNG * getThreadRNG()
returns RNG associated with the current thread
static bool myWithTaz
whether taz shall be used at initial rerouting
static std::vector< std::vector< double > > myPastEdgeBikeSpeeds
static std::vector< double > myEdgeSpeeds
The container of edge speeds.
std::pair< SUMOTime, int > TimeAndCount
static std::map< std::thread::id, SumoRNG * > myThreadRNGs
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 bool myHaveRoutingThreads
static SUMOTime myLastAdaptation
Information when the last edge weight adaptation occurred.
static void cleanup()
deletes the router instance
static void initRouter(SUMOVehicle *vehicle=nullptr)
static SUMOAbstractRouter< MSEdge, SUMOVehicle >::Operation myEffortFunc
static void initGUIThreadRNG()
initialize RNG for the gui thread
static ConstMSRoutePtr getCachedRoute(const std::pair< const MSEdge *, const MSEdge * > &key)
return the cached route or nullptr on miss
static int myAdaptationSteps
The number of steps for averaging edge speeds (ring-buffer)
static MSRouterProvider * myRouterProvider
The router to use.
std::map< const MSEdge *, double > Prohibitions
static Command * myEdgeWeightSettingCommand
The weights adaptation/overwriting command.
static std::vector< std::vector< double > > myPastEdgeSpeeds
The container of past edge speeds (when using a simple moving average)
static void reroute(SUMOVehicle &vehicle, const SUMOTime currentTime, const std::string &info, const bool onInit=false, const bool silent=false, const Prohibitions &prohibited={})
initiate the rerouting, create router / thread pool on first use
static double getEffort(const MSEdge *const e, const SUMOVehicle *const v, double t)
Returns the effort to pass an edge.
static double getAssumedSpeed(const MSEdge *edge, const SUMOVehicle *veh)
return current travel speed assumption
static void loadState(const SUMOSAXAttributes &attrs)
Loads the state.
static double patchSpeedForTurns(const MSEdge *edge, double currSpeed)
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
static double getEffortExtra(const MSEdge *const e, const SUMOVehicle *const v, double t)
static MSTransportableRouter & getIntermodalRouterTT(const int rngIndex, const Prohibitions &prohibited={})
return the person router instance
static std::vector< double > myEdgeBikeSpeeds
int getRNGIndex() const
returns the index of the associated RNG
bool reroute(SUMOTime t, const std::string &info, MSTransportableRouter &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
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)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
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.
static bool createDeviceByOption(const std::string &optionName, const std::string &rootElement="", const std::string &schemaFile="")
Creates the device using the output definition stored in the named option.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
SUMOAbstractRouter< E, V > & getVehicleRouter(SUMOVehicleClass svc) const
RouterProvider * clone()
IntermodalRouter< E, L, N, V > & getIntermodalRouter() const
virtual void prohibit(const Prohibitions &toProhibit)
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.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
virtual double getChosenSpeedFactor() const =0
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)=0
Performs a rerouting using the given router.
virtual void setChosenSpeedFactor(const double factor)=0
static int parseCarWalkTransfer(const OptionsCont &oc, const bool hasTaxi=false)
A wrapper for a Command function.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
@ key
the parser read a key of a value in an object