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