Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
RORouteHandler.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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/****************************************************************************/
21// Parser and container for routes during their loading
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
26#include <map>
27#include <vector>
28#include <iostream>
40#include <utils/xml/XMLSubSys.h>
42#include "RONet.h"
43#include "ROEdge.h"
44#include "ROLane.h"
45#include "RORouteDef.h"
46#include "RORouteHandler.h"
47
48// ===========================================================================
49// method definitions
50// ===========================================================================
51RORouteHandler::RORouteHandler(RONet& net, const std::string& file,
52 const bool tryRepair,
53 const bool emptyDestinationsAllowed,
54 const bool ignoreErrors,
55 const bool checkSchema) :
56 SUMORouteHandler(file, checkSchema ? "routes" : "", true),
57 MapMatcher(OptionsCont::getOptions().getBool("mapmatch.junctions"),
58 OptionsCont::getOptions().getBool("mapmatch.taz"),
59 OptionsCont::getOptions().getFloat("mapmatch.distance"),
60 ignoreErrors ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
61 myNet(net),
62 myActiveRouteRepeat(0),
63 myActiveRoutePeriod(0),
64 myActivePlan(nullptr),
65 myActiveContainerPlan(nullptr),
66 myActiveContainerPlanSize(0),
67 myTryRepair(tryRepair),
68 myEmptyDestinationsAllowed(emptyDestinationsAllowed),
69 myErrorOutput(ignoreErrors ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
70 myBegin(string2time(OptionsCont::getOptions().getString("begin"))),
71 myKeepVTypeDist(OptionsCont::getOptions().getBool("keep-vtype-distributions")),
72 myUnsortedInput(OptionsCont::getOptions().exists("unsorted-input") && OptionsCont::getOptions().getBool("unsorted-input")),
73 myCurrentVTypeDistribution(nullptr),
74 myCurrentAlternatives(nullptr) {
75 myActiveRoute.reserve(100);
76}
77
78
82
83
84void
86 if (myActivePlan != nullptr) {
87 for (ROPerson::PlanItem* const it : *myActivePlan) {
88 delete it;
89 }
90 delete myActivePlan;
91 myActivePlan = nullptr;
92 }
94 myActiveContainerPlan = nullptr;
95 delete myVehicleParameter;
96 myVehicleParameter = nullptr;
97}
98
99
100void
102 const std::string element = toString(tag);
103 myActiveRoute.clear();
104 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
106 WRITE_WARNINGF(TL("Taz usage was requested but no taz present in % '%'!"), element, myVehicleParameter->id);
107 useTaz = false;
108 }
112 if (type != nullptr) {
113 vClass = type->vehicleClass;
114 }
115 }
116 // from-attributes
117 const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
118 if ((useTaz || (!attrs.hasAttribute(SUMO_ATTR_FROM) && !attrs.hasAttribute(SUMO_ATTR_FROMXY) && !attrs.hasAttribute(SUMO_ATTR_FROMLONLAT))) &&
120 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION);
121 const std::string tazType = useJunction ? "junction" : "taz";
122 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROM_JUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok, true);
123 const ROEdge* fromTaz = myNet.getEdge(tazID + "-source");
124 if (fromTaz == nullptr) {
125 myErrorOutput->inform("Source " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
126 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
127 ok = false;
128 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
129 myErrorOutput->inform("Source " + tazType + " '" + tazID + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
130 ok = false;
131 } else {
132 myActiveRoute.push_back(fromTaz);
133 }
134 } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
135 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, vClass, myActiveRoute, rid, true, ok);
136 if (myMapMatchTAZ && ok) {
137 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
139 }
140 } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
141 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, myActiveRoute, rid, true, ok);
142 if (myMapMatchTAZ && ok) {
143 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
145 }
146 } else {
147 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok), myActiveRoute, rid, ok);
148 }
151 }
152
153 // via-attributes
154 ConstROEdgeVector viaEdges;
155 if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
156 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, vClass, viaEdges, rid, false, ok);
157 } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
158 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, viaEdges, rid, false, ok);
159 } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
160 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
161 const ROEdge* viaSink = myNet.getEdge(junctionID + "-sink");
162 if (viaSink == nullptr) {
163 myErrorOutput->inform("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
164 ok = false;
165 } else {
166 viaEdges.push_back(viaSink);
167 }
168 }
169 } else {
170 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true), viaEdges, rid, ok);
171 }
172 for (const ROEdge* e : viaEdges) {
173 myActiveRoute.push_back(e);
174 myVehicleParameter->via.push_back(e->getID());
175 }
176
177 // to-attributes
178 if ((useTaz || (!attrs.hasAttribute(SUMO_ATTR_TO) && !attrs.hasAttribute(SUMO_ATTR_TOXY) && !attrs.hasAttribute(SUMO_ATTR_TOLONLAT))) &&
180 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION);
181 const std::string tazType = useJunction ? "junction" : "taz";
182 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TO_JUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
183 const ROEdge* toTaz = myNet.getEdge(tazID + "-sink");
184 if (toTaz == nullptr) {
185 myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
186 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
187 ok = false;
188 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
189 myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
190 ok = false;
191 } else {
192 myActiveRoute.push_back(toTaz);
193 }
194 } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
195 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, vClass, myActiveRoute, rid, false, ok);
196 if (myMapMatchTAZ && ok) {
197 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
199 }
200 } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
201 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, vClass, myActiveRoute, rid, false, ok);
202 if (myMapMatchTAZ && ok) {
203 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
205 }
206 } else {
207 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true), myActiveRoute, rid, ok);
208 }
210 if (myVehicleParameter->routeid == "") {
212 }
213}
214
215
216void
218 const SUMOSAXAttributes& attrs) {
219 try {
220 if (myActivePlan != nullptr && myActivePlan->empty() && myVehicleParameter->departProcedure == DepartDefinition::TRIGGERED && element != SUMO_TAG_RIDE && element != SUMO_TAG_PARAM) {
221 throw ProcessError(TLF("Triggered departure for person '%' requires starting with a ride.", myVehicleParameter->id));
223 throw ProcessError(TLF("Triggered departure for container '%' requires starting with a transport.", myVehicleParameter->id));
224 }
225 SUMORouteHandler::myStartElement(element, attrs);
226 bool ok = true;
227 switch (element) {
228 case SUMO_TAG_PERSON:
229 case SUMO_TAG_PERSONFLOW: {
230 myActivePlan = new std::vector<ROPerson::PlanItem*>();
231 break;
232 }
233 case SUMO_TAG_RIDE:
234 break; // handled in addRide, called from SUMORouteHandler::myStartElement
240 (*myActiveContainerPlan) << attrs;
241 break;
244 if (myActiveContainerPlan == nullptr) {
245 throw ProcessError(TLF("Found % outside container element", toString((SumoXMLTag)element)));
246 }
247 // copy container elements
249 (*myActiveContainerPlan) << attrs;
252 break;
253 case SUMO_TAG_FLOW:
255 parseFromViaTo((SumoXMLTag)element, attrs, ok);
256 break;
257 case SUMO_TAG_TRIP:
259 parseFromViaTo((SumoXMLTag)element, attrs, ok);
260 break;
261 default:
262 break;
263 }
264 } catch (ProcessError&) {
266 throw;
267 }
268}
269
270
271void
273 bool ok = true;
274 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
275 if (ok) {
277 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
278 std::vector<double> probs;
279 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
280 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
281 while (st.hasNext()) {
282 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
283 }
284 }
285 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
286 StringTokenizer st(vTypes);
287 int probIndex = 0;
288 while (st.hasNext()) {
289 const std::string typeID = st.next();
291 if (dist != nullptr) {
292 const double distProb = ((int)probs.size() > probIndex ? probs[probIndex] : 1.) / dist->getOverallProb();
293 std::vector<double>::const_iterator probIt = dist->getProbs().begin();
294 for (SUMOVTypeParameter* const type : dist->getVals()) {
295 myCurrentVTypeDistribution->add(type, distProb * *probIt);
296 probIt++;
297 }
298 } else {
299 SUMOVTypeParameter* const type = myNet.getVehicleTypeSecure(typeID);
300 if (type == nullptr) {
301 myErrorOutput->inform("Unknown vehicle type '" + typeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
302 } else {
303 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->defaultProbability);
304 myCurrentVTypeDistribution->add(type, prob);
305 }
306 }
307 probIndex++;
308 }
309 if (probs.size() > 0 && probIndex != (int)probs.size()) {
310 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
311 " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
312 }
313 }
314 }
315}
316
317
318void
320 if (myCurrentVTypeDistribution != nullptr) {
323 myErrorOutput->inform("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
326 myErrorOutput->inform("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
327 }
329 }
330}
331
332
333void
337 // check whether the id is really necessary
338 std::string rid;
339 if (myCurrentAlternatives != nullptr) {
341 rid = "distribution '" + myCurrentAlternatives->getID() + "'";
342 } else if (myVehicleParameter != nullptr) {
343 // ok, a vehicle is wrapping the route,
344 // we may use this vehicle's id as default
345 myVehicleParameter->routeid = myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
346 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
347 WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
348 }
349 } else {
350 bool ok = true;
351 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
352 if (!ok) {
353 return;
354 }
355 rid = "'" + myActiveRouteID + "'";
356 }
357 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
358 rid = "for vehicle '" + myVehicleParameter->id + "'";
359 }
360 bool ok = true;
361 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
362 parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid, ok);
363 }
364 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
365 if (myActiveRouteRefID != "" && myNet.getRouteDef(myActiveRouteRefID) == nullptr) {
366 myErrorOutput->inform("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
367 }
368 if (myCurrentAlternatives != nullptr && !attrs.hasAttribute(SUMO_ATTR_PROB)) {
369 WRITE_WARNINGF(TL("No probability for route %, using default."), rid);
370 }
372 if (ok && myActiveRouteProbability < 0) {
373 myErrorOutput->inform("Invalid probability for route '" + myActiveRouteID + "'.");
374 }
376 ok = true;
377 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
379 if (myActiveRouteRepeat > 0) {
381 if (myVehicleParameter != nullptr) {
383 if (type != nullptr) {
384 vClass = type->vehicleClass;
385 }
386 }
387 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
388 myErrorOutput->inform("Disconnected route " + rid + " when repeating.");
389 }
390 }
391 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
392 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
393 myErrorOutput->inform("Invalid cost for route '" + myActiveRouteID + "'.");
394 }
395}
396
397
398void
400 // currently unused
401}
402
403
404void
406 // currently unused
407}
408
409
410void
412 // currently unused
413}
414
415
416void
417RORouteHandler::closeRoute(const bool mayBeDisconnected) {
418 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
419 if (mustReroute) {
420 // implicit route from stops
422 ROEdge* edge = myNet.getEdge(stop.edge);
423 myActiveRoute.push_back(edge);
424 }
425 }
426 if (myActiveRoute.size() == 0) {
427 if (myActiveRouteRefID != "" && myCurrentAlternatives != nullptr) {
429 myActiveRouteID = "";
431 return;
432 }
433 if (myVehicleParameter != nullptr) {
434 myErrorOutput->inform("The route for vehicle '" + myVehicleParameter->id + "' has no edges.");
435 } else {
436 myErrorOutput->inform("Route '" + myActiveRouteID + "' has no edges.");
437 }
438 myActiveRouteID = "";
439 myActiveRouteStops.clear();
440 return;
441 }
442 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
443 myErrorOutput->inform("The routing information for vehicle '" + myVehicleParameter->id + "' is insufficient.");
444 myActiveRouteID = "";
445 myActiveRouteStops.clear();
446 return;
447 }
448 if (!mayBeDisconnected && OptionsCont::getOptions().exists("no-internal-links") && !OptionsCont::getOptions().getBool("no-internal-links")) {
449 // fix internal edges which did not get parsed
450 const ROEdge* last = nullptr;
451 ConstROEdgeVector fullRoute;
452 for (const ROEdge* roe : myActiveRoute) {
453 if (last != nullptr) {
454 for (const ROEdge* intern : last->getSuccessors()) {
455 if (intern->isInternal() && intern->getSuccessors().size() == 1 && intern->getSuccessors().front() == roe) {
456 fullRoute.push_back(intern);
457 }
458 }
459 }
460 fullRoute.push_back(roe);
461 last = roe;
462 }
463 myActiveRoute = fullRoute;
464 }
465 if (myActiveRouteRepeat > 0) {
466 // duplicate route
468 auto tmpStops = myActiveRouteStops;
469 for (int i = 0; i < myActiveRouteRepeat; i++) {
470 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
471 for (SUMOVehicleParameter::Stop stop : tmpStops) {
472 if (stop.until > 0) {
473 if (myActiveRoutePeriod <= 0) {
474 const std::string description = myVehicleParameter != nullptr
475 ? "for vehicle '" + myVehicleParameter->id + "'"
476 : "'" + myActiveRouteID + "'";
477 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
478 }
479 stop.until += myActiveRoutePeriod * (i + 1);
480 stop.arrival += myActiveRoutePeriod * (i + 1);
481 }
482 myActiveRouteStops.push_back(stop);
483 }
484 }
485 }
488 myActiveRoute.clear();
489 if (myCurrentAlternatives == nullptr) {
490 if (myNet.getRouteDef(myActiveRouteID) != nullptr) {
491 delete route;
492 if (myVehicleParameter != nullptr) {
493 myErrorOutput->inform("Another route for vehicle '" + myVehicleParameter->id + "' exists.");
494 } else {
495 myErrorOutput->inform("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
496 }
497 myActiveRouteID = "";
498 myActiveRouteStops.clear();
499 return;
500 } else {
501 myCurrentAlternatives = new RORouteDef(myActiveRouteID, 0, mayBeDisconnected || myTryRepair, mayBeDisconnected);
504 myCurrentAlternatives = nullptr;
505 }
506 } else {
508 }
509 myActiveRouteID = "";
510 myActiveRouteStops.clear();
511}
512
513
514void
516 // check whether the id is really necessary
517 bool ok = true;
518 std::string id;
519 if (myVehicleParameter != nullptr) {
520 // ok, a vehicle is wrapping the route,
521 // we may use this vehicle's id as default
522 myVehicleParameter->routeid = id = "!" + myVehicleParameter->id; // !!! document this
523 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
524 WRITE_WARNINGF(TL("Ids of internal route distributions are ignored (vehicle '%')."), myVehicleParameter->id);
525 }
526 } else {
527 id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
528 if (!ok) {
529 return;
530 }
531 }
532 // try to get the index of the last element
533 int index = attrs.getOpt<int>(SUMO_ATTR_LAST, id.c_str(), ok, 0);
534 if (ok && index < 0) {
535 myErrorOutput->inform("Negative index of a route alternative (id='" + id + "').");
536 return;
537 }
538 // build the alternative cont
539 myCurrentAlternatives = new RORouteDef(id, index, myTryRepair, false);
540 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
541 ok = true;
542 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, id.c_str(), ok));
543 while (st.hasNext()) {
544 const std::string routeID = st.next();
545 const RORouteDef* route = myNet.getRouteDef(routeID);
546 if (route == nullptr) {
547 myErrorOutput->inform("Unknown route '" + routeID + "' in distribution '" + id + "'.");
548 } else {
550 }
551 }
552 }
553}
554
555
556void
558 if (myCurrentAlternatives != nullptr) {
560 myErrorOutput->inform("Route distribution '" + myCurrentAlternatives->getID() + "' is empty.");
563 myErrorOutput->inform("Another route (or distribution) with the id '" + myCurrentAlternatives->getID() + "' exists.");
565 }
566 myCurrentAlternatives = nullptr;
567 }
568}
569
570
571void
574 // get the vehicle id
576 return;
577 }
578 // get vehicle type
580 if (type == nullptr) {
581 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
583 } else {
584 if (!myKeepVTypeDist) {
585 // fix the type id in case we used a distribution
587 }
588 }
589 if (type->vehicleClass == SVC_PEDESTRIAN) {
590 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), type->id, myVehicleParameter->id);
591 }
592 // get the route
594 if (route == nullptr) {
595 myErrorOutput->inform("The route of the vehicle '" + myVehicleParameter->id + "' is not known.");
596 return;
597 }
598 if (MsgHandler::getErrorInstance()->wasInformed()) {
599 return;
600 }
601 const bool needCopy = route->getID()[0] != '!';
602 if (needCopy) {
603 route = route->copy("!" + myVehicleParameter->id, myVehicleParameter->depart);
604 }
605 // build the vehicle
606 ROVehicle* veh = new ROVehicle(*myVehicleParameter, route, type, &myNet, myErrorOutput);
609 } else if (needCopy) {
610 delete route;
611 }
612 delete myVehicleParameter;
613 myVehicleParameter = nullptr;
614}
615
616
617void
620 if (myCurrentVTypeDistribution != nullptr) {
622 }
623 }
624 if (OptionsCont::getOptions().isSet("restriction-params")) {
625 const std::vector<std::string> paramKeys = OptionsCont::getOptions().getStringVector("restriction-params");
627 }
628 myCurrentVType = nullptr;
629}
630
631
632void
635 if (type == nullptr) {
636 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for person '" + myVehicleParameter->id + "' is not known.");
638 }
639 if (myActivePlan == nullptr || myActivePlan->empty()) {
640 WRITE_WARNINGF(TL("Discarding person '%' because her plan is empty"), myVehicleParameter->id);
641 } else {
642 ROPerson* person = new ROPerson(*myVehicleParameter, type);
643 for (ROPerson::PlanItem* item : *myActivePlan) {
644 person->getPlan().push_back(item);
645 }
646 if (myNet.addPerson(person)) {
649 }
650 }
651 delete myVehicleParameter;
652 myVehicleParameter = nullptr;
653 delete myActivePlan;
654 myActivePlan = nullptr;
655}
656
657
658void
660 std::string typeID = DEFAULT_PEDTYPE_ID;
662 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for personFlow '" + myVehicleParameter->id + "' is not known.");
663 } else {
664 typeID = myVehicleParameter->vtypeid;
665 }
666 if (myActivePlan == nullptr || myActivePlan->empty()) {
667 WRITE_WARNINGF(TL("Discarding personFlow '%' because their plan is empty"), myVehicleParameter->id);
668 } else {
670 // instantiate all persons of this flow
671 int i = 0;
672 std::string baseID = myVehicleParameter->id;
675 throw ProcessError(TLF("probabilistic personFlow '%' must specify end time", myVehicleParameter->id));
676 } else {
679 addFlowPerson(typeID, t, baseID, i++);
680 }
681 }
682 }
683 } else {
685 // uniform sampling of departures from range is equivalent to poisson flow (encoded by negative offset)
686 if (OptionsCont::getOptions().getBool("randomize-flows") && myVehicleParameter->repetitionOffset >= 0) {
687 std::vector<SUMOTime> departures;
689 for (int j = 0; j < myVehicleParameter->repetitionNumber; ++j) {
690 departures.push_back(depart + RandHelper::rand(range));
691 }
692 std::sort(departures.begin(), departures.end());
693 std::reverse(departures.begin(), departures.end());
694 for (; i < myVehicleParameter->repetitionNumber; i++) {
695 addFlowPerson(typeID, departures[i], baseID, i);
697 }
698 } else {
701 // poisson: randomize first depart
703 }
705 addFlowPerson(typeID, depart + myVehicleParameter->repetitionTotalOffset, baseID, i);
708 }
709 }
710 }
711 }
712 }
713 delete myVehicleParameter;
714 myVehicleParameter = nullptr;
715 for (ROPerson::PlanItem* const it : *myActivePlan) {
716 delete it;
717 }
718 delete myActivePlan;
719 myActivePlan = nullptr;
720}
721
722
723void
724RORouteHandler::addFlowPerson(const std::string& typeID, SUMOTime depart, const std::string& baseID, int i) {
726 pars.id = baseID + "." + toString(i);
727 pars.depart = depart;
728 const SUMOVTypeParameter* const type = myNet.getVehicleTypeSecure(typeID);
729 if (!myKeepVTypeDist) {
730 pars.vtypeid = type->id;
731 }
732 ROPerson* person = new ROPerson(pars, type);
733 for (ROPerson::PlanItem* item : *myActivePlan) {
734 person->getPlan().push_back(item->clone());
735 }
736 if (myNet.addPerson(person)) {
737 if (i == 0) {
739 }
740 }
741}
742
743
744void
751 } else {
752 WRITE_WARNINGF(TL("Discarding container '%' because its plan is empty"), myVehicleParameter->id);
753 }
754 delete myVehicleParameter;
755 myVehicleParameter = nullptr;
757 myActiveContainerPlan = nullptr;
759}
760
761
768 } else {
769 WRITE_WARNINGF(TL("Discarding containerFlow '%' because its plan is empty"), myVehicleParameter->id);
770 }
771 delete myVehicleParameter;
772 myVehicleParameter = nullptr;
774 myActiveContainerPlan = nullptr;
776}
777
778
779void
782 // @todo: consider myScale?
784 delete myVehicleParameter;
785 myVehicleParameter = nullptr;
786 return;
787 }
788 // let's check whether vehicles had to depart before the simulation starts
790 const SUMOTime offsetToBegin = myBegin - myVehicleParameter->depart;
791 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
794 delete myVehicleParameter;
795 myVehicleParameter = nullptr;
796 return;
797 }
798 }
800 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
801 }
802 if (myVehicleParameter->routeid[0] == '!' && myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
803 closeRoute(true);
804 }
805 if (myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
806 myErrorOutput->inform("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
807 delete myVehicleParameter;
808 myVehicleParameter = nullptr;
809 return;
810 }
811 myActiveRouteID = "";
812 if (!MsgHandler::getErrorInstance()->wasInformed()) {
815 } else {
816 myErrorOutput->inform("Another flow with the id '" + myVehicleParameter->id + "' exists.");
817 delete myVehicleParameter;
818 }
819 } else {
820 delete myVehicleParameter;
821 }
822 myVehicleParameter = nullptr;
824}
825
826
827void
832
833
835RORouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, std::string& id, const SUMOVehicleParameter::Stop* stopParam) {
836 // dummy stop parameter to hold the attributes
838 if (stopParam != nullptr) {
839 stop = *stopParam;
840 } else {
841 bool ok = true;
842 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
843 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
844 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
845 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
846 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
847 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
848 }
849 const SUMOVehicleParameter::Stop* toStop = nullptr;
850 if (stop.busstop != "") {
852 id = stop.busstop;
853 if (toStop == nullptr) {
854 WRITE_ERROR("The busStop '" + stop.busstop + "' is not known" + errorSuffix);
855 }
856 } else if (stop.containerstop != "") {
858 id = stop.containerstop;
859 if (toStop == nullptr) {
860 WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known" + errorSuffix);
861 }
862 } else if (stop.parkingarea != "") {
864 id = stop.parkingarea;
865 if (toStop == nullptr) {
866 WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known" + errorSuffix);
867 }
868 } else if (stop.chargingStation != "") {
869 // ok, we have a charging station
871 id = stop.chargingStation;
872 if (toStop == nullptr) {
873 WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known" + errorSuffix);
874 }
875 } else if (stop.overheadWireSegment != "") {
876 // ok, we have an overhead wire segment
878 id = stop.overheadWireSegment;
879 if (toStop == nullptr) {
880 WRITE_ERROR("The overhead wire segment '" + stop.overheadWireSegment + "' is not known" + errorSuffix);
881 }
882 }
883 return toStop;
884}
885
888 Parameterised* result = nullptr;
889 if (myActiveContainerPlan != nullptr) {
891 (*myActiveContainerPlan) << attrs;
894 return result;
895 }
896 std::string errorSuffix;
897 if (myActivePlan != nullptr) {
898 errorSuffix = " in person '" + myVehicleParameter->id + "'.";
899 } else if (myActiveContainerPlan != nullptr) {
900 errorSuffix = " in container '" + myVehicleParameter->id + "'.";
901 } else if (myVehicleParameter != nullptr) {
902 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
903 } else {
904 errorSuffix = " in route '" + myActiveRouteID + "'.";
905 }
907 bool ok = parseStop(stop, attrs, errorSuffix, myErrorOutput);
908 if (!ok) {
909 return result;
910 }
911 // try to parse the assigned bus stop
912 const ROEdge* edge = nullptr;
913 std::string stoppingPlaceID;
914 const SUMOVehicleParameter::Stop* stoppingPlace = retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID, &stop);
915 bool hasPos = false;
916 if (stoppingPlace != nullptr) {
917 stop.lane = stoppingPlace->lane;
918 stop.endPos = stoppingPlace->endPos;
919 stop.startPos = stoppingPlace->startPos;
921 } else {
922 // no, the lane and the position should be given
923 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
924 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
925 if (ok && stop.edge != "") {
926 edge = myNet.getEdge(stop.edge);
927 if (edge == nullptr) {
928 myErrorOutput->inform("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
929 return result;
930 }
931 } else if (ok && stop.lane != "") {
933 if (edge == nullptr) {
934 myErrorOutput->inform("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
935 return result;
936 }
937 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
938 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
939 Position pos;
940 bool geo = false;
941 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
942 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
943 } else {
944 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
945 geo = true;
946 }
947 PositionVector positions;
948 positions.push_back(pos);
949 ConstROEdgeVector geoEdges;
953 if (type != nullptr) {
954 vClass = type->vehicleClass;
955 }
956 }
957 parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok, true);
958 if (ok) {
959 edge = geoEdges.front();
960 hasPos = true;
961 if (geo) {
963 }
965 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
966 } else {
967 return result;
968 }
969 } else if (!ok || (stop.lane == "" && stop.edge == "")) {
970 myErrorOutput->inform("A stop must be placed on a bus stop, a container stop, a parking area, an edge or a lane" + errorSuffix);
971 return result;
972 }
973 if (!hasPos) {
974 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
975 }
976 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, stop.endPos - 2 * POSITION_EPS);
977 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS));
978 const double endPosOffset = edge->isInternal() ? edge->getNormalBefore()->getLength() : 0;
979 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength() + endPosOffset, POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
980 myErrorOutput->inform("Invalid start or end position for stop" + errorSuffix);
981 return result;
982 }
983 }
984 stop.edge = edge->getID();
985 if (myActivePlan != nullptr) {
986 ROPerson::addStop(*myActivePlan, stop, edge);
987 result = myActivePlan->back()->getStopParameters();
988 } else if (myVehicleParameter != nullptr) {
989 myVehicleParameter->stops.push_back(stop);
990 result = &myVehicleParameter->stops.back();
991 } else {
992 myActiveRouteStops.push_back(stop);
993 result = &myActiveRouteStops.back();
994 }
995 if (myInsertStopEdgesAt >= 0) {
996 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
998 }
999 return result;
1000}
1001
1002
1003void
1005 bool ok = true;
1006 std::vector<ROPerson::PlanItem*>& plan = *myActivePlan;
1007 const std::string pid = myVehicleParameter->id;
1008
1009 const ROEdge* from = nullptr;
1010 const ROEdge* to = nullptr;
1011 parseFromViaTo(SUMO_TAG_PERSON, attrs, ok);
1014 if (ok) {
1015 from = myActiveRoute.front();
1016 }
1017 } else if (plan.empty()) {
1018 myErrorOutput->inform("The start edge for person '" + pid + "' is not known.");
1019 return;
1020 }
1021 std::string stoppingPlaceID;
1022 const SUMOVehicleParameter::Stop* stop = retrieveStoppingPlace(attrs, " for ride of person '" + myVehicleParameter->id + "'", stoppingPlaceID);
1023 if (stop != nullptr) {
1025 } else {
1028 to = myActiveRoute.back();
1029 } else {
1030 myErrorOutput->inform("The to edge is missing within a ride of '" + myVehicleParameter->id + "'.");
1031 return;
1032 }
1033 }
1034 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
1035 stop == nullptr ? std::numeric_limits<double>::infinity() : stop->endPos);
1036 const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
1037 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, pid.c_str(), ok, "");
1038
1040 StringTokenizer st(desc);
1041 if (st.size() != 1) {
1042 myErrorOutput->inform("Triggered departure for person '" + pid + "' requires a unique lines value.");
1043 return;
1044 }
1045 const std::string vehID = st.front();
1046 if (!myNet.knowsVehicle(vehID)) {
1047 myErrorOutput->inform("Unknown vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
1048 return;
1049 }
1050 SUMOTime vehDepart = myNet.getDeparture(vehID);
1051 if (vehDepart == -1) {
1052 myErrorOutput->inform("Cannot use triggered vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
1053 return;
1054 }
1055 myVehicleParameter->depart = vehDepart + 1; // write person after vehicle
1056 }
1057 ROPerson::addRide(plan, from, to, desc, arrivalPos, stoppingPlaceID, group);
1058}
1059
1060
1061void
1064 bool ok = true;
1065 const std::string pid = myVehicleParameter->id;
1066 const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
1067 StringTokenizer st(desc);
1068 if (st.size() != 1) {
1069 throw ProcessError(TLF("Triggered departure for container '%' requires a unique lines value.", pid));
1070 }
1071 const std::string vehID = st.front();
1072 if (!myNet.knowsVehicle(vehID)) {
1073 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
1074 }
1075 SUMOTime vehDepart = myNet.getDeparture(vehID);
1076 if (vehDepart == -1) {
1077 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
1078 }
1079 myVehicleParameter->depart = vehDepart + 1; // write container after vehicle
1080 }
1081}
1082
1083
1084void
1087
1088
1089void
1090RORouteHandler::parseEdges(const std::string& desc, ConstROEdgeVector& into,
1091 const std::string& rid, bool& ok) {
1092 for (StringTokenizer st(desc); st.hasNext();) {
1093 const std::string id = st.next();
1094 const ROEdge* edge = myNet.getEdge(id);
1095 if (edge == nullptr) {
1096 myErrorOutput->inform("The edge '" + id + "' within the route " + rid + " is not known.");
1097 ok = false;
1098 } else {
1099 into.push_back(edge);
1100 }
1101 }
1102}
1103
1104
1105void
1106RORouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1107 const ROEdge* /*fromEdge*/, const ROEdge*& toEdge,
1108 double& departPos, double& arrivalPos, std::string& busStopID,
1109 const ROPerson::PlanItem* const lastStage, bool& ok) {
1110 const std::string description = "walk or personTrip of '" + personID + "'.";
1111 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1112 WRITE_WARNING(TL("The attribute departPos is no longer supported for walks, please use the person attribute, the arrivalPos of the previous step or explicit stops."));
1113 }
1114 departPos = myVehicleParameter->departPos;
1115 if (lastStage != nullptr) {
1116 departPos = lastStage->getDestinationPos();
1117 }
1118
1119 busStopID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1120
1121 const SUMOVehicleParameter::Stop* bs = retrieveStoppingPlace(attrs, description, busStopID);
1122 if (bs != nullptr) {
1124 arrivalPos = (bs->startPos + bs->endPos) / 2;
1125 }
1126 if (toEdge != nullptr) {
1129 myHardFail, description, toEdge->getLength(),
1130 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok));
1131 }
1132 } else {
1133 throw ProcessError(TLF("No destination edge for %.", description));
1134 }
1135}
1136
1137
1138void
1140 bool ok = true;
1141 const char* const id = myVehicleParameter->id.c_str();
1142 assert(!attrs.hasAttribute(SUMO_ATTR_EDGES));
1143 const ROEdge* from = nullptr;
1144 const ROEdge* to = nullptr;
1145 parseFromViaTo(SUMO_TAG_PERSON, attrs, ok);
1149 if (ok) {
1150 from = myActiveRoute.front();
1151 }
1152 } else if (myActivePlan->empty()) {
1153 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1154 } else {
1155 from = myActivePlan->back()->getDestination();
1156 }
1159 to = myActiveRoute.back();
1160 } // else, to may also be derived from stopping place
1161
1162 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1163 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1164 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1165 }
1166
1167 double departPos = 0;
1168 double arrivalPos = std::numeric_limits<double>::infinity();
1169 std::string busStopID;
1170 const ROPerson::PlanItem* const lastStage = myActivePlan->empty() ? nullptr : myActivePlan->back();
1171 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, busStopID, lastStage, ok);
1172
1173 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1174 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, "");
1175 SVCPermissions modeSet = 0;
1176 for (StringTokenizer st(modes); st.hasNext();) {
1177 const std::string mode = st.next();
1178 if (mode == "car") {
1179 modeSet |= SVC_PASSENGER;
1180 } else if (mode == "taxi") {
1181 modeSet |= SVC_TAXI;
1182 } else if (mode == "bicycle") {
1183 modeSet |= SVC_BICYCLE;
1184 } else if (mode == "public") {
1185 modeSet |= SVC_BUS;
1186 } else {
1187 throw InvalidArgument("Unknown person mode '" + mode + "'.");
1188 }
1189 }
1190 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1191 double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1192 if (ok) {
1193 const std::string originStopID = myActivePlan->empty() ? "" : myActivePlan->back()->getStopDest();
1194 ROPerson::addTrip(*myActivePlan, myVehicleParameter->id, from, to, modeSet, types,
1195 departPos, originStopID, arrivalPos, busStopID, walkFactor, group);
1196 myParamStack.push_back(myActivePlan->back());
1197 }
1198}
1199
1200
1201void
1203 // parse walks from->to as person trips
1205 // XXX allow --repair?
1206 bool ok = true;
1207 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1208 const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1209 RORouteDef* routeDef = myNet.getRouteDef(routeID);
1210 const RORoute* route = routeDef != nullptr ? routeDef->getFirstRoute() : nullptr;
1211 if (route == nullptr) {
1212 throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1213 }
1214 myActiveRoute = route->getEdgeVector();
1215 } else {
1216 myActiveRoute.clear();
1217 parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myVehicleParameter->id.c_str(), ok), myActiveRoute, " walk for person '" + myVehicleParameter->id + "'", ok);
1218 }
1219 const char* const objId = myVehicleParameter->id.c_str();
1220 const double duration = attrs.getOpt<double>(SUMO_ATTR_DURATION, objId, ok, -1);
1221 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1222 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1223 }
1224 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, objId, ok, -1.);
1225 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1226 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1227 }
1228 double departPos = 0.;
1229 double arrivalPos = std::numeric_limits<double>::infinity();
1230 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1231 WRITE_WARNING(TL("The attribute departPos is no longer supported for walks, please use the person attribute, the arrivalPos of the previous step or explicit stops."));
1232 }
1234 arrivalPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, objId, myActiveRoute.back()->getLength(), attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, objId, ok));
1235 }
1236 std::string stoppingPlaceID;
1237 const std::string errorSuffix = " for walk of person '" + myVehicleParameter->id + "'";
1238 retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID);
1239 if (ok) {
1240 ROPerson::addWalk(*myActivePlan, myActiveRoute, duration, speed, departPos, arrivalPos, stoppingPlaceID);
1241 myParamStack.push_back(myActivePlan->back());
1242 }
1243 } else {
1244 addPersonTrip(attrs);
1245 }
1246}
1247
1248
1249void
1251 for (const auto& edgeItem : myNet.getEdgeMap()) {
1252 for (ROLane* lane : edgeItem.second->getLanes()) {
1253 Boundary b = lane->getShape().getBoxBoundary();
1254 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1255 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1256 tree->Insert(cmin, cmax, lane);
1257 }
1258 }
1259}
1260
1261
1262ROEdge*
1263RORouteHandler::retrieveEdge(const std::string& id) {
1264 return myNet.getEdge(id);
1265}
1266
1267bool
1269 if (!myUnsortedInput) {
1271 }
1272 return true;
1273}
1274
1275/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define JUNCTION_TAZ_MISSING_HELP
Definition MapMatcher.h:30
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
std::vector< const ROEdge * > ConstROEdgeVector
Definition ROEdge.h:56
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define TIME2STEPS(x)
Definition SUMOTime.h:57
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const double DEFAULT_VEH_PROB
const std::string DEFAULT_PEDTYPE_ID
const std::string DEFAULT_VTYPE_ID
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TAXI
vehicle is a taxi
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
const long long int VEHPARS_TO_TAZ_SET
const long long int VEHPARS_FROM_TAZ_SET
const int STOP_END_SET
@ GIVEN
The time is given.
@ TRIGGERED
The departure is person triggered.
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_TRANSHIP
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_STOP
stop for vehicles
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_TRANSPORT
@ SUMO_TAG_CONTAINER
@ SUMO_TAG_RIDE
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_TAG_PERSON
@ SUMO_TAG_PERSONFLOW
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_ATTR_STARTPOS
@ SUMO_ATTR_LINES
@ SUMO_ATTR_LAST
@ SUMO_ATTR_LANE
@ SUMO_ATTR_LON
@ SUMO_ATTR_REFID
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_VIALONLAT
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_VIAXY
@ SUMO_ATTR_Y
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_TO_JUNCTION
@ SUMO_ATTR_X
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_PROBS
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_TOLONLAT
@ SUMO_ATTR_CHARGING_STATION
@ SUMO_ATTR_ROUTES
@ SUMO_ATTR_MODES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_OVERHEAD_WIRE_SEGMENT
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_GROUP
@ SUMO_ATTR_COST
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_VIAJUNCTIONS
@ SUMO_ATTR_FROMXY
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_LAT
@ SUMO_ATTR_WALKFACTOR
@ SUMO_ATTR_TOXY
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_FROMLONLAT
@ SUMO_ATTR_REPEAT
@ SUMO_ATTR_CYCLETIME
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:118
PositionVector getShape(const bool closeShape) const
get position vector (shape) based on this boundary
Definition Boundary.cpp:447
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:124
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
Provides utility functions for matching locations to edges (during route parsing)
Definition MapMatcher.h:45
void parseGeoEdges(const PositionVector &positions, bool geo, SUMOVehicleClass vClass, std::vector< const ROEdge * > &into, const std::string &rid, bool isFrom, bool &ok, bool forceEdge=false)
Definition MapMatcher.h:48
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
const std::string & getID() const
Returns the id.
Definition Named.h:74
A RT-tree for efficient storing of SUMO's Named objects.
Definition NamedRTree.h:61
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition NamedRTree.h:79
A storage for options typed value containers)
Definition OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
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)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
An output device that encapsulates an ofstream.
std::string getString() const
Returns the current content as a string.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
An upper class for objects with additional parameters.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
A basic edge for routing applications.
Definition ROEdge.h:72
const ROEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition ROEdge.cpp:289
bool isInternal() const
return whether this edge is an internal edge
Definition ROEdge.h:159
const ROEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition ROEdge.cpp:386
const std::vector< ROLane * > & getLanes() const
Returns this edge's lanes.
Definition ROEdge.h:529
double getLength() const
Returns the length of the edge.
Definition ROEdge.h:224
A single lane the router may use.
Definition ROLane.h:48
The router's network representation.
Definition RONet.h:63
SUMOVTypeParameter * getVehicleTypeSecure(const std::string &id)
Retrieves the named vehicle type.
Definition RONet.cpp:364
const RandomDistributor< SUMOVTypeParameter * > * getVTypeDistribution(const std::string &id)
Retrieves the named vehicle type distribution.
Definition RONet.h:281
bool addRouteDef(RORouteDef *def)
Definition RONet.cpp:286
bool knowsVehicle(const std::string &id) const
returns whether a vehicle with the given id was already loaded
Definition RONet.cpp:488
virtual bool addVehicle(const std::string &id, ROVehicle *veh)
Definition RONet.cpp:466
SUMOTime getDeparture(const std::string &vehID) const
returns departure time for the given vehicle id
Definition RONet.cpp:493
const SUMOVehicleParameter::Stop * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Retrieves a stopping place from the network.
Definition RONet.h:217
void addContainer(const SUMOTime depart, const std::string desc)
Definition RONet.cpp:534
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition RONet.h:158
bool addPerson(ROPerson *person)
Definition RONet.cpp:522
RORouteDef * getRouteDef(const std::string &name) const
Returns the named route definition.
Definition RONet.h:319
virtual bool addVehicleType(SUMOVTypeParameter *type)
Adds a read vehicle type definition to the network.
Definition RONet.cpp:442
bool addVTypeDistribution(const std::string &id, RandomDistributor< SUMOVTypeParameter * > *vehTypeDistribution)
Adds a vehicle type distribution.
Definition RONet.cpp:455
const NamedObjectCont< ROEdge * > & getEdgeMap() const
Definition RONet.h:423
bool addFlow(SUMOVehicleParameter *flow, const bool randomize)
Definition RONet.cpp:504
Every person has a plan comprising of multiple planItems.
Definition ROPerson.h:83
virtual double getDestinationPos() const =0
A person as used by router.
Definition ROPerson.h:50
static void addTrip(std::vector< PlanItem * > &plan, const std::string &id, const ROEdge *const from, const ROEdge *const to, const SVCPermissions modeSet, const std::string &vTypes, const double departPos, const std::string &stopOrigin, const double arrivalPos, const std::string &busStop, double walkFactor, const std::string &group)
Definition ROPerson.cpp:61
static void addStop(std::vector< PlanItem * > &plan, const SUMOVehicleParameter::Stop &stopPar, const ROEdge *const stopEdge)
Definition ROPerson.cpp:133
static void addRide(std::vector< PlanItem * > &plan, const ROEdge *const from, const ROEdge *const to, const std::string &lines, double arrivalPos, const std::string &destStop, const std::string &group)
Definition ROPerson.cpp:116
static void addWalk(std::vector< PlanItem * > &plan, const ConstROEdgeVector &edges, const double duration, const double speed, const double departPos, const double arrivalPos, const std::string &busStop)
Definition ROPerson.cpp:124
std::vector< PlanItem * > & getPlan()
Definition ROPerson.h:440
Base class for a vehicle's route definition.
Definition RORouteDef.h:53
void addLoadedAlternative(RORoute *alternative)
Adds a single alternative loaded from the file An alternative may also be generated during DUA.
double getOverallProb() const
Returns the sum of the probablities of the contained routes.
void addAlternativeDef(const RORouteDef *alternative)
Adds an alternative loaded from the file.
RORouteDef * copy(const std::string &id, const SUMOTime stopOffset) const
Returns a deep copy of the route definition.
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs) override
opens a type distribution for reading
const SUMOVehicleParameter::Stop * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, std::string &id, const SUMOVehicleParameter::Stop *stopParam=nullptr)
retrieve stopping place element
void addTransport(const SUMOSAXAttributes &attrs) override
Processing of a transport.
void deleteActivePlanAndVehicleParameter()
void openRoute(const SUMOSAXAttributes &attrs) override
opens a route for reading
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
void addFlowPerson(const std::string &typeID, SUMOTime depart, const std::string &baseID, int i)
Processing of a person from a personFlow.
void closeContainerFlow() override
Ends the processing of a containerFlow.
RORouteHandler(RONet &net, const std::string &file, const bool tryRepair, const bool emptyDestinationsAllowed, const bool ignoreErrors, const bool checkSchema)
standard constructor
void parseEdges(const std::string &desc, ConstROEdgeVector &into, const std::string &rid, bool &ok)
Parse edges from strings.
RONet & myNet
The current route.
void addRide(const SUMOSAXAttributes &attrs) override
Processing of a ride.
ConstROEdgeVector myActiveRoute
The current route.
void closeRouteDistribution() override
closes (ends) the building of a distribution
void addTranship(const SUMOSAXAttributes &attrs) override
Processing of a tranship.
void closeContainer() override
Ends the processing of a container.
std::vector< ROPerson::PlanItem * > * myActivePlan
The plan of the current person.
const bool myTryRepair
Information whether routes shall be repaired.
bool checkLastDepart() override
Checks whether the route file is sorted by departure time if needed.
OutputDevice_String * myActiveContainerPlan
The plan of the current container.
void closeVehicle() override
Ends the processing of a vehicle.
SUMOTime myActiveRoutePeriod
const SUMOTime myBegin
The begin time.
void closeRoute(const bool mayBeDisconnected=false) override
closes (ends) the building of a route.
Parameterised * addStop(const SUMOSAXAttributes &attrs) override
Processing of a stop.
RandomDistributor< SUMOVTypeParameter * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
void closePersonFlow() override
Ends the processing of a personFlow.
void openRouteDistribution(const SUMOSAXAttributes &attrs) override
opens a route distribution for reading
int myActiveContainerPlanSize
The number of stages in myActiveContainerPlan.
const bool myKeepVTypeDist
whether to keep the vtype distribution in output
void openTrip(const SUMOSAXAttributes &attrs) override
opens a trip for reading
const bool myUnsortedInput
whether input is read all at once (no sorting check is necessary)
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const ROEdge *fromEdge, const ROEdge *&toEdge, double &departPos, double &arrivalPos, std::string &busStopID, const ROPerson::PlanItem *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
MsgHandler *const myErrorOutput
Depending on the "ignore-errors" option different outputs are used.
int myActiveRouteRepeat
number of repetitions of the active route
void closeFlow() override
Ends the processing of a flow.
ROEdge * retrieveEdge(const std::string &id) override
void addPersonTrip(const SUMOSAXAttributes &attrs) override
add a routing request for a walking or intermodal person
void closePerson() override
Ends the processing of a person.
~RORouteHandler() override
standard destructor
RORouteDef * myCurrentAlternatives
The currently parsed route alternatives.
void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
void addWalk(const SUMOSAXAttributes &attrs) override
add a fully specified walk
void initLaneTree(NamedRTree *tree) override
void openRouteFlow(const SUMOSAXAttributes &attrs) override
opens a route flow for reading
void closeTrip() override
Ends the processing of a trip.
void openFlow(const SUMOSAXAttributes &attrs) override
opens a flow for reading
void closeVType() override
Ends the processing of a vehicle type.
void closeVehicleTypeDistribution() override
closes (ends) the building of a distribution
void parseFromViaTo(SumoXMLTag tag, const SUMOSAXAttributes &attrs, bool &ok)
Called for parsing from and to and the corresponding taz attributes.
A complete router's route.
Definition RORoute.h:52
const ConstROEdgeVector & getEdgeVector() const
Returns the list of edges this route consists of.
Definition RORoute.h:152
A vehicle as used by router.
Definition ROVehicle.h:50
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Represents a generic random distribution.
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
const std::vector< T > & getVals() const
Returns the members of the distribution.
void clear()
Clears the distribution.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
Parser for routes during their loading.
bool parseStop(SUMOVehicleParameter::Stop &stop, const SUMOSAXAttributes &attrs, std::string errorSuffix, MsgHandler *const errorOutput)
parses attributes common to all stops
std::vector< SUMOVehicleParameter::Stop > myActiveRouteStops
List of the stops on the parsed route.
void registerLastDepart()
save last depart (only to be used if vehicle is not discarded)
double myCurrentCosts
The currently parsed route costs.
std::string myActiveRouteID
The id of the current route.
std::vector< Parameterised * > myParamStack
The stack of currently parsed parameterised objects.
SUMOVehicleParameter * myVehicleParameter
Parameter of the current vehicle, trip, person, container or flow.
const bool myHardFail
flag to enable or disable hard fails
SUMOVTypeParameter * myCurrentVType
The currently parsed vehicle type.
static StopPos checkStopPos(double &startPos, double &endPos, const double laneLength, const double minLength, const bool friendlyPos)
check start and end position of a stop
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
double myActiveRouteProbability
The probability of the current route.
int myInsertStopEdgesAt
where stop edges can be inserted into the current route (-1 means no insertion)
std::string myActiveRouteRefID
The id of the route the current route references to.
const RGBColor * myActiveRouteColor
The currently parsed route's color.
virtual bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
Structure representing possible vehicle parameter.
double defaultProbability
The probability when being added to a distribution without an explicit probability.
void cacheParamRestrictions(const std::vector< std::string > &restrictionKeys)
SUMOVehicleClass vehicleClass
The vehicle's class.
std::string id
The vehicle type's id.
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
std::string overheadWireSegment
(Optional) overhead line segment if one is assigned to the stop
int parametersSet
Information for the output which parameter were set.
double endPos
The stopping position end.
std::string busstop
(Optional) bus stop if one is assigned to the stop
std::string containerstop
(Optional) container 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.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
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.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double departPos
(optional) The position the vehicle shall depart from
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.
std::string toTaz
The vehicle's destination zone (district)
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
std::string fromTaz
The vehicle's origin zone (district)
static double parseWalkPos(SumoXMLAttr attr, const bool hardFail, const std::string &id, double maxPos, const std::string &val, SumoRNG *rng=0)
parse departPos or arrivalPos for a walk
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
std::string front()
returns the first substring without moving the iterator
int size() const
returns the number of existing substrings
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it