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>
47
48//#define DEBUG_SEPARATE_TURNS
49#define DEBUG_COND(obj) (obj->isSelected())
50
51// ===========================================================================
52// static member variables
53// ===========================================================================
54std::vector<double> MSRoutingEngine::myEdgeSpeeds;
55std::vector<double> MSRoutingEngine::myEdgeBikeSpeeds;
56std::vector<MSRoutingEngine::TimeAndCount> MSRoutingEngine::myEdgeTravelTimes;
57std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeSpeeds;
58std::vector<std::vector<double> > MSRoutingEngine::myPastEdgeBikeSpeeds;
68std::map<std::pair<const MSEdge*, const MSEdge*>, ConstMSRoutePtr> MSRoutingEngine::myCachedRoutes;
70double MSRoutingEngine::myMinEdgePriority(std::numeric_limits<double>::max());
72std::map<std::thread::id, SumoRNG*> MSRoutingEngine::myThreadRNGs;
74
76#ifdef HAVE_FOX
77FXMutex MSRoutingEngine::myRouteCacheMutex;
78#endif
79
80
81// ===========================================================================
82// method definitions
83// ===========================================================================
84void
86 if (myAdaptationInterval == -1) {
88 myEdgeSpeeds.clear();
89 myEdgeTravelTimes.clear();
93 myWithTaz = oc.getBool("device.rerouting.with-taz");
94 myAdaptationInterval = string2time(oc.getString("device.rerouting.adaptation-interval"));
95 myAdaptationWeight = oc.getFloat("device.rerouting.adaptation-weight");
96 const SUMOTime period = string2time(oc.getString("device.rerouting.period"));
100 } else if (period > 0) {
101 WRITE_WARNING(TL("Rerouting is useless if the edge weights do not get updated!"));
102 }
103 OutputDevice::createDeviceByOption("device.rerouting.output", "weights", "meandata_file.xsd");
104 }
105}
106
107
108void
110 if (myBikeSpeeds && svc == SVC_BICYCLE) {
112 } else {
114 }
115 if (lastAdaption >= 0) {
116 myLastAdaptation = lastAdaption;
117 }
118 if (index >= 0) {
119 assert(index < (int)myPastEdgeSpeeds.size());
121 }
122}
123
124
125void
126MSRoutingEngine::_initEdgeWeights(std::vector<double>& edgeSpeeds, std::vector<std::vector<double> >& pastEdgeSpeeds) {
127 if (edgeSpeeds.empty()) {
129 if (myAdaptationWeight == 0 || !oc.isDefault("device.rerouting.adaptation-steps")) {
130 myAdaptationSteps = oc.getInt("device.rerouting.adaptation-steps");
131 }
132 const bool useLoaded = oc.getBool("device.rerouting.init-with-loaded-weights");
133 const double currentSecond = SIMTIME;
134 double maxEdgePriority = -std::numeric_limits<double>::max();
135 for (const MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
136 while (edge->getNumericalID() >= (int)edgeSpeeds.size()) {
137 edgeSpeeds.push_back(0);
138 if (myAdaptationSteps > 0) {
139 pastEdgeSpeeds.push_back(std::vector<double>());
140 }
141 if (MSGlobals::gWeightsSeparateTurns && edgeSpeeds == myEdgeSpeeds) {
142 myEdgeTravelTimes.push_back(TimeAndCount(0, 0));
143 }
144 }
145 if (useLoaded) {
146 edgeSpeeds[edge->getNumericalID()] = edge->getLength() / MSNet::getTravelTime(edge, nullptr, currentSecond);
147 } else {
148 edgeSpeeds[edge->getNumericalID()] = edge->getMeanSpeed();
149 }
150 if (myAdaptationSteps > 0) {
151 pastEdgeSpeeds[edge->getNumericalID()] = std::vector<double>(myAdaptationSteps, edgeSpeeds[edge->getNumericalID()]);
152 }
153 maxEdgePriority = MAX2(maxEdgePriority, (double)edge->getPriority());
154 myMinEdgePriority = MIN2(myMinEdgePriority, (double)edge->getPriority());
155 }
156 myEdgePriorityRange = maxEdgePriority - myMinEdgePriority;
158 myPriorityFactor = oc.getFloat("weights.priority-factor");
159 if (myPriorityFactor < 0) {
160 throw ProcessError(TL("weights.priority-factor cannot be negative."));
161 }
162 if (myPriorityFactor > 0) {
163 if (myEdgePriorityRange == 0) {
164 WRITE_WARNING(TL("Option weights.priority-factor does not take effect because all edges have the same priority"));
166 }
167 }
168 }
169}
170
171
172double
173MSRoutingEngine::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double) {
174 const int id = e->getNumericalID();
175 if (id < (int)myEdgeSpeeds.size()) {
176 return MAX2(e->getLength() / MAX2(myEdgeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
177 }
178 return e->getMinimumTravelTime(v);
179}
180
181
182double
183MSRoutingEngine::getEffortBike(const MSEdge* const e, const SUMOVehicle* const v, double) {
184 const int id = e->getNumericalID();
185 if (id < (int)myEdgeBikeSpeeds.size()) {
186 return MAX2(e->getLength() / MAX2(myEdgeBikeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
187 }
188 return e->getMinimumTravelTime(v);
189}
190
191SumoRNG*
194 auto it = myThreadRNGs.find(std::this_thread::get_id());
195 // created by InitTask
196 assert(it != myThreadRNGs.end());
197 return it->second;
198 }
199 return nullptr;
200}
201
202
203double
204MSRoutingEngine::getEffortExtra(const MSEdge* const e, const SUMOVehicle* const v, double t) {
205 double effort = (!myBikeSpeeds || v == nullptr || v->getVClass() != SVC_BICYCLE
206 ? getEffort(e, v, t)
207 : getEffortBike(e, v, t));
208 if (gWeightsRandomFactor != 1.) {
210 }
211 if (myPriorityFactor != 0) {
212 // lower priority should result in higher effort (and the edge with
213 // minimum priority receives a factor of 1 + myPriorityFactor
214 const double relativeInversePrio = 1 - ((e->getPriority() - myMinEdgePriority) / myEdgePriorityRange);
215 effort *= 1 + relativeInversePrio * myPriorityFactor;
216 }
219 }
220 return effort;
221}
222
223
224double
226 return edge->getLength() / myEffortFunc(edge, veh, 0);
227}
228
229
233 if (myBikeSpeeds) {
235 }
236 if (MSNet::getInstance()->getVehicleControl().getDepartedVehicleNo() == 0) {
238 }
239 myCachedRoutes.clear();
241 const double newWeightFactor = (double)(1. - myAdaptationWeight);
242 for (const MSEdge* const e : edges) {
243 if (e->isDelayed()) {
244 const int id = e->getNumericalID();
245 double currSpeed = e->getMeanSpeed();
246 if (MSGlobals::gWeightsSeparateTurns > 0 && e->getNumSuccessors() > 1) {
247 currSpeed = patchSpeedForTurns(e, currSpeed);
248 }
249#ifdef DEBUG_SEPARATE_TURNS
250 if (DEBUG_COND(e->getLanes()[0])) {
251 std::cout << SIMTIME << " edge=" << e->getID()
252 << " meanSpeed=" << e->getMeanSpeed()
253 << " currSpeed=" << currSpeed
254 << " oldestSpeed=" << myPastEdgeSpeeds[id][myAdaptationStepsIndex]
255 << " oldAvg=" << myEdgeSpeeds[id]
256 << "\n";
257 }
258#endif
259 if (myAdaptationSteps > 0) {
260 // moving average
263 if (myBikeSpeeds) {
264 const double currBikeSpeed = e->getMeanSpeedBike();
266 myPastEdgeBikeSpeeds[id][myAdaptationStepsIndex] = currBikeSpeed;
267 }
268 } else {
269 // exponential moving average
270 if (currSpeed != myEdgeSpeeds[id]) {
271 myEdgeSpeeds[id] = myEdgeSpeeds[id] * myAdaptationWeight + currSpeed * newWeightFactor;
272 }
273 if (myBikeSpeeds) {
274 const double currBikeSpeed = e->getMeanSpeedBike();
275 if (currBikeSpeed != myEdgeBikeSpeeds[id]) {
276 myEdgeBikeSpeeds[id] = myEdgeBikeSpeeds[id] * myAdaptationWeight + currBikeSpeed * newWeightFactor;
277 }
278 }
279 }
280 }
281 }
282 if (myAdaptationSteps > 0) {
284 }
285 myLastAdaptation = currentTime + DELTA_T; // because we run at the end of the time step
286 if (OptionsCont::getOptions().isSet("device.rerouting.output")) {
287 OutputDevice& dev = OutputDevice::getDeviceByOption("device.rerouting.output");
289 dev.writeAttr(SUMO_ATTR_ID, "device.rerouting");
290 dev.writeAttr(SUMO_ATTR_BEGIN, STEPS2TIME(currentTime));
292 for (const MSEdge* e : edges) {
294 dev.writeAttr(SUMO_ATTR_ID, e->getID());
295 dev.writeAttr("traveltime", myEffortFunc(e, nullptr, STEPS2TIME(currentTime)));
296 if (myBikeSpeeds) {
297 // @note edge-priority is not included here
298 dev.writeAttr("traveltimeBike", getEffortBike(e, nullptr, STEPS2TIME(currentTime)));
299 }
300 dev.closeTag();
301 }
302 dev.closeTag();
303 }
305}
306
307
308double
309MSRoutingEngine::patchSpeedForTurns(const MSEdge* edge, double currSpeed) {
310 const double length = edge->getLength();
311 double maxSpeed = 0;
312 for (const auto& pair : edge->getViaSuccessors()) {
313 if (pair.second == nullptr) {
314 continue;
315 }
316 TimeAndCount& tc = myEdgeTravelTimes[pair.second->getNumericalID()];
317 if (tc.second > 0) {
318 const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
319 maxSpeed = MAX2(avgSpeed, maxSpeed);
320 }
321 }
322 if (maxSpeed > 0) {
323 // perform correction
324 const double correctedSpeed = MSGlobals::gWeightsSeparateTurns * maxSpeed + (1 - MSGlobals::gWeightsSeparateTurns) * currSpeed;
325 for (const auto& pair : edge->getViaSuccessors()) {
326 if (pair.second == nullptr) {
327 continue;
328 }
329 const int iid = pair.second->getNumericalID();
331 if (tc.second > 0) {
332 const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
333 if (avgSpeed < correctedSpeed) {
334 double internalTT = pair.second->getLength() / pair.second->getSpeedLimit();
335 internalTT += (length / avgSpeed - length / correctedSpeed) * MSGlobals::gWeightsSeparateTurns;
336 const double origInternalSpeed = myEdgeSpeeds[iid];
337 const double newInternalSpeed = pair.second->getLength() / internalTT;
338 const double origCurrSpeed = myPastEdgeSpeeds[iid][myAdaptationStepsIndex];
339
340 myEdgeSpeeds[iid] = newInternalSpeed;
341 // to ensure myEdgeSpeed reverts to the speed limit
342 // when there are no updates, we also have to patch
343 // myPastEdgeSpeeds with a virtual value that is consistent
344 // with the updated speed
345 // note: internal edges were handled before the normal ones
346 const double virtualSpeed = (newInternalSpeed - (origInternalSpeed - origCurrSpeed / myAdaptationSteps)) * myAdaptationSteps;
347 myPastEdgeSpeeds[iid][myAdaptationStepsIndex] = virtualSpeed;
348
349#ifdef DEBUG_SEPARATE_TURNS
350 if (DEBUG_COND(pair.second->getLanes()[0])) {
351 std::cout << SIMTIME << " edge=" << edge->getID() << " to=" << pair.first->getID() << " via=" << pair.second->getID()
352 << " origSpeed=" << currSpeed
353 << " maxSpeed=" << maxSpeed
354 << " correctedSpeed=" << correctedSpeed
355 << " avgSpeed=" << avgSpeed
356 << " internalTT=" << internalTT
357 << " internalSpeed=" << origInternalSpeed
358 << " newInternalSpeed=" << newInternalSpeed
359 << " virtualSpeed=" << virtualSpeed
360 << "\n";
361 }
362#endif
363 }
364 if (myAdaptationStepsIndex == 0) {
365 tc.first = 0;
366 tc.second = 0;
367 }
368 }
369 }
370 return correctedSpeed;
371 }
372 return currSpeed;
373}
374
375
377MSRoutingEngine::getCachedRoute(const std::pair<const MSEdge*, const MSEdge*>& key) {
378 auto routeIt = myCachedRoutes.find(key);
379 if (routeIt != myCachedRoutes.end()) {
380 return routeIt->second;
381 }
382 return nullptr;
383}
384
385
386void
389 const std::string routingAlgorithm = oc.getString("routing-algorithm");
390 const bool hasPermissions = MSNet::getInstance()->hasPermissions();
391 myBikeSpeeds = oc.getBool("device.rerouting.bike-speeds");
393
395 if (routingAlgorithm == "dijkstra") {
396 router = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, nullptr, true);
397 } else if (routingAlgorithm == "astar") {
399 std::shared_ptr<const AStar::LookupTable> lookup = nullptr;
400 if (oc.isSet("astar.all-distances")) {
401 lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)MSEdge::getAllEdges().size());
402 } else if (oc.isSet("astar.landmark-distances") && vehicle != nullptr) {
403 const double speedFactor = vehicle->getChosenSpeedFactor();
404 // we need an exemplary vehicle with speedFactor 1
405 vehicle->setChosenSpeedFactor(1);
408 string2time(oc.getString("begin")), string2time(oc.getString("end")), SUMOTime_MAX, hasPermissions, 1);
409 lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), MSEdge::getAllEdges(), &chrouter,
410 nullptr, vehicle, "", oc.getInt("device.rerouting.threads"), MSNet::getInstance()->getMapMatcher());
411 vehicle->setChosenSpeedFactor(speedFactor);
412 }
413 router = new AStar(MSEdge::getAllEdges(), true, myEffortFunc, lookup, true);
414 } else if (routingAlgorithm == "CH" && !hasPermissions) {
417 MSEdge::getAllEdges(), true, myEffortFunc, vehicle == nullptr ? SVC_PASSENGER : vehicle->getVClass(), weightPeriod, true, false);
418 } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
419 // use CHWrapper instead of CH if the net has permissions
423 string2time(oc.getString("begin")), string2time(oc.getString("end")), weightPeriod, hasPermissions, oc.getInt("device.rerouting.threads"));
424 } else {
425 throw ProcessError(TLF("Unknown routing algorithm '%'!", routingAlgorithm));
426 }
427
428 RailwayRouter<MSEdge, SUMOVehicle>* railRouter = nullptr;
429 if (MSNet::getInstance()->hasBidiEdges()) {
430 railRouter = new RailwayRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, true, false,
431 oc.getFloat("railway.max-train-length"),
432 oc.getFloat("weights.reversal-penalty"));
433 }
434 const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, MSDevice_Taxi::hasFleet() || MSNet::getInstance()->getInsertionControl().hasTaxiFlow());
435 const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
436 MSTransportableRouter* transRouter = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, 0);
437 myRouterProvider = new MSRouterProvider(router, nullptr, transRouter, railRouter);
438#ifndef THREAD_POOL
439#ifdef HAVE_FOX
440 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
441 if (threadPool.size() > 0) {
442 const std::vector<MFXWorkerThread*>& threads = threadPool.getWorkers();
443 if (static_cast<MSEdgeControl::WorkerThread*>(threads.front())->setRouterProvider(myRouterProvider)) {
444 for (std::vector<MFXWorkerThread*>::const_iterator t = threads.begin() + 1; t != threads.end(); ++t) {
445 static_cast<MSEdgeControl::WorkerThread*>(*t)->setRouterProvider(myRouterProvider->clone());
446 }
447 }
449 for (int i = 0; i < threadPool.size(); i++) {
450 threadPool.add(new InitTask(), i);
451 }
452 threadPool.waitAll();
453 // to use when routing is triggered from the main thread (i.e. by a rerouter)
454 myThreadRNGs[std::this_thread::get_id()] = nullptr;
455 }
456#endif
457#endif
458}
459
460
461void
463#ifndef THREAD_POOL
464#ifdef HAVE_FOX
465 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
466 if (threadPool.size() > 0) {
467 FXMutexLock lock(myRouteCacheMutex);
468 SumoRNG* rng = new SumoRNG("routingGUI");
469 myThreadRNGs[std::this_thread::get_id()] = rng;
470 }
471#endif
472#endif
473}
474
475
476void
477MSRoutingEngine::reroute(SUMOVehicle& vehicle, const SUMOTime currentTime, const std::string& info,
478 const bool onInit, const bool silent, const Prohibitions& prohibited) {
479 if (myRouterProvider == nullptr) {
480 initRouter(&vehicle);
481 }
482 auto& router = myRouterProvider->getVehicleRouter(vehicle.getVClass());
483#ifndef THREAD_POOL
484#ifdef HAVE_FOX
485 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
486 if (threadPool.size() > 0) {
487 threadPool.add(new RoutingTask(vehicle, currentTime, info, onInit, silent, prohibited));
488 return;
489 }
490#endif
491#endif
492 if (!prohibited.empty()) {
493 router.prohibit(prohibited);
494 }
495 try {
496 vehicle.reroute(currentTime, info, router, onInit, myWithTaz, silent);
497 } catch (ProcessError&) {
498 if (!silent) {
499 if (!prohibited.empty()) {
500 router.prohibit(Prohibitions());
501 }
502 throw;
503 }
504 }
505 if (!prohibited.empty()) {
506 router.prohibit(Prohibitions());
507 }
508}
509
510
511void
512MSRoutingEngine::reroute(MSTransportable& t, const SUMOTime currentTime, const std::string& info,
513 const bool onInit, const bool silent, const Prohibitions& prohibited) {
515#ifndef THREAD_POOL
516#ifdef HAVE_FOX
517 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
518 if (threadPool.size() > 0) {
519 // threadPool.add(new RoutingTask(t, currentTime, info, onInit, silent, prohibited));
520 return;
521 }
522#endif
523#endif
524 if (!prohibited.empty()) {
525 router.prohibit(prohibited);
526 }
527 try {
528 t.reroute(currentTime, info, router, onInit, myWithTaz, silent);
529 } catch (ProcessError&) {
530 if (!silent) {
531 if (!prohibited.empty()) {
532 router.prohibit(Prohibitions());
533 }
534 throw;
535 }
536 }
537 if (!prohibited.empty()) {
538 router.prohibit(Prohibitions());
539 }
540}
541
542
543void
544MSRoutingEngine::setEdgeTravelTime(const MSEdge* const edge, const double travelTime) {
545 myEdgeSpeeds[edge->getNumericalID()] = edge->getLength() / travelTime;
546}
547
548void
549MSRoutingEngine::addEdgeTravelTime(const MSEdge& edge, const SUMOTime travelTime) {
551 tc.first += travelTime;
552 tc.second += 1;
553}
554
555
557MSRoutingEngine::getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions& prohibited) {
558 if (myRouterProvider == nullptr) {
560 initEdgeWeights(svc);
561 initRouter();
562 }
563#ifndef THREAD_POOL
564#ifdef HAVE_FOX
565 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
566 if (threadPool.size() > 0) {
567 auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getRouter(svc);
568 router.prohibit(prohibited);
569 return router;
570 }
571#else
572 UNUSED_PARAMETER(rngIndex);
573#endif
574#endif
575 myRouterProvider->getVehicleRouter(svc).prohibit(prohibited);
576 return myRouterProvider->getVehicleRouter(svc);
577}
578
579
581MSRoutingEngine::getIntermodalRouterTT(const int rngIndex, const Prohibitions& prohibited) {
582 if (myRouterProvider == nullptr) {
585 initRouter();
586 }
587#ifndef THREAD_POOL
588#ifdef HAVE_FOX
589 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
590 if (threadPool.size() > 0) {
591 auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getIntermodalRouter();
592 router.prohibit(prohibited);
593 return router;
594 }
595#else
596 UNUSED_PARAMETER(rngIndex);
597#endif
598#endif
599 myRouterProvider->getIntermodalRouter().prohibit(prohibited);
600 return myRouterProvider->getIntermodalRouter();
601}
602
603
604void
606 myAdaptationInterval = -1; // responsible for triggering initEdgeWeights
607 myPastEdgeSpeeds.clear();
608 myEdgeSpeeds.clear();
609 myEdgeTravelTimes.clear();
610 myPastEdgeBikeSpeeds.clear();
611 myEdgeBikeSpeeds.clear();
612 // @todo recheck. calling release crashes in parallel routing
613 //for (auto& item : myCachedRoutes) {
614 // item.second->release();
615 //}
616 myCachedRoutes.clear();
618#ifdef HAVE_FOX
619 if (MSGlobals::gNumThreads > 1) {
620 // router deletion is done in thread destructor
621 myRouterProvider = nullptr;
622 return;
623 }
624#endif
625 delete myRouterProvider;
626 myRouterProvider = nullptr;
627}
628
629
630void
632 if (myEdgeSpeeds.size() == 0) {
633 return;
634 }
639 for (const MSEdge* const e : edges) {
640 if (e->isDelayed()) {
641 const int id = e->getNumericalID();
643 out.writeAttr(SUMO_ATTR_ID, e->getID());
645 if (myAdaptationSteps > 0) {
647 }
648 if (myBikeSpeeds) {
650 if (myAdaptationSteps > 0) {
652 }
653 }
654 out.closeTag();
655 }
656 }
657 out.closeTag();
658}
659
660
661void
663 const MSEdge* const e = MSEdge::dictionary(attrs.getString(SUMO_ATTR_ID));
664 e->markDelayed();
665 const int id = e->getNumericalID();
666 bool checkedSteps = false;
667 bool checkedBikeSpeeds = false;
668 bool ok = true;
669 if ((int)myEdgeSpeeds.size() > id) {
670 myEdgeSpeeds[id] = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
671 if (myBikeSpeeds) {
673 myEdgeBikeSpeeds[id] = attrs.get<double>(SUMO_ATTR_BIKESPEED, nullptr, ok);
674 } else if (!checkedBikeSpeeds) {
675 checkedBikeSpeeds = true;
676 WRITE_WARNING("Bike speeds missing in loaded state");
677 }
678 }
679 if (myAdaptationSteps > 0) {
680 const std::vector<double> speeds = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PASTSPEED, nullptr, ok);
681 if ((int)speeds.size() == myAdaptationSteps) {
682 myPastEdgeSpeeds[id] = speeds;
684 myPastEdgeBikeSpeeds[id] = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PASTBIKESPEED, nullptr, ok);
685 }
686 } else if (!checkedSteps) {
687 checkedSteps = true;
688 WRITE_WARNING("Number of adaptation speeds in loaded state doesn't match option --device.rerouting.adaptation-steps");
689 }
690 }
691 }
692}
693
694
695#ifdef HAVE_FOX
696void
697MSRoutingEngine::waitForAll() {
698#ifndef THREAD_POOL
699 MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
700 if (threadPool.size() > 0) {
701 threadPool.waitAll();
702 }
703#endif
704}
705
706
707// ---------------------------------------------------------------------------
708// MSRoutingEngine::RoutingTask-methods
709// ---------------------------------------------------------------------------
710void
711MSRoutingEngine::RoutingTask::run(MFXWorkerThread* context) {
712 SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = static_cast<MSEdgeControl::WorkerThread*>(context)->getRouter(myVehicle.getVClass());
713 if (!myProhibited.empty()) {
714 router.prohibit(myProhibited);
715 }
716 try {
717 myVehicle.reroute(myTime, myInfo, router, myOnInit, myWithTaz, mySilent);
718 } catch (ProcessError&) {
719 if (!mySilent) {
720 if (!myProhibited.empty()) {
721 router.prohibit(Prohibitions());
722 }
723 throw;
724 }
725 }
726 if (!myProhibited.empty()) {
727 router.prohibit(Prohibitions());
728 }
729 const MSEdge* source = *myVehicle.getRoute().begin();
730 const MSEdge* dest = myVehicle.getRoute().getLastEdge();
731 if (source->isTazConnector() && dest->isTazConnector()) {
732 const std::pair<const MSEdge*, const MSEdge*> key = std::make_pair(source, dest);
733 FXMutexLock lock(myRouteCacheMutex);
735 MSRoutingEngine::myCachedRoutes[key] = myVehicle.getRoutePtr();
736 }
737 }
738}
739
740// ---------------------------------------------------------------------------
741// MSRoutingEngine::InitTask-methods
742// ---------------------------------------------------------------------------
743void
744MSRoutingEngine::InitTask::run(MFXWorkerThread* /*context*/) {
745 FXMutexLock lock(myRouteCacheMutex);
746 SumoRNG* rng = new SumoRNG("routing_" + toString(myThreadRNGs.size()));
747 myThreadRNGs[std::this_thread::get_id()] = rng;
748}
749
750#endif
751
752
753/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< MSEdge * > MSEdgeVector
Definition MSEdge.h:73
SUMOAbstractRouter< MSEdge, SUMOVehicle > MSVehicleRouter
RouterProvider< MSEdge, MSLane, MSJunction, SUMOVehicle > MSRouterProvider
IntermodalRouter< MSEdge, MSLane, MSJunction, SUMOVehicle > MSTransportableRouter
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
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
bool gRoutingPreferences
Definition StdDefs.cpp:37
double gWeightsRandomFactor
Definition StdDefs.cpp:35
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
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.
static bool hasFleet()
returns whether taxis have been loaded
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:1096
int getPriority() const
Returns the priority of the edge.
Definition MSEdge.h:336
const MSConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges with internal vias, restricted by vClass.
Definition MSEdge.cpp:1298
double getLength() const
return the length of the edge
Definition MSEdge.h:693
bool isTazConnector() const
Definition MSEdge.h:291
const std::string & getRoutingType() const
Returns the type of the edge.
Definition MSEdge.h:325
double getMinimumTravelTime(const SUMOVehicle *const veh) const
returns the minimum travel time for the given vehicle
Definition MSEdge.h:484
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:1057
void markDelayed() const
Definition MSEdge.h:737
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
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:495
double getPreference(const std::string &routingType, const SUMOVTypeParameter &pars) const
retriefe edge type specific routing preference
Definition MSNet.cpp:364
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
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:435
static void adaptIntermodalRouter(MSTransportableRouter &router)
Definition MSNet.cpp:1655
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 override
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).
double(* Operation)(const E *const, const V *const, double)
Type of the function that is used to retrieve the edge effort.
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 const SUMOVTypeParameter & getVTypeParameter() const =0
Returns the object's "vehicle" type parameter.
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)
A wrapper for a Command function.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
iterator find(const Key &key)
Definition json.hpp:17191
*brief create JSON pointer *sa reference_tokens end()