Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSRouteHandler.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/****************************************************************************/
22// Parser and container for routes during their loading
23/****************************************************************************/
24#include <config.h>
25
26#include "MSRouteHandler.h"
34#include <microsim/MSEdge.h>
35#include <microsim/MSLane.h>
45
46// ===========================================================================
47// static members
48// ===========================================================================
50
51
52// ===========================================================================
53// method definitions
54// ===========================================================================
55MSRouteHandler::MSRouteHandler(const std::string& file, bool addVehiclesDirectly) :
56 SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes", true),
57 MapMatcher(OptionsCont::getOptions().getBool("mapmatch.junctions"),
58 OptionsCont::getOptions().getBool("mapmatch.taz"),
59 OptionsCont::getOptions().getFloat("mapmatch.distance"),
60 MsgHandler::getErrorInstance()),
61 myActiveRouteRepeat(0),
62 myActiveRoutePeriod(0),
63 myActiveRoutePermanent(false),
64 myActiveType(ObjectTypeEnum::UNDEFINED),
65 myHaveVia(false),
66 myActiveTransportablePlan(nullptr),
67 myAddVehiclesDirectly(addVehiclesDirectly),
68 myCurrentVTypeDistribution(nullptr),
69 myCurrentRouteDistribution(nullptr),
70 myAmLoadingState(false),
71 myScaleSuffix(OptionsCont::getOptions().getString("scale-suffix")),
72 myReplayRerouting(OptionsCont::getOptions().getBool("replay-rerouting")),
73 myStartTriggeredInFlow(false) {
74 myActiveRoute.reserve(100);
75}
76
77
79
80
81void
92
93
94void
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 bool ok = true;
112 const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
115 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
116 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
117 if (type != nullptr) {
118 vClass = type->getParameter().vehicleClass;
119 }
120 }
121 // from-attributes
122 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
124 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION);
125 const std::string tazType = useJunction ? "junction" : "taz";
126 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROM_JUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok);
127 const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
128 if (fromTaz == nullptr) {
129 throw ProcessError("Source " + tazType + " '" + tazID + "' not known " + rid + "!"
130 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
131 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
132 throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges " + rid + "!");
133 } else {
134 myActiveRoute.push_back(fromTaz);
135 }
136 } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
137 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, vClass, myActiveRoute, rid, true, ok);
138 if (myMapMatchTAZ && ok) {
139 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
141 }
142 } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
143 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, myActiveRoute, rid, true, ok);
144 if (myMapMatchTAZ && ok) {
145 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
147 }
148 } else {
149 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok),
150 myActiveRoute, rid);
151 }
152 if (!ok) {
153 throw ProcessError();
154 }
155
156 // via-attributes
159 }
160 ConstMSEdgeVector viaEdges;
161 if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
162 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, vClass, viaEdges, rid, false, ok);
163 } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
164 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, viaEdges, rid, false, ok);
165 } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
166 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
167 const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
168 if (viaSink == nullptr) {
169 throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
170 } else {
171 viaEdges.push_back(viaSink);
172 }
173 }
174 } else {
175 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok),
176 viaEdges, rid);
177 }
178 if (!viaEdges.empty()) {
179 myHaveVia = true;
180 }
181 for (const MSEdge* e : viaEdges) {
182 myActiveRoute.push_back(e);
183 myVehicleParameter->via.push_back(e->getID());
184 }
185
186 // to-attributes
187 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
189 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION);
190 const std::string tazType = useJunction ? "junction" : "taz";
191 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TO_JUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
192 const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
193 if (toTaz == nullptr) {
194 throw ProcessError("Sink " + tazType + " '" + tazID + "' not known " + rid + "!"
195 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
196 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
197 throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges " + rid + "!");
198 } else {
199 myActiveRoute.push_back(toTaz);
200 }
201 } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
202 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, vClass, myActiveRoute, rid, false, ok);
203 if (myMapMatchTAZ && ok) {
204 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
206 }
207 } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
208 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, vClass, myActiveRoute, rid, false, ok);
209 if (myMapMatchTAZ && ok) {
210 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
212 }
213 } else {
214 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
215 myActiveRoute, rid);
216 }
218 if (myVehicleParameter->routeid == "") {
220 }
221}
222
223
224void
226 try {
228 && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT && element != SUMO_TAG_PARAM) {
229 const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
230 throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
231 }
232 if (myVehicleParameter == nullptr) {
234 myHaveVia = false;
235 }
236 SUMORouteHandler::myStartElement(element, attrs);
237 switch (element) {
239 addTransportable(attrs, true);
240 break;
242 addTransportable(attrs, false);
243 break;
244 case SUMO_TAG_FLOW:
245 if (myVehicleParameter) {
246 parseFromViaTo((SumoXMLTag)element, attrs);
247 }
248 break;
249 case SUMO_TAG_TRIP:
250 parseFromViaTo((SumoXMLTag)element, attrs);
251 break;
252 default:
253 break;
254 }
255 } catch (ProcessError&) {
257 throw;
258 }
259}
260
261
262void
264 bool ok = true;
265 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
266 if (ok) {
268 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
269 std::vector<double> probs;
270 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
271 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
272 while (st.hasNext()) {
273 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
274 }
275 }
276 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
277 StringTokenizer st(vTypes);
278 int probIndex = 0;
279 while (st.hasNext()) {
280 const std::string& vtypeID = st.next();
282 if (dist != nullptr) {
283 const double distProb = ((int)probs.size() > probIndex ? probs[probIndex] : 1.) / dist->getOverallProb();
284 std::vector<double>::const_iterator probIt = dist->getProbs().begin();
285 for (MSVehicleType* const type : dist->getVals()) {
286 myCurrentVTypeDistribution->add(type, distProb * *probIt);
287 probIt++;
288 }
289 } else {
291 if (type == nullptr) {
292 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
293 }
294 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->getDefaultProbability());
295 myCurrentVTypeDistribution->add(type, prob);
296 }
297 probIndex++;
298 }
299 if (probs.size() > 0 && probIndex != (int)probs.size()) {
300 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
301 " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
302 }
303 }
304 }
305}
306
307
308void
310 if (myCurrentVTypeDistribution != nullptr) {
311 if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
313 return;
314 }
317 throw ProcessError(TLF("Vehicle type distribution '%' is empty.", myCurrentVTypeDistributionID));
318 }
319 if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
321 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", myCurrentVTypeDistributionID));
322 }
324 }
325}
326
327
328void
332 // check whether the id is really necessary
333 std::string rid;
334 if (myCurrentRouteDistribution != nullptr) {
336 rid = "distribution '" + myCurrentRouteDistributionID + "'";
337 } else if (myVehicleParameter != nullptr) {
338 // ok, a vehicle is wrapping the route,
339 // we may use this vehicle's id as default
340 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
341 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
342 WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
343 }
344 } else {
345 bool ok = true;
346 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
347 if (!ok) {
348 return;
349 }
350 rid = "'" + myActiveRouteID + "'";
351 }
352 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
353 rid = "for vehicle '" + myVehicleParameter->id + "'";
354 }
355 bool ok = true;
356 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
357 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
358 }
359 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
361 throw ProcessError(TLF("Invalid reference to route '%' in route %.", myActiveRouteRefID, rid));
362 }
365 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
369 // handle obsolete attribute name
371 myActiveRoutePermanent = attrs.getOpt<bool>(SUMO_ATTR_STATE, myActiveRouteID.c_str(), ok, false);
372 if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
373 WRITE_WARNING(TL("Attribute 'period' is deprecated for route. Use 'cycleTime' instead."));
374 }
375 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
376 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
377 WRITE_WARNING(TLF("Invalid cost for route '%'.", myActiveRouteID));
378 }
379}
380
381
382void
384 // Currently unused
385}
386
387
388void
390 // Currently unused
391}
392
393
394void
396 // Currently unsued
397}
398
399
400void
401MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
402 std::string type = "vehicle";
403 if (mayBeDisconnected) {
405 type = "flow";
406 } else {
407 type = "trip";
408 }
409 }
410
411 try {
412 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
413 if (mustReroute) {
414 // implicit route from stops
416 myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
417 }
418 }
419 if (myActiveRoute.size() == 0) {
420 delete myActiveRouteColor;
421 myActiveRouteColor = nullptr;
422 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
424 if (route != nullptr) {
426 }
427 myActiveRouteID = "";
429 return;
430 }
431 if (myVehicleParameter != nullptr) {
432 throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
433 } else {
434 throw ProcessError(TLF("Route '%' has no edges.", myActiveRouteID));
435 }
436 }
437 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
438 throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
439 }
440 if (myActiveRouteRepeat > 0) {
441 // duplicate route
443 auto tmpStops = myActiveRouteStops;
444
447 std::string errSuffix = ".";
448 if (myVehicleParameter != nullptr) {
451 if (vtype != nullptr) {
452 vClass = vtype->getVehicleClass();
453 errSuffix = TLF(" for vehicle '%' with vClass %.", myVehicleParameter->id, getVehicleClassNames(vClass));
454 }
455 }
456 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
457 if (tmpStops.size() == 0 || tmpStops.back().jump < 0) {
458 throw ProcessError(TLF("Disconnected route '%' when repeating. Last edge '%' is not connected to first edge '%'%",
459 myActiveRouteID, myActiveRoute.back()->getID(), myActiveRoute.front()->getID(), errSuffix));
460 }
461 }
462 }
463 for (int i = 0; i < myActiveRouteRepeat; i++) {
464 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
465 for (SUMOVehicleParameter::Stop stop : tmpStops) {
466 if (stop.until > 0) {
467 if (myActiveRoutePeriod <= 0) {
468 const std::string description = myVehicleParameter != nullptr
469 ? "for " + type + " '" + myVehicleParameter->id + "'"
470 : "'" + myActiveRouteID + "'";
471 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
472 }
473 stop.until += myActiveRoutePeriod * (i + 1);
474 }
475 if (stop.arrival > 0) {
476 if (myActiveRoutePeriod <= 0) {
477 const std::string description = myVehicleParameter != nullptr
478 ? "for " + type + " '" + myVehicleParameter->id + "'"
479 : "'" + myActiveRouteID + "'";
480 throw ProcessError(TLF("Cannot repeat stops with 'arrival' in route % because no cycleTime is defined.", description));
481 }
482 stop.arrival += myActiveRoutePeriod * (i + 1);
483 }
484 stop.index = STOP_INDEX_REPEAT;
485 myActiveRouteStops.push_back(stop);
486 }
487 }
488 if (myActiveRouteStops.size() > 0) {
489 // never jump on the last stop of a repeating route
490 myActiveRouteStops.back().jump = -1;
491 }
492 }
493 MSRoute* const route = new MSRoute(myActiveRouteID, myActiveRoute,
498 route->setCosts(myCurrentCosts);
499 route->setReroute(mustReroute);
500 myActiveRoute.clear();
501 ConstMSRoutePtr constRoute = std::shared_ptr<const MSRoute>(route);
502 if (!MSRoute::dictionary(myActiveRouteID, constRoute)) {
504 if (myVehicleParameter != nullptr) {
505 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
506 throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
507 } else {
508 throw ProcessError(TLF("A vehicle with id '%' already exists.", myVehicleParameter->id));
509 }
510 } else {
511 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myActiveRouteID));
512 }
513 }
514 } else {
515 if (myCurrentRouteDistribution != nullptr) {
517 }
518 }
519 myActiveRouteID = "";
520 myActiveRouteColor = nullptr;
521 myActiveRouteStops.clear();
523 } catch (ProcessError&) {
525 throw;
526 }
527}
528
529
530void
532 // check whether the id is really necessary
533 if (myVehicleParameter != nullptr) {
534 // ok, a vehicle is wrapping the route,
535 // we may use this vehicle's id as default
536 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
537 // we have to record this or we cannot remove the distribution later
539 } else {
540 bool ok = true;
541 myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
542 if (!ok) {
543 return;
544 }
545 }
547 std::vector<double> probs;
548 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
549 bool ok = true;
550 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
551 while (st.hasNext()) {
552 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
553 }
554 }
555 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
556 bool ok = true;
557 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
558 int probIndex = 0;
559 while (st.hasNext()) {
560 std::string routeID = st.next();
562 if (route == nullptr) {
563 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
564 }
565 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
566 myCurrentRouteDistribution->add(route, prob, false);
567 probIndex++;
568 }
569 if (probs.size() > 0 && probIndex != (int)probs.size()) {
570 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
571 " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
572 }
573 }
574}
575
576
577void
579 if (myCurrentRouteDistribution != nullptr) {
580 const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
581 if (MSGlobals::gStateLoaded && haveSameID) {
584 return;
585 }
586 if (haveSameID) {
588 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myCurrentRouteDistributionID));
589 }
592 throw ProcessError(TLF("Route distribution '%' is empty.", myCurrentRouteDistributionID));
593 }
596 }
597}
598
599
600void
602 // get nested route
603 const std::string embeddedRouteID = "!" + myVehicleParameter->id;
604 ConstMSRoutePtr route = nullptr;
605 if (myReplayRerouting) {
607 if (rDist != nullptr && rDist->getVals().size() > 0) {
608 route = rDist->getVals().front();
609 }
610 }
611 if (route == nullptr) {
612 route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
613 }
616 // let's check whether this vehicle had to depart before the simulation starts
618 return;
619 }
620 }
621
622 // get the vehicle's type
623 MSVehicleType* vtype = nullptr;
624
625 try {
626 if (myVehicleParameter->vtypeid != "") {
627 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
628 if (vtype == nullptr) {
629 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
630 }
631 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
632 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
633 }
634 } else {
635 // there should be one (at least the default one)
636 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
637 }
639 // if the route id was given, prefer that one
640 if (route != nullptr && !myAmLoadingState) {
641 WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
642 }
644 }
645 if (route == nullptr) {
646 // nothing found? -> error
647 if (myVehicleParameter->routeid != "") {
648 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
649 } else {
650 throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
651 }
652 }
653 myActiveRouteID = "";
654
655 } catch (ProcessError&) {
657 throw;
658 }
659 if (route->mustReroute()) {
661 if (myVehicleParameter->stops.size() > 0) {
662 route = addVehicleStopsToImplicitRoute(route, false);
663 }
664 }
668 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
669 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
670 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
671 }
672 }
676 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
677 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
678 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
679 }
680 }
681
682 // try to build the vehicle
683 SUMOVehicle* vehicle = nullptr;
684 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
686 try {
687 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
688 } catch (const ProcessError& e) {
689 myVehicleParameter = nullptr;
691 WRITE_WARNING(e.what());
692 vehControl.fixVehicleCounts();
693 return;
694 } else {
695 throw e;
696 }
697 }
698 const SUMOTime origDepart = myVehicleParameter->depart;
699 // maybe we do not want this vehicle to be inserted due to scaling
700 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
701 if (quota > 0) {
704 vehControl.addVehicle(myVehicleParameter->id, vehicle);
705 if (myReplayRerouting) {
707 if (rDist != nullptr) {
708 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
709 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
710 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
711 if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
712 // routing in the insertion step happens *after* insertion
714 } else {
716 }
717 }
718 }
719 }
720 int offset = 0;
721 for (int i = 1; i < quota; i++) {
724 }
726 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
727 while (vehControl.getVehicle(newPars->id) != nullptr) {
728 offset += 1;
729 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
730 }
733 // resample type
734 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
735 }
736 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
737 vehControl.addVehicle(newPars->id, vehicle);
738 }
739 myVehicleParameter = nullptr;
740 } else {
741 vehControl.deleteVehicle(vehicle, true);
742 myVehicleParameter = nullptr;
743 vehicle = nullptr;
744 }
745 } else {
746 // strange: another vehicle with the same id already exists
748 // and was not loaded while loading a simulation state
749 // -> error
750 std::string veh_id = myVehicleParameter->id;
752 std::string scaleWarning = "";
753 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
754 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
755 }
756 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
757 } else {
758 // ok, it seems to be loaded previously while loading a simulation state
759 vehicle = nullptr;
760 }
761 }
762 // check whether the vehicle shall be added directly to the network or
763 // shall stay in the internal buffer
764 if (vehicle != nullptr) {
767 }
768 }
769}
770
771
774 // the route was defined without edges and its current edges were
775 // derived from route-stops.
776 // We may need to add additional edges for the vehicle-stops
778 assert(route->getStops().size() > 0);
779 ConstMSEdgeVector edges = route->getEdges();
781 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
782 if (stop.index == 0) {
783 if (edges.front() != stopEdge ||
784 route->getStops().front().endPos < stop.endPos) {
785 edges.insert(edges.begin(), stopEdge);
786 }
787 } else if (stop.index == STOP_INDEX_END) {
788 if (edges.back() != stopEdge ||
789 route->getStops().back().endPos > stop.endPos) {
790 edges.push_back(stopEdge);
791 }
792 } else {
793 WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
794 }
795 }
796 ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
797 isPermanent, new RGBColor(route->getColor()), route->getStops());
798 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
799 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
800 }
801 return newRoute;
802}
803
804
805void
807 try {
808 if (myActiveTransportablePlan->size() == 0) {
809 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
810 error[0] = (char)::toupper((char)error[0]);
811 throw ProcessError(error);
812 }
813 // let's check whether this transportable had to depart before the simulation starts
817 return;
818 }
819 // type existence has been checked on opening
822 && type->getVehicleClass() != SVC_PEDESTRIAN
824 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
825 }
828 if (created > 0) {
830 } else {
832 }
833 } catch (ProcessError&) {
835 throw;
836 }
837}
838
839
840void
844
845
846void
850
851
852void
856
857
858void
862
863
864void
866 try {
867 const std::string fid = myVehicleParameter->id;
868 if (myActiveTransportablePlan->size() == 0) {
869 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
870 }
871 // let's check whether this transportable (person/container) had to depart before the simulation starts
875 return;
876 }
877 // instantiate all persons/containers of this flow
878 int i = 0;
880 std::string baseID = myVehicleParameter->id;
883 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
884 } else {
887 // type existence has been checked on opening
889 addFlowTransportable(t, type, baseID, i++);
890 }
891 }
892 }
893 } else {
896 // poisson: randomize first depart
898 }
899 for (; i < myVehicleParameter->repetitionNumber && (myVehicleParameter->repetitionNumber != std::numeric_limits<int>::max()
901 // type existence has been checked on opening
905 }
906 }
908 } catch (ProcessError&) {
910 throw;
911 }
913}
914
915
916int
917MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
918 try {
919 int numCreated = 0;
920 MSNet* const net = MSNet::getInstance();
923 //MSTransportableControl& pc = net->getPersonControl();
924 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
925 if (quota == 0) {
926 tc.addDiscarded();
927 }
928 for (int j = 0; j < quota; j++) {
929 if (i > 0 || j > 0) {
930 // copy parameter and plan because the transportable takes over responsibility
932 *copyParam = *myVehicleParameter;
933 myVehicleParameter = copyParam;
935 MSStage* lastStage = nullptr;
936 for (MSStage* const s : *myActiveTransportablePlan) {
937 copyPlan->push_back(s->clone());
938 if (lastStage != nullptr && s->getStageType() == MSStageType::WALKING && lastStage->getDestinationStop() != nullptr) {
939 MSStageMoving* walk = static_cast<MSStageMoving*>(copyPlan->back());
940 walk->setDepartPos(lastStage->getDestinationStop()->getAccessPos(walk->getEdge(), &myParsingRNG));
941 }
942 lastStage = s;
943 }
944 myActiveTransportablePlan = copyPlan;
946 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
947 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
948 }
949 }
950 myVehicleParameter->id = (baseID
951 + (i >= 0 ? "." + toString(i) : "")
952 + (j > 0 ? "." + toString(j) : ""));
957 numCreated++;
958 if (!tc.add(transportable)) {
959 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
960 delete transportable;
963 throw ProcessError(error);
964 }
965 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
966 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
967 WRITE_WARNINGF(TL("There exists a person and a container with the same id '%'. Starting with SUMO 1.9.0 this is an error."), myVehicleParameter->id);
968 }
969 }
970 return numCreated;
971 } catch (ProcessError&) {
973 throw;
974 }
975}
976
977
978void
981 vehType->check();
982 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
983 const std::string id = vehType->getID();
984 delete vehType;
986 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
987 }
988 } else {
989 if (myCurrentVTypeDistribution != nullptr) {
991 }
992 }
993}
994
995
996void
1000 delete myVehicleParameter;
1001 myVehicleParameter = nullptr;
1002 return;
1003 }
1004 // let's check whether vehicles had to depart before the simulation starts
1007 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
1008 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
1011 delete myVehicleParameter;
1012 myVehicleParameter = nullptr;
1013 return;
1014 }
1015 }
1016 }
1017 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
1018 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1019 }
1022 closeRoute(true);
1023 }
1025 if (route == nullptr) {
1026 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1027 }
1028 if (route->mustReroute()) {
1030 if (myVehicleParameter->stops.size() > 0) {
1031 route = addVehicleStopsToImplicitRoute(route, true);
1032 myVehicleParameter->routeid = route->getID();
1033 }
1034 }
1038 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
1039 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
1040 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1041 }
1042 }
1046 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
1047 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
1048 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1049 }
1050 }
1051 myActiveRouteID = "";
1052
1053 // check whether the vehicle shall be added directly to the network or
1054 // shall stay in the internal buffer
1056 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
1058 } else {
1060 delete myVehicleParameter;
1061 } else {
1062 throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
1063 }
1064 }
1065 }
1066 myVehicleParameter = nullptr;
1067}
1068
1069
1070void
1076
1077void
1081
1082void
1086
1087void
1089 if (myVehicleParameter == nullptr) {
1090 throw ProcessError(TLF("Cannot define % stage without %.", toString(modeTag), toString(modeTag)));
1091 }
1092 try {
1093 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1094 std::string agent = "person";
1095 std::string stop = "bus stop";
1097 agent = "container";
1098 stop = "container stop";
1099 }
1100
1101 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1103 throw ProcessError("Found " + mode + " inside " + agent + " element");
1104 }
1105 const std::string aid = myVehicleParameter->id;
1106 bool ok = true;
1107 const MSEdge* from = nullptr;
1108 const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, "ANY");
1109 StringTokenizer st(desc);
1110 MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1111 MSEdge* to = nullptr;
1112 if (s != nullptr) {
1113 to = &s->getLane().getEdge();
1114 }
1115 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1116 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1117
1118 const SUMOVehicleParameter* startVeh = nullptr;
1119 const MSEdge* startVehFrom = nullptr;
1121 if (st.size() != 1) {
1122 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1123 }
1124 // agent starts
1126 const std::string vehID = st.front();
1127 SUMOVehicle* sVeh = vehControl.getVehicle(vehID);
1128 if (sVeh == nullptr) {
1129 if (MSNet::getInstance()->hasFlow(vehID)) {
1130 startVeh = MSNet::getInstance()->getInsertionControl().getFlowPars(vehID);
1131 if (startVeh != nullptr) {
1132 ConstMSRoutePtr const route = MSRoute::dictionary(startVeh->routeid);
1133 startVehFrom = route->getEdges().front();
1134 // flows are inserted at the end of the time step so we
1135 // do delay the pedestrian event by one time step
1136 myVehicleParameter->depart = startVeh->depart + DELTA_T;
1138 }
1139 }
1140 } else {
1141 startVeh = &sVeh->getParameter();
1142 startVehFrom = sVeh->getRoute().getEdges().front();
1143 myVehicleParameter->depart = startVeh->depart;
1144 }
1145 if (startVeh == nullptr) {
1146 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1147 }
1148 if (startVeh->departProcedure == DepartDefinition::TRIGGERED) {
1149 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1150 }
1151 }
1152
1153 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1154 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1155 from = MSEdge::dictionary(fromID);
1156 if (from == nullptr) {
1157 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1158 }
1159 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1160 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1161 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1162 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1163 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1164 if (!(stopWithAccess || transferAtJunction)) {
1165 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1166 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1167 }
1168 }
1169 if (startVeh != nullptr && startVehFrom != from) {
1170 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1171 "' (edge '" + fromID + "' != edge '" + startVehFrom->getID() + "').");
1172 }
1173 } else if (startVeh != nullptr) {
1174 from = startVehFrom;
1175 }
1176 if (myActiveTransportablePlan->empty()) {
1177 if (from == nullptr) {
1178 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1179 } else {
1181 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1182 }
1183 }
1184 // given attribute may override given stopping place due access requirements
1185 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1186 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1187 to = MSEdge::dictionary(toID);
1188 if (to == nullptr) {
1189 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1190 }
1191 }
1192 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1193 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1194 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1195 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1196 myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, 0.0, st.getVector(), group, intendedVeh, intendedDepart));
1197 myParamStack.push_back(myActiveTransportablePlan->back());
1198 } catch (ProcessError&) {
1200 throw;
1201 }
1202}
1203
1205MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1206 bool ok = true;
1207 // dummy stop parameter to hold the attributes
1209 if (stopParam != nullptr) {
1210 stop = *stopParam;
1211 } else {
1212 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1213 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1214 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1215 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1216 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1217 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1218 }
1219 MSStoppingPlace* toStop = nullptr;
1220 if (stop.busstop != "") {
1222 if (toStop == nullptr) {
1223 ok = false;
1224 WRITE_ERROR(TLF("The busStop '%' is not known%.", stop.busstop, errorSuffix));
1225 }
1226 } else if (stop.containerstop != "") {
1228 if (toStop == nullptr) {
1229 ok = false;
1230 WRITE_ERROR(TLF("The containerStop '%' is not known%.", stop.containerstop, errorSuffix));
1231 }
1232 } else if (stop.parkingarea != "") {
1234 if (toStop == nullptr) {
1235 ok = false;
1236 WRITE_ERROR(TLF("The parkingArea '%' is not known%.", stop.parkingarea, errorSuffix));
1237 }
1238 } else if (stop.chargingStation != "") {
1239 // ok, we have a charging station
1241 if (toStop == nullptr) {
1242 ok = false;
1243 WRITE_ERROR(TLF("The chargingStation '%' is not known%.", stop.chargingStation, errorSuffix));
1244 }
1245 } else if (stop.overheadWireSegment != "") {
1246 // ok, we have an overhead wire segment
1248 if (toStop == nullptr) {
1249 ok = false;
1250 WRITE_ERROR(TLF("The overhead wire segment '%' is not known%.", stop.overheadWireSegment, errorSuffix));
1251 }
1252 }
1253 if (!ok && MSGlobals::gCheckRoutes) {
1254 throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1255 }
1256 return toStop;
1257}
1258
1261 Parameterised* result = nullptr;
1262 try {
1263 std::string errorSuffix;
1265 errorSuffix = " in person '" + myVehicleParameter->id + "'";
1267 errorSuffix = " in container '" + myVehicleParameter->id + "'";
1268 } else if (myVehicleParameter != nullptr) {
1269 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'";
1270 } else {
1271 errorSuffix = " in route '" + myActiveRouteID + "'";
1272 }
1274 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1275 if (!ok) {
1277 throw ProcessError();
1278 }
1279 return result;
1280 }
1281 const MSEdge* edge = nullptr;
1282 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1283 // if one of the previous stops is defined
1284 if (toStop != nullptr) {
1285 const MSLane& l = toStop->getLane();
1286 stop.lane = l.getID();
1287 if ((stop.parametersSet & STOP_END_SET) == 0) {
1288 stop.endPos = toStop->getEndLanePosition();
1289 } else {
1290 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1291 }
1292 stop.startPos = toStop->getBeginLanePosition();
1293 edge = &l.getEdge();
1294 } else {
1295 // no, the lane and the position should be given directly
1296 // get the lane
1297 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1298 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1299 if (ok && stop.edge != "") { // edge is given directly
1300 edge = MSEdge::dictionary(stop.edge);
1301 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1302 throw ProcessError(TLF("The edge '%' for a stop is not known%.", stop.edge, errorSuffix));
1303 }
1304 } else if (ok && stop.lane != "") { // lane is given directly
1305 MSLane* stopLane = MSLane::dictionary(stop.lane);
1306 if (stopLane == nullptr) {
1307 // check for opposite-direction stop
1308 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1309 if (stopLane != nullptr) {
1310 edge = MSEdge::dictionary(stop.edge);
1311 }
1312 } else {
1313 edge = &stopLane->getEdge();
1314 }
1315 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1316 throw ProcessError(TLF("The lane '%' for a stop is not known%.", stop.lane, errorSuffix));
1317 }
1318 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
1319 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
1320 Position pos;
1321 bool geo = false;
1322 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
1323 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
1324 } else {
1325 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
1326 geo = true;
1327 }
1328 PositionVector positions;
1329 positions.push_back(pos);
1330 ConstMSEdgeVector geoEdges;
1332 auto& vc = MSNet::getInstance()->getVehicleControl();
1333 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
1334 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1335 if (type != nullptr) {
1336 vClass = type->getParameter().vehicleClass;
1337 }
1338 }
1339 parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok, true);
1340 if (ok) {
1341 edge = geoEdges.front();
1342 if (geo) {
1344 }
1346 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
1347 } else {
1348 throw ProcessError(TLF("Could not map stop position '%' to the network%.", pos, errorSuffix));
1349 }
1350 } else {
1351 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1352 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1353 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1354 edge = &toStop->getLane().getEdge();
1355 stop.lane = toStop->getLane().getID();
1356 stop.endPos = toStop->getEndLanePosition();
1357 stop.startPos = toStop->getBeginLanePosition();
1358 } else { // use end of movement before definied as lane/edge
1359 edge = myActiveTransportablePlan->back()->getDestination();
1360 stop.lane = edge->getLanes()[0]->getID();
1361 stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1362 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1363 }
1364 } else {
1365 const std::string msg = TLF("A stop must be placed on a busStop, a chargingStation, an overheadWireSegment, a containerStop, a parkingArea, an edge or a lane%.", errorSuffix);
1367 throw ProcessError(msg);
1368 } else {
1369 WRITE_WARNING(msg);
1370 return result;
1371 }
1372 }
1373 }
1374 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1375 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1376 WRITE_WARNINGF(TL("Deprecated attribute 'pos' in description of stop%."), errorSuffix);
1377 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1378 }
1379 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1380 if (!myAmLoadingState) {
1381 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1383 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1384 throw ProcessError(TLF("Invalid start or end position for stop on %'%.",
1385 stop.lane != "" ? ("lane '" + stop.lane) : ("edge '" + stop.edge), errorSuffix));
1386 }
1387 }
1388 }
1389 stop.edge = edge->getID();
1391 if (myActiveTransportablePlan->empty()) {
1392 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1394 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1396 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1397 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1398 if (myActiveTransportablePlan->back()->getDestination()->isTazConnector()) {
1399 myActiveTransportablePlan->back()->setDestination(edge, toStop);
1400 } else {
1401 throw ProcessError(TLF("Disconnected plan for % '%' (%!=%).", myActiveTypeName, myVehicleParameter->id,
1402 edge->getID(), myActiveTransportablePlan->back()->getDestination()->getID()));
1403 }
1404 }
1405 // transporting veh stops somewhere
1406 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1408 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1409 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1410 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1411 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1412 WRITE_WARNINGF(TL("Disconnected plan for % '%' (stop range %-% does not cover previous arrival position %)."),
1414 }
1415 }
1416 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1417 double pos = (stop.startPos + stop.endPos) / 2.;
1418 if (!myActiveTransportablePlan->empty()) {
1419 pos = myActiveTransportablePlan->back()->getArrivalPos();
1420 }
1421 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1422 result = myActiveTransportablePlan->back();
1423
1424 } else if (myVehicleParameter != nullptr) {
1425 myVehicleParameter->stops.push_back(stop);
1426 result = &myVehicleParameter->stops.back();
1427 } else {
1428 myActiveRouteStops.push_back(stop);
1429 result = &myActiveRouteStops.back();
1430 }
1431 if (myInsertStopEdgesAt >= 0) {
1432 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1433 if (edge->isInternal()) {
1434 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1437 }
1440 } else {
1441 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1443 }
1444 } else if (myHaveVia) {
1445 // vias were loaded, check for consistency
1446 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1447 WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'."),
1449 }
1450 }
1451 } catch (ProcessError&) {
1453 throw;
1454 }
1455 return result;
1456}
1457
1458
1459void
1460MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1461 const MSEdge* fromEdge, const MSEdge*& toEdge,
1462 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1463 const MSStage* const lastStage, bool& ok) {
1464 try {
1465 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1466
1467 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1468 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."));
1469 }
1470 departPos = 0.;
1471 if (lastStage != nullptr) {
1472 if (lastStage->getDestinationStop() != nullptr) {
1473 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge, &myParsingRNG);
1474 } else if (lastStage->getDestination() == fromEdge) {
1475 departPos = lastStage->getArrivalPos();
1476 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1477 departPos = fromEdge->getLength();
1478 }
1479 }
1480
1481 bs = retrieveStoppingPlace(attrs, " " + description);
1482 if (bs != nullptr) {
1483 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1484 if (arrivalPos < 0) {
1485 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1486 }
1488 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1489 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1490 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1491 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1492 arrivalPos = arrPos;
1493 } else {
1494 WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1495 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1496 }
1497 }
1498 } else {
1499 if (toEdge == nullptr) {
1500 throw ProcessError(TLF("No destination edge for %.", description));
1501 }
1504 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1505 } else {
1506 arrivalPos = toEdge->getLength() / 2.;
1507 }
1508 }
1509 } catch (ProcessError&) {
1511 throw;
1512 }
1513}
1514
1515
1516void
1518 if (myVehicleParameter == nullptr) {
1519 throw ProcessError(TL("Cannot define person stage without person."));
1520 }
1521 try {
1522 myActiveRoute.clear();
1523 bool ok = true;
1524 const char* const id = myVehicleParameter->id.c_str();
1525 const MSEdge* from = nullptr;
1526 const MSEdge* to = nullptr;
1531 from = myActiveRoute.front();
1532 } else if (myActiveTransportablePlan->empty()) {
1533 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1534 } else {
1535 from = myActiveTransportablePlan->back()->getDestination();
1536 }
1539 to = myActiveRoute.back();
1540 } // else, to may also be derived from stopping place
1541
1542 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1543 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1544 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1545 }
1546
1547 double departPos = 0;
1548 double arrivalPos = 0;
1549 MSStoppingPlace* stoppingPlace = nullptr;
1550 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1551
1552 SVCPermissions modeSet = 0;
1553 if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
1554 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1555 std::string errorMsg;
1556 // try to parse person modes
1557 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1558 throw InvalidArgument(errorMsg);
1559 }
1560 } else {
1561 modeSet = myVehicleParameter->modes;
1562 }
1563 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1565 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, myVehicleParameter->vTypes);
1566 for (StringTokenizer st(types); st.hasNext();) {
1567 const std::string vtypeid = st.next();
1568 const MSVehicleType* const vType = vehControl.getVType(vtypeid);
1569 if (vType == nullptr) {
1570 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1571 }
1572 modeSet |= (vType->getVehicleClass() == SVC_BICYCLE) ? SVC_BICYCLE : SVC_PASSENGER;
1573 }
1574 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1575 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1576 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1577 }
1578 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1579 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1580 if (ok) {
1581 if (myActiveTransportablePlan->empty()) {
1582 double initialDepartPos = myVehicleParameter->departPos;
1584 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1585 }
1586 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1587 }
1589 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1590 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1591 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1592 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1593 myParamStack.push_back(myActiveTransportablePlan->back());
1596 }
1597 }
1598 myActiveRoute.clear();
1599 } catch (ProcessError&) {
1601 throw;
1602 }
1603}
1604
1605
1606void
1608 if (myVehicleParameter == nullptr) {
1609 throw ProcessError(TL("Cannot define person stage without person."));
1610 }
1611 myActiveRouteID = "";
1613 try {
1614 myActiveRoute.clear();
1615 bool ok = true;
1616 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1617 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1618 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1619 }
1620 double speed = -1; // default to vType speed
1621 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1622 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1623 if (speed <= 0) {
1624 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1625 }
1626 }
1627 double departPos = 0;
1628 double arrivalPos = 0;
1629 MSStoppingPlace* bs = nullptr;
1630 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1631 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1633 if (route == nullptr) {
1634 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1635 }
1636 myActiveRoute = route->getEdges();
1637 } else {
1639 }
1640 if (myActiveTransportablePlan->empty()) {
1641 double initialDepartPos = myVehicleParameter->departPos;
1643 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1644 }
1645 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1646 }
1647 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1648 if (myActiveRoute.empty()) {
1649 throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1650 }
1651 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1652 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1653 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1654 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1655 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1656 }
1657 }
1658 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1659 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1660 myActiveTransportablePlan->push_back(new MSStageWalking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1661 myParamStack.push_back(myActiveTransportablePlan->back());
1664 }
1665 myActiveRoute.clear();
1666 } catch (ProcessError&) {
1668 throw;
1669 }
1670 } else { // parse walks from->to as person trips
1671 addPersonTrip(attrs);
1672 }
1673}
1674
1675double
1676MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1677 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1678 if (value == "") {
1679 return pos;
1680 }
1681 std::string error;
1683 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1684 if (dpd != DepartPosLatDefinition::GIVEN) {
1686 if (lane == nullptr) {
1687 throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1688 }
1689 const double usableWidth = lane->getWidth() - 0.5;
1690 switch (dpd) {
1692 pos = -usableWidth / 2;
1693 break;
1695 pos = usableWidth / 2;
1696 break;
1698 pos = 0;
1699 break;
1705 break;
1706 default:
1707 break;
1708 }
1709 }
1710 } else {
1711 throw ProcessError(error);
1712 }
1713 return pos;
1714}
1715
1716
1717void
1718MSRouteHandler::addTransportable(const SUMOSAXAttributes& /*attrs*/, const bool isPerson) {
1720 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1721 const std::string error = TLF("The type '%' for % '%' is not known.", myVehicleParameter->vtypeid, myActiveTypeName, myVehicleParameter->id);
1723 throw ProcessError(error);
1724 }
1726}
1727
1728
1729void
1731 try {
1732 myActiveRoute.clear();
1733 const std::string cid = myVehicleParameter->id;
1734 bool ok = true;
1735 const MSEdge* from = nullptr;
1736 const MSEdge* to = nullptr;
1737 MSStoppingPlace* cs = nullptr;
1738
1739 double speed;
1741 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1742 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1743 if (!ok) {
1744 throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1745 }
1746 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1747 speed = vtype->getMaxSpeed();
1748 } else { // default speed value
1750 }
1751 if (speed <= 0) {
1752 throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1753 }
1754 // values from preceding stage:
1755 const MSEdge* preEdge = nullptr;
1756 double prePos = 0;
1757 if (!myActiveTransportablePlan->empty()) {
1758 preEdge = myActiveTransportablePlan->back()->getDestination();
1759 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1760 }
1761 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1762 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1763
1764 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1765 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1766 } else {
1767 // set 'from':
1768 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1769 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1770 from = MSEdge::dictionary(fromID);
1771 if (from == nullptr) {
1772 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1773 }
1774 if (preEdge != nullptr && preEdge != from) {
1775 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1776 }
1777 } else if (preEdge == nullptr) {
1778 throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1779 } else {
1780 from = preEdge;
1781 }
1782 // set 'to':
1783 if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1784 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1785 to = MSEdge::dictionary(toID);
1786 if (to == nullptr) {
1787 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1788 }
1789 } else {
1790 const std::string description = "container '" + cid + "' transhipping from edge '" + from->getID() + "'";
1791 cs = retrieveStoppingPlace(attrs, " " + description);
1792 if (cs != nullptr) {
1793 to = &cs->getLane().getEdge();
1794 } else {
1795 throw ProcessError(TLF("Inconsistent tranship for container '%', needs either: 'edges', 'to', 'containerStop' (or any other stopping place)", cid));
1796 }
1797 }
1798 myActiveRoute.push_back(from);
1799 myActiveRoute.push_back(to);
1800 }
1801 if (myActiveRoute.empty()) {
1802 throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1803 }
1804 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1806 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1807 }
1808 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1809 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1810 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1811 myParamStack.push_back(myActiveTransportablePlan->back());
1812 myActiveRoute.clear();
1813 } catch (ProcessError&) {
1815 throw;
1816 }
1817}
1818
1819
1820void
1822 for (const auto& edge : MSEdge::getAllEdges()) {
1823 if (edge->isNormal() || MSGlobals::gUsingInternalLanes) {
1824 for (MSLane* lane : edge->getLanes()) {
1825 Boundary b = lane->getShape().getBoxBoundary();
1826 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1827 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1828 tree->Insert(cmin, cmax, lane);
1829 }
1830 }
1831 }
1832}
1833
1834
1835SumoRNG*
1837 return &myParsingRNG;
1838}
1839
1840
1841MSEdge*
1842MSRouteHandler::retrieveEdge(const std::string& id) {
1843 return MSEdge::dictionary(id);
1844}
1845
1846
1847/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
#define JUNCTION_TAZ_MISSING_HELP
Definition MapMatcher.h:30
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
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
const long long int VTYPEPARS_MAXSPEED_SET
const long long int VTYPEPARS_VEHICLECLASS_SET
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
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_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_PEDESTRIAN
pedestrian
const double DEFAULT_CONTAINER_TRANSHIP_SPEED
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const long long int VEHPARS_FORCE_REROUTE
DepartPosLatDefinition
Possible ways to choose the lateral departure position.
@ RANDOM
The lateral position is chosen randomly.
@ RIGHT
At the rightmost side of the lane.
@ GIVEN
The position is given.
@ LEFT
At the leftmost side of the lane.
@ FREE
A free lateral position is chosen.
@ CENTER
At the center of the lane.
@ RANDOM_FREE
If a fixed number of random choices fails, a free lateral position is chosen.
@ RANDOM
A random position is chosen.
const long long int VEHPARS_ROUTE_SET
const long long int VEHPARS_TO_TAZ_SET
const long long int VEHPARS_DEPARTPOS_SET
const long long int VEHPARS_ARRIVALPOS_SET
const int STOP_INDEX_REPEAT
const long long int VEHPARS_FROM_TAZ_SET
const int STOP_END_SET
const double MIN_STOP_LENGTH
@ BEGIN
The departure is at simulation start.
@ 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_CONTAINER_STOP
A container stop.
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_BUS_STOP
A bus stop.
@ 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_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_LANE
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_LON
@ SUMO_ATTR_REFID
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_VIALONLAT
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_REPLACED_AT_TIME
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_VIAXY
@ SUMO_ATTR_Y
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_DEPARTPOS_LAT
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_TO_JUNCTION
@ SUMO_ATTR_X
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_ACTTYPE
@ 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_PERIOD
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_REPLACED_ON_INDEX
@ 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_INTENDED
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_CYCLETIME
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition StdDefs.h:82
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
Writes the state of the tls to a file (in each second)
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
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 MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1086
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
static void parseEdgesList(const std::string &desc, ConstMSEdgeVector &into, const std::string &rid)
Parses the given string assuming it contains a list of edge ids divided by spaces.
Definition MSEdge.cpp:1110
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:947
const MSJunction * getToJunction() const
Definition MSEdge.h:418
double getLength() const
return the length of the edge
Definition MSEdge.h:685
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1047
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:937
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gCheckRoutes
Definition MSGlobals.h:91
static bool gStateLoaded
Information whether a state has been loaded.
Definition MSGlobals.h:103
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
const SUMOVehicleParameter * getFlowPars(const std::string &id) const
return parameters for the given flow
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
SUMOTime computeRandomDepartOffset() const
compute (optional) random offset to the departure time
Representation of a lane in the micro simulation.
Definition MSLane.h:84
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2414
bool isInternal() const
Definition MSLane.cpp:2545
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
double getWidth() const
Returns the lane's width.
Definition MSLane.h:635
The simulated network and simulation perfomer.
Definition MSNet.h:89
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:185
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:471
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:481
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition MSNet.cpp:1198
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1380
bool hasContainers() const
Returns whether containers are simulated.
Definition MSNet.h:411
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:395
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:431
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:378
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1189
static const double RANDOM_POS_LAT
magic value to encode randomized lateral offset for persons when starting a walk
Definition MSPModel.h:68
static const double UNSPECIFIED_POS_LAT
the default lateral offset for persons when starting a walk
Definition MSPModel.h:65
void closePerson() override
Ends the processing of a person.
RandomDistributor< ConstMSRoutePtr > * myCurrentRouteDistribution
The currently parsed distribution of routes (probability->route)
void addRideOrTransport(const SUMOSAXAttributes &attrs, const SumoXMLTag modeTag)
Processing of a transport.
void closeContainerFlow() override
Ends the processing of a containerFlow.
void openFlow(const SUMOSAXAttributes &attrs) override
opens a flow for reading
ConstMSRoutePtr addVehicleStopsToImplicitRoute(ConstMSRoutePtr route, bool isPermanent)
adapt implicit route (edges derived from stops) to additional vehicle-stops
void addWalk(const SUMOSAXAttributes &attrs) override
add a fully specified walk
void addTransport(const SUMOSAXAttributes &attrs) override
Processing of a transport.
void deleteActivePlanAndVehicleParameter()
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void initLaneTree(NamedRTree *tree) override
bool myAmLoadingState
whether a state file is being loaded
bool myStartTriggeredInFlow
whether we are loading a personFlow that is starting triggered in a vehicle flow
void resetActivePlanAndVehicleParameter()
reset MSTransportablePlans after transportable tag closes
SUMOTime myActiveRoutePeriod
bool myHaveVia
Wether an object with 'via'-attribute is being parsed.
int addFlowTransportable(SUMOTime depart, MSVehicleType *type, const std::string &baseID, int i)
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void closeTransportable()
ends the processing of a transportable (as person or container)
MSEdge * retrieveEdge(const std::string &id) override
MSStoppingPlace * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, SUMOVehicleParameter::Stop *stopParam=nullptr)
Parse destination stop.
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
void openRoute(const SUMOSAXAttributes &attrs) override
opens a route for reading
void closeVehicleTypeDistribution() override
closes (ends) the building of a distribution
void addTranship(const SUMOSAXAttributes &attrs) override
Processing of a tranship.
void closeRoute(const bool mayBeDisconnected=false) override
closes (ends) the building of a route.
static SumoRNG myParsingRNG
A random number generator used to choose from vtype/route distributions and computing the speed facto...
void parseFromViaTo(SumoXMLTag tag, const SUMOSAXAttributes &attrs)
Called for parsing from and to and the corresponding taz attributes.
void closeFlow() override
Ends the processing of a flow.
MSTransportable::MSTransportablePlan * myActiveTransportablePlan
The plan of the current transportable (person or container)
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
std::string myCurrentRouteDistributionID
The id of the currently parsed route distribution.
RandomDistributor< MSVehicleType * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
void closeContainer() override
Ends the processing of a container.
SUMOTime myActiveRouteReplacedAtTime
The time at which this route was replaced (from vehroute-output)
void closeTrip() override
Ends the processing of a trip.
void openTrip(const SUMOSAXAttributes &attrs) override
opens a trip for reading
void addPersonTrip(const SUMOSAXAttributes &attrs) override
add a routing request for a walking or intermodal person
ConstMSEdgeVector myActiveRoute
The current route.
int myActiveRouteRepeat
number of repetitions of the active route
ObjectTypeEnum myActiveType
The type of the current object.
void closePersonFlow() override
Ends the processing of a personFlow.
int myActiveRouteReplacedIndex
The index at which this route was replaced (from vehroute-output)
void closeRouteDistribution() override
closes (ends) the building of a distribution
MSRouteHandler(const std::string &file, bool addVehiclesDirectly)
standard constructor
std::string myScaleSuffix
prefix when copying vehicles with –scale
ObjectTypeEnum
enum for object type
double interpretDepartPosLat(const std::string &value, int departLane, const std::string &element)
virtual ~MSRouteHandler()
standard destructor
bool myAddVehiclesDirectly
Information whether vehicles shall be directly added to the network or kept within the buffer.
bool myReplayRerouting
whether loaded rerouting events shall be replayed
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs) override
opens a type distribution for reading
Parameterised * addStop(const SUMOSAXAttributes &attrs) override
Processing of a stop.
virtual void closeVehicle() override
Ends the processing of a vehicle (note: is virtual because is reimplemented in MSStateHandler)
void openRouteFlow(const SUMOSAXAttributes &attrs) override
opens a route flow for reading
void openRouteDistribution(const SUMOSAXAttributes &attrs) override
opens a route distribution for reading
void addRide(const SUMOSAXAttributes &attrs) override
Processing of a ride.
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const MSEdge *fromEdge, const MSEdge *&toEdge, double &departPos, double &arrivalPos, MSStoppingPlace *&bs, const MSStage *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
bool myActiveRoutePermanent
whether the active route is stored indefinitely (used by state loader)
std::string myActiveTypeName
The name of the current object type.
void closeVType() override
Ends the processing of a vehicle type.
void addTransportable(const SUMOSAXAttributes &attrs, const bool isPerson) override
Processing of a person.
void closeTransportableFlow()
ends the flow of a transportable
void setReroute(bool reroute=true)
Definition MSRoute.h:221
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:125
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:206
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:109
static RandomDistributor< ConstMSRoutePtr > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition MSRoute.cpp:161
void setPeriod(SUMOTime period)
sets the period
Definition MSRoute.h:198
const MSEdge * getDestination() const
returns the destination edge
Definition MSStage.cpp:65
virtual double getArrivalPos() const
Definition MSStage.h:94
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition MSStage.h:85
MSStageType getStageType() const
Definition MSStage.h:127
static const MSLane * checkDepartLane(const MSEdge *edge, SUMOVehicleClass svc, int laneIndex, const std::string &id)
interpret custom depart lane
const MSEdge * getEdge() const
Returns the current edge.
void setDepartPos(const double pos)
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
double getAccessPos(const MSEdge *edge, SumoRNG *rng=nullptr) const
the position on the given edge which is connected to this stop, -1 on failure
int getLoadedNumber() const
Returns the number of build transportables.
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, SumoRNG *rng) const
Builds a new person.
bool add(MSTransportable *transportable)
Adds a single transportable, returns false if an id clash occurred.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
The class responsible for building and deletion of vehicles.
VehicleDefinitionSource
possible origins of a vehicle definition
double getScale() const
sets the demand scaling factor
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
int getQuota(double frac=-1, int loaded=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, ConstMSRoutePtr route, MSVehicleType *type, const bool ignoreStopErrors, const VehicleDefinitionSource source=ROUTEFILE, bool addRouteStops=true)
Builds a vehicle, increases the number of built vehicles.
const RandomDistributor< MSVehicleType * > * getVTypeDistribution(const std::string &typeDistID) const
return the vehicle type distribution with the given id
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false, bool wasKept=false)
Deletes the vehicle.
The car-following model and parameter.
double getDefaultProbability() const
Get the default probability of this vehicle type.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
static MSVehicleType * build(SUMOVTypeParameter &from)
Builds the microsim vehicle type described by the given parameter.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
const std::string & getID() const
Returns the name of the vehicle type.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
const SUMOVTypeParameter & getParameter() const
void check()
Checks whether vehicle type parameters may be problematic (Currently, only the value for the action s...
Provides utility functions for matching locations to edges (during route parsing)
Definition MapMatcher.h:45
void parseGeoEdges(const PositionVector &positions, bool geo, SUMOVehicleClass vClass, std::vector< const MSEdge * > &into, const std::string &rid, bool isFrom, bool &ok, bool forceEdge=false)
Definition MapMatcher.h:58
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
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)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
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.
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.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double scale
individual scaling factor (-1 for undefined)
SUMOVehicleClass vehicleClass
The vehicle's class.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual const MSRoute & getRoute() const =0
Returns the current route.
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.
SUMOTime until
The time at which the vehicle may continue its journey.
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
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
void incrementFlow(double scale, SumoRNG *rng=nullptr)
increment flow
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
int repetitionsDone
The number of times the vehicle was already inserted.
SUMOTime repetitionTotalOffset
The offset between depart and the time for the next vehicle insertions.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
SVCPermissions modes
The modes a person or container can use.
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.
std::string vTypes
The types of usable (auto-generated) vehicles for a person / container.
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.
int departEdge
(optional) The initial edge within the route of the vehicle
static bool parsePersonModes(const std::string &modes, const std::string &element, const std::string &id, SVCPermissions &modeSet, std::string &error)
Validates a given person modes value.
static bool parseDepartPosLat(const std::string &val, const std::string &element, const std::string &id, double &pos, DepartPosLatDefinition &dpd, std::string &error)
Validates a given departPosLat value.
std::string toTaz
The vehicle's destination zone (district)
static double interpretEdgePos(double pos, double maximumValue, SumoXMLAttr attr, const std::string &id, bool silent=false)
Interprets negative edge positions and fits them onto a given edge.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int arrivalEdge
(optional) The final edge within the route of the vehicle
std::string fromTaz
The vehicle's origin zone (district)
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
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
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