Eclipse SUMO - Simulation of Urban MObility
RORouteHandler.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/****************************************************************************/
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#define JUNCTION_TAZ_MISSING_HELP "\nSet option '--junction-taz' or load a TAZ-file"
49
50// ===========================================================================
51// method definitions
52// ===========================================================================
53RORouteHandler::RORouteHandler(RONet& net, const std::string& file,
54 const bool tryRepair,
55 const bool emptyDestinationsAllowed,
56 const bool ignoreErrors,
57 const bool checkSchema) :
58 SUMORouteHandler(file, checkSchema ? "routes" : "", true),
59 myNet(net),
60 myActiveRouteRepeat(0),
61 myActiveRoutePeriod(0),
62 myActivePlan(nullptr),
63 myActiveContainerPlan(nullptr),
64 myActiveContainerPlanSize(0),
65 myTryRepair(tryRepair),
66 myEmptyDestinationsAllowed(emptyDestinationsAllowed),
67 myErrorOutput(ignoreErrors ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
68 myBegin(string2time(OptionsCont::getOptions().getString("begin"))),
69 myKeepVTypeDist(OptionsCont::getOptions().getBool("keep-vtype-distributions")),
70 myMapMatchingDistance(OptionsCont::getOptions().getFloat("mapmatch.distance")),
71 myMapMatchJunctions(OptionsCont::getOptions().getBool("mapmatch.junctions")),
72 myUnsortedInput(OptionsCont::getOptions().exists("unsorted-input") && OptionsCont::getOptions().getBool("unsorted-input")),
73 myCurrentVTypeDistribution(nullptr),
74 myCurrentAlternatives(nullptr),
75 myLaneTree(nullptr) {
76 myActiveRoute.reserve(100);
77}
78
79
81 delete myLaneTree;
83}
84
85
86void
88 const std::string element = toString(tag);
89 myActiveRoute.clear();
90 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
92 WRITE_WARNING("Taz usage was requested but no taz present in " + element + " '" + myVehicleParameter->id + "'!");
93 useTaz = false;
94 }
95 // from-attributes
96 const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
97 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
99 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROMJUNCTION);
100 const std::string tazType = useJunction ? "junction" : "taz";
101 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROMJUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok, true);
102 const ROEdge* fromTaz = myNet.getEdge(tazID + "-source");
103 if (fromTaz == nullptr) {
104 myErrorOutput->inform("Source " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
105 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
106 ok = false;
107 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
108 myErrorOutput->inform("Source " + tazType + " '" + tazID + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
109 ok = false;
110 } else {
111 myActiveRoute.push_back(fromTaz);
112 }
113 } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
114 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, myActiveRoute, rid, true, ok);
115 } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
116 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, myActiveRoute, rid, true, ok);
117 } else {
118 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok), myActiveRoute, rid, ok);
119 }
122 }
123
124 // via-attributes
125 ConstROEdgeVector viaEdges;
126 if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
127 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, viaEdges, rid, false, ok);
128 } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
129 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, viaEdges, rid, false, ok);
130 } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
131 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
132 const ROEdge* viaSink = myNet.getEdge(junctionID + "-sink");
133 if (viaSink == nullptr) {
134 myErrorOutput->inform("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
135 ok = false;
136 } else {
137 viaEdges.push_back(viaSink);
138 }
139 }
140 } else {
141 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true), viaEdges, rid, ok);
142 }
143 for (const ROEdge* e : viaEdges) {
144 myActiveRoute.push_back(e);
145 myVehicleParameter->via.push_back(e->getID());
146 }
147
148 // to-attributes
149 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
151 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TOJUNCTION);
152 const std::string tazType = useJunction ? "junction" : "taz";
153 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TOJUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
154 const ROEdge* toTaz = myNet.getEdge(tazID + "-sink");
155 if (toTaz == nullptr) {
156 myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
157 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
158 ok = false;
159 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
160 myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
161 ok = false;
162 } else {
163 myActiveRoute.push_back(toTaz);
164 }
165 } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
166 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, myActiveRoute, rid, false, ok);
167 } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
168 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, myActiveRoute, rid, false, ok);
169 } else {
170 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true), myActiveRoute, rid, ok);
171 }
173 if (myVehicleParameter->routeid == "") {
175 }
176}
177
178
179void
181 const SUMOSAXAttributes& attrs) {
183 throw ProcessError("Triggered departure for person '" + myVehicleParameter->id + "' requires starting with a ride.");
185 throw ProcessError("Triggered departure for container '" + myVehicleParameter->id + "' requires starting with a transport.");
186 }
187 SUMORouteHandler::myStartElement(element, attrs);
188 bool ok = true;
189 switch (element) {
190 case SUMO_TAG_PERSON:
191 case SUMO_TAG_PERSONFLOW: {
192 myActivePlan = new std::vector<ROPerson::PlanItem*>();
193 break;
194 }
195 case SUMO_TAG_RIDE:
196 break; // handled in addRide, called from SUMORouteHandler::myStartElement
202 (*myActiveContainerPlan) << attrs;
203 break;
206 if (myActiveContainerPlan == nullptr) {
207 throw ProcessError("Found " + toString((SumoXMLTag)element) + " outside container element");
208 }
209 // copy container elements
211 (*myActiveContainerPlan) << attrs;
214 break;
215 case SUMO_TAG_FLOW:
217 parseFromViaTo((SumoXMLTag)element, attrs, ok);
218 break;
219 case SUMO_TAG_TRIP:
221 parseFromViaTo((SumoXMLTag)element, attrs, ok);
222 break;
223 default:
224 break;
225 }
226}
227
228
229void
231 bool ok = true;
232 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
233 if (ok) {
235 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
236 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
237 StringTokenizer st(vTypes);
238 while (st.hasNext()) {
239 const std::string typeID = st.next();
240 SUMOVTypeParameter* const type = myNet.getVehicleTypeSecure(typeID);
241 if (type == nullptr) {
242 myErrorOutput->inform("Unknown vehicle type '" + typeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
243 } else {
245 }
246 }
247 }
248 }
249}
250
251
252void
254 if (myCurrentVTypeDistribution != nullptr) {
257 myErrorOutput->inform("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
260 myErrorOutput->inform("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
261 }
263 }
264}
265
266
267void
269 myActiveRoute.clear();
271 // check whether the id is really necessary
272 std::string rid;
273 if (myCurrentAlternatives != nullptr) {
275 rid = "distribution '" + myCurrentAlternatives->getID() + "'";
276 } else if (myVehicleParameter != nullptr) {
277 // ok, a vehicle is wrapping the route,
278 // we may use this vehicle's id as default
279 myVehicleParameter->routeid = myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
280 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
281 WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "').");
282 }
283 } else {
284 bool ok = true;
285 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
286 if (!ok) {
287 return;
288 }
289 rid = "'" + myActiveRouteID + "'";
290 }
291 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
292 rid = "for vehicle '" + myVehicleParameter->id + "'";
293 }
294 bool ok = true;
295 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
296 parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid, ok);
297 }
298 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
299 if (myActiveRouteRefID != "" && myNet.getRouteDef(myActiveRouteRefID) == nullptr) {
300 myErrorOutput->inform("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
301 }
302 if (myCurrentAlternatives != nullptr && !attrs.hasAttribute(SUMO_ATTR_PROB)) {
303 WRITE_WARNINGF(TL("No probability for route %, using default."), rid);
304 }
306 if (ok && myActiveRouteProbability < 0) {
307 myErrorOutput->inform("Invalid probability for route '" + myActiveRouteID + "'.");
308 }
310 ok = true;
311 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
313 if (myActiveRouteRepeat > 0) {
315 if (myVehicleParameter != nullptr) {
317 if (type != nullptr) {
318 vClass = type->vehicleClass;
319 }
320 }
321 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
322 myErrorOutput->inform("Disconnected route " + rid + " when repeating.");
323 }
324 }
325 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
326 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
327 myErrorOutput->inform("Invalid cost for route '" + myActiveRouteID + "'.");
328 }
329}
330
331
332void
334 // currently unused
335}
336
337
338void
340 // currently unused
341}
342
343
344void
346 // currently unused
347}
348
349
350void
351RORouteHandler::closeRoute(const bool mayBeDisconnected) {
352 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
353 if (mustReroute) {
354 // implicit route from stops
356 ROEdge* edge = myNet.getEdge(stop.edge);
357 myActiveRoute.push_back(edge);
358 }
359 }
360 if (myActiveRoute.size() == 0) {
361 if (myActiveRouteRefID != "" && myCurrentAlternatives != nullptr) {
363 myActiveRouteID = "";
365 return;
366 }
367 if (myVehicleParameter != nullptr) {
368 myErrorOutput->inform("The route for vehicle '" + myVehicleParameter->id + "' has no edges.");
369 } else {
370 myErrorOutput->inform("Route '" + myActiveRouteID + "' has no edges.");
371 }
372 myActiveRouteID = "";
373 myActiveRouteStops.clear();
374 return;
375 }
376 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
377 myErrorOutput->inform("The routing information for vehicle '" + myVehicleParameter->id + "' is insufficient.");
378 myActiveRouteID = "";
379 myActiveRouteStops.clear();
380 return;
381 }
382 if (!mayBeDisconnected && OptionsCont::getOptions().exists("no-internal-links") && !OptionsCont::getOptions().getBool("no-internal-links")) {
383 // fix internal edges which did not get parsed
384 const ROEdge* last = nullptr;
385 ConstROEdgeVector fullRoute;
386 for (const ROEdge* roe : myActiveRoute) {
387 if (last != nullptr) {
388 for (const ROEdge* intern : last->getSuccessors()) {
389 if (intern->isInternal() && intern->getSuccessors().size() == 1 && intern->getSuccessors().front() == roe) {
390 fullRoute.push_back(intern);
391 }
392 }
393 }
394 fullRoute.push_back(roe);
395 last = roe;
396 }
397 myActiveRoute = fullRoute;
398 }
399 if (myActiveRouteRepeat > 0) {
400 // duplicate route
402 auto tmpStops = myActiveRouteStops;
403 for (int i = 0; i < myActiveRouteRepeat; i++) {
404 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
405 for (SUMOVehicleParameter::Stop stop : tmpStops) {
406 if (stop.until > 0) {
407 if (myActiveRoutePeriod <= 0) {
408 const std::string description = myVehicleParameter != nullptr
409 ? "for vehicle '" + myVehicleParameter->id + "'"
410 : "'" + myActiveRouteID + "'";
411 throw ProcessError("Cannot repeat stops with 'until' in route " + description + " because no cycleTime is defined.");
412 }
413 stop.until += myActiveRoutePeriod * (i + 1);
414 stop.arrival += myActiveRoutePeriod * (i + 1);
415 }
416 myActiveRouteStops.push_back(stop);
417 }
418 }
419 }
422 myActiveRoute.clear();
423 if (myCurrentAlternatives == nullptr) {
424 if (myNet.getRouteDef(myActiveRouteID) != nullptr) {
425 delete route;
426 if (myVehicleParameter != nullptr) {
427 myErrorOutput->inform("Another route for vehicle '" + myVehicleParameter->id + "' exists.");
428 } else {
429 myErrorOutput->inform("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
430 }
431 myActiveRouteID = "";
432 myActiveRouteStops.clear();
433 return;
434 } else {
435 myCurrentAlternatives = new RORouteDef(myActiveRouteID, 0, mayBeDisconnected || myTryRepair, mayBeDisconnected);
438 myCurrentAlternatives = nullptr;
439 }
440 } else {
442 }
443 myActiveRouteID = "";
444 myActiveRouteStops.clear();
445}
446
447
448void
450 // check whether the id is really necessary
451 bool ok = true;
452 std::string id;
453 if (myVehicleParameter != nullptr) {
454 // ok, a vehicle is wrapping the route,
455 // we may use this vehicle's id as default
456 myVehicleParameter->routeid = id = "!" + myVehicleParameter->id; // !!! document this
457 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
458 WRITE_WARNING("Ids of internal route distributions are ignored (vehicle '" + myVehicleParameter->id + "').");
459 }
460 } else {
461 id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
462 if (!ok) {
463 return;
464 }
465 }
466 // try to get the index of the last element
467 int index = attrs.getOpt<int>(SUMO_ATTR_LAST, id.c_str(), ok, 0);
468 if (ok && index < 0) {
469 myErrorOutput->inform("Negative index of a route alternative (id='" + id + "').");
470 return;
471 }
472 // build the alternative cont
473 myCurrentAlternatives = new RORouteDef(id, index, myTryRepair, false);
474 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
475 ok = true;
476 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, id.c_str(), ok));
477 while (st.hasNext()) {
478 const std::string routeID = st.next();
479 const RORouteDef* route = myNet.getRouteDef(routeID);
480 if (route == nullptr) {
481 myErrorOutput->inform("Unknown route '" + routeID + "' in distribution '" + id + "'.");
482 } else {
484 }
485 }
486 }
487}
488
489
490void
492 if (myCurrentAlternatives != nullptr) {
494 myErrorOutput->inform("Route distribution '" + myCurrentAlternatives->getID() + "' is empty.");
497 myErrorOutput->inform("Another route (or distribution) with the id '" + myCurrentAlternatives->getID() + "' exists.");
499 }
500 myCurrentAlternatives = nullptr;
501 }
502}
503
504
505void
508 // get the vehicle id
510 return;
511 }
512 // get vehicle type
514 if (type == nullptr) {
515 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
517 } else {
518 if (!myKeepVTypeDist) {
519 // fix the type id in case we used a distribution
521 }
522 }
523 if (type->vehicleClass == SVC_PEDESTRIAN) {
524 WRITE_WARNING("Vehicle type '" + type->id + "' with vClass=pedestrian should only be used for persons and not for vehicle '" + myVehicleParameter->id + "'.");
525 }
526 // get the route
528 if (route == nullptr) {
529 myErrorOutput->inform("The route of the vehicle '" + myVehicleParameter->id + "' is not known.");
530 return;
531 }
532 if (MsgHandler::getErrorInstance()->wasInformed()) {
533 return;
534 }
535 if (route->getID()[0] != '!') {
536 route = route->copy("!" + myVehicleParameter->id, myVehicleParameter->depart);
537 }
538 // build the vehicle
539 ROVehicle* veh = new ROVehicle(*myVehicleParameter, route, type, &myNet, myErrorOutput);
542 }
543 delete myVehicleParameter;
544 myVehicleParameter = nullptr;
545}
546
547
548void
551 if (myCurrentVTypeDistribution != nullptr) {
553 }
554 }
555 if (OptionsCont::getOptions().isSet("restriction-params")) {
556 const std::vector<std::string> paramKeys = OptionsCont::getOptions().getStringVector("restriction-params");
558 }
559 myCurrentVType = nullptr;
560}
561
562
563void
566 if (type == nullptr) {
567 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for person '" + myVehicleParameter->id + "' is not known.");
569 }
570 if (myActivePlan == nullptr || myActivePlan->empty()) {
571 WRITE_WARNING("Discarding person '" + myVehicleParameter->id + "' because it's plan is empty");
572 } else {
573 ROPerson* person = new ROPerson(*myVehicleParameter, type);
574 for (ROPerson::PlanItem* item : *myActivePlan) {
575 person->getPlan().push_back(item);
576 }
577 if (myNet.addPerson(person)) {
580 }
581 }
582 delete myVehicleParameter;
583 myVehicleParameter = nullptr;
584 delete myActivePlan;
585 myActivePlan = nullptr;
586}
587
588
589void
592 if (type == nullptr) {
593 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for personFlow '" + myVehicleParameter->id + "' is not known.");
595 }
596 if (myActivePlan == nullptr || myActivePlan->empty()) {
597 WRITE_WARNING("Discarding personFlow '" + myVehicleParameter->id + "' because it's plan is empty");
598 } else {
600 // instantiate all persons of this flow
601 int i = 0;
602 std::string baseID = myVehicleParameter->id;
605 throw ProcessError("probabilistic personFlow '" + myVehicleParameter->id + "' must specify end time");
606 } else {
607 for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
609 addFlowPerson(type, t, baseID, i++);
610 }
611 }
612 }
613 } else {
615 // uniform sampling of departures from range is equivalent to poisson flow (encoded by negative offset)
616 if (OptionsCont::getOptions().getBool("randomize-flows") && myVehicleParameter->repetitionOffset >= 0) {
617 std::vector<SUMOTime> departures;
619 for (int j = 0; j < myVehicleParameter->repetitionNumber; ++j) {
620 departures.push_back(depart + RandHelper::rand(range));
621 }
622 std::sort(departures.begin(), departures.end());
623 std::reverse(departures.begin(), departures.end());
624 for (; i < myVehicleParameter->repetitionNumber; i++) {
625 addFlowPerson(type, departures[i], baseID, i);
627 }
628 } else {
631 // poisson: randomize first depart
633 }
635 addFlowPerson(type, depart + myVehicleParameter->repetitionTotalOffset, baseID, i);
638 }
639 }
640 }
641 }
642 }
643 delete myVehicleParameter;
644 myVehicleParameter = nullptr;
645 delete myActivePlan;
646 myActivePlan = nullptr;
647}
648
649
650void
651RORouteHandler::addFlowPerson(SUMOVTypeParameter* type, SUMOTime depart, const std::string& baseID, int i) {
653 pars.id = baseID + "." + toString(i);
654 pars.depart = depart;
655 ROPerson* person = new ROPerson(pars, type);
656 for (ROPerson::PlanItem* item : *myActivePlan) {
657 person->getPlan().push_back(item->clone());
658 }
659 if (myNet.addPerson(person)) {
660 if (i == 0) {
662 }
663 }
664}
665
666void
673 } else {
674 WRITE_WARNING("Discarding container '" + myVehicleParameter->id + "' because it's plan is empty");
675 }
676 delete myVehicleParameter;
677 myVehicleParameter = nullptr;
679 myActiveContainerPlan = nullptr;
681}
682
689 } else {
690 WRITE_WARNING("Discarding containerFlow '" + myVehicleParameter->id + "' because it's plan is empty");
691 }
692 delete myVehicleParameter;
693 myVehicleParameter = nullptr;
695 myActiveContainerPlan = nullptr;
697}
698
699
700void
703 // @todo: consider myScale?
705 delete myVehicleParameter;
706 myVehicleParameter = nullptr;
707 return;
708 }
709 // let's check whether vehicles had to depart before the simulation starts
711 const SUMOTime offsetToBegin = myBegin - myVehicleParameter->depart;
712 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
715 delete myVehicleParameter;
716 myVehicleParameter = nullptr;
717 return;
718 }
719 }
721 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
722 }
723 if (myVehicleParameter->routeid[0] == '!' && myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
724 closeRoute(true);
725 }
726 if (myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
727 myErrorOutput->inform("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
728 delete myVehicleParameter;
729 myVehicleParameter = nullptr;
730 return;
731 }
732 myActiveRouteID = "";
733 if (!MsgHandler::getErrorInstance()->wasInformed()) {
736 } else {
737 myErrorOutput->inform("Another flow with the id '" + myVehicleParameter->id + "' exists.");
738 }
739 } else {
740 delete myVehicleParameter;
741 }
742 myVehicleParameter = nullptr;
744}
745
746
747void
749 closeRoute(true);
750 closeVehicle();
751}
752
754RORouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, std::string& id, const SUMOVehicleParameter::Stop* stopParam) {
755 // dummy stop parameter to hold the attributes
757 if (stopParam != nullptr) {
758 stop = *stopParam;
759 } else {
760 bool ok = true;
761 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
762 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
763 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
764 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
765 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
766 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
767 }
768 const SUMOVehicleParameter::Stop* toStop = nullptr;
769 if (stop.busstop != "") {
771 id = stop.busstop;
772 if (toStop == nullptr) {
773 WRITE_ERROR("The busStop '" + stop.busstop + "' is not known" + errorSuffix);
774 }
775 } else if (stop.containerstop != "") {
777 id = stop.containerstop;
778 if (toStop == nullptr) {
779 WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known" + errorSuffix);
780 }
781 } else if (stop.parkingarea != "") {
783 id = stop.parkingarea;
784 if (toStop == nullptr) {
785 WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known" + errorSuffix);
786 }
787 } else if (stop.chargingStation != "") {
788 // ok, we have a charging station
790 id = stop.chargingStation;
791 if (toStop == nullptr) {
792 WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known" + errorSuffix);
793 }
794 } else if (stop.overheadWireSegment != "") {
795 // ok, we have an overhead wire segment
797 id = stop.overheadWireSegment;
798 if (toStop == nullptr) {
799 WRITE_ERROR("The overhead wire segment '" + stop.overheadWireSegment + "' is not known" + errorSuffix);
800 }
801 }
802 return toStop;
803}
804
805void
807 if (myActiveContainerPlan != nullptr) {
809 (*myActiveContainerPlan) << attrs;
812 return;
813 }
814 std::string errorSuffix;
815 if (myActivePlan != nullptr) {
816 errorSuffix = " in person '" + myVehicleParameter->id + "'.";
817 } else if (myActiveContainerPlan != nullptr) {
818 errorSuffix = " in container '" + myVehicleParameter->id + "'.";
819 } else if (myVehicleParameter != nullptr) {
820 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
821 } else {
822 errorSuffix = " in route '" + myActiveRouteID + "'.";
823 }
825 bool ok = parseStop(stop, attrs, errorSuffix, myErrorOutput);
826 if (!ok) {
827 return;
828 }
829 // try to parse the assigned bus stop
830 const ROEdge* edge = nullptr;
831 std::string stoppingPlaceID;
832 const SUMOVehicleParameter::Stop* stoppingPlace = retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID, &stop);
833 bool hasPos = false;
834 if (stoppingPlace != nullptr) {
835 stop.lane = stoppingPlace->lane;
836 stop.endPos = stoppingPlace->endPos;
837 stop.startPos = stoppingPlace->startPos;
839 } else {
840 // no, the lane and the position should be given
841 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
842 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
843 if (ok && stop.edge != "") {
844 edge = myNet.getEdge(stop.edge);
845 if (edge == nullptr) {
846 myErrorOutput->inform("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
847 return;
848 }
849 } else if (ok && stop.lane != "") {
851 if (edge == nullptr) {
852 myErrorOutput->inform("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
853 return;
854 }
855 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
856 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
857 Position pos;
858 bool geo = false;
859 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
860 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
861 } else {
862 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
863 geo = true;
864 }
865 PositionVector positions;
866 positions.push_back(pos);
867 ConstROEdgeVector geoEdges;
868 parseGeoEdges(positions, geo, geoEdges, myVehicleParameter->id, true, ok);
869 if (ok) {
870 edge = geoEdges.front();
871 hasPos = true;
872 if (geo) {
874 }
876 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
877 } else {
878 return;
879 }
880 } else if (!ok || (stop.lane == "" && stop.edge == "")) {
881 myErrorOutput->inform("A stop must be placed on a bus stop, a container stop, a parking area, an edge or a lane" + errorSuffix);
882 return;
883 }
884 if (!hasPos) {
885 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
886 }
887 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, stop.endPos - 2 * POSITION_EPS);
888 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS));
889 const double endPosOffset = edge->isInternal() ? edge->getNormalBefore()->getLength() : 0;
890 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength() + endPosOffset, POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
891 myErrorOutput->inform("Invalid start or end position for stop" + errorSuffix);
892 return;
893 }
894 }
895 stop.edge = edge->getID();
896 if (myActivePlan != nullptr) {
897 ROPerson::addStop(*myActivePlan, stop, edge);
898 } else if (myVehicleParameter != nullptr) {
899 myVehicleParameter->stops.push_back(stop);
900 } else {
901 myActiveRouteStops.push_back(stop);
902 }
903 if (myInsertStopEdgesAt >= 0) {
904 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
906 }
907}
908
909
910void
912}
913
914
915void
917}
918
919
920void
922 bool ok = true;
923 std::vector<ROPerson::PlanItem*>& plan = *myActivePlan;
924 const std::string pid = myVehicleParameter->id;
925
926 ROEdge* from = nullptr;
927 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
928 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, pid.c_str(), ok);
929 from = myNet.getEdge(fromID);
930 if (from == nullptr) {
931 throw ProcessError("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known.");
932 }
933 } else if (plan.empty()) {
934 throw ProcessError("The start edge for person '" + pid + "' is not known.");
935 }
936 ROEdge* to = nullptr;
937 std::string stoppingPlaceID;
938 const SUMOVehicleParameter::Stop* stop = retrieveStoppingPlace(attrs, " for ride of person '" + myVehicleParameter->id + "'", stoppingPlaceID);
939 if (stop != nullptr) {
941 } else {
942 const std::string toID = attrs.getOpt<std::string>(SUMO_ATTR_TO, pid.c_str(), ok, "");
943 if (toID != "") {
944 to = myNet.getEdge(toID);
945 if (to == nullptr) {
946 throw ProcessError("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known.");
947 }
948 } else {
949 throw ProcessError("The to edge is missing within a ride of '" + myVehicleParameter->id + "'.");
950 }
951 }
952 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
953 stop == nullptr ? std::numeric_limits<double>::infinity() : stop->endPos);
954 const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
955 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, pid.c_str(), ok, "");
956
958 StringTokenizer st(desc);
959 if (st.size() != 1) {
960 throw ProcessError("Triggered departure for person '" + pid + "' requires a unique lines value.");
961 }
962 const std::string vehID = st.front();
963 if (!myNet.knowsVehicle(vehID)) {
964 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
965 }
966 SUMOTime vehDepart = myNet.getDeparture(vehID);
967 if (vehDepart == -1) {
968 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
969 }
970 myVehicleParameter->depart = vehDepart + 1; // write person after vehicle
971 }
972 ROPerson::addRide(plan, from, to, desc, arrivalPos, stoppingPlaceID, group);
973}
974
975
976void
979 bool ok = true;
980 const std::string pid = myVehicleParameter->id;
981 const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
982 StringTokenizer st(desc);
983 if (st.size() != 1) {
984 throw ProcessError("Triggered departure for container '" + pid + "' requires a unique lines value.");
985 }
986 const std::string vehID = st.front();
987 if (!myNet.knowsVehicle(vehID)) {
988 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
989 }
990 SUMOTime vehDepart = myNet.getDeparture(vehID);
991 if (vehDepart == -1) {
992 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
993 }
994 myVehicleParameter->depart = vehDepart + 1; // write container after vehicle
995 }
996}
997
998
999void
1001}
1002
1003
1004void
1005RORouteHandler::parseEdges(const std::string& desc, ConstROEdgeVector& into,
1006 const std::string& rid, bool& ok) {
1007 for (StringTokenizer st(desc); st.hasNext();) {
1008 const std::string id = st.next();
1009 const ROEdge* edge = myNet.getEdge(id);
1010 if (edge == nullptr) {
1011 myErrorOutput->inform("The edge '" + id + "' within the route " + rid + " is not known.");
1012 ok = false;
1013 } else {
1014 into.push_back(edge);
1015 }
1016 }
1017}
1018
1019void
1021 ConstROEdgeVector& into, const std::string& rid, bool isFrom, bool& ok) {
1022 if (geo && !GeoConvHelper::getFinal().usingGeoProjection()) {
1023 WRITE_ERROR(TL("Cannot convert geo-positions because the network has no geo-reference"));
1024 return;
1025 }
1028 if (type != nullptr) {
1029 vClass = type->vehicleClass;
1030 }
1031 for (Position pos : positions) {
1032 Position orig = pos;
1033 if (geo) {
1035 }
1036 double dist = MIN2(10.0, myMapMatchingDistance);
1037 const ROEdge* best = getClosestEdge(pos, dist, vClass);
1038 while (best == nullptr && dist < myMapMatchingDistance) {
1039 dist = MIN2(dist * 2, myMapMatchingDistance);
1040 best = getClosestEdge(pos, dist, vClass);
1041 }
1042 if (best == nullptr) {
1043 myErrorOutput->inform("No edge found near position " + toString(orig, geo ? gPrecisionGeo : gPrecision) + " within the route " + rid + ".");
1044 ok = false;
1045 } else {
1046 if (myMapMatchJunctions) {
1047 best = getJunctionTaz(pos, best, vClass, isFrom);
1048 if (best != nullptr) {
1049 into.push_back(best);
1050 }
1051 } else {
1052 into.push_back(best);
1053 }
1054 }
1055 }
1056}
1057
1058
1059const ROEdge*
1060RORouteHandler::getClosestEdge(const Position& pos, double distance, SUMOVehicleClass vClass) {
1061 NamedRTree* t = getLaneTree();
1062 Boundary b;
1063 b.add(pos);
1064 b.grow(distance);
1065 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1066 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1067 std::set<const Named*> lanes;
1068 Named::StoringVisitor sv(lanes);
1069 t->Search(cmin, cmax, sv);
1070 // use closest
1071 double minDist = std::numeric_limits<double>::max();
1072 const ROLane* best = nullptr;
1073 for (const Named* o : lanes) {
1074 const ROLane* cand = static_cast<const ROLane*>(o);
1075 if (!cand->allowsVehicleClass(vClass)) {
1076 continue;
1077 }
1078 double dist = cand->getShape().distance2D(pos);
1079 if (dist < minDist) {
1080 minDist = dist;
1081 best = cand;
1082 }
1083 }
1084 if (best == nullptr) {
1085 return nullptr;
1086 } else {
1087 const ROEdge* bestEdge = &best->getEdge();
1088 while (bestEdge->isInternal()) {
1089 bestEdge = bestEdge->getSuccessors().front();
1090 }
1091 return bestEdge;
1092 }
1093}
1094
1095
1096const ROEdge*
1097RORouteHandler::getJunctionTaz(const Position& pos, const ROEdge* closestEdge, SUMOVehicleClass vClass, bool isFrom) {
1098 if (closestEdge == nullptr) {
1099 return nullptr;
1100 } else {
1101 const RONode* fromJunction = closestEdge->getFromJunction();
1102 const RONode* toJunction = closestEdge->getToJunction();
1103 const bool fromCloser = (fromJunction->getPosition().distanceSquaredTo2D(pos) <
1104 toJunction->getPosition().distanceSquaredTo2D(pos));
1105 const ROEdge* fromSource = myNet.getEdge(fromJunction->getID() + "-source");
1106 const ROEdge* fromSink = myNet.getEdge(fromJunction->getID() + "-sink");
1107 const ROEdge* toSource = myNet.getEdge(toJunction->getID() + "-source");
1108 const ROEdge* toSink = myNet.getEdge(toJunction->getID() + "-sink");
1109 if (fromSource == nullptr || fromSink == nullptr) {
1110 myErrorOutput->inform("Junction-taz '" + fromJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
1111 return nullptr;
1112 }
1113 if (toSource == nullptr || toSink == nullptr) {
1114 myErrorOutput->inform("Junction-taz '" + toJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
1115 return nullptr;
1116 }
1117 const bool fromPossible = isFrom ? fromSource->getSuccessors(vClass).size() > 0 : fromSink->getPredecessors().size() > 0;
1118 const bool toPossible = isFrom ? toSource->getSuccessors(vClass).size() > 0 : toSink->getPredecessors().size() > 0;
1119 //std::cout << "getJunctionTaz pos=" << pos << " isFrom=" << isFrom << " closest=" << closestEdge->getID() << " fromPossible=" << fromPossible << " toPossible=" << toPossible << "\n";
1120 if (fromCloser && fromPossible) {
1121 // return closest if possible
1122 return isFrom ? fromSource : fromSink;
1123 } else if (!fromCloser && toPossible) {
1124 // return closest if possible
1125 return isFrom ? toSource : toSink;
1126 } else {
1127 // return possible
1128 if (fromPossible) {
1129 return isFrom ? fromSource : fromSink;
1130 } else {
1131 return isFrom ? toSource : toSink;
1132 }
1133 }
1134 }
1135}
1136
1137
1138void
1139RORouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1140 const ROEdge* /*fromEdge*/, const ROEdge*& toEdge,
1141 double& departPos, double& arrivalPos, std::string& busStopID,
1142 const ROPerson::PlanItem* const lastStage, bool& ok) {
1143 const std::string description = "walk or personTrip of '" + personID + "'.";
1144 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1145 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."));
1146 }
1147 departPos = myVehicleParameter->departPos;
1148 if (lastStage != nullptr) {
1149 departPos = lastStage->getDestinationPos();
1150 }
1151
1152 busStopID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1153
1154 const SUMOVehicleParameter::Stop* bs = retrieveStoppingPlace(attrs, description, busStopID);
1155 if (bs != nullptr) {
1157 arrivalPos = (bs->startPos + bs->endPos) / 2;
1158 }
1159 if (toEdge != nullptr) {
1162 myHardFail, description, toEdge->getLength(),
1163 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok));
1164 }
1165 } else {
1166 throw ProcessError("No destination edge for " + description + ".");
1167 }
1168}
1169
1170
1171void
1173 bool ok = true;
1174 const char* const id = myVehicleParameter->id.c_str();
1175 assert(!attrs.hasAttribute(SUMO_ATTR_EDGES));
1176 const ROEdge* from = nullptr;
1177 const ROEdge* to = nullptr;
1178 parseFromViaTo(SUMO_TAG_PERSON, attrs, ok);
1182 if (ok) {
1183 from = myActiveRoute.front();
1184 }
1185 } else if (myActivePlan->empty()) {
1186 throw ProcessError("Start edge not defined for person '" + myVehicleParameter->id + "'.");
1187 } else {
1188 from = myActivePlan->back()->getDestination();
1189 }
1192 to = myActiveRoute.back();
1193 } // else, to may also be derived from stopping place
1194
1195 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1196 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1197 throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1198 }
1199
1200 double departPos = 0;
1201 double arrivalPos = std::numeric_limits<double>::infinity();
1202 std::string busStopID;
1203 const ROPerson::PlanItem* const lastStage = myActivePlan->empty() ? nullptr : myActivePlan->back();
1204 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, busStopID, lastStage, ok);
1205
1206 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1207 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, "");
1208 SVCPermissions modeSet = 0;
1209 for (StringTokenizer st(modes); st.hasNext();) {
1210 const std::string mode = st.next();
1211 if (mode == "car") {
1212 modeSet |= SVC_PASSENGER;
1213 } else if (mode == "taxi") {
1214 modeSet |= SVC_TAXI;
1215 } else if (mode == "bicycle") {
1216 modeSet |= SVC_BICYCLE;
1217 } else if (mode == "public") {
1218 modeSet |= SVC_BUS;
1219 } else {
1220 throw InvalidArgument("Unknown person mode '" + mode + "'.");
1221 }
1222 }
1223 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1224 double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1225 if (ok) {
1226 const std::string originStopID = myActivePlan->empty() ? "" : myActivePlan->back()->getStopDest();
1227 ROPerson::addTrip(*myActivePlan, myVehicleParameter->id, from, to, modeSet, types,
1228 departPos, originStopID, arrivalPos, busStopID, walkFactor, group);
1229 }
1230}
1231
1232
1233void
1235 // parse walks from->to as person trips
1237 // XXX allow --repair?
1238 bool ok = true;
1239 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1240 const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1241 RORouteDef* routeDef = myNet.getRouteDef(routeID);
1242 const RORoute* route = routeDef != nullptr ? routeDef->getFirstRoute() : nullptr;
1243 if (route == nullptr) {
1244 throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1245 }
1246 myActiveRoute = route->getEdgeVector();
1247 } else {
1248 myActiveRoute.clear();
1249 parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myVehicleParameter->id.c_str(), ok), myActiveRoute, " walk for person '" + myVehicleParameter->id + "'", ok);
1250 }
1251 const char* const objId = myVehicleParameter->id.c_str();
1252 const double duration = attrs.getOpt<double>(SUMO_ATTR_DURATION, objId, ok, -1);
1253 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1254 throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1255 }
1256 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, objId, ok, -1.);
1257 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1258 throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1259 }
1260 double departPos = 0.;
1261 double arrivalPos = std::numeric_limits<double>::infinity();
1262 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1263 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."));
1264 }
1266 arrivalPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, objId, myActiveRoute.back()->getLength(), attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, objId, ok));
1267 }
1268 std::string stoppingPlaceID;
1269 const std::string errorSuffix = " for walk of person '" + myVehicleParameter->id + "'";
1270 retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID);
1271 if (ok) {
1272 ROPerson::addWalk(*myActivePlan, myActiveRoute, duration, speed, departPos, arrivalPos, stoppingPlaceID);
1273 }
1274 } else {
1275 addPersonTrip(attrs);
1276 }
1277}
1278
1279
1282 if (myLaneTree == nullptr) {
1283 myLaneTree = new NamedRTree();
1284 for (const auto& edgeItem : myNet.getEdgeMap()) {
1285 for (ROLane* lane : edgeItem.second->getLanes()) {
1286 Boundary b = lane->getShape().getBoxBoundary();
1287 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1288 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1289 myLaneTree->Insert(cmin, cmax, lane);
1290 }
1291 }
1292 }
1293 return myLaneTree;
1294}
1295
1296bool
1298 if (!myUnsortedInput) {
1300 }
1301 return true;
1302}
1303
1304/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:266
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:274
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
std::vector< const ROEdge * > ConstROEdgeVector
Definition: ROEdge.h:54
#define JUNCTION_TAZ_MISSING_HELP
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
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 double DEFAULT_VEH_PROB
const std::string DEFAULT_PEDTYPE_ID
const std::string DEFAULT_VTYPE_ID
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const int VEHPARS_TO_TAZ_SET
const 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 definitio nusing a from-to edges instead of a route (used by router)
@ 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_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_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_FROMJUNCTION
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_X
@ SUMO_ATTR_ARRIVALPOS
@ 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
@ SUMO_ATTR_TOJUNCTION
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:25
int gPrecisionGeo
Definition: StdDefs.cpp:26
T MIN2(T a, T b)
Definition: StdDefs.h:71
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
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:118
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:300
PositionVector getShape(const bool closeShape) const
get position vector (shape) based on this boundary
Definition: Boundary.cpp:404
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.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:79
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:116
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition: Named.h:90
Base class for objects which have an id.
Definition: Named.h:54
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
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
Definition: NamedRTree.h:112
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 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.
Definition: OptionsCont.cpp:59
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.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:257
A list of positions.
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
A basic edge for routing applications.
Definition: ROEdge.h:70
const ROEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: ROEdge.cpp:269
const RONode * getToJunction() const
Definition: ROEdge.h:507
const RONode * getFromJunction() const
Definition: ROEdge.h:503
bool isInternal() const
return whether this edge is an internal edge
Definition: ROEdge.h:145
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition: ROEdge.h:361
const ROEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: ROEdge.cpp:366
const std::vector< ROLane * > & getLanes() const
Returns this edge's lanes.
Definition: ROEdge.h:515
double getLength() const
Returns the length of the edge.
Definition: ROEdge.h:210
A single lane the router may use.
Definition: ROLane.h:48
const PositionVector & getShape() const
Definition: ROLane.h:115
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: ROLane.h:111
ROEdge & getEdge() const
Returns the lane's edge.
Definition: ROLane.h:93
The router's network representation.
Definition: RONet.h:62
SUMOVTypeParameter * getVehicleTypeSecure(const std::string &id)
Retrieves the named vehicle type.
Definition: RONet.cpp:353
bool addRouteDef(RORouteDef *def)
Definition: RONet.cpp:275
bool knowsVehicle(const std::string &id) const
returns whether a vehicle with the given id was already loaded
Definition: RONet.cpp:454
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
const SUMOVehicleParameter::Stop * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Retrieves a stopping place from the network.
Definition: RONet.h:216
void addContainer(const SUMOTime depart, const std::string desc)
Definition: RONet.cpp:500
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition: RONet.h:157
bool addPerson(ROPerson *person)
Definition: RONet.cpp:488
RORouteDef * getRouteDef(const std::string &name) const
Returns the named route definition.
Definition: RONet.h:305
virtual bool addVehicleType(SUMOVTypeParameter *type)
Adds a read vehicle type definition to the network.
Definition: RONet.cpp:408
bool addVTypeDistribution(const std::string &id, RandomDistributor< SUMOVTypeParameter * > *vehTypeDistribution)
Adds a vehicle type distribution.
Definition: RONet.cpp:421
const NamedObjectCont< ROEdge * > & getEdgeMap() const
Definition: RONet.h:409
bool addFlow(SUMOVehicleParameter *flow, const bool randomize)
Definition: RONet.cpp:470
Base class for nodes used by the router.
Definition: RONode.h:43
const Position & getPosition() const
Returns the position of the node.
Definition: RONode.h:64
Every person has a plan comprising of multiple planItems.
Definition: ROPerson.h:82
virtual double getDestinationPos() const =0
A person as used by router.
Definition: ROPerson.h:49
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:419
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.
Definition: RORouteDef.cpp:69
double getOverallProb() const
Returns the sum of the probablities of the contained routes.
Definition: RORouteDef.cpp:413
void addAlternativeDef(const RORouteDef *alternative)
Adds an alternative loaded from the file.
Definition: RORouteDef.cpp:75
RORouteDef * copy(const std::string &id, const SUMOTime stopOffset) const
Returns a deep copy of the route definition.
Definition: RORouteDef.cpp:400
void closeTrip()
Ends the processing of a trip.
void closeRouteDistribution()
closes (ends) the building of a distribution
const SUMOVehicleParameter::Stop * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, std::string &id, const SUMOVehicleParameter::Stop *stopParam=nullptr)
retrieve stopping place element
NamedRTree * myLaneTree
RTree for finding lanes.
void addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
const double myMapMatchingDistance
maximum distance when map-matching
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
virtual ~RORouteHandler()
standard destructor
RORouteHandler(RONet &net, const std::string &file, const bool tryRepair, const bool emptyDestinationsAllowed, const bool ignoreErrors, const bool checkSchema)
standard constructor
void addTranship(const SUMOSAXAttributes &attrs)
Processing of a tranship.
void parseEdges(const std::string &desc, ConstROEdgeVector &into, const std::string &rid, bool &ok)
Parse edges from strings.
void closeVType()
Ends the processing of a vehicle type.
void addRide(const SUMOSAXAttributes &attrs)
Processing of a ride.
void addWalk(const SUMOSAXAttributes &attrs)
add a fully specified walk
RONet & myNet
The current route.
NamedRTree * getLaneTree()
initialize lane-RTree
bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
ConstROEdgeVector myActiveRoute
The current route.
const ROEdge * getJunctionTaz(const Position &pos, const ROEdge *closestEdge, SUMOVehicleClass vClass, bool isFrom)
find closest junction taz given the closest edge
std::vector< ROPerson::PlanItem * > * myActivePlan
The plan of the current person.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
const bool myTryRepair
Information whether routes shall be repaired.
OutputDevice_String * myActiveContainerPlan
The plan of the current container.
SUMOTime myActiveRoutePeriod
const SUMOTime myBegin
The begin time.
RandomDistributor< SUMOVTypeParameter * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
void closePersonFlow()
Ends the processing of a personFlow.
void closePerson()
Ends the processing of a person.
void openRouteDistribution(const SUMOSAXAttributes &attrs)
opens a route distribution for reading
int myActiveContainerPlanSize
The number of stages in myActiveContainerPlan.
const bool myKeepVTypeDist
whether to keep the the vtype distribution in output
void openRouteFlow(const SUMOSAXAttributes &attrs)
opens a route flow for reading
const bool myUnsortedInput
whether input is read all at once (no sorting check is necessary)
void openTrip(const SUMOSAXAttributes &attrs)
opens a trip for reading
void closeVehicle()
Ends the processing of a vehicle.
void addContainer(const SUMOSAXAttributes &attrs)
Processing of a container.
const bool myMapMatchJunctions
void addTransport(const SUMOSAXAttributes &attrs)
Processing of a transport.
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.
void closeRoute(const bool mayBeDisconnected=false)
closes (ends) the building of a route.
void closeFlow()
Ends the processing of a flow.
int myActiveRouteRepeat
number of repetitions of the active route
void closeContainer()
Ends the processing of a container.
void closeVehicleTypeDistribution()
closes (ends) the building of a distribution
void addFlowPerson(SUMOVTypeParameter *type, SUMOTime depart, const std::string &baseID, int i)
Processing of a person from a personFlow.
void addPerson(const SUMOSAXAttributes &attrs)
Processing of a person.
void parseGeoEdges(const PositionVector &positions, bool geo, ConstROEdgeVector &into, const std::string &rid, bool isFrom, bool &ok)
Parse edges from coordinates.
RORouteDef * myCurrentAlternatives
The currently parsed route alternatives.
void openFlow(const SUMOSAXAttributes &attrs)
opens a flow for reading
void closeContainerFlow()
Ends the processing of a containerFlow.
void addPersonTrip(const SUMOSAXAttributes &attrs)
add a routing request for a walking or intermodal person
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs)
opens a type distribution for reading
const ROEdge * getClosestEdge(const Position &pos, double distance, SUMOVehicleClass vClass)
find closest edge within distance for the given position or nullptr
void openRoute(const SUMOSAXAttributes &attrs)
opens a route for reading
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)
Definition: RandHelper.cpp:94
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.
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.
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 (used only in NETEDIT)
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.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
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.
bool wasSet(int what) const
Returns whether the given parameter was set.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
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