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