Eclipse SUMO - Simulation of Urban MObility
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-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 /****************************************************************************/
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>
32 #include <microsim/MSGlobals.h>
41 #include <utils/router/CHRouter.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;
65 std::map<std::pair<const MSEdge*, const MSEdge*>, ConstMSRoutePtr> MSRoutingEngine::myCachedRoutes;
67 double MSRoutingEngine::myMinEdgePriority(std::numeric_limits<double>::max());
69 std::map<std::thread::id, SumoRNG*> MSRoutingEngine::myThreadRNGs;
71 
73 #ifdef HAVE_FOX
74 FXMutex MSRoutingEngine::myRouteCacheMutex;
75 #endif
76 
77 
78 // ===========================================================================
79 // method definitions
80 // ===========================================================================
81 void
83  if (myAdaptationInterval == -1) {
85  myEdgeSpeeds.clear();
86  myEdgeTravelTimes.clear();
87  myAdaptationSteps = -1;
88  myLastAdaptation = -1;
90  myWithTaz = oc.getBool("device.rerouting.with-taz");
91  myAdaptationInterval = string2time(oc.getString("device.rerouting.adaptation-interval"));
92  myAdaptationWeight = oc.getFloat("device.rerouting.adaptation-weight");
93  const SUMOTime period = string2time(oc.getString("device.rerouting.period"));
94  if (myAdaptationWeight < 1. && myAdaptationInterval > 0) {
97  } else if (period > 0) {
98  WRITE_WARNING(TL("Rerouting is useless if the edge weights do not get updated!"));
99  }
100  OutputDevice::createDeviceByOption("device.rerouting.output", "weights", "meandata_file.xsd");
101  }
102 }
103 
104 
105 void
107  if (myBikeSpeeds && svc == SVC_BICYCLE) {
109  } else {
111  }
112 }
113 
114 
115 void
116 MSRoutingEngine::_initEdgeWeights(std::vector<double>& edgeSpeeds, std::vector<std::vector<double> >& pastEdgeSpeeds) {
117  if (edgeSpeeds.empty()) {
118  const OptionsCont& oc = OptionsCont::getOptions();
119  if (myAdaptationWeight == 0 || !oc.isDefault("device.rerouting.adaptation-steps")) {
120  myAdaptationSteps = oc.getInt("device.rerouting.adaptation-steps");
121  }
122  const bool useLoaded = oc.getBool("device.rerouting.init-with-loaded-weights");
123  const double currentSecond = SIMTIME;
124  double maxEdgePriority = -std::numeric_limits<double>::max();
125  for (const MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
126  while (edge->getNumericalID() >= (int)edgeSpeeds.size()) {
127  edgeSpeeds.push_back(0);
128  if (myAdaptationSteps > 0) {
129  pastEdgeSpeeds.push_back(std::vector<double>());
130  }
131  if (MSGlobals::gWeightsSeparateTurns && edgeSpeeds == myEdgeSpeeds) {
132  myEdgeTravelTimes.push_back(TimeAndCount(0, 0));
133  }
134  }
135  if (useLoaded) {
136  edgeSpeeds[edge->getNumericalID()] = edge->getLength() / MSNet::getTravelTime(edge, nullptr, currentSecond);
137  } else {
138  edgeSpeeds[edge->getNumericalID()] = edge->getMeanSpeed();
139  }
140  if (myAdaptationSteps > 0) {
141  pastEdgeSpeeds[edge->getNumericalID()] = std::vector<double>(myAdaptationSteps, edgeSpeeds[edge->getNumericalID()]);
142  }
143  maxEdgePriority = MAX2(maxEdgePriority, (double)edge->getPriority());
144  myMinEdgePriority = MIN2(myMinEdgePriority, (double)edge->getPriority());
145  }
146  myEdgePriorityRange = maxEdgePriority - myMinEdgePriority;
148  myPriorityFactor = oc.getFloat("weights.priority-factor");
149  if (myPriorityFactor < 0) {
150  throw ProcessError(TL("weights.priority-factor cannot be negative."));
151  }
152  if (myPriorityFactor > 0) {
153  if (myEdgePriorityRange == 0) {
154  WRITE_WARNING(TL("Option weights.priority-factor does not take effect because all edges have the same priority"));
155  myPriorityFactor = 0;
156  }
157  }
158  }
159 }
160 
161 
162 double
163 MSRoutingEngine::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double) {
164  const int id = e->getNumericalID();
165  if (id < (int)myEdgeSpeeds.size()) {
166  return MAX2(e->getLength() / MAX2(myEdgeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
167  }
168  return e->getMinimumTravelTime(v);
169 }
170 
171 
172 double
173 MSRoutingEngine::getEffortBike(const MSEdge* const e, const SUMOVehicle* const v, double) {
174  const int id = e->getNumericalID();
175  if (id < (int)myEdgeBikeSpeeds.size()) {
176  return MAX2(e->getLength() / MAX2(myEdgeBikeSpeeds[id], NUMERICAL_EPS), e->getMinimumTravelTime(v));
177  }
178  return e->getMinimumTravelTime(v);
179 }
180 
181 SumoRNG*
183  if (myHaveRoutingThreads) {
184  auto it = myThreadRNGs.find(std::this_thread::get_id());
185  if (it != myThreadRNGs.end()) {
186  return it->second;
187  } else {
188  SumoRNG* rng = new SumoRNG("routing_" + toString(myThreadRNGs.size()));
189  myThreadRNGs[std::this_thread::get_id()] = rng;
190  return rng;
191  }
192  }
193  return nullptr;
194 }
195 
196 
197 double
198 MSRoutingEngine::getEffortExtra(const MSEdge* const e, const SUMOVehicle* const v, double t) {
199  double effort = (!myBikeSpeeds || v == nullptr || v->getVClass() != SVC_BICYCLE
200  ? getEffort(e, v, t)
201  : getEffortBike(e, v, t));
202  if (gWeightsRandomFactor != 1.) {
204  }
205  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  const double relativeInversePrio = 1 - ((e->getPriority() - myMinEdgePriority) / myEdgePriorityRange);
209  effort *= 1 + relativeInversePrio * myPriorityFactor;
210  }
211  return effort;
212 }
213 
214 
215 double
217  return edge->getLength() / myEffortFunc(edge, veh, 0);
218 }
219 
220 
221 SUMOTime
224  if (myBikeSpeeds) {
226  }
227  if (MSNet::getInstance()->getVehicleControl().getDepartedVehicleNo() == 0) {
228  return myAdaptationInterval;
229  }
230  myCachedRoutes.clear();
232  const double newWeightFactor = (double)(1. - myAdaptationWeight);
233  for (const MSEdge* const e : edges) {
234  if (e->isDelayed()) {
235  const int id = e->getNumericalID();
236  double currSpeed = e->getMeanSpeed();
237  if (MSGlobals::gWeightsSeparateTurns > 0 && e->getNumSuccessors() > 1) {
238  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  if (myAdaptationSteps > 0) {
251  // moving average
253  myPastEdgeSpeeds[id][myAdaptationStepsIndex] = currSpeed;
254  if (myBikeSpeeds) {
255  const double currBikeSpeed = e->getMeanSpeedBike();
257  myPastEdgeBikeSpeeds[id][myAdaptationStepsIndex] = currBikeSpeed;
258  }
259  } else {
260  // exponential moving average
261  if (currSpeed != myEdgeSpeeds[id]) {
262  myEdgeSpeeds[id] = myEdgeSpeeds[id] * myAdaptationWeight + currSpeed * newWeightFactor;
263  }
264  if (myBikeSpeeds) {
265  const double currBikeSpeed = e->getMeanSpeedBike();
266  if (currBikeSpeed != myEdgeBikeSpeeds[id]) {
267  myEdgeBikeSpeeds[id] = myEdgeBikeSpeeds[id] * myAdaptationWeight + currBikeSpeed * newWeightFactor;
268  }
269  }
270  }
271  }
272  }
273  if (myAdaptationSteps > 0) {
275  }
276  myLastAdaptation = currentTime + DELTA_T; // because we run at the end of the time step
277  if (OptionsCont::getOptions().isSet("device.rerouting.output")) {
278  OutputDevice& dev = OutputDevice::getDeviceByOption("device.rerouting.output");
280  dev.writeAttr(SUMO_ATTR_ID, "device.rerouting");
281  dev.writeAttr(SUMO_ATTR_BEGIN, STEPS2TIME(currentTime));
283  for (const MSEdge* e : edges) {
284  dev.openTag(SUMO_TAG_EDGE);
285  dev.writeAttr(SUMO_ATTR_ID, e->getID());
286  dev.writeAttr("traveltime", myEffortFunc(e, nullptr, STEPS2TIME(currentTime)));
287  if (myBikeSpeeds) {
288  // @note edge-priority is not included here
289  dev.writeAttr("traveltimeBike", getEffortBike(e, nullptr, STEPS2TIME(currentTime)));
290  }
291  dev.closeTag();
292  }
293  dev.closeTag();
294  }
295  return myAdaptationInterval;
296 }
297 
298 
299 double
300 MSRoutingEngine::patchSpeedForTurns(const MSEdge* edge, double currSpeed) {
301  const double length = edge->getLength();
302  double maxSpeed = 0;
303  for (const auto& pair : edge->getViaSuccessors()) {
304  if (pair.second == nullptr) {
305  continue;
306  }
307  TimeAndCount& tc = myEdgeTravelTimes[pair.second->getNumericalID()];
308  if (tc.second > 0) {
309  const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
310  maxSpeed = MAX2(avgSpeed, maxSpeed);
311  }
312  }
313  if (maxSpeed > 0) {
314  // perform correction
315  const double correctedSpeed = MSGlobals::gWeightsSeparateTurns * maxSpeed + (1 - MSGlobals::gWeightsSeparateTurns) * currSpeed;
316  for (const auto& pair : edge->getViaSuccessors()) {
317  if (pair.second == nullptr) {
318  continue;
319  }
320  const int iid = pair.second->getNumericalID();
321  TimeAndCount& tc = myEdgeTravelTimes[iid];
322  if (tc.second > 0) {
323  const double avgSpeed = length / STEPS2TIME(tc.first / tc.second);
324  if (avgSpeed < correctedSpeed) {
325  double internalTT = pair.second->getLength() / pair.second->getSpeedLimit();
326  internalTT += (length / avgSpeed - length / correctedSpeed) * MSGlobals::gWeightsSeparateTurns;
327  const double origInternalSpeed = myEdgeSpeeds[iid];
328  const double newInternalSpeed = pair.second->getLength() / internalTT;
329  const double origCurrSpeed = myPastEdgeSpeeds[iid][myAdaptationStepsIndex];
330 
331  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  const double virtualSpeed = (newInternalSpeed - (origInternalSpeed - origCurrSpeed / myAdaptationSteps)) * myAdaptationSteps;
338  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  if (myAdaptationStepsIndex == 0) {
356  tc.first = 0;
357  tc.second = 0;
358  }
359  }
360  }
361  return correctedSpeed;
362  }
363  return currSpeed;
364 }
365 
366 
368 MSRoutingEngine::getCachedRoute(const std::pair<const MSEdge*, const MSEdge*>& key) {
369  auto routeIt = myCachedRoutes.find(key);
370  if (routeIt != myCachedRoutes.end()) {
371  return routeIt->second;
372  }
373  return nullptr;
374 }
375 
376 
377 void
380  const std::string routingAlgorithm = oc.getString("routing-algorithm");
381  const bool hasPermissions = MSNet::getInstance()->hasPermissions();
382  myBikeSpeeds = oc.getBool("device.rerouting.bike-speeds");
384 
385  SUMOAbstractRouter<MSEdge, SUMOVehicle>* router = nullptr;
386  if (routingAlgorithm == "dijkstra") {
387  router = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, nullptr, true);
388  } else if (routingAlgorithm == "astar") {
389  typedef AStarRouter<MSEdge, SUMOVehicle> AStar;
390  std::shared_ptr<const AStar::LookupTable> lookup = nullptr;
391  if (oc.isSet("astar.all-distances")) {
392  lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)MSEdge::getAllEdges().size());
393  } else if (oc.isSet("astar.landmark-distances") && vehicle != nullptr) {
394  const double speedFactor = vehicle->getChosenSpeedFactor();
395  // we need an exemplary vehicle with speedFactor 1
396  vehicle->setChosenSpeedFactor(1);
399  string2time(oc.getString("begin")), string2time(oc.getString("end")), SUMOTime_MAX, hasPermissions, 1);
400  lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), MSEdge::getAllEdges(), &chrouter,
401  nullptr, vehicle, "", oc.getInt("device.rerouting.threads"));
402  vehicle->setChosenSpeedFactor(speedFactor);
403  }
404  router = new AStar(MSEdge::getAllEdges(), true, myEffortFunc, lookup, true);
405  } else if (routingAlgorithm == "CH" && !hasPermissions) {
406  const SUMOTime weightPeriod = myAdaptationInterval > 0 ? myAdaptationInterval : SUMOTime_MAX;
407  router = new CHRouter<MSEdge, SUMOVehicle>(
408  MSEdge::getAllEdges(), true, myEffortFunc, vehicle == nullptr ? SVC_PASSENGER : vehicle->getVClass(), weightPeriod, true, false);
409  } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
410  // use CHWrapper instead of CH if the net has permissions
411  const SUMOTime weightPeriod = myAdaptationInterval > 0 ? myAdaptationInterval : SUMOTime_MAX;
414  string2time(oc.getString("begin")), string2time(oc.getString("end")), weightPeriod, hasPermissions, oc.getInt("device.rerouting.threads"));
415  } else {
416  throw ProcessError(TLF("Unknown routing algorithm '%'!", routingAlgorithm));
417  }
418 
419  RailwayRouter<MSEdge, SUMOVehicle>* railRouter = nullptr;
420  if (MSNet::getInstance()->hasBidiEdges()) {
421  railRouter = new RailwayRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, myEffortFunc, nullptr, false, true, false, oc.getFloat("railway.max-train-length"));
422  }
423  const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc);
424  const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
425  MSTransportableRouter* transRouter = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, 0);
426  myRouterProvider = new MSRouterProvider(router, nullptr, transRouter, railRouter);
427 #ifndef THREAD_POOL
428 #ifdef HAVE_FOX
429  MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
430  if (threadPool.size() > 0) {
431  const std::vector<MFXWorkerThread*>& threads = threadPool.getWorkers();
432  if (static_cast<MSEdgeControl::WorkerThread*>(threads.front())->setRouterProvider(myRouterProvider)) {
433  for (std::vector<MFXWorkerThread*>::const_iterator t = threads.begin() + 1; t != threads.end(); ++t) {
434  static_cast<MSEdgeControl::WorkerThread*>(*t)->setRouterProvider(myRouterProvider->clone());
435  }
436  }
437  myHaveRoutingThreads = true;
438  }
439 #endif
440 #endif
441 }
442 
443 
444 void
445 MSRoutingEngine::reroute(SUMOVehicle& vehicle, const SUMOTime currentTime, const std::string& info,
446  const bool onInit, const bool silent, const MSEdgeVector& prohibited) {
447  if (myRouterProvider == nullptr) {
448  initRouter(&vehicle);
449  }
450  auto& router = myRouterProvider->getVehicleRouter(vehicle.getVClass());
451 #ifndef THREAD_POOL
452 #ifdef HAVE_FOX
453  MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
454  if (threadPool.size() > 0) {
455  threadPool.add(new RoutingTask(vehicle, currentTime, info, onInit, silent, prohibited));
456  return;
457  }
458 #endif
459 #endif
460  if (!prohibited.empty()) {
461  router.prohibit(prohibited);
462  }
463  try {
464  vehicle.reroute(currentTime, info, router, onInit, myWithTaz, silent);
465  } catch (ProcessError&) {
466  if (!silent) {
467  if (!prohibited.empty()) {
468  router.prohibit(MSEdgeVector());
469  }
470  throw;
471  }
472  }
473  if (!prohibited.empty()) {
474  router.prohibit(MSEdgeVector());
475  }
476 }
477 
478 
479 void
480 MSRoutingEngine::reroute(MSTransportable& t, const SUMOTime currentTime, const std::string& info,
481  const bool onInit, const bool silent, const MSEdgeVector& prohibited) {
482  MSTransportableRouter& router = getIntermodalRouterTT(t.getRNGIndex(), prohibited);
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(t, currentTime, info, onInit, silent, prohibited));
488  return;
489  }
490 #endif
491 #endif
492  if (!prohibited.empty()) {
493  router.prohibit(prohibited);
494  }
495  try {
496  t.reroute(currentTime, info, router, onInit, myWithTaz, silent);
497  } catch (ProcessError&) {
498  if (!silent) {
499  if (!prohibited.empty()) {
500  router.prohibit(MSEdgeVector());
501  }
502  throw;
503  }
504  }
505  if (!prohibited.empty()) {
506  router.prohibit(MSEdgeVector());
507  }
508 }
509 
510 
511 void
512 MSRoutingEngine::setEdgeTravelTime(const MSEdge* const edge, const double travelTime) {
513  myEdgeSpeeds[edge->getNumericalID()] = edge->getLength() / travelTime;
514 }
515 
516 void
517 MSRoutingEngine::addEdgeTravelTime(const MSEdge& edge, const SUMOTime travelTime) {
519  tc.first += travelTime;
520  tc.second += 1;
521 }
522 
523 
525 MSRoutingEngine::getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector& prohibited) {
526  if (myRouterProvider == nullptr) {
528  initEdgeWeights(svc);
529  initRouter();
530  }
531 #ifndef THREAD_POOL
532 #ifdef HAVE_FOX
533  MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
534  if (threadPool.size() > 0) {
535  auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getRouter(svc);
536  router.prohibit(prohibited);
537  return router;
538  }
539 #else
540  UNUSED_PARAMETER(rngIndex);
541 #endif
542 #endif
543  myRouterProvider->getVehicleRouter(svc).prohibit(prohibited);
544  return myRouterProvider->getVehicleRouter(svc);
545 }
546 
547 
549 MSRoutingEngine::getIntermodalRouterTT(const int rngIndex, const MSEdgeVector& prohibited) {
550  if (myRouterProvider == nullptr) {
553  initRouter();
554  }
555 #ifndef THREAD_POOL
556 #ifdef HAVE_FOX
557  MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
558  if (threadPool.size() > 0) {
559  auto& router = static_cast<MSEdgeControl::WorkerThread*>(threadPool.getWorkers()[rngIndex % MSGlobals::gNumThreads])->getIntermodalRouter();
560  router.prohibit(prohibited);
561  return router;
562  }
563 #else
564  UNUSED_PARAMETER(rngIndex);
565 #endif
566 #endif
567  myRouterProvider->getIntermodalRouter().prohibit(prohibited);
569 }
570 
571 
572 void
574  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();
586 #ifdef HAVE_FOX
587  if (MSGlobals::gNumThreads > 1) {
588  // router deletion is done in thread destructor
589  myRouterProvider = nullptr;
590  return;
591  }
592 #endif
593  delete myRouterProvider;
594  myRouterProvider = nullptr;
595 }
596 
597 
598 #ifdef HAVE_FOX
599 void
600 MSRoutingEngine::waitForAll() {
601 #ifndef THREAD_POOL
602  MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
603  if (threadPool.size() > 0) {
604  threadPool.waitAll();
605  }
606 #endif
607 }
608 
609 
610 // ---------------------------------------------------------------------------
611 // MSRoutingEngine::RoutingTask-methods
612 // ---------------------------------------------------------------------------
613 void
614 MSRoutingEngine::RoutingTask::run(MFXWorkerThread* context) {
615  SUMOAbstractRouter<MSEdge, SUMOVehicle>& router = static_cast<MSEdgeControl::WorkerThread*>(context)->getRouter(myVehicle.getVClass());
616  if (!myProhibited.empty()) {
617  router.prohibit(myProhibited);
618  }
619  try {
620  myVehicle.reroute(myTime, myInfo, router, myOnInit, myWithTaz, mySilent);
621  } catch (ProcessError&) {
622  if (!mySilent) {
623  if (!myProhibited.empty()) {
624  router.prohibit(MSEdgeVector());
625  }
626  throw;
627  }
628  }
629  if (!myProhibited.empty()) {
630  router.prohibit(MSEdgeVector());
631  }
632  const MSEdge* source = *myVehicle.getRoute().begin();
633  const MSEdge* dest = myVehicle.getRoute().getLastEdge();
634  if (source->isTazConnector() && dest->isTazConnector()) {
635  const std::pair<const MSEdge*, const MSEdge*> key = std::make_pair(source, dest);
636  FXMutexLock lock(myRouteCacheMutex);
638  MSRoutingEngine::myCachedRoutes[key] = myVehicle.getRoutePtr();
639  }
640  }
641 }
642 #endif
643 
644 
645 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:73
RouterProvider< MSEdge, MSLane, MSJunction, SUMOVehicle > MSRouterProvider
Definition: MSRouterDefs.h:39
IntermodalRouter< MSEdge, MSLane, MSJunction, SUMOVehicle > MSTransportableRouter
Definition: MSRouterDefs.h:41
#define DEBUG_COND(obj)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:31
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_EDGE
begin/end of the description of an edge
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ID
double gWeightsRandomFactor
Definition: StdDefs.cpp:32
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
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::vector< E * > &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:1034
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:1236
double getLength() const
return the length of the edge
Definition: MSEdge.h:670
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
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:174
static int gNumThreads
how many threads to use
Definition: MSGlobals.h:146
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:481
static double getTravelTime(const MSEdge *const e, const SUMOVehicle *const v, double t)
Returns the travel time to pass an edge.
Definition: MSNet.cpp:164
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:421
bool hasPermissions() const
Returns whether the network has specific vehicle class permissions.
Definition: MSNet.h:207
static void adaptIntermodalRouter(MSTransportableRouter &router)
Definition: MSNet.cpp:1544
static SUMOTime myAdaptationInterval
At which time interval the edge weights get updated.
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 void reroute(SUMOVehicle &vehicle, const SUMOTime currentTime, const std::string &info, const bool onInit=false, const bool silent=false, const MSEdgeVector &prohibited=MSEdgeVector())
initiate the rerouting, create router / thread pool on first use
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 void initEdgeWeights(SUMOVehicleClass svc)
initialize the edge weights if not done before
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector &prohibited=MSEdgeVector())
return the vehicle router instance
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 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.
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 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 MSTransportableRouter & getIntermodalRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector())
return the person router instance
static double patchSpeedForTurns(const MSEdge *edge, double currSpeed)
static double getEffortExtra(const MSEdge *const e, const SUMOVehicle *const v, double t)
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.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
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.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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)
Definition: RandHelper.cpp:94
RouterProvider * clone()
SUMOAbstractRouter< E, V > & getVehicleRouter(SUMOVehicleClass svc) const
IntermodalRouter< E, L, N, V > & getIntermodalRouter() const
virtual void prohibit(const std::vector< E * > &toProhibit)
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.
Definition: StaticCommand.h:38
@ key
the parser read a key of a value in an object