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-2023 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
84
85
86void
88 if (myActivePlan != nullptr) {
89 for (ROPerson::PlanItem* const it : *myActivePlan) {
90 delete it;
91 }
92 delete myActivePlan;
93 myActivePlan = nullptr;
94 }
96 myActiveContainerPlan = nullptr;
97 delete myVehicleParameter;
98 myVehicleParameter = nullptr;
99}
100
101
102void
104 const std::string element = toString(tag);
105 myActiveRoute.clear();
106 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
108 WRITE_WARNINGF(TL("Taz usage was requested but no taz present in % '%'!"), element, myVehicleParameter->id);
109 useTaz = false;
110 }
111 // from-attributes
112 const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
113 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
115 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROMJUNCTION);
116 const std::string tazType = useJunction ? "junction" : "taz";
117 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROMJUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok, true);
118 const ROEdge* fromTaz = myNet.getEdge(tazID + "-source");
119 if (fromTaz == nullptr) {
120 myErrorOutput->inform("Source " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
121 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
122 ok = false;
123 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
124 myErrorOutput->inform("Source " + tazType + " '" + tazID + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
125 ok = false;
126 } else {
127 myActiveRoute.push_back(fromTaz);
128 }
129 } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
130 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, myActiveRoute, rid, true, ok);
131 } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
132 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, myActiveRoute, rid, true, ok);
133 } else {
134 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok), myActiveRoute, rid, ok);
135 }
138 }
139
140 // via-attributes
141 ConstROEdgeVector viaEdges;
142 if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
143 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, viaEdges, rid, false, ok);
144 } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
145 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, viaEdges, rid, false, ok);
146 } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
147 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
148 const ROEdge* viaSink = myNet.getEdge(junctionID + "-sink");
149 if (viaSink == nullptr) {
150 myErrorOutput->inform("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
151 ok = false;
152 } else {
153 viaEdges.push_back(viaSink);
154 }
155 }
156 } else {
157 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true), viaEdges, rid, ok);
158 }
159 for (const ROEdge* e : viaEdges) {
160 myActiveRoute.push_back(e);
161 myVehicleParameter->via.push_back(e->getID());
162 }
163
164 // to-attributes
165 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
167 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TOJUNCTION);
168 const std::string tazType = useJunction ? "junction" : "taz";
169 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TOJUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
170 const ROEdge* toTaz = myNet.getEdge(tazID + "-sink");
171 if (toTaz == nullptr) {
172 myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
173 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
174 ok = false;
175 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
176 myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
177 ok = false;
178 } else {
179 myActiveRoute.push_back(toTaz);
180 }
181 } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
182 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, myActiveRoute, rid, false, ok);
183 } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
184 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, myActiveRoute, rid, false, ok);
185 } else {
186 parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true), myActiveRoute, rid, ok);
187 }
189 if (myVehicleParameter->routeid == "") {
191 }
192}
193
194
195void
197 const SUMOSAXAttributes& attrs) {
198 try {
200 throw ProcessError(TLF("Triggered departure for person '%' requires starting with a ride.", myVehicleParameter->id));
202 throw ProcessError(TLF("Triggered departure for container '%' requires starting with a transport.", myVehicleParameter->id));
203 }
204 SUMORouteHandler::myStartElement(element, attrs);
205 bool ok = true;
206 switch (element) {
207 case SUMO_TAG_PERSON:
208 case SUMO_TAG_PERSONFLOW: {
209 myActivePlan = new std::vector<ROPerson::PlanItem*>();
210 break;
211 }
212 case SUMO_TAG_RIDE:
213 break; // handled in addRide, called from SUMORouteHandler::myStartElement
219 (*myActiveContainerPlan) << attrs;
220 break;
223 if (myActiveContainerPlan == nullptr) {
224 throw ProcessError(TLF("Found % outside container element", toString((SumoXMLTag)element)));
225 }
226 // copy container elements
228 (*myActiveContainerPlan) << attrs;
231 break;
232 case SUMO_TAG_FLOW:
234 parseFromViaTo((SumoXMLTag)element, attrs, ok);
235 break;
236 case SUMO_TAG_TRIP:
238 parseFromViaTo((SumoXMLTag)element, attrs, ok);
239 break;
240 default:
241 break;
242 }
243 } catch (ProcessError&) {
245 throw;
246 }
247}
248
249
250void
252 bool ok = true;
253 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
254 if (ok) {
256 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
257 std::vector<double> probs;
258 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
259 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
260 while (st.hasNext()) {
261 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
262 }
263 }
264 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
265 StringTokenizer st(vTypes);
266 int probIndex = 0;
267 while (st.hasNext()) {
268 const std::string typeID = st.next();
269 SUMOVTypeParameter* const type = myNet.getVehicleTypeSecure(typeID);
270 if (type == nullptr) {
271 myErrorOutput->inform("Unknown vehicle type '" + typeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
272 } else {
273 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->defaultProbability);
274 myCurrentVTypeDistribution->add(type, prob);
275 }
276 probIndex++;
277 }
278 if (probs.size() > 0 && probIndex != (int)probs.size()) {
279 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
280 " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
281 }
282 }
283 }
284}
285
286
287void
289 if (myCurrentVTypeDistribution != nullptr) {
292 myErrorOutput->inform("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
295 myErrorOutput->inform("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
296 }
298 }
299}
300
301
302void
306 // check whether the id is really necessary
307 std::string rid;
308 if (myCurrentAlternatives != nullptr) {
310 rid = "distribution '" + myCurrentAlternatives->getID() + "'";
311 } else if (myVehicleParameter != nullptr) {
312 // ok, a vehicle is wrapping the route,
313 // we may use this vehicle's id as default
314 myVehicleParameter->routeid = myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
315 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
316 WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
317 }
318 } else {
319 bool ok = true;
320 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
321 if (!ok) {
322 return;
323 }
324 rid = "'" + myActiveRouteID + "'";
325 }
326 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
327 rid = "for vehicle '" + myVehicleParameter->id + "'";
328 }
329 bool ok = true;
330 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
331 parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid, ok);
332 }
333 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
334 if (myActiveRouteRefID != "" && myNet.getRouteDef(myActiveRouteRefID) == nullptr) {
335 myErrorOutput->inform("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
336 }
337 if (myCurrentAlternatives != nullptr && !attrs.hasAttribute(SUMO_ATTR_PROB)) {
338 WRITE_WARNINGF(TL("No probability for route %, using default."), rid);
339 }
341 if (ok && myActiveRouteProbability < 0) {
342 myErrorOutput->inform("Invalid probability for route '" + myActiveRouteID + "'.");
343 }
345 ok = true;
346 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
348 if (myActiveRouteRepeat > 0) {
350 if (myVehicleParameter != nullptr) {
352 if (type != nullptr) {
353 vClass = type->vehicleClass;
354 }
355 }
356 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
357 myErrorOutput->inform("Disconnected route " + rid + " when repeating.");
358 }
359 }
360 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
361 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
362 myErrorOutput->inform("Invalid cost for route '" + myActiveRouteID + "'.");
363 }
364}
365
366
367void
369 // currently unused
370}
371
372
373void
375 // currently unused
376}
377
378
379void
381 // currently unused
382}
383
384
385void
386RORouteHandler::closeRoute(const bool mayBeDisconnected) {
387 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
388 if (mustReroute) {
389 // implicit route from stops
391 ROEdge* edge = myNet.getEdge(stop.edge);
392 myActiveRoute.push_back(edge);
393 }
394 }
395 if (myActiveRoute.size() == 0) {
396 if (myActiveRouteRefID != "" && myCurrentAlternatives != nullptr) {
398 myActiveRouteID = "";
400 return;
401 }
402 if (myVehicleParameter != nullptr) {
403 myErrorOutput->inform("The route for vehicle '" + myVehicleParameter->id + "' has no edges.");
404 } else {
405 myErrorOutput->inform("Route '" + myActiveRouteID + "' has no edges.");
406 }
407 myActiveRouteID = "";
408 myActiveRouteStops.clear();
409 return;
410 }
411 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
412 myErrorOutput->inform("The routing information for vehicle '" + myVehicleParameter->id + "' is insufficient.");
413 myActiveRouteID = "";
414 myActiveRouteStops.clear();
415 return;
416 }
417 if (!mayBeDisconnected && OptionsCont::getOptions().exists("no-internal-links") && !OptionsCont::getOptions().getBool("no-internal-links")) {
418 // fix internal edges which did not get parsed
419 const ROEdge* last = nullptr;
420 ConstROEdgeVector fullRoute;
421 for (const ROEdge* roe : myActiveRoute) {
422 if (last != nullptr) {
423 for (const ROEdge* intern : last->getSuccessors()) {
424 if (intern->isInternal() && intern->getSuccessors().size() == 1 && intern->getSuccessors().front() == roe) {
425 fullRoute.push_back(intern);
426 }
427 }
428 }
429 fullRoute.push_back(roe);
430 last = roe;
431 }
432 myActiveRoute = fullRoute;
433 }
434 if (myActiveRouteRepeat > 0) {
435 // duplicate route
437 auto tmpStops = myActiveRouteStops;
438 for (int i = 0; i < myActiveRouteRepeat; i++) {
439 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
440 for (SUMOVehicleParameter::Stop stop : tmpStops) {
441 if (stop.until > 0) {
442 if (myActiveRoutePeriod <= 0) {
443 const std::string description = myVehicleParameter != nullptr
444 ? "for vehicle '" + myVehicleParameter->id + "'"
445 : "'" + myActiveRouteID + "'";
446 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
447 }
448 stop.until += myActiveRoutePeriod * (i + 1);
449 stop.arrival += myActiveRoutePeriod * (i + 1);
450 }
451 myActiveRouteStops.push_back(stop);
452 }
453 }
454 }
457 myActiveRoute.clear();
458 if (myCurrentAlternatives == nullptr) {
459 if (myNet.getRouteDef(myActiveRouteID) != nullptr) {
460 delete route;
461 if (myVehicleParameter != nullptr) {
462 myErrorOutput->inform("Another route for vehicle '" + myVehicleParameter->id + "' exists.");
463 } else {
464 myErrorOutput->inform("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
465 }
466 myActiveRouteID = "";
467 myActiveRouteStops.clear();
468 return;
469 } else {
470 myCurrentAlternatives = new RORouteDef(myActiveRouteID, 0, mayBeDisconnected || myTryRepair, mayBeDisconnected);
473 myCurrentAlternatives = nullptr;
474 }
475 } else {
477 }
478 myActiveRouteID = "";
479 myActiveRouteStops.clear();
480}
481
482
483void
485 // check whether the id is really necessary
486 bool ok = true;
487 std::string id;
488 if (myVehicleParameter != nullptr) {
489 // ok, a vehicle is wrapping the route,
490 // we may use this vehicle's id as default
491 myVehicleParameter->routeid = id = "!" + myVehicleParameter->id; // !!! document this
492 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
493 WRITE_WARNINGF(TL("Ids of internal route distributions are ignored (vehicle '%')."), myVehicleParameter->id);
494 }
495 } else {
496 id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
497 if (!ok) {
498 return;
499 }
500 }
501 // try to get the index of the last element
502 int index = attrs.getOpt<int>(SUMO_ATTR_LAST, id.c_str(), ok, 0);
503 if (ok && index < 0) {
504 myErrorOutput->inform("Negative index of a route alternative (id='" + id + "').");
505 return;
506 }
507 // build the alternative cont
508 myCurrentAlternatives = new RORouteDef(id, index, myTryRepair, false);
509 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
510 ok = true;
511 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, id.c_str(), ok));
512 while (st.hasNext()) {
513 const std::string routeID = st.next();
514 const RORouteDef* route = myNet.getRouteDef(routeID);
515 if (route == nullptr) {
516 myErrorOutput->inform("Unknown route '" + routeID + "' in distribution '" + id + "'.");
517 } else {
519 }
520 }
521 }
522}
523
524
525void
527 if (myCurrentAlternatives != nullptr) {
529 myErrorOutput->inform("Route distribution '" + myCurrentAlternatives->getID() + "' is empty.");
532 myErrorOutput->inform("Another route (or distribution) with the id '" + myCurrentAlternatives->getID() + "' exists.");
534 }
535 myCurrentAlternatives = nullptr;
536 }
537}
538
539
540void
543 // get the vehicle id
545 return;
546 }
547 // get vehicle type
549 if (type == nullptr) {
550 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
552 } else {
553 if (!myKeepVTypeDist) {
554 // fix the type id in case we used a distribution
556 }
557 }
558 if (type->vehicleClass == SVC_PEDESTRIAN) {
559 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), type->id, myVehicleParameter->id);
560 }
561 // get the route
563 if (route == nullptr) {
564 myErrorOutput->inform("The route of the vehicle '" + myVehicleParameter->id + "' is not known.");
565 return;
566 }
567 if (MsgHandler::getErrorInstance()->wasInformed()) {
568 return;
569 }
570 const bool needCopy = route->getID()[0] != '!';
571 if (needCopy) {
572 route = route->copy("!" + myVehicleParameter->id, myVehicleParameter->depart);
573 }
574 // build the vehicle
575 ROVehicle* veh = new ROVehicle(*myVehicleParameter, route, type, &myNet, myErrorOutput);
578 } else if (needCopy) {
579 delete route;
580 }
581 delete myVehicleParameter;
582 myVehicleParameter = nullptr;
583}
584
585
586void
589 if (myCurrentVTypeDistribution != nullptr) {
591 }
592 }
593 if (OptionsCont::getOptions().isSet("restriction-params")) {
594 const std::vector<std::string> paramKeys = OptionsCont::getOptions().getStringVector("restriction-params");
596 }
597 myCurrentVType = nullptr;
598}
599
600
601void
604 if (type == nullptr) {
605 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for person '" + myVehicleParameter->id + "' is not known.");
607 }
608 if (myActivePlan == nullptr || myActivePlan->empty()) {
609 WRITE_WARNINGF(TL("Discarding person '%' because her plan is empty"), myVehicleParameter->id);
610 } else {
611 ROPerson* person = new ROPerson(*myVehicleParameter, type);
612 for (ROPerson::PlanItem* item : *myActivePlan) {
613 person->getPlan().push_back(item);
614 }
615 if (myNet.addPerson(person)) {
618 }
619 }
620 delete myVehicleParameter;
621 myVehicleParameter = nullptr;
622 delete myActivePlan;
623 myActivePlan = nullptr;
624}
625
626
627void
630 if (type == nullptr) {
631 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for personFlow '" + myVehicleParameter->id + "' is not known.");
633 }
634 if (myActivePlan == nullptr || myActivePlan->empty()) {
635 WRITE_WARNINGF(TL("Discarding personFlow '%' because their plan is empty"), myVehicleParameter->id);
636 } else {
638 // instantiate all persons of this flow
639 int i = 0;
640 std::string baseID = myVehicleParameter->id;
643 throw ProcessError(TLF("probabilistic personFlow '%' must specify end time", myVehicleParameter->id));
644 } else {
647 addFlowPerson(type, t, baseID, i++);
648 }
649 }
650 }
651 } else {
653 // uniform sampling of departures from range is equivalent to poisson flow (encoded by negative offset)
654 if (OptionsCont::getOptions().getBool("randomize-flows") && myVehicleParameter->repetitionOffset >= 0) {
655 std::vector<SUMOTime> departures;
657 for (int j = 0; j < myVehicleParameter->repetitionNumber; ++j) {
658 departures.push_back(depart + RandHelper::rand(range));
659 }
660 std::sort(departures.begin(), departures.end());
661 std::reverse(departures.begin(), departures.end());
662 for (; i < myVehicleParameter->repetitionNumber; i++) {
663 addFlowPerson(type, departures[i], baseID, i);
665 }
666 } else {
669 // poisson: randomize first depart
671 }
673 addFlowPerson(type, depart + myVehicleParameter->repetitionTotalOffset, baseID, i);
676 }
677 }
678 }
679 }
680 }
681 delete myVehicleParameter;
682 myVehicleParameter = nullptr;
683 for (ROPerson::PlanItem* const it : *myActivePlan) {
684 delete it;
685 }
686 delete myActivePlan;
687 myActivePlan = nullptr;
688}
689
690
691void
692RORouteHandler::addFlowPerson(SUMOVTypeParameter* type, SUMOTime depart, const std::string& baseID, int i) {
694 pars.id = baseID + "." + toString(i);
695 pars.depart = depart;
696 ROPerson* person = new ROPerson(pars, type);
697 for (ROPerson::PlanItem* item : *myActivePlan) {
698 person->getPlan().push_back(item->clone());
699 }
700 if (myNet.addPerson(person)) {
701 if (i == 0) {
703 }
704 }
705}
706
707
708void
715 } else {
716 WRITE_WARNINGF(TL("Discarding container '%' because it's plan is empty"), myVehicleParameter->id);
717 }
718 delete myVehicleParameter;
719 myVehicleParameter = nullptr;
721 myActiveContainerPlan = nullptr;
723}
724
725
732 } else {
733 WRITE_WARNINGF(TL("Discarding containerFlow '%' because it's plan is empty"), myVehicleParameter->id);
734 }
735 delete myVehicleParameter;
736 myVehicleParameter = nullptr;
738 myActiveContainerPlan = nullptr;
740}
741
742
743void
746 // @todo: consider myScale?
748 delete myVehicleParameter;
749 myVehicleParameter = nullptr;
750 return;
751 }
752 // let's check whether vehicles had to depart before the simulation starts
754 const SUMOTime offsetToBegin = myBegin - myVehicleParameter->depart;
755 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
758 delete myVehicleParameter;
759 myVehicleParameter = nullptr;
760 return;
761 }
762 }
764 myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
765 }
766 if (myVehicleParameter->routeid[0] == '!' && myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
767 closeRoute(true);
768 }
769 if (myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
770 myErrorOutput->inform("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
771 delete myVehicleParameter;
772 myVehicleParameter = nullptr;
773 return;
774 }
775 myActiveRouteID = "";
776 if (!MsgHandler::getErrorInstance()->wasInformed()) {
779 } else {
780 myErrorOutput->inform("Another flow with the id '" + myVehicleParameter->id + "' exists.");
781 delete myVehicleParameter;
782 }
783 } else {
784 delete myVehicleParameter;
785 }
786 myVehicleParameter = nullptr;
788}
789
790
791void
796
797
799RORouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, std::string& id, const SUMOVehicleParameter::Stop* stopParam) {
800 // dummy stop parameter to hold the attributes
802 if (stopParam != nullptr) {
803 stop = *stopParam;
804 } else {
805 bool ok = true;
806 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
807 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
808 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
809 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
810 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
811 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
812 }
813 const SUMOVehicleParameter::Stop* toStop = nullptr;
814 if (stop.busstop != "") {
816 id = stop.busstop;
817 if (toStop == nullptr) {
818 WRITE_ERROR("The busStop '" + stop.busstop + "' is not known" + errorSuffix);
819 }
820 } else if (stop.containerstop != "") {
822 id = stop.containerstop;
823 if (toStop == nullptr) {
824 WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known" + errorSuffix);
825 }
826 } else if (stop.parkingarea != "") {
828 id = stop.parkingarea;
829 if (toStop == nullptr) {
830 WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known" + errorSuffix);
831 }
832 } else if (stop.chargingStation != "") {
833 // ok, we have a charging station
835 id = stop.chargingStation;
836 if (toStop == nullptr) {
837 WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known" + errorSuffix);
838 }
839 } else if (stop.overheadWireSegment != "") {
840 // ok, we have an overhead wire segment
842 id = stop.overheadWireSegment;
843 if (toStop == nullptr) {
844 WRITE_ERROR("The overhead wire segment '" + stop.overheadWireSegment + "' is not known" + errorSuffix);
845 }
846 }
847 return toStop;
848}
849
852 Parameterised* result = nullptr;
853 if (myActiveContainerPlan != nullptr) {
855 (*myActiveContainerPlan) << attrs;
858 return result;
859 }
860 std::string errorSuffix;
861 if (myActivePlan != nullptr) {
862 errorSuffix = " in person '" + myVehicleParameter->id + "'.";
863 } else if (myActiveContainerPlan != nullptr) {
864 errorSuffix = " in container '" + myVehicleParameter->id + "'.";
865 } else if (myVehicleParameter != nullptr) {
866 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
867 } else {
868 errorSuffix = " in route '" + myActiveRouteID + "'.";
869 }
871 bool ok = parseStop(stop, attrs, errorSuffix, myErrorOutput);
872 if (!ok) {
873 return result;
874 }
875 // try to parse the assigned bus stop
876 const ROEdge* edge = nullptr;
877 std::string stoppingPlaceID;
878 const SUMOVehicleParameter::Stop* stoppingPlace = retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID, &stop);
879 bool hasPos = false;
880 if (stoppingPlace != nullptr) {
881 stop.lane = stoppingPlace->lane;
882 stop.endPos = stoppingPlace->endPos;
883 stop.startPos = stoppingPlace->startPos;
885 } else {
886 // no, the lane and the position should be given
887 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
888 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
889 if (ok && stop.edge != "") {
890 edge = myNet.getEdge(stop.edge);
891 if (edge == nullptr) {
892 myErrorOutput->inform("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
893 return result;
894 }
895 } else if (ok && stop.lane != "") {
897 if (edge == nullptr) {
898 myErrorOutput->inform("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
899 return result;
900 }
901 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
902 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
903 Position pos;
904 bool geo = false;
905 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
906 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
907 } else {
908 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
909 geo = true;
910 }
911 PositionVector positions;
912 positions.push_back(pos);
913 ConstROEdgeVector geoEdges;
914 parseGeoEdges(positions, geo, geoEdges, myVehicleParameter->id, true, ok);
915 if (ok) {
916 edge = geoEdges.front();
917 hasPos = true;
918 if (geo) {
920 }
922 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
923 } else {
924 return result;
925 }
926 } else if (!ok || (stop.lane == "" && stop.edge == "")) {
927 myErrorOutput->inform("A stop must be placed on a bus stop, a container stop, a parking area, an edge or a lane" + errorSuffix);
928 return result;
929 }
930 if (!hasPos) {
931 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
932 }
933 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, stop.endPos - 2 * POSITION_EPS);
934 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS));
935 const double endPosOffset = edge->isInternal() ? edge->getNormalBefore()->getLength() : 0;
936 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength() + endPosOffset, POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
937 myErrorOutput->inform("Invalid start or end position for stop" + errorSuffix);
938 return result;
939 }
940 }
941 stop.edge = edge->getID();
942 if (myActivePlan != nullptr) {
943 ROPerson::addStop(*myActivePlan, stop, edge);
944 result = myActivePlan->back()->getStopParameters();
945 } else if (myVehicleParameter != nullptr) {
946 myVehicleParameter->stops.push_back(stop);
947 result = &myVehicleParameter->stops.back();
948 } else {
949 myActiveRouteStops.push_back(stop);
950 result = &myActiveRouteStops.back();
951 }
952 if (myInsertStopEdgesAt >= 0) {
953 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
955 }
956 return result;
957}
958
959
960void
963
964
965void
968
969
970void
972 bool ok = true;
973 std::vector<ROPerson::PlanItem*>& plan = *myActivePlan;
974 const std::string pid = myVehicleParameter->id;
975
976 ROEdge* from = nullptr;
977 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
978 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, pid.c_str(), ok);
979 from = myNet.getEdge(fromID);
980 if (from == nullptr) {
981 myErrorOutput->inform("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known.");
982 return;
983 }
984 } else if (plan.empty()) {
985 myErrorOutput->inform("The start edge for person '" + pid + "' is not known.");
986 return;
987 }
988 ROEdge* to = nullptr;
989 std::string stoppingPlaceID;
990 const SUMOVehicleParameter::Stop* stop = retrieveStoppingPlace(attrs, " for ride of person '" + myVehicleParameter->id + "'", stoppingPlaceID);
991 if (stop != nullptr) {
993 } else {
994 const std::string toID = attrs.getOpt<std::string>(SUMO_ATTR_TO, pid.c_str(), ok, "");
995 if (toID != "") {
996 to = myNet.getEdge(toID);
997 if (to == nullptr) {
998 myErrorOutput->inform("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known.");
999 return;
1000 }
1001 } else {
1002 myErrorOutput->inform("The to edge is missing within a ride of '" + myVehicleParameter->id + "'.");
1003 return;
1004 }
1005 }
1006 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
1007 stop == nullptr ? std::numeric_limits<double>::infinity() : stop->endPos);
1008 const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
1009 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, pid.c_str(), ok, "");
1010
1012 StringTokenizer st(desc);
1013 if (st.size() != 1) {
1014 myErrorOutput->inform("Triggered departure for person '" + pid + "' requires a unique lines value.");
1015 return;
1016 }
1017 const std::string vehID = st.front();
1018 if (!myNet.knowsVehicle(vehID)) {
1019 myErrorOutput->inform("Unknown vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
1020 return;
1021 }
1022 SUMOTime vehDepart = myNet.getDeparture(vehID);
1023 if (vehDepart == -1) {
1024 myErrorOutput->inform("Cannot use triggered vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
1025 return;
1026 }
1027 myVehicleParameter->depart = vehDepart + 1; // write person after vehicle
1028 }
1029 ROPerson::addRide(plan, from, to, desc, arrivalPos, stoppingPlaceID, group);
1030}
1031
1032
1033void
1036 bool ok = true;
1037 const std::string pid = myVehicleParameter->id;
1038 const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
1039 StringTokenizer st(desc);
1040 if (st.size() != 1) {
1041 throw ProcessError(TLF("Triggered departure for container '%' requires a unique lines value.", pid));
1042 }
1043 const std::string vehID = st.front();
1044 if (!myNet.knowsVehicle(vehID)) {
1045 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
1046 }
1047 SUMOTime vehDepart = myNet.getDeparture(vehID);
1048 if (vehDepart == -1) {
1049 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
1050 }
1051 myVehicleParameter->depart = vehDepart + 1; // write container after vehicle
1052 }
1053}
1054
1055
1056void
1059
1060
1061void
1062RORouteHandler::parseEdges(const std::string& desc, ConstROEdgeVector& into,
1063 const std::string& rid, bool& ok) {
1064 for (StringTokenizer st(desc); st.hasNext();) {
1065 const std::string id = st.next();
1066 const ROEdge* edge = myNet.getEdge(id);
1067 if (edge == nullptr) {
1068 myErrorOutput->inform("The edge '" + id + "' within the route " + rid + " is not known.");
1069 ok = false;
1070 } else {
1071 into.push_back(edge);
1072 }
1073 }
1074}
1075
1076
1077void
1079 ConstROEdgeVector& into, const std::string& rid, bool isFrom, bool& ok) {
1080 if (geo && !GeoConvHelper::getFinal().usingGeoProjection()) {
1081 WRITE_ERROR(TL("Cannot convert geo-positions because the network has no geo-reference"));
1082 return;
1083 }
1086 if (type != nullptr) {
1087 vClass = type->vehicleClass;
1088 }
1089 for (Position pos : positions) {
1090 Position orig = pos;
1091 if (geo) {
1093 }
1094 double dist = MIN2(10.0, myMapMatchingDistance);
1095 const ROEdge* best = getClosestEdge(pos, dist, vClass);
1096 while (best == nullptr && dist < myMapMatchingDistance) {
1097 dist = MIN2(dist * 2, myMapMatchingDistance);
1098 best = getClosestEdge(pos, dist, vClass);
1099 }
1100 if (best == nullptr) {
1101 myErrorOutput->inform("No edge found near position " + toString(orig, geo ? gPrecisionGeo : gPrecision) + " within the route " + rid + ".");
1102 ok = false;
1103 } else {
1104 if (myMapMatchJunctions) {
1105 best = getJunctionTaz(pos, best, vClass, isFrom);
1106 if (best != nullptr) {
1107 into.push_back(best);
1108 }
1109 } else {
1110 into.push_back(best);
1111 }
1112 }
1113 }
1114}
1115
1116
1117const ROEdge*
1118RORouteHandler::getClosestEdge(const Position& pos, double distance, SUMOVehicleClass vClass) {
1119 NamedRTree* t = getLaneTree();
1120 Boundary b;
1121 b.add(pos);
1122 b.grow(distance);
1123 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1124 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1125 std::set<const Named*> lanes;
1126 Named::StoringVisitor sv(lanes);
1127 t->Search(cmin, cmax, sv);
1128 // use closest
1129 double minDist = std::numeric_limits<double>::max();
1130 const ROLane* best = nullptr;
1131 for (const Named* o : lanes) {
1132 const ROLane* cand = static_cast<const ROLane*>(o);
1133 if (!cand->allowsVehicleClass(vClass)) {
1134 continue;
1135 }
1136 double dist = cand->getShape().distance2D(pos);
1137 if (dist < minDist) {
1138 minDist = dist;
1139 best = cand;
1140 }
1141 }
1142 if (best == nullptr) {
1143 return nullptr;
1144 } else {
1145 const ROEdge* bestEdge = &best->getEdge();
1146 while (bestEdge->isInternal()) {
1147 bestEdge = bestEdge->getSuccessors().front();
1148 }
1149 return bestEdge;
1150 }
1151}
1152
1153
1154const ROEdge*
1155RORouteHandler::getJunctionTaz(const Position& pos, const ROEdge* closestEdge, SUMOVehicleClass vClass, bool isFrom) {
1156 if (closestEdge == nullptr) {
1157 return nullptr;
1158 } else {
1159 const RONode* fromJunction = closestEdge->getFromJunction();
1160 const RONode* toJunction = closestEdge->getToJunction();
1161 const bool fromCloser = (fromJunction->getPosition().distanceSquaredTo2D(pos) <
1162 toJunction->getPosition().distanceSquaredTo2D(pos));
1163 const ROEdge* fromSource = myNet.getEdge(fromJunction->getID() + "-source");
1164 const ROEdge* fromSink = myNet.getEdge(fromJunction->getID() + "-sink");
1165 const ROEdge* toSource = myNet.getEdge(toJunction->getID() + "-source");
1166 const ROEdge* toSink = myNet.getEdge(toJunction->getID() + "-sink");
1167 if (fromSource == nullptr || fromSink == nullptr) {
1168 myErrorOutput->inform("Junction-taz '" + fromJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
1169 return nullptr;
1170 }
1171 if (toSource == nullptr || toSink == nullptr) {
1172 myErrorOutput->inform("Junction-taz '" + toJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
1173 return nullptr;
1174 }
1175 const bool fromPossible = isFrom ? fromSource->getSuccessors(vClass).size() > 0 : fromSink->getPredecessors().size() > 0;
1176 const bool toPossible = isFrom ? toSource->getSuccessors(vClass).size() > 0 : toSink->getPredecessors().size() > 0;
1177 //std::cout << "getJunctionTaz pos=" << pos << " isFrom=" << isFrom << " closest=" << closestEdge->getID() << " fromPossible=" << fromPossible << " toPossible=" << toPossible << "\n";
1178 if (fromCloser && fromPossible) {
1179 // return closest if possible
1180 return isFrom ? fromSource : fromSink;
1181 } else if (!fromCloser && toPossible) {
1182 // return closest if possible
1183 return isFrom ? toSource : toSink;
1184 } else {
1185 // return possible
1186 if (fromPossible) {
1187 return isFrom ? fromSource : fromSink;
1188 } else {
1189 return isFrom ? toSource : toSink;
1190 }
1191 }
1192 }
1193}
1194
1195
1196void
1197RORouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1198 const ROEdge* /*fromEdge*/, const ROEdge*& toEdge,
1199 double& departPos, double& arrivalPos, std::string& busStopID,
1200 const ROPerson::PlanItem* const lastStage, bool& ok) {
1201 const std::string description = "walk or personTrip of '" + personID + "'.";
1202 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1203 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."));
1204 }
1205 departPos = myVehicleParameter->departPos;
1206 if (lastStage != nullptr) {
1207 departPos = lastStage->getDestinationPos();
1208 }
1209
1210 busStopID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1211
1212 const SUMOVehicleParameter::Stop* bs = retrieveStoppingPlace(attrs, description, busStopID);
1213 if (bs != nullptr) {
1215 arrivalPos = (bs->startPos + bs->endPos) / 2;
1216 }
1217 if (toEdge != nullptr) {
1220 myHardFail, description, toEdge->getLength(),
1221 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok));
1222 }
1223 } else {
1224 throw ProcessError(TLF("No destination edge for %.", description));
1225 }
1226}
1227
1228
1229void
1231 bool ok = true;
1232 const char* const id = myVehicleParameter->id.c_str();
1233 assert(!attrs.hasAttribute(SUMO_ATTR_EDGES));
1234 const ROEdge* from = nullptr;
1235 const ROEdge* to = nullptr;
1236 parseFromViaTo(SUMO_TAG_PERSON, attrs, ok);
1240 if (ok) {
1241 from = myActiveRoute.front();
1242 }
1243 } else if (myActivePlan->empty()) {
1244 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1245 } else {
1246 from = myActivePlan->back()->getDestination();
1247 }
1250 to = myActiveRoute.back();
1251 } // else, to may also be derived from stopping place
1252
1253 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1254 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1255 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1256 }
1257
1258 double departPos = 0;
1259 double arrivalPos = std::numeric_limits<double>::infinity();
1260 std::string busStopID;
1261 const ROPerson::PlanItem* const lastStage = myActivePlan->empty() ? nullptr : myActivePlan->back();
1262 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, busStopID, lastStage, ok);
1263
1264 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1265 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, "");
1266 SVCPermissions modeSet = 0;
1267 for (StringTokenizer st(modes); st.hasNext();) {
1268 const std::string mode = st.next();
1269 if (mode == "car") {
1270 modeSet |= SVC_PASSENGER;
1271 } else if (mode == "taxi") {
1272 modeSet |= SVC_TAXI;
1273 } else if (mode == "bicycle") {
1274 modeSet |= SVC_BICYCLE;
1275 } else if (mode == "public") {
1276 modeSet |= SVC_BUS;
1277 } else {
1278 throw InvalidArgument("Unknown person mode '" + mode + "'.");
1279 }
1280 }
1281 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1282 double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1283 if (ok) {
1284 const std::string originStopID = myActivePlan->empty() ? "" : myActivePlan->back()->getStopDest();
1285 ROPerson::addTrip(*myActivePlan, myVehicleParameter->id, from, to, modeSet, types,
1286 departPos, originStopID, arrivalPos, busStopID, walkFactor, group);
1287 }
1288}
1289
1290
1291void
1293 // parse walks from->to as person trips
1295 // XXX allow --repair?
1296 bool ok = true;
1297 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1298 const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1299 RORouteDef* routeDef = myNet.getRouteDef(routeID);
1300 const RORoute* route = routeDef != nullptr ? routeDef->getFirstRoute() : nullptr;
1301 if (route == nullptr) {
1302 throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1303 }
1304 myActiveRoute = route->getEdgeVector();
1305 } else {
1306 myActiveRoute.clear();
1307 parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myVehicleParameter->id.c_str(), ok), myActiveRoute, " walk for person '" + myVehicleParameter->id + "'", ok);
1308 }
1309 const char* const objId = myVehicleParameter->id.c_str();
1310 const double duration = attrs.getOpt<double>(SUMO_ATTR_DURATION, objId, ok, -1);
1311 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1312 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1313 }
1314 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, objId, ok, -1.);
1315 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1316 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1317 }
1318 double departPos = 0.;
1319 double arrivalPos = std::numeric_limits<double>::infinity();
1320 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1321 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."));
1322 }
1324 arrivalPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, objId, myActiveRoute.back()->getLength(), attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, objId, ok));
1325 }
1326 std::string stoppingPlaceID;
1327 const std::string errorSuffix = " for walk of person '" + myVehicleParameter->id + "'";
1328 retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID);
1329 if (ok) {
1330 ROPerson::addWalk(*myActivePlan, myActiveRoute, duration, speed, departPos, arrivalPos, stoppingPlaceID);
1331 }
1332 } else {
1333 addPersonTrip(attrs);
1334 }
1335}
1336
1337
1340 if (myLaneTree == nullptr) {
1341 myLaneTree = new NamedRTree();
1342 for (const auto& edgeItem : myNet.getEdgeMap()) {
1343 for (ROLane* lane : edgeItem.second->getLanes()) {
1344 Boundary b = lane->getShape().getBoxBoundary();
1345 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1346 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1347 myLaneTree->Insert(cmin, cmax, lane);
1348 }
1349 }
1350 }
1351 return myLaneTree;
1352}
1353
1354bool
1356 if (!myUnsortedInput) {
1358 }
1359 return true;
1360}
1361
1362/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define JUNCTION_TAZ_MISSING_HELP
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:271
#define WRITE_ERROR(msg)
Definition MsgHandler.h:279
#define WRITE_WARNING(msg)
Definition MsgHandler.h:270
#define TL(string)
Definition MsgHandler.h:287
#define TLF(string,...)
Definition MsgHandler.h:288
std::vector< const ROEdge * > ConstROEdgeVector
Definition ROEdge.h:54
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
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 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_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_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
@ SUMO_ATTR_TOJUNCTION
int gPrecision
the precision for floating point outputs
Definition StdDefs.cpp:26
int gPrecisionGeo
Definition StdDefs.cpp:27
T MIN2(T a, T b)
Definition StdDefs.h:76
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.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
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 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
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition Position.h:259
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:512
const RONode * getFromJunction() const
Definition ROEdge.h:508
bool isInternal() const
return whether this edge is an internal edge
Definition ROEdge.h:150
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition ROEdge.h:366
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:520
double getLength() const
Returns the length of the edge.
Definition ROEdge.h:215
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:364
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:216
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:157
bool addPerson(ROPerson *person)
Definition RONet.cpp:522
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: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:409
bool addFlow(SUMOVehicleParameter *flow, const bool randomize)
Definition RONet.cpp:504
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:457
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 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.
const double myMapMatchingDistance
maximum distance when map-matching
void deleteActivePlanAndVehicleParameter()
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
Parameterised * addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
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)
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.
void clear()
Clears 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
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it