Eclipse SUMO - Simulation of Urban MObility
RONet.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 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 /****************************************************************************/
20 // The router's network representation
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <algorithm>
30 #include <utils/common/ToString.h>
35 #include "ROEdge.h"
36 #include "ROLane.h"
37 #include "RONode.h"
38 #include "ROPerson.h"
39 #include "RORoute.h"
40 #include "RORouteDef.h"
41 #include "ROVehicle.h"
42 #include "ROAbstractEdgeBuilder.h"
43 #include "RONet.h"
44 
45 
46 // ===========================================================================
47 // static member definitions
48 // ===========================================================================
49 RONet* RONet::myInstance = nullptr;
50 
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 RONet*
57  if (myInstance != nullptr) {
58  return myInstance;
59  }
60  throw ProcessError("A network was not yet constructed.");
61 }
62 
63 
65  myVehicleTypes(), myDefaultVTypeMayBeDeleted(true),
66  myDefaultPedTypeMayBeDeleted(true), myDefaultBikeTypeMayBeDeleted(true),
67  myHaveActiveFlows(true),
68  myRoutesOutput(nullptr), myRouteAlternativesOutput(nullptr), myTypesOutput(nullptr),
69  myReadRouteNo(0), myDiscardedRouteNo(0), myWrittenRouteNo(0),
70  myHavePermissions(false),
71  myNumInternalEdges(0),
72  myErrorHandler(OptionsCont::getOptions().exists("ignore-errors")
73  && OptionsCont::getOptions().getBool("ignore-errors") ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
74  myKeepVTypeDist(OptionsCont::getOptions().exists("keep-vtype-distributions")
75  && OptionsCont::getOptions().getBool("keep-vtype-distributions")),
76  myHasBidiEdges(false) {
77  if (myInstance != nullptr) {
78  throw ProcessError("A network was already constructed.");
79  }
81  type->onlyReferenced = true;
82  myVehicleTypes.add(type->id, type);
83 
85  defPedType->onlyReferenced = true;
87  myVehicleTypes.add(defPedType->id, defPedType);
88 
90  defBikeType->onlyReferenced = true;
92  myVehicleTypes.add(defBikeType->id, defBikeType);
93 
95  defTaxiType->onlyReferenced = true;
97  myVehicleTypes.add(defTaxiType->id, defTaxiType);
98 
99  myInstance = this;
100 }
101 
102 
104  for (RoutablesMap::iterator routables = myRoutables.begin(); routables != myRoutables.end(); ++routables) {
105  for (RORoutable* const r : routables->second) {
106  const ROVehicle* const veh = dynamic_cast<const ROVehicle*>(r);
107  // delete routes and the vehicle
108  if (veh != nullptr && veh->getRouteDefinition()->getID()[0] == '!') {
109  if (!myRoutes.remove(veh->getRouteDefinition()->getID())) {
110  delete veh->getRouteDefinition();
111  }
112  }
113  delete r;
114  }
115  }
116  for (const RORoutable* const r : myPTVehicles) {
117  const ROVehicle* const veh = dynamic_cast<const ROVehicle*>(r);
118  // delete routes and the vehicle
119  if (veh != nullptr && veh->getRouteDefinition()->getID()[0] == '!') {
120  if (!myRoutes.remove(veh->getRouteDefinition()->getID())) {
121  delete veh->getRouteDefinition();
122  }
123  }
124  delete r;
125  }
126  myRoutables.clear();
127 }
128 
129 
130 void
131 RONet::addRestriction(const std::string& id, const SUMOVehicleClass svc, const double speed) {
132  myRestrictions[id][svc] = speed;
133 }
134 
135 
136 const std::map<SUMOVehicleClass, double>*
137 RONet::getRestrictions(const std::string& id) const {
138  std::map<std::string, std::map<SUMOVehicleClass, double> >::const_iterator i = myRestrictions.find(id);
139  if (i == myRestrictions.end()) {
140  return nullptr;
141  }
142  return &i->second;
143 }
144 
145 
146 bool
148  if (!myEdges.add(edge->getID(), edge)) {
149  WRITE_ERROR("The edge '" + edge->getID() + "' occurs at least twice.");
150  delete edge;
151  return false;
152  }
153  if (edge->isInternal()) {
154  myNumInternalEdges += 1;
155  }
156  return true;
157 }
158 
159 
160 bool
161 RONet::addDistrict(const std::string id, ROEdge* source, ROEdge* sink) {
162  if (myDistricts.count(id) > 0) {
163  WRITE_ERROR("The TAZ '" + id + "' occurs at least twice.");
164  delete source;
165  delete sink;
166  return false;
167  }
169  addEdge(sink);
171  addEdge(source);
172  sink->setOtherTazConnector(source);
173  source->setOtherTazConnector(sink);
174  myDistricts[id] = std::make_pair(std::vector<std::string>(), std::vector<std::string>());
175  return true;
176 }
177 
178 
179 bool
180 RONet::addDistrictEdge(const std::string tazID, const std::string edgeID, const bool isSource) {
181  if (myDistricts.count(tazID) == 0) {
182  WRITE_ERROR("The TAZ '" + tazID + "' is unknown.");
183  return false;
184  }
185  ROEdge* edge = getEdge(edgeID);
186  if (edge == nullptr) {
187  WRITE_ERROR("The edge '" + edgeID + "' for TAZ '" + tazID + "' is unknown.");
188  return false;
189  }
190  if (isSource) {
191  getEdge(tazID + "-source")->addSuccessor(edge);
192  myDistricts[tazID].first.push_back(edgeID);
193  } else {
194  edge->addSuccessor(getEdge(tazID + "-sink"));
195  myDistricts[tazID].second.push_back(edgeID);
196  }
197  return true;
198 }
199 
200 
201 void
203  for (auto item : myNodes) {
204  const std::string tazID = item.first;
205  if (myDistricts.count(tazID) != 0) {
206  WRITE_WARNINGF("A TAZ with id '%' already exists. Not building junction TAZ.", tazID);
207  continue;
208  }
209  const std::string sourceID = tazID + "-source";
210  const std::string sinkID = tazID + "-sink";
211  // sink must be addd before source
212  ROEdge* sink = eb.buildEdge(sinkID, nullptr, nullptr, 0);
213  ROEdge* source = eb.buildEdge(sourceID, nullptr, nullptr, 0);
214  sink->setOtherTazConnector(source);
215  source->setOtherTazConnector(sink);
216  addDistrict(tazID, source, sink);
217  auto& district = myDistricts[tazID];
218  const RONode* junction = item.second;
219  for (const ROEdge* edge : junction->getIncoming()) {
220  if (!edge->isInternal()) {
221  const_cast<ROEdge*>(edge)->addSuccessor(sink);
222  district.second.push_back(edge->getID());
223  }
224  }
225  for (const ROEdge* edge : junction->getOutgoing()) {
226  if (!edge->isInternal()) {
227  source->addSuccessor(const_cast<ROEdge*>(edge));
228  district.first.push_back(edge->getID());
229  }
230  }
231  }
232 }
233 
234 void
235 RONet::setBidiEdges(const std::map<ROEdge*, std::string>& bidiMap) {
236  for (const auto& item : bidiMap) {
237  ROEdge* bidi = myEdges.get(item.second);
238  if (bidi == nullptr) {
239  WRITE_ERROR("The bidi edge '" + item.second + "' is not known.");
240  }
241  item.first->setBidiEdge(bidi);
242  myHasBidiEdges = true;
243  }
244 }
245 
246 void
248  if (!myNodes.add(node->getID(), node)) {
249  WRITE_ERROR("The node '" + node->getID() + "' occurs at least twice.");
250  delete node;
251  }
252 }
253 
254 
255 void
256 RONet::addStoppingPlace(const std::string& id, const SumoXMLTag category, SUMOVehicleParameter::Stop* stop) {
257  if (!myStoppingPlaces[category == SUMO_TAG_TRAIN_STOP ? SUMO_TAG_BUS_STOP : category].add(id, stop)) {
258  WRITE_ERROR("The " + toString(category) + " '" + id + "' occurs at least twice.");
259  delete stop;
260  }
261 }
262 
263 
264 bool
266  return myRoutes.add(def->getID(), def);
267 }
268 
269 
270 void
272  if (options.isSet("output-file") && options.getString("output-file") != "") {
273  myRoutesOutput = &OutputDevice::getDevice(options.getString("output-file"));
274  if (myRoutesOutput->isNull()) {
275  myRoutesOutput = nullptr;
276  } else {
278  myRoutesOutput->writeAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance").writeAttr("xsi:noNamespaceSchemaLocation", "http://sumo.dlr.de/xsd/routes_file.xsd");
279  }
280  }
281  if (options.exists("alternatives-output") && options.isSet("alternatives-output")
282  && !(options.exists("write-trips") && options.getBool("write-trips"))) {
283  myRouteAlternativesOutput = &OutputDevice::getDevice(options.getString("alternatives-output"));
285  myRouteAlternativesOutput = nullptr;
286  } else {
288  myRouteAlternativesOutput->writeAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance").writeAttr("xsi:noNamespaceSchemaLocation", "http://sumo.dlr.de/xsd/routes_file.xsd");
289  }
290  }
291  if (options.isSet("vtype-output")) {
292  myTypesOutput = &OutputDevice::getDevice(options.getString("vtype-output"));
294  myTypesOutput->writeAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance").writeAttr("xsi:noNamespaceSchemaLocation", "http://sumo.dlr.de/xsd/routes_file.xsd");
295  }
296 }
297 
298 
299 void
300 RONet::writeIntermodal(const OptionsCont& options, ROIntermodalRouter& router) const {
301  if (options.exists("intermodal-network-output") && options.isSet("intermodal-network-output")) {
302  OutputDevice::createDeviceByOption("intermodal-network-output", "intermodal");
303  router.writeNetwork(OutputDevice::getDevice(options.getString("intermodal-network-output")));
304  }
305  if (options.exists("intermodal-weight-output") && options.isSet("intermodal-weight-output")) {
306  OutputDevice::createDeviceByOption("intermodal-weight-output", "weights", "meandata_file.xsd");
307  OutputDevice& dev = OutputDevice::getDeviceByOption("intermodal-weight-output");
309  dev.writeAttr(SUMO_ATTR_ID, "intermodalweights");
310  dev.writeAttr(SUMO_ATTR_BEGIN, 0);
312  router.writeWeights(dev);
313  dev.closeTag();
314  }
315 }
316 
317 
318 void
320  // end writing
321  if (myRoutesOutput != nullptr) {
323  }
324  // only if opened
325  if (myRouteAlternativesOutput != nullptr) {
327  }
328  // only if opened
329  if (myTypesOutput != nullptr) {
330  myTypesOutput->close();
331  }
333 #ifdef HAVE_FOX
334  if (myThreadPool.size() > 0) {
335  myThreadPool.clear();
336  }
337 #endif
338 }
339 
340 
341 
343 RONet::getVehicleTypeSecure(const std::string& id) {
344  // check whether the type was already known
346  if (id == DEFAULT_VTYPE_ID) {
348  }
349  if (id == DEFAULT_PEDTYPE_ID) {
351  }
352  if (id == DEFAULT_BIKETYPE_ID) {
354  }
355  if (type != nullptr) {
356  return type;
357  }
358  VTypeDistDictType::iterator it2 = myVTypeDistDict.find(id);
359  if (it2 != myVTypeDistDict.end()) {
360  return it2->second->get();
361  }
362  if (id == "") {
363  // ok, no vehicle type or an unknown type was given within the user input
364  // return the default type
367  }
368  return type;
369 }
370 
371 
372 bool
373 RONet::checkVType(const std::string& id) {
374  if (id == DEFAULT_VTYPE_ID) {
378  } else {
379  return false;
380  }
381  } else if (id == DEFAULT_PEDTYPE_ID) {
385  } else {
386  return false;
387  }
388  } else {
389  if (myVehicleTypes.get(id) != 0 || myVTypeDistDict.find(id) != myVTypeDistDict.end()) {
390  return false;
391  }
392  }
393  return true;
394 }
395 
396 
397 bool
399  if (checkVType(type->id)) {
400  myVehicleTypes.add(type->id, type);
401  } else {
402  WRITE_ERROR("The vehicle type '" + type->id + "' occurs at least twice.");
403  delete type;
404  return false;
405  }
406  return true;
407 }
408 
409 
410 bool
411 RONet::addVTypeDistribution(const std::string& id, RandomDistributor<SUMOVTypeParameter*>* vehTypeDistribution) {
412  if (checkVType(id)) {
413  myVTypeDistDict[id] = vehTypeDistribution;
414  return true;
415  }
416  delete vehTypeDistribution;
417  return false;
418 }
419 
420 
421 bool
422 RONet::addVehicle(const std::string& id, ROVehicle* veh) {
423  if (myVehIDs.find(id) == myVehIDs.end()) {
425 
426  if (veh->isPublicTransport()) {
427  if (!veh->isPartOfFlow()) {
428  myPTVehicles.push_back(veh);
429  }
430  if (OptionsCont::getOptions().exists("ptline-routing") && !OptionsCont::getOptions().getBool("ptline-routing")) {
431  return true;
432  }
433  }
434  myRoutables[veh->getDepart()].push_back(veh);
435  return true;
436  }
437  WRITE_ERROR("Another vehicle with the id '" + id + "' exists.");
438  delete veh;
439  return false;
440 }
441 
442 
443 bool
444 RONet::knowsVehicle(const std::string& id) const {
445  return myVehIDs.find(id) != myVehIDs.end();
446 }
447 
448 SUMOTime
449 RONet::getDeparture(const std::string& vehID) const {
450  auto it = myVehIDs.find(vehID);
451  if (it != myVehIDs.end()) {
452  return it->second;
453  } else {
454  throw ProcessError("Requesting departure time for unknown vehicle '" + vehID + "'");
455  }
456 }
457 
458 
459 bool
460 RONet::addFlow(SUMOVehicleParameter* flow, const bool randomize) {
461  if (randomize) {
462  myDepartures[flow->id].reserve(flow->repetitionNumber);
463  for (int i = 0; i < flow->repetitionNumber; ++i) {
464  myDepartures[flow->id].push_back(flow->depart + RandHelper::rand(flow->repetitionNumber * flow->repetitionOffset));
465  }
466  std::sort(myDepartures[flow->id].begin(), myDepartures[flow->id].end());
467  std::reverse(myDepartures[flow->id].begin(), myDepartures[flow->id].end());
468  }
469  const bool added = myFlows.add(flow->id, flow);
470  if (added) {
471  myHaveActiveFlows = true;
472  }
473  return added;
474 }
475 
476 
477 bool
479  if (myPersonIDs.count(person->getID()) == 0) {
480  myPersonIDs.insert(person->getID());
481  myRoutables[person->getDepart()].push_back(person);
482  return true;
483  }
484  WRITE_ERROR("Another person with the id '" + person->getID() + "' exists.");
485  return false;
486 }
487 
488 
489 void
490 RONet::addContainer(const SUMOTime depart, const std::string desc) {
491  myContainers.insert(std::pair<const SUMOTime, const std::string>(depart, desc));
492 }
493 
494 
495 void
496 RONet::checkFlows(SUMOTime time, MsgHandler* errorHandler) {
497  myHaveActiveFlows = false;
498  for (const auto& i : myFlows) {
499  SUMOVehicleParameter* pars = i.second;
500  if (pars->repetitionProbability > 0) {
501  if (pars->repetitionEnd > pars->depart && pars->repetitionsDone < pars->repetitionNumber) {
502  myHaveActiveFlows = true;
503  }
504  const SUMOTime origDepart = pars->depart;
505  while (pars->depart < time && pars->repetitionsDone < pars->repetitionNumber) {
506  if (pars->repetitionEnd <= pars->depart) {
507  break;
508  }
509  // only call rand if all other conditions are met
510  if (RandHelper::rand() < (pars->repetitionProbability * TS)) {
511  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
512  newPars->id = pars->id + "." + toString(pars->repetitionsDone);
513  newPars->depart = pars->depart;
514  for (std::vector<SUMOVehicleParameter::Stop>::iterator stop = newPars->stops.begin(); stop != newPars->stops.end(); ++stop) {
515  if (stop->until >= 0) {
516  stop->until += pars->depart - origDepart;
517  }
518  }
519  pars->repetitionsDone++;
520  // try to build the vehicle
522  if (type == nullptr) {
524  } else if (!myKeepVTypeDist) {
525  // fix the type id in case we used a distribution
526  newPars->vtypeid = type->id;
527  }
528  const SUMOTime stopOffset = pars->routeid[0] == '!' ? pars->depart - origDepart : pars->depart;
529  RORouteDef* route = getRouteDef(pars->routeid)->copy("!" + newPars->id, stopOffset);
530  ROVehicle* veh = new ROVehicle(*newPars, route, type, this, errorHandler);
531  addVehicle(newPars->id, veh);
532  delete newPars;
533  }
534  pars->depart += DELTA_T;
535  }
536  } else {
537  while (pars->repetitionsDone < pars->repetitionNumber) {
538  myHaveActiveFlows = true;
539  SUMOTime depart = static_cast<SUMOTime>(pars->depart + pars->repetitionsDone * pars->repetitionOffset);
540  if (myDepartures.find(pars->id) != myDepartures.end()) {
541  depart = myDepartures[pars->id].back();
542  }
543  if (depart >= time + DELTA_T) {
544  break;
545  }
546  if (myDepartures.find(pars->id) != myDepartures.end()) {
547  myDepartures[pars->id].pop_back();
548  }
549  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
550  newPars->id = pars->id + "." + toString(pars->repetitionsDone);
551  newPars->depart = depart;
552  for (std::vector<SUMOVehicleParameter::Stop>::iterator stop = newPars->stops.begin(); stop != newPars->stops.end(); ++stop) {
553  if (stop->until >= 0) {
554  stop->until += depart - pars->depart;
555  }
556  }
557  pars->repetitionsDone++;
558  // try to build the vehicle
560  if (type == nullptr) {
562  } else {
563  // fix the type id in case we used a distribution
564  newPars->vtypeid = type->id;
565  }
566  const SUMOTime stopOffset = pars->routeid[0] == '!' ? depart - pars->depart : depart;
567  RORouteDef* route = getRouteDef(pars->routeid)->copy("!" + newPars->id, stopOffset);
568  ROVehicle* veh = new ROVehicle(*newPars, route, type, this, errorHandler);
569  addVehicle(newPars->id, veh);
570  delete newPars;
571  }
572  }
573  }
574 }
575 
576 
577 void
578 RONet::createBulkRouteRequests(const RORouterProvider& provider, const SUMOTime time, const bool removeLoops) {
579  std::map<const int, std::vector<RORoutable*> > bulkVehs;
580  for (RoutablesMap::const_iterator i = myRoutables.begin(); i != myRoutables.end(); ++i) {
581  if (i->first >= time) {
582  break;
583  }
584  for (RORoutable* const routable : i->second) {
585  const ROEdge* const depEdge = routable->getDepartEdge();
586  bulkVehs[depEdge->getNumericalID()].push_back(routable);
587  RORoutable* const first = bulkVehs[depEdge->getNumericalID()].front();
588  if (first->getMaxSpeed() != routable->getMaxSpeed()) {
589  WRITE_WARNING("Bulking different maximum speeds ('" + first->getID() + "' and '" + routable->getID() + "') may lead to suboptimal routes.");
590  }
591  if (first->getVClass() != routable->getVClass()) {
592  WRITE_WARNING("Bulking different vehicle classes ('" + first->getID() + "' and '" + routable->getID() + "') may lead to invalid routes.");
593  }
594  }
595  }
596  int workerIndex = 0;
597  for (std::map<const int, std::vector<RORoutable*> >::const_iterator i = bulkVehs.begin(); i != bulkVehs.end(); ++i) {
598 #ifdef HAVE_FOX
599  if (myThreadPool.size() > 0) {
600  bool bulk = true;
601  for (RORoutable* const r : i->second) {
602  myThreadPool.add(new RoutingTask(r, removeLoops, myErrorHandler), workerIndex);
603  if (bulk) {
604  myThreadPool.add(new BulkmodeTask(true), workerIndex);
605  bulk = false;
606  }
607  }
608  myThreadPool.add(new BulkmodeTask(false), workerIndex);
609  workerIndex++;
610  if (workerIndex == (int)myThreadPool.size()) {
611  workerIndex = 0;
612  }
613  continue;
614  }
615 #endif
616  for (RORoutable* const r : i->second) {
617  r->computeRoute(provider, removeLoops, myErrorHandler);
618  provider.setBulkMode(true);
619  }
620  provider.setBulkMode(false);
621  }
622 }
623 
624 
625 SUMOTime
627  SUMOTime time) {
628  MsgHandler* mh = (options.getBool("ignore-errors") ?
630  if (myHaveActiveFlows) {
631  checkFlows(time, mh);
632  }
633  SUMOTime lastTime = -1;
634  const bool removeLoops = options.getBool("remove-loops");
635  const int maxNumThreads = options.getInt("routing-threads");
636  if (myRoutables.size() != 0) {
637  if (options.getBool("bulk-routing")) {
638 #ifdef HAVE_FOX
639  while ((int)myThreadPool.size() < maxNumThreads) {
640  new WorkerThread(myThreadPool, provider);
641  }
642 #endif
643  createBulkRouteRequests(provider, time, removeLoops);
644  } else {
645  for (RoutablesMap::const_iterator i = myRoutables.begin(); i != myRoutables.end(); ++i) {
646  if (i->first >= time) {
647  break;
648  }
649  for (RORoutable* const routable : i->second) {
650 #ifdef HAVE_FOX
651  // add task
652  if (maxNumThreads > 0) {
653  const int numThreads = (int)myThreadPool.size();
654  if (numThreads == 0) {
655  // This is the very first routing. Since at least the CHRouter needs initialization
656  // before it gets cloned, we do not do this in parallel
657  routable->computeRoute(provider, removeLoops, myErrorHandler);
658  new WorkerThread(myThreadPool, provider);
659  } else {
660  // add thread if necessary
661  if (numThreads < maxNumThreads && myThreadPool.isFull()) {
662  new WorkerThread(myThreadPool, provider);
663  }
664  myThreadPool.add(new RoutingTask(routable, removeLoops, myErrorHandler));
665  }
666  continue;
667  }
668 #endif
669  routable->computeRoute(provider, removeLoops, myErrorHandler);
670  }
671  }
672  }
673 #ifdef HAVE_FOX
674  myThreadPool.waitAll();
675 #endif
676  }
677  // write all vehicles (and additional structures)
678  while (myRoutables.size() != 0 || myContainers.size() != 0) {
679  // get the next vehicle, person or container
680  RoutablesMap::iterator routables = myRoutables.begin();
681  const SUMOTime routableTime = routables == myRoutables.end() ? SUMOTime_MAX : routables->first;
682  ContainerMap::iterator container = myContainers.begin();
683  const SUMOTime containerTime = container == myContainers.end() ? SUMOTime_MAX : container->first;
684  // check whether it shall not yet be computed
685  if (routableTime >= time && containerTime >= time) {
686  lastTime = MIN2(routableTime, containerTime);
687  break;
688  }
689  const SUMOTime minTime = MIN2(routableTime, containerTime);
690  if (routableTime == minTime) {
691  // check whether to print the output
692  if (lastTime != routableTime && lastTime != -1) {
693  // report writing progress
694  if (options.getInt("stats-period") >= 0 && ((int)routableTime % options.getInt("stats-period")) == 0) {
695  WRITE_MESSAGE("Read: " + toString(myVehIDs.size()) + ", Discarded: " + toString(myDiscardedRouteNo) + ", Written: " + toString(myWrittenRouteNo));
696  }
697  }
698  lastTime = routableTime;
699  for (const RORoutable* const r : routables->second) {
700  // ok, check whether it has been routed
701  if (r->getRoutingSuccess()) {
702  // write the route
705  } else {
707  }
708  // we need to keep individual public transport vehicles but not the flows
709  if (!r->isPublicTransport() || r->isPartOfFlow()) {
710  // delete routes and the vehicle
711  const ROVehicle* const veh = dynamic_cast<const ROVehicle*>(r);
712  if (veh != nullptr && veh->getRouteDefinition()->getID()[0] == '!') {
713  if (!myRoutes.remove(veh->getRouteDefinition()->getID())) {
714  delete veh->getRouteDefinition();
715  }
716  }
717  delete r;
718  }
719  }
720  myRoutables.erase(routables);
721  }
722  if (containerTime == minTime) {
723  myRoutesOutput->writePreformattedTag(container->second);
724  if (myRouteAlternativesOutput != nullptr) {
726  }
727  myContainers.erase(container);
728  }
729  }
730  return lastTime;
731 }
732 
733 
734 bool
736  return myRoutables.size() > 0 || (myFlows.size() > 0 && myHaveActiveFlows) || myContainers.size() > 0;
737 }
738 
739 
740 int
742  return myEdges.size();
743 }
744 
745 
746 int
748  return myNumInternalEdges;
749 }
750 
751 
752 ROEdge*
753 RONet::getEdgeForLaneID(const std::string& laneID) const {
755 }
756 
757 ROLane*
758 RONet::getLane(const std::string& laneID) const {
759  int laneIndex = SUMOXMLDefinitions::getIndexFromLane(laneID);
760  return getEdgeForLaneID(laneID)->getLanes()[laneIndex];
761 }
762 
763 void
765  double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
766  for (const auto& stopType : myInstance->myStoppingPlaces) {
767  // add access to all stopping places
768  const SumoXMLTag element = stopType.first;
769  for (const auto& stop : stopType.second) {
770  router.getNetwork()->addAccess(stop.first, myInstance->getEdgeForLaneID(stop.second->lane),
771  stop.second->startPos, stop.second->endPos, 0., element, false, taxiWait);
772  // add access to all public transport stops
773  if (element == SUMO_TAG_BUS_STOP) {
774  for (const auto& a : stop.second->accessPos) {
775  router.getNetwork()->addAccess(stop.first, myInstance->getEdgeForLaneID(std::get<0>(a)),
776  std::get<1>(a), std::get<1>(a), std::get<2>(a), SUMO_TAG_BUS_STOP, true, taxiWait);
777  }
778  }
779  }
780  }
781  // fill the public transport router with pre-parsed public transport lines
782  for (const auto& i : myInstance->myFlows) {
783  if (i.second->line != "") {
784  const RORouteDef* const route = myInstance->getRouteDef(i.second->routeid);
785  const std::vector<SUMOVehicleParameter::Stop>* addStops = nullptr;
786  if (route != nullptr && route->getFirstRoute() != nullptr) {
787  addStops = &route->getFirstRoute()->getStops();
788  }
789  router.getNetwork()->addSchedule(*i.second, addStops);
790  }
791  }
792  for (const RORoutable* const veh : myInstance->myPTVehicles) {
793  // add single vehicles with line attribute which are not part of a flow
794  // no need to add route stops here, they have been added to the vehicle before
795  router.getNetwork()->addSchedule(veh->getParameter());
796  }
797  // add access to transfer from walking to taxi-use
799  for (const ROEdge* edge : ROEdge::getAllEdges()) {
800  if ((edge->getPermissions() & SVC_PEDESTRIAN) != 0 && (edge->getPermissions() & SVC_TAXI) != 0) {
801  router.getNetwork()->addCarAccess(edge, SVC_TAXI, taxiWait);
802  }
803  }
804  }
805 }
806 
807 
808 bool
810  return myHavePermissions;
811 }
812 
813 
814 void
816  myHavePermissions = true;
817 }
818 
819 bool
821  for (const auto& item : myEdges) {
822  if (item.second->hasStoredEffort()) {
823  return true;
824  }
825  }
826  return false;
827 }
828 
829 const std::string
830 RONet::getStoppingPlaceName(const std::string& id) const {
831  for (const auto& mapItem : myStoppingPlaces) {
832  SUMOVehicleParameter::Stop* stop = mapItem.second.get(id);
833  if (stop != nullptr) {
834  // see RONetHandler::parseStoppingPlace
835  return stop->busstop;
836  }
837  }
838  return "";
839 }
840 
841 const std::string
842 RONet::getStoppingPlaceElement(const std::string& id) const {
843  for (const auto& mapItem : myStoppingPlaces) {
844  SUMOVehicleParameter::Stop* stop = mapItem.second.get(id);
845  if (stop != nullptr) {
846  // see RONetHandler::parseStoppingPlace
847  return stop->actType;
848  }
849  }
850  return toString(SUMO_TAG_BUS_STOP);
851 }
852 
853 
854 #ifdef HAVE_FOX
855 // ---------------------------------------------------------------------------
856 // RONet::RoutingTask-methods
857 // ---------------------------------------------------------------------------
858 void
859 RONet::RoutingTask::run(FXWorkerThread* context) {
860  myRoutable->computeRoute(*static_cast<WorkerThread*>(context), myRemoveLoops, myErrorHandler);
861 }
862 #endif
863 
864 
865 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:281
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:282
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define TS
Definition: SUMOTime.h:40
long long int SUMOTime
Definition: SUMOTime.h:32
const int VTYPEPARS_VEHICLECLASS_SET
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_TAXI
vehicle is a taxi
@ SVC_PEDESTRIAN
pedestrian
const std::string DEFAULT_TAXITYPE_ID
const std::string DEFAULT_PEDTYPE_ID
const std::string DEFAULT_VTYPE_ID
const std::string DEFAULT_BIKETYPE_ID
@ DEPART_TRIGGERED
The departure is person triggered.
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_ROUTES
root element of a route file
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_TRAIN_STOP
A train stop (alias for bus stop)
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ID
T MIN2(T a, T b)
Definition: StdDefs.h:74
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A thread repeatingly calculating incoming tasks.
void addCarAccess(const E *edge, SUMOVehicleClass svc, double traveltime)
Adds access edges for transfering from walking to vehicle use.
void addAccess(const std::string &stopId, const E *stopEdge, const double startPos, const double endPos, const double length, const SumoXMLTag category, bool isAccess, double taxiWait)
Adds access edges for stopping places to the intermodal network.
@ TAXI_PICKUP_ANYWHERE
taxi customer may be picked up anywhere
void addSchedule(const SUMOVehicleParameter &pars, const std::vector< SUMOVehicleParameter::Stop > *addStops=nullptr)
Network * getNetwork() const
void writeWeights(OutputDevice &dev)
int getCarWalkTransfer() const
void writeNetwork(OutputDevice &dev)
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
T get(const std::string &id) const
Retrieves an item.
int size() const
Returns the number of stored items within the container.
bool remove(const std::string &id, const bool del=true)
Removes an item.
bool add(const std::string &id, T item)
Adds an item.
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.
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 exists(const std::string &name) const
Returns the information whether the named option is known.
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:58
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writePreformattedTag(const std::string &val)
writes a preformatted tag to the device but ensures that any pending tags are closed
Definition: OutputDevice.h:305
void close()
Closes the device and removes it from the dictionary.
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.
virtual bool isNull()
returns the information whether the device will discard all output
Definition: OutputDevice.h:152
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:248
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.
bool writeHeader(const SumoXMLTag &rootElement)
Definition: OutputDevice.h:193
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
Interface for building instances of router-edges.
virtual ROEdge * buildEdge(const std::string &name, RONode *from, RONode *to, const int priority)=0
Builds an edge with the given name.
A basic edge for routing applications.
Definition: ROEdge.h:70
int getNumericalID() const
Returns the index (numeric id) of the edge.
Definition: ROEdge.h:217
void setFunction(SumoXMLEdgeFunc func)
Sets the function of the edge.
Definition: ROEdge.h:112
bool isInternal() const
return whether this edge is an internal edge
Definition: ROEdge.h:145
const std::vector< ROLane * > & getLanes() const
Returns this edge's lanes.
Definition: ROEdge.h:520
void setOtherTazConnector(const ROEdge *edge)
Definition: ROEdge.h:163
virtual void addSuccessor(ROEdge *s, ROEdge *via=nullptr, std::string dir="")
Adds information about a connected edge.
Definition: ROEdge.cpp:109
static const ROEdgeVector & getAllEdges()
Returns all ROEdges.
Definition: ROEdge.cpp:350
A single lane the router may use.
Definition: ROLane.h:48
The router's network representation.
Definition: RONet.h:62
void createBulkRouteRequests(const RORouterProvider &provider, const SUMOTime time, const bool removeLoops)
Definition: RONet.cpp:578
SUMOVTypeParameter * getVehicleTypeSecure(const std::string &id)
Retrieves the named vehicle type.
Definition: RONet.cpp:343
static RONet * getInstance()
Returns the pointer to the unique instance of RONet (singleton).
Definition: RONet.cpp:56
int myNumInternalEdges
The number of internal edges in the dictionary.
Definition: RONet.h:555
bool myDefaultPedTypeMayBeDeleted
Whether the default pedestrian type was already used or can still be replaced.
Definition: RONet.h:500
void setPermissionsFound()
Definition: RONet.cpp:815
bool myDefaultVTypeMayBeDeleted
Whether the default vehicle type was already used or can still be replaced.
Definition: RONet.h:497
void checkFlows(SUMOTime time, MsgHandler *errorHandler)
Definition: RONet.cpp:496
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition: RONet.h:157
const std::map< SUMOVehicleClass, double > * getRestrictions(const std::string &id) const
Returns the restrictions for an edge type If no restrictions are present, 0 is returned.
Definition: RONet.cpp:137
ContainerMap myContainers
Definition: RONet.h:519
std::set< std::string > myPersonIDs
Known person ids.
Definition: RONet.h:477
std::map< std::string, std::pair< std::vector< std::string >, std::vector< std::string > > > myDistricts
traffic assignment zones with sources and sinks
Definition: RONet.h:528
bool addRouteDef(RORouteDef *def)
Definition: RONet.cpp:265
void addStoppingPlace(const std::string &id, const SumoXMLTag category, SUMOVehicleParameter::Stop *stop)
Definition: RONet.cpp:256
bool knowsVehicle(const std::string &id) const
returns whether a vehicle with the given id was already loaded
Definition: RONet.cpp:444
void cleanup()
closes the file output for computed routes and deletes associated threads if necessary
Definition: RONet.cpp:319
bool myHaveActiveFlows
whether any flows are still active
Definition: RONet.h:515
std::map< std::string, SUMOTime > myVehIDs
Known vehicle ids and their departure.
Definition: RONet.h:474
void openOutput(const OptionsCont &options)
Opens the output for computed routes.
Definition: RONet.cpp:271
NamedObjectCont< SUMOVehicleParameter * > myFlows
Known flows.
Definition: RONet.h:512
OutputDevice * myRouteAlternativesOutput
The file to write the computed route alternatives into.
Definition: RONet.h:534
bool myDefaultBikeTypeMayBeDeleted
Whether the default bicycle type was already used or can still be replaced.
Definition: RONet.h:503
RoutablesMap myRoutables
Known routables.
Definition: RONet.h:509
int getInternalEdgeNumber() const
Returns the number of internal edges the network contains.
Definition: RONet.cpp:747
virtual bool addVehicle(const std::string &id, ROVehicle *veh)
Definition: RONet.cpp:422
SUMOTime getDeparture(const std::string &vehID) const
returns departure time for the given vehicle id
Definition: RONet.cpp:449
bool myHasBidiEdges
whether the network contains bidirectional railway edges
Definition: RONet.h:564
bool addDistrictEdge(const std::string tazID, const std::string edgeID, const bool isSource)
Definition: RONet.cpp:180
MsgHandler * myErrorHandler
handler for ignorable error messages
Definition: RONet.h:558
void writeIntermodal(const OptionsCont &options, ROIntermodalRouter &router) const
Writes the intermodal network and weights if requested.
Definition: RONet.cpp:300
RONet()
Constructor.
Definition: RONet.cpp:64
NamedObjectCont< RONode * > myNodes
Known nodes.
Definition: RONet.h:480
const std::string getStoppingPlaceElement(const std::string &id) const
return the element name for the given stopping place id
Definition: RONet.cpp:842
void addContainer(const SUMOTime depart, const std::string desc)
Definition: RONet.cpp:490
static void adaptIntermodalRouter(ROIntermodalRouter &router)
Definition: RONet.cpp:764
void addRestriction(const std::string &id, const SUMOVehicleClass svc, const double speed)
Adds a restriction for an edge type.
Definition: RONet.cpp:131
NamedObjectCont< RORouteDef * > myRoutes
Known routes.
Definition: RONet.h:506
bool furtherStored()
Returns the information whether further vehicles, persons or containers are stored.
Definition: RONet.cpp:735
bool checkVType(const std::string &id)
Checks whether the vehicle type (distribution) may be added.
Definition: RONet.cpp:373
OutputDevice * myRoutesOutput
The file to write the computed routes into.
Definition: RONet.h:531
bool addPerson(ROPerson *person)
Definition: RONet.cpp:478
int myWrittenRouteNo
The number of written routes.
Definition: RONet.h:546
static RONet * myInstance
Unique instance of RONet.
Definition: RONet.h:471
SUMOTime saveAndRemoveRoutesUntil(OptionsCont &options, const RORouterProvider &provider, SUMOTime time)
Computes routes described by their definitions and saves them.
Definition: RONet.cpp:626
virtual bool addEdge(ROEdge *edge)
Definition: RONet.cpp:147
std::map< std::string, std::map< SUMOVehicleClass, double > > myRestrictions
The vehicle class specific speed restrictions.
Definition: RONet.h:552
std::map< SumoXMLTag, NamedObjectCont< SUMOVehicleParameter::Stop * > > myStoppingPlaces
Known bus / train / container stops and parking areas.
Definition: RONet.h:486
virtual bool addVehicleType(SUMOVTypeParameter *type)
Adds a read vehicle type definition to the network.
Definition: RONet.cpp:398
bool myHavePermissions
Whether the network contains edges which not all vehicles may pass.
Definition: RONet.h:549
bool hasPermissions() const
Definition: RONet.cpp:809
void setBidiEdges(const std::map< ROEdge *, std::string > &bidiMap)
add a taz for every junction unless a taz with the same id already exists
Definition: RONet.cpp:235
ROLane * getLane(const std::string &laneID) const
Retrieves a lane rom the network given it's id.
Definition: RONet.cpp:758
int myDiscardedRouteNo
The number of discarded routes.
Definition: RONet.h:543
RORouteDef * getRouteDef(const std::string &name) const
Returns the named route definition.
Definition: RONet.h:305
VTypeDistDictType myVTypeDistDict
A distribution of vehicle types (probability->vehicle type)
Definition: RONet.h:494
std::vector< const RORoutable * > myPTVehicles
vehicles to keep for public transport routing
Definition: RONet.h:522
NamedObjectCont< ROEdge * > myEdges
Known edges.
Definition: RONet.h:483
void addNode(RONode *node)
Definition: RONet.cpp:247
bool addVTypeDistribution(const std::string &id, RandomDistributor< SUMOVTypeParameter * > *vehTypeDistribution)
Adds a vehicle type distribution.
Definition: RONet.cpp:411
void addJunctionTaz(ROAbstractEdgeBuilder &eb)
add a taz for every junction unless a taz with the same id already exists
Definition: RONet.cpp:202
OutputDevice * myTypesOutput
The file to write the vehicle types into.
Definition: RONet.h:537
const bool myKeepVTypeDist
whether to keep the the vtype distribution in output
Definition: RONet.h:561
virtual ~RONet()
Destructor.
Definition: RONet.cpp:103
const std::string getStoppingPlaceName(const std::string &id) const
return the name for the given stopping place id
Definition: RONet.cpp:830
std::map< std::string, std::vector< SUMOTime > > myDepartures
Departure times for randomized flows.
Definition: RONet.h:525
int getEdgeNumber() const
Returns the total number of edges the network contains including internal edges.
Definition: RONet.cpp:741
ROEdge * getEdgeForLaneID(const std::string &laneID) const
Retrieves an edge from the network when the lane id is given.
Definition: RONet.cpp:753
bool addFlow(SUMOVehicleParameter *flow, const bool randomize)
Definition: RONet.cpp:460
bool hasLoadedEffort() const
whether efforts were loaded from file
Definition: RONet.cpp:820
NamedObjectCont< SUMOVTypeParameter * > myVehicleTypes
Known vehicle types.
Definition: RONet.h:489
bool addDistrict(const std::string id, ROEdge *source, ROEdge *sink)
Definition: RONet.cpp:161
Base class for nodes used by the router.
Definition: RONode.h:43
const ConstROEdgeVector & getIncoming() const
Definition: RONode.h:69
const ConstROEdgeVector & getOutgoing() const
Definition: RONode.h:73
A person as used by router.
Definition: ROPerson.h:49
A routable thing such as a vehicle or person.
Definition: RORoutable.h:52
bool getRoutingSuccess() const
Definition: RORoutable.h:157
const SUMOVehicleParameter & getParameter() const
Returns the definition of the vehicle / person parameter.
Definition: RORoutable.h:71
const std::string & getID() const
Returns the id of the routable.
Definition: RORoutable.h:91
SUMOVehicleClass getVClass() const
Definition: RORoutable.h:109
bool isPublicTransport() const
Definition: RORoutable.h:123
bool isPartOfFlow() const
Definition: RORoutable.h:127
virtual void computeRoute(const RORouterProvider &provider, const bool removeLoops, MsgHandler *errorHandler)=0
SUMOTime getDepart() const
Returns the time the vehicle starts at, -1 for triggered vehicles.
Definition: RORoutable.h:100
virtual const ROEdge * getDepartEdge() const =0
void write(OutputDevice *os, OutputDevice *const altos, OutputDevice *const typeos, OptionsCont &options) const
Saves the routable including the vehicle type (if it was not saved before).
Definition: RORoutable.h:142
double getMaxSpeed() const
Returns the vehicle's maximum speed.
Definition: RORoutable.h:115
Base class for a vehicle's route definition.
Definition: RORouteDef.h:53
const RORoute * getFirstRoute() const
Definition: RORouteDef.h:98
RORouteDef * copy(const std::string &id, const SUMOTime stopOffset) const
Returns a deep copy of the route definition.
Definition: RORouteDef.cpp:399
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the list of stops this route contains.
Definition: RORoute.h:183
A vehicle as used by router.
Definition: ROVehicle.h:50
RORouteDef * getRouteDefinition() const
Returns the definition of the route the vehicle takes.
Definition: ROVehicle.h:73
SUMOTime getDepartureTime() const
Returns the time the vehicle starts at, 0 for triggered vehicles.
Definition: ROVehicle.h:92
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:119
void setBulkMode(const bool mode) const
Structure representing possible vehicle parameter.
bool onlyReferenced
Information whether this is a type-stub, being only referenced but not defined (needed by routers)
int parametersSet
Information for the router which parameter were set.
std::string id
The vehicle type's id.
Definition of vehicle stop (position and duration)
std::string actType
act Type (only used by Persons) (used by NETEDIT)
std::string busstop
(Optional) bus stop if one is assigned to the stop
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
int repetitionsDone
The number of times the vehicle was already inserted.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
static int getIndexFromLane(const std::string laneID)
return lane index when given the lane ID