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-2026 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/****************************************************************************/
23// Parser and container for routes during their loading
24/****************************************************************************/
25#include <config.h>
26
27#include "MSRouteHandler.h"
35#include <microsim/MSEdge.h>
36#include <microsim/MSLane.h>
48
49// ===========================================================================
50// static members
51// ===========================================================================
52
53
54// ===========================================================================
55// method definitions
56// ===========================================================================
57MSRouteHandler::MSRouteHandler(const std::string& file, bool addVehiclesDirectly) :
58 SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes", true),
59 MapMatcher(OptionsCont::getOptions().getBool("mapmatch.junctions"),
60 OptionsCont::getOptions().getBool("mapmatch.taz"),
61 OptionsCont::getOptions().getFloat("mapmatch.distance"),
62 MsgHandler::getErrorInstance()),
63 myActiveRouteRepeat(0),
64 myActiveRoutePeriod(0),
65 myActiveRoutePermanent(false),
66 myActiveType(ObjectTypeEnum::UNDEFINED),
67 myHaveVia(false),
68 myActiveTransportablePlan(nullptr),
69 myAddVehiclesDirectly(addVehiclesDirectly),
70 myCurrentVTypeDistribution(nullptr),
71 myCurrentRouteDistribution(nullptr),
72 myAmLoadingState(false),
73 myScaleSuffix(OptionsCont::getOptions().getString("scale-suffix")),
74 myReplayRerouting(OptionsCont::getOptions().getBool("replay-rerouting")),
75 myStartTriggeredInFlow(false) {
76 myActiveRoute.reserve(100);
77}
78
79
81
82
83void
94
95
96void
102
103
104void
106 const std::string element = toString(tag);
107 myActiveRoute.clear();
108 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
110 WRITE_WARNINGF(TL("Taz usage was requested but no taz present in % '%'!"), element, myVehicleParameter->id);
111 useTaz = false;
112 }
113 bool ok = true;
114 const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
117 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
118 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
119 if (type != nullptr) {
120 vClass = type->getParameter().vehicleClass;
121 }
122 }
123 // from-attributes
124 if ((useTaz || (!attrs.hasAttribute(SUMO_ATTR_FROM) && !attrs.hasAttribute(SUMO_ATTR_FROMXY) && !attrs.hasAttribute(SUMO_ATTR_FROMLONLAT))) &&
126 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION);
127 const std::string tazType = useJunction ? "junction" : "taz";
128 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROM_JUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok);
129 const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
130 if (fromTaz == nullptr) {
131 throw ProcessError("Source " + tazType + " '" + tazID + "' not known " + rid + "!"
132 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
133 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
134 throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges " + rid + "!");
135 } else {
136 myActiveRoute.push_back(fromTaz);
137 }
138 } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
139 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, vClass, myActiveRoute, rid, true, ok);
140 if (myMapMatchTAZ && ok) {
141 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
143 }
144 } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
145 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, myActiveRoute, rid, true, ok);
146 if (myMapMatchTAZ && ok) {
147 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
149 }
150 } else {
151 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok),
152 myActiveRoute, rid);
153 }
154 if (!ok) {
155 throw ProcessError();
156 }
157
158 // via-attributes
161 }
162 ConstMSEdgeVector viaEdges;
163 if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
164 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, vClass, viaEdges, rid, false, ok);
165 } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
166 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, viaEdges, rid, false, ok);
167 } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
168 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
169 const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
170 if (viaSink == nullptr) {
171 throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
172 } else {
173 viaEdges.push_back(viaSink);
174 }
175 }
176 } else {
177 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok),
178 viaEdges, rid);
179 }
180 if (!viaEdges.empty()) {
181 myHaveVia = true;
182 }
183 for (const MSEdge* e : viaEdges) {
184 myActiveRoute.push_back(e);
185 myVehicleParameter->via.push_back(e->getID());
186 }
187
188 // to-attributes
189 if ((useTaz || (!attrs.hasAttribute(SUMO_ATTR_TO) && !attrs.hasAttribute(SUMO_ATTR_TOXY) && !attrs.hasAttribute(SUMO_ATTR_TOLONLAT))) &&
191 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION);
192 const std::string tazType = useJunction ? "junction" : "taz";
193 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TO_JUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
194 const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
195 if (toTaz == nullptr) {
196 throw ProcessError("Sink " + tazType + " '" + tazID + "' not known " + rid + "!"
197 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
198 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
199 throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges " + rid + "!");
200 } else {
201 myActiveRoute.push_back(toTaz);
202 }
203 } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
204 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, vClass, myActiveRoute, rid, false, ok);
205 if (myMapMatchTAZ && ok) {
206 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
208 }
209 } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
210 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, vClass, myActiveRoute, rid, false, ok);
211 if (myMapMatchTAZ && ok) {
212 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
214 }
215 } else {
216 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
217 myActiveRoute, rid);
218 }
220 if (myVehicleParameter->routeid == "") {
222 }
223}
224
225
226void
228 try {
230 && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT && element != SUMO_TAG_PARAM) {
231 const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
232 throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
233 }
234 if (myVehicleParameter == nullptr) {
236 myHaveVia = false;
237 }
238 SUMORouteHandler::myStartElement(element, attrs);
239 switch (element) {
241 addTransportable(attrs, true);
242 break;
244 addTransportable(attrs, false);
245 break;
246 case SUMO_TAG_FLOW:
247 if (myVehicleParameter) {
248 parseFromViaTo((SumoXMLTag)element, attrs);
249 }
250 break;
251 case SUMO_TAG_TRIP:
252 parseFromViaTo((SumoXMLTag)element, attrs);
253 break;
254 default:
255 break;
256 }
257 } catch (ProcessError&) {
259 throw;
260 }
261}
262
263
264void
266 bool ok = true;
267 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
268 if (ok) {
270 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
271 std::vector<double> probs;
272 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
273 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
274 while (st.hasNext()) {
275 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
276 }
277 }
278 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
279 StringTokenizer st(vTypes);
280 int probIndex = 0;
281 while (st.hasNext()) {
282 const std::string& vtypeID = st.next();
284 if (dist != nullptr) {
285 const double distProb = ((int)probs.size() > probIndex ? probs[probIndex] : 1.) / dist->getOverallProb();
286 std::vector<double>::const_iterator probIt = dist->getProbs().begin();
287 for (MSVehicleType* const type : dist->getVals()) {
288 myCurrentVTypeDistribution->add(type, distProb * *probIt);
289 probIt++;
290 }
291 } else {
293 if (type == nullptr) {
294 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
295 }
296 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->getDefaultProbability());
297 myCurrentVTypeDistribution->add(type, prob);
298 }
299 probIndex++;
300 }
301 if (probs.size() > 0 && probIndex != (int)probs.size()) {
302 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
303 " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
304 }
305 }
306 }
307}
308
309
310void
312 if (myCurrentVTypeDistribution != nullptr) {
313 if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
316 return;
317 }
320 throw ProcessError(TLF("Vehicle type distribution '%' is empty.", myCurrentVTypeDistributionID));
321 }
322 if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
324 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", myCurrentVTypeDistributionID));
325 }
327 }
328}
329
330
331void
335 // check whether the id is really necessary
336 std::string rid;
337 if (myCurrentRouteDistribution != nullptr) {
339 rid = "distribution '" + myCurrentRouteDistributionID + "'";
340 } else if (myVehicleParameter != nullptr) {
341 // ok, a vehicle is wrapping the route,
342 // we may use this vehicle's id as default
343 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
344 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
345 WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
346 }
347 } else {
348 bool ok = true;
349 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
350 if (!ok) {
351 return;
352 }
353 rid = "'" + myActiveRouteID + "'";
354 }
355 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
356 rid = "for vehicle '" + myVehicleParameter->id + "'";
357 }
358 bool ok = true;
359 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
360 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
361 }
362 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
364 throw ProcessError(TLF("Invalid reference to route '%' in route %.", myActiveRouteRefID, rid));
365 }
368 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
372 // handle obsolete attribute name
374 myActiveRoutePermanent = attrs.getOpt<bool>(SUMO_ATTR_STATE, myActiveRouteID.c_str(), ok, false);
375 if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
376 WRITE_WARNING(TL("Attribute 'period' is deprecated for route. Use 'cycleTime' instead."));
377 }
378 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
379 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
380 WRITE_WARNING(TLF("Invalid cost for route '%'.", myActiveRouteID));
381 }
382}
383
384
385void
387 // Currently unused
388}
389
390
391void
393 // Currently unused
394}
395
396
397void
399 // Currently unsued
400}
401
402
403void
404MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
405 std::string type = "vehicle";
406 if (mayBeDisconnected) {
408 type = "flow";
409 } else {
410 type = "trip";
411 }
412 }
413
414 try {
415 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
416 if (mustReroute) {
417 // implicit route from stops
419 myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
420 }
421 }
422 if (myActiveRoute.size() == 0) {
423 delete myActiveRouteColor;
424 myActiveRouteColor = nullptr;
425 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
427 if (route != nullptr) {
429 }
430 myActiveRouteID = "";
432 return;
433 }
434 if (myVehicleParameter != nullptr) {
435 throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
436 } else {
437 throw ProcessError(TLF("Route '%' has no edges.", myActiveRouteID));
438 }
439 }
440 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
441 throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
442 }
443 if (myActiveRouteRepeat > 0) {
444 // duplicate route
446 auto tmpStops = myActiveRouteStops;
447
450 std::string errSuffix = ".";
451 if (myVehicleParameter != nullptr) {
454 if (vtype != nullptr) {
455 vClass = vtype->getVehicleClass();
456 errSuffix = TLF(" for vehicle '%' with vClass %.", myVehicleParameter->id, getVehicleClassNames(vClass));
457 }
458 }
459 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
460 if (tmpStops.size() == 0 || tmpStops.back().jump < 0) {
461 throw ProcessError(TLF("Disconnected route '%' when repeating. Last edge '%' is not connected to first edge '%'%",
462 myActiveRouteID, myActiveRoute.back()->getID(), myActiveRoute.front()->getID(), errSuffix));
463 }
464 }
465 }
466 for (int i = 0; i < myActiveRouteRepeat; i++) {
467 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
468 for (SUMOVehicleParameter::Stop stop : tmpStops) {
469 if (stop.until > 0) {
470 if (myActiveRoutePeriod <= 0) {
471 const std::string description = myVehicleParameter != nullptr
472 ? "for " + type + " '" + myVehicleParameter->id + "'"
473 : "'" + myActiveRouteID + "'";
474 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
475 }
476 stop.until += myActiveRoutePeriod * (i + 1);
477 }
478 if (stop.arrival > 0) {
479 if (myActiveRoutePeriod <= 0) {
480 const std::string description = myVehicleParameter != nullptr
481 ? "for " + type + " '" + myVehicleParameter->id + "'"
482 : "'" + myActiveRouteID + "'";
483 throw ProcessError(TLF("Cannot repeat stops with 'arrival' in route % because no cycleTime is defined.", description));
484 }
485 stop.arrival += myActiveRoutePeriod * (i + 1);
486 }
487 stop.index = STOP_INDEX_REPEAT;
488 myActiveRouteStops.push_back(stop);
489 }
490 }
491 if (myActiveRouteStops.size() > 0) {
492 // never jump on the last stop of a repeating route
493 myActiveRouteStops.back().jump = -1;
494 }
495 }
496 MSRoute* const route = new MSRoute(myActiveRouteID, myActiveRoute,
501 route->setCosts(myCurrentCosts);
502 route->setReroute(mustReroute);
503 myActiveRoute.clear();
504 ConstMSRoutePtr constRoute = std::shared_ptr<const MSRoute>(route);
505 if (!MSRoute::dictionary(myActiveRouteID, constRoute)) {
507 if (myVehicleParameter != nullptr) {
508 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
509 throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
510 } else {
511 throw ProcessError(TLF("A vehicle with id '%' already exists.", myVehicleParameter->id));
512 }
513 } else {
514 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myActiveRouteID));
515 }
516 }
517 } else {
518 if (myCurrentRouteDistribution != nullptr) {
520 }
521 }
522 myActiveRouteID = "";
523 myActiveRouteColor = nullptr;
524 myActiveRouteStops.clear();
526 } catch (ProcessError&) {
528 throw;
529 }
530}
531
532
533void
535 // check whether the id is really necessary
536 if (myVehicleParameter != nullptr) {
537 // ok, a vehicle is wrapping the route,
538 // we may use this vehicle's id as default
539 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
540 // we have to record this or we cannot remove the distribution later
542 } else {
543 bool ok = true;
544 myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
545 if (!ok) {
546 return;
547 }
548 }
550 std::vector<double> probs;
551 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
552 bool ok = true;
553 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
554 while (st.hasNext()) {
555 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
556 }
557 }
558 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
559 bool ok = true;
560 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
561 int probIndex = 0;
562 while (st.hasNext()) {
563 std::string routeID = st.next();
565 if (route == nullptr) {
566 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
567 }
568 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
569 myCurrentRouteDistribution->add(route, prob, false);
570 probIndex++;
571 }
572 if (probs.size() > 0 && probIndex != (int)probs.size()) {
573 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
574 " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
575 }
576 }
577}
578
579
580void
582 if (myCurrentRouteDistribution != nullptr) {
583 const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
584 if (MSGlobals::gStateLoaded && haveSameID) {
587 return;
588 }
589 if (haveSameID) {
591 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myCurrentRouteDistributionID));
592 }
595 throw ProcessError(TLF("Route distribution '%' is empty.", myCurrentRouteDistributionID));
596 }
599 }
600}
601
602
603void
605 // get nested route
606 const std::string embeddedRouteID = "!" + myVehicleParameter->id;
607 ConstMSRoutePtr route = nullptr;
608 if (myReplayRerouting) {
610 if (rDist != nullptr && rDist->getVals().size() > 0) {
611 route = rDist->getVals().front();
612 }
613 }
614 if (route == nullptr) {
615 route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
616 }
619 // let's check whether this vehicle had to depart before the simulation starts
622 return;
623 }
624 }
625
626 // get the vehicle's type
627 MSVehicleType* vtype = nullptr;
628
629 try {
630 if (myVehicleParameter->vtypeid != "") {
631 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
632 if (vtype == nullptr) {
633 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
634 }
635 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
636 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
637 }
638 } else {
639 // there should be one (at least the default one)
640 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
641 }
643 // if the route id was given, prefer that one
644 if (route != nullptr && !myAmLoadingState) {
645 WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
646 }
648 }
649 if (route == nullptr) {
650 // nothing found? -> error
651 if (myVehicleParameter->routeid != "") {
652 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
653 } else {
654 throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
655 }
656 }
657 myActiveRouteID = "";
658
659 } catch (ProcessError&) {
661 throw;
662 }
663 if (route->mustReroute()) {
665 if (myVehicleParameter->stops.size() > 0) {
666 route = addVehicleStopsToImplicitRoute(route, false);
667 }
668 }
672 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
673 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
674 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
675 }
676 }
680 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
681 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
682 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
683 }
684 }
685
686 // try to build the vehicle
687 SUMOVehicle* vehicle = nullptr;
688 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
690 try {
691 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
692 } catch (const ProcessError& e) {
693 myVehicleParameter = nullptr;
695 WRITE_WARNING(e.what());
696 vehControl.deleteVehicle(vehicle, true);
697 myVehicleParameter = nullptr;
698 vehicle = nullptr;
699 return;
700 } else {
701 throw;
702 }
703 }
704 const SUMOTime origDepart = myVehicleParameter->depart;
705 // maybe we do not want this vehicle to be inserted due to scaling
706 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
707 if (quota > 0) {
710 vehControl.addVehicle(myVehicleParameter->id, vehicle);
711 if (myReplayRerouting) {
713 if (rDist != nullptr) {
714 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
715 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
716 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
717 if (replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
718 // routing in the insertion step happens *after* insertion
720 } else {
722 }
723 }
724 }
725 }
726 int offset = 0;
727 for (int i = 1; i < quota; i++) {
730 }
732 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
733 while (vehControl.getVehicle(newPars->id) != nullptr) {
734 offset += 1;
735 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
736 }
739 // resample type
740 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
741 }
742 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
743 vehControl.addVehicle(newPars->id, vehicle);
744 }
745 myVehicleParameter = nullptr;
746 } else {
747 vehControl.deleteVehicle(vehicle, true);
748 myVehicleParameter = nullptr;
749 vehicle = nullptr;
750 }
751 } else {
752 // strange: another vehicle with the same id already exists
754 // and was not loaded while loading a simulation state
755 // -> error
756 std::string veh_id = myVehicleParameter->id;
758 std::string scaleWarning = "";
759 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
760 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
761 }
762 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
763 } else {
764 // ok, it seems to be loaded previously while loading a simulation state
765 vehicle = nullptr;
766 }
767 }
768 // check whether the vehicle shall be added directly to the network or
769 // shall stay in the internal buffer
770 if (vehicle != nullptr) {
773 }
774 }
775}
776
777
780 // the route was defined without edges and its current edges were
781 // derived from route-stops.
782 // We may need to add additional edges for the vehicle-stops
784 assert(route->getStops().size() > 0);
785 ConstMSEdgeVector edges = route->getEdges();
787 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
788 if (stop.index == 0) {
789 if (edges.front() != stopEdge ||
790 route->getStops().front().endPos < stop.endPos) {
791 edges.insert(edges.begin(), stopEdge);
792 }
793 } else if (stop.index == STOP_INDEX_END) {
794 if (edges.back() != stopEdge ||
795 route->getStops().back().endPos > stop.endPos) {
796 edges.push_back(stopEdge);
797 }
798 } else {
799 WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
800 }
801 }
802 ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
803 isPermanent, new RGBColor(route->getColor()), route->getStops());
804 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
805 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
806 }
807 return newRoute;
808}
809
810
811void
813 try {
814 if (myActiveTransportablePlan->size() == 0) {
815 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
816 error[0] = (char)::toupper((char)error[0]);
817 throw ProcessError(error);
818 }
819 // let's check whether this transportable had to depart before the simulation starts
823 return;
824 }
825 // type existence has been checked on opening
828 && type->getVehicleClass() != SVC_PEDESTRIAN
830 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
831 }
834 if (created > 0) {
836 } else {
838 }
839 } catch (ProcessError&) {
841 throw;
842 }
843}
844
845
846void
850
851
852void
856
857
858void
862
863
864void
868
869
870void
872 try {
873 const std::string fid = myVehicleParameter->id;
874 if (myActiveTransportablePlan->size() == 0) {
875 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
876 }
877 // let's check whether this transportable (person/container) had to depart before the simulation starts
881 return;
882 }
883 // instantiate all persons/containers of this flow
884 int i = 0;
886 std::string baseID = myVehicleParameter->id;
889 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
890 } else {
893 // type existence has been checked on opening
895 addFlowTransportable(t, type, baseID, i++);
896 }
897 }
898 }
899 } else {
902 // poisson: randomize first depart
904 }
905 for (; i < myVehicleParameter->repetitionNumber && (myVehicleParameter->repetitionNumber != std::numeric_limits<long long int>::max()
907 // type existence has been checked on opening
911 }
912 }
914 } catch (ProcessError&) {
916 throw;
917 }
919}
920
921
922int
923MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
924 try {
925 int numCreated = 0;
926 MSNet* const net = MSNet::getInstance();
929 //MSTransportableControl& pc = net->getPersonControl();
930 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
931 if (quota == 0) {
932 tc.addDiscarded();
933 }
934 for (int j = 0; j < quota; j++) {
935 if (i > 0 || j > 0) {
936 // copy parameter and plan because the transportable takes over responsibility
938 *copyParam = *myVehicleParameter;
939 myVehicleParameter = copyParam;
941 MSStage* lastStage = nullptr;
942 for (MSStage* const s : *myActiveTransportablePlan) {
943 copyPlan->push_back(s->clone());
944 if (lastStage != nullptr && s->getStageType() == MSStageType::WALKING && lastStage->getDestinationStop() != nullptr) {
945 MSStageMoving* walk = static_cast<MSStageMoving*>(copyPlan->back());
946 walk->setDepartPos(lastStage->getDestinationStop()->getAccessPos(walk->getEdge(), &myParsingRNG));
947 }
948 lastStage = s;
949 }
950 myActiveTransportablePlan = copyPlan;
952 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
953 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
954 }
955 }
956 myVehicleParameter->id = (baseID
957 + (i >= 0 ? "." + toString(i) : "")
958 + (j > 0 ? "." + toString(j) : ""));
959 if (MSGlobals::gStateLoaded && tc.get(myVehicleParameter->id) != nullptr) {
960 return numCreated;
961 }
966 numCreated++;
967 if (!tc.add(transportable)) {
968 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
969 delete transportable;
971 throw ProcessError(error);
972 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
973 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
974 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);
975 }
976 }
977 return numCreated;
978 } catch (ProcessError&) {
980 throw;
981 }
982}
983
984
985void
987 MSVehicleType* vehType = nullptr;
988 if (myCurrentVTypeRef.empty()) {
990 vehType->check();
991 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
992 const std::string id = vehType->getID();
993 delete vehType;
995 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
996 }
997 }
998 }
999 if (myCurrentVTypeDistribution != nullptr) {
1000 if (!myCurrentVTypeRef.empty()) {
1002 if (dist != nullptr) {
1003 const double distProb = (myCurrentVTypeProbability >= 0 ? myCurrentVTypeProbability : 1) / dist->getOverallProb();
1004 std::vector<double>::const_iterator probIt = dist->getProbs().begin();
1005 for (MSVehicleType* const type : dist->getVals()) {
1006 myCurrentVTypeDistribution->add(type, distProb * *probIt);
1007 probIt++;
1008 }
1009 return;
1010 } else {
1012 }
1013 }
1014 double probability = myCurrentVTypeProbability >= 0 ? myCurrentVTypeProbability : vehType->getDefaultProbability();
1015 myCurrentVTypeDistribution->add(vehType, probability);
1016 }
1017}
1018
1019
1020void
1024 delete myVehicleParameter;
1025 myVehicleParameter = nullptr;
1026 return;
1027 }
1028 // let's check whether vehicles had to depart before the simulation starts
1031 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
1032 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
1035 delete myVehicleParameter;
1036 myVehicleParameter = nullptr;
1037 return;
1038 }
1039 }
1040 }
1041 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
1042 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1043 }
1046 closeRoute(true);
1047 }
1049 if (route == nullptr) {
1050 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1051 }
1052 if (route->mustReroute()) {
1054 if (myVehicleParameter->stops.size() > 0) {
1055 route = addVehicleStopsToImplicitRoute(route, true);
1056 myVehicleParameter->routeid = route->getID();
1057 }
1058 }
1062 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
1063 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
1064 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1065 }
1066 }
1070 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
1071 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
1072 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1073 }
1074 }
1075 myActiveRouteID = "";
1076
1077 // check whether the vehicle shall be added directly to the network or
1078 // shall stay in the internal buffer
1080 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
1082 } else {
1084 delete myVehicleParameter;
1085 } else {
1086 throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
1087 }
1088 }
1089 }
1090 myVehicleParameter = nullptr;
1091}
1092
1093
1094void
1100
1101void
1105
1106void
1110
1111void
1113 if (myVehicleParameter == nullptr) {
1114 throw ProcessError(TLF("Cannot define % stage without %.", toString(modeTag), toString(modeTag)));
1115 }
1116 try {
1117 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1118 std::string agent = "person";
1119 std::string stop = "bus stop";
1121 agent = "container";
1122 stop = "container stop";
1123 }
1124
1125 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1127 throw ProcessError("Found " + mode + " inside " + agent + " element");
1128 }
1129 const std::string aid = myVehicleParameter->id;
1130 bool ok = true;
1131 const MSEdge* from = nullptr;
1132 const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, LINE_ANY);
1133 StringTokenizer st(desc);
1134 MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1135 MSEdge* to = nullptr;
1136 if (s != nullptr) {
1137 to = &s->getLane().getEdge();
1138 }
1139 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1140 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1141
1142 const SUMOVehicleParameter* startVeh = nullptr;
1143 const MSEdge* startVehFrom = nullptr;
1145 if (st.size() != 1) {
1146 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1147 }
1148 // agent starts
1150 const std::string vehID = st.front();
1151 SUMOVehicle* sVeh = vehControl.getVehicle(vehID);
1152 if (sVeh == nullptr) {
1153 if (MSNet::getInstance()->hasFlow(vehID)) {
1154 startVeh = MSNet::getInstance()->getInsertionControl().getFlowPars(vehID);
1155 if (startVeh != nullptr) {
1156 ConstMSRoutePtr const route = MSRoute::dictionary(startVeh->routeid);
1157 startVehFrom = route->getEdges().front();
1158 // flows are inserted at the end of the time step so we
1159 // do delay the pedestrian event by one time step
1160 myVehicleParameter->depart = startVeh->depart + DELTA_T;
1162 }
1163 }
1164 } else {
1165 startVeh = &sVeh->getParameter();
1166 startVehFrom = sVeh->getRoute().getEdges().front();
1167 myVehicleParameter->depart = startVeh->depart;
1168 }
1169 if (startVeh == nullptr) {
1170 if (mySkippedVehicles.count(vehID) == 0) {
1171 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1172 }
1173 // we cannot simply throw here because we need to parse the rest of the person (just to discard it)
1174 from = MSEdge::getAllEdges().front(); // a dummy edge to keep parsing active
1175 } else if (startVeh->departProcedure == DepartDefinition::TRIGGERED) {
1176 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1177 }
1178 }
1179
1180 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1181 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1182 from = MSEdge::dictionary(fromID);
1183 if (from == nullptr) {
1184 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1185 }
1186 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1187 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1188 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1189 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1190 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1191 if (!(stopWithAccess || transferAtJunction)) {
1192 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1193 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1194 }
1195 }
1196 if (startVeh != nullptr && startVehFrom != from) {
1197 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1198 "' (edge '" + fromID + "' != edge '" + startVehFrom->getID() + "').");
1199 }
1200 } else if (startVeh != nullptr) {
1201 from = startVehFrom;
1202 }
1203 if (myActiveTransportablePlan->empty()) {
1204 if (from == nullptr) {
1205 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1206 } else {
1208 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1209 }
1210 }
1211 // given attribute may override given stopping place due access requirements
1212 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1213 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1214 to = MSEdge::dictionary(toID);
1215 if (to == nullptr) {
1216 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1217 }
1218 }
1219 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1220 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1221 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1222 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1223 MSStageDriving* stage = new MSStageDriving(from, to, s, arrivalPos, 0.0, st.getVector(), group, intendedVeh, intendedDepart);
1224 // for loading from saved state
1225 stage->setDeparted(attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1));
1226 stage->setEnded(attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1));
1227 stage->setVehicleID(attrs.getOpt<std::string>(SUMO_ATTR_VEHICLE, nullptr, ok, ""));
1228 stage->setVehicleDistance(attrs.getOpt<double>(SUMO_ATTR_ROUTELENGTH, nullptr, ok, -1));
1229 myActiveTransportablePlan->push_back(stage);
1230 myParamStack.push_back(stage);
1231 } catch (ProcessError&) {
1233 throw;
1234 }
1235}
1236
1238MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1239 MSStoppingPlace* toStop = nullptr;
1241 std::string id;
1242 bool ok = SUMOVehicleParserHelper::parseStopTag(attrs, stopParam, tag, id);
1243 if (tag != SUMO_TAG_NOTHING) {
1244 toStop = MSNet::getInstance()->getStoppingPlace(id, tag);
1245 if (toStop == nullptr) {
1246 ok = false;
1247 WRITE_ERROR(TLF("The % '%' is not known%.", toString(tag), id, errorSuffix));
1248 }
1249 }
1250 if (!ok && MSGlobals::gCheckRoutes) {
1251 throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1252 }
1253 return toStop;
1254}
1255
1258 Parameterised* result = nullptr;
1259 try {
1260 std::string errorSuffix;
1262 errorSuffix = " in person '" + myVehicleParameter->id + "'";
1264 errorSuffix = " in container '" + myVehicleParameter->id + "'";
1265 } else if (myVehicleParameter != nullptr) {
1266 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'";
1267 } else {
1268 errorSuffix = " in route '" + myActiveRouteID + "'";
1269 }
1271 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1272 if (!ok) {
1274 throw ProcessError();
1275 }
1276 return result;
1277 }
1278 const MSEdge* edge = nullptr;
1279 // patch chargingStation stop on a parkingArea
1280 if (stop.chargingStation != "") {
1282 const MSParkingArea* pa = cs->getParkingArea();
1283 if (pa != nullptr) {
1284 stop.parkingarea = pa->getID();
1286 }
1287 }
1288 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1289 // if one of the previous stops is defined
1290 if (toStop != nullptr) {
1291 const MSLane& l = toStop->getLane();
1292 stop.lane = l.getID();
1293 if ((stop.parametersSet & STOP_END_SET) == 0) {
1294 stop.endPos = toStop->getEndLanePosition();
1295 } else {
1296 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1297 }
1298 stop.startPos = toStop->getBeginLanePosition();
1299 edge = &l.getEdge();
1300 } else {
1301 // no, the lane and the position should be given directly
1302 // get the lane
1303 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1304 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1305 if (ok && stop.edge != "") { // edge is given directly
1306 edge = MSEdge::dictionary(stop.edge);
1307 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1308 throw ProcessError(TLF("The edge '%' for a stop is not known%.", stop.edge, errorSuffix));
1309 }
1310 } else if (ok && stop.lane != "") { // lane is given directly
1311 MSLane* stopLane = MSLane::dictionary(stop.lane);
1312 if (stopLane == nullptr) {
1313 // check for opposite-direction stop
1314 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1315 if (stopLane != nullptr) {
1316 edge = MSEdge::dictionary(stop.edge);
1317 }
1318 } else {
1319 edge = &stopLane->getEdge();
1320 }
1321 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1322 throw ProcessError(TLF("The lane '%' for a stop is not known%.", stop.lane, errorSuffix));
1323 }
1324 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
1325 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
1326 Position pos;
1327 bool geo = false;
1328 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
1329 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
1330 } else {
1331 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
1332 geo = true;
1333 }
1334 PositionVector positions;
1335 positions.push_back(pos);
1336 ConstMSEdgeVector geoEdges;
1338 auto& vc = MSNet::getInstance()->getVehicleControl();
1339 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
1340 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1341 if (type != nullptr) {
1342 vClass = type->getParameter().vehicleClass;
1343 }
1344 }
1345 parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok, true);
1346 if (ok) {
1347 edge = geoEdges.front();
1348 if (geo) {
1350 }
1352 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
1353 } else {
1354 throw ProcessError(TLF("Could not map stop position '%' to the network%.", pos, errorSuffix));
1355 }
1356 } else {
1357 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1358 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1359 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1360 edge = &toStop->getLane().getEdge();
1361 stop.lane = toStop->getLane().getID();
1362 stop.endPos = toStop->getEndLanePosition();
1363 stop.startPos = toStop->getBeginLanePosition();
1364 } else { // use end of movement before definied as lane/edge
1365 edge = myActiveTransportablePlan->back()->getDestination();
1366 stop.lane = edge->getLanes()[0]->getID();
1367 stop.endPos = myActiveTransportablePlan->back()->unspecifiedArrivalPos() ?
1369 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1370 }
1371 } else {
1372 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);
1374 throw ProcessError(msg);
1375 } else {
1376 WRITE_WARNING(msg);
1377 return result;
1378 }
1379 }
1380 }
1381 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1382 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1383 WRITE_WARNINGF(TL("Deprecated attribute 'pos' in description of stop%."), errorSuffix);
1384 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1385 }
1386 if (stop.endPos < 0) {
1387 stop.endPos += edge->getLength();
1388 }
1389 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1390 if (!myAmLoadingState) {
1391 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1393 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1394 throw ProcessError(TLF("Invalid start or end position for stop on %'%.",
1395 stop.lane != "" ? ("lane '" + stop.lane) : ("edge '" + stop.edge), errorSuffix));
1396 }
1397 }
1398 }
1399 stop.edge = edge->getID();
1401 if (myActiveTransportablePlan->empty()) {
1402 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1404 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1406 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1407 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1408 if (myActiveTransportablePlan->back()->getDestination()->isTazConnector()) {
1409 myActiveTransportablePlan->back()->setDestination(edge, toStop);
1410 } else if (myActiveTransportablePlan->back()->getJumpDuration() < 0) {
1411 throw ProcessError(TLF("Disconnected plan for % '%' (%!=%).", myActiveTypeName, myVehicleParameter->id,
1412 edge->getID(), myActiveTransportablePlan->back()->getDestination()->getID()));
1413 }
1414 }
1415 // transporting veh stops somewhere
1416 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1418 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1419 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1420 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1421 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1422 WRITE_WARNINGF(TL("Disconnected plan for % '%' (stop range %-% does not cover previous arrival position %)."),
1424 }
1425 }
1426 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1427 double pos = (stop.startPos + stop.endPos) / 2.;
1428 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getJumpDuration() < 0) {
1429 pos = myActiveTransportablePlan->back()->unspecifiedArrivalPos() ?
1431 }
1432 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false, stop.jump));
1433 result = myActiveTransportablePlan->back();
1434
1435 } else if (myVehicleParameter != nullptr) {
1436 myVehicleParameter->stops.push_back(stop);
1437 result = &myVehicleParameter->stops.back();
1438 } else {
1439 myActiveRouteStops.push_back(stop);
1440 result = &myActiveRouteStops.back();
1441 }
1442 if (myInsertStopEdgesAt >= 0) {
1443 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1444 if (edge->isInternal()) {
1445 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1448 }
1451 } else {
1452 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1454 }
1455 } else if (myHaveVia) {
1456 // vias were loaded, check for consistency
1457 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1458 WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'."),
1460 }
1461 }
1462 } catch (ProcessError&) {
1464 throw;
1465 }
1466 return result;
1467}
1468
1469
1470void
1471MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1472 const MSEdge* fromEdge, const MSEdge*& toEdge,
1473 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1474 const MSStage* const lastStage, bool& ok) {
1475 try {
1476 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1477
1478 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1479 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."));
1480 }
1481 departPos = 0.;
1482 if (lastStage != nullptr) {
1483 if (lastStage->getDestinationStop() != nullptr) {
1484 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge, &myParsingRNG);
1485 } else if (lastStage->getDestination() == fromEdge) {
1486 departPos = lastStage->getArrivalPos();
1487 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1488 departPos = fromEdge->getLength();
1489 }
1490 }
1491
1492 bs = retrieveStoppingPlace(attrs, " " + description);
1493 if (bs != nullptr) {
1494 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1495 if (arrivalPos < 0) {
1496 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1497 }
1499 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1500 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1501 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1502 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1503 arrivalPos = arrPos;
1504 } else {
1505 WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1506 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1507 }
1508 }
1509 } else {
1510 if (toEdge == nullptr) {
1511 throw ProcessError(TLF("No destination edge for %.", description));
1512 }
1515 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1516 } else {
1517 arrivalPos = toEdge->getLength() / 2.;
1518 }
1519 }
1520 } catch (ProcessError&) {
1522 throw;
1523 }
1524}
1525
1526
1527void
1529 if (myVehicleParameter == nullptr) {
1530 throw ProcessError(TL("Cannot define person stage without person."));
1531 }
1532 try {
1533 myActiveRoute.clear();
1534 bool ok = true;
1535 const char* const id = myVehicleParameter->id.c_str();
1536 const MSEdge* from = nullptr;
1537 const MSEdge* to = nullptr;
1542 from = myActiveRoute.front();
1543 } else if (myActiveTransportablePlan->empty()) {
1544 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1545 } else {
1546 from = myActiveTransportablePlan->back()->getDestination();
1547 }
1550 to = myActiveRoute.back();
1551 } // else, to may also be derived from stopping place
1552
1553 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1554 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1555 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1556 }
1557
1558 double departPos = 0;
1559 double arrivalPos = 0;
1560 MSStoppingPlace* stoppingPlace = nullptr;
1561 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1562
1563 SVCPermissions modeSet = 0;
1564 if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
1565 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1566 std::string errorMsg;
1567 // try to parse person modes
1568 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1569 throw InvalidArgument(errorMsg);
1570 }
1571 } else {
1572 modeSet = myVehicleParameter->modes;
1573 }
1574 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1576 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, myVehicleParameter->vTypes);
1577 for (StringTokenizer st(types); st.hasNext();) {
1578 const std::string vtypeid = st.next();
1579 const MSVehicleType* const vType = vehControl.getVType(vtypeid);
1580 if (vType == nullptr) {
1581 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1582 }
1583 modeSet |= (vType->getVehicleClass() == SVC_BICYCLE) ? SVC_BICYCLE : SVC_PASSENGER;
1584 }
1585 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1586 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1587 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1588 }
1589 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1590 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1591 if (ok) {
1592 if (myActiveTransportablePlan->empty()) {
1593 double initialDepartPos = myVehicleParameter->departPos;
1595 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1596 }
1597 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1598 }
1600 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1601 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1602 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1603 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1604 myParamStack.push_back(myActiveTransportablePlan->back());
1607 }
1608 }
1609 myActiveRoute.clear();
1610 } catch (ProcessError&) {
1612 throw;
1613 }
1614}
1615
1616
1617void
1619 if (myVehicleParameter == nullptr) {
1620 throw ProcessError(TL("Cannot define person stage without person."));
1621 }
1622 myActiveRouteID = "";
1624 try {
1625 myActiveRoute.clear();
1626 bool ok = true;
1627 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1628 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1629 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1630 }
1631 double speed = -1; // default to vType speed
1632 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1633 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1634 if (speed <= 0) {
1635 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1636 }
1637 }
1638 double departPos = 0;
1639 double arrivalPos = 0;
1640 MSStoppingPlace* bs = nullptr;
1641 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1642 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1644 if (route == nullptr) {
1645 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1646 }
1647 myActiveRoute = route->getEdges();
1648 } else {
1650 }
1651 if (myActiveTransportablePlan->empty()) {
1652 double initialDepartPos = myVehicleParameter->departPos;
1654 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1655 }
1656 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1657 }
1658 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1659 if (myActiveRoute.empty()) {
1660 throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1661 }
1662 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1663 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1664 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1665 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1666 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1667 }
1668 }
1669 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1670 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1671 MSStageWalking* stage = new MSStageWalking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID);
1672 stage->setDeparted(attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1));
1673 stage->setEnded(attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1));
1675 if (attrs.hasAttribute(SUMO_ATTR_EXITTIMES) && OptionsCont::getOptions().getBool("vehroute-output.exit-times")) {
1676 std::vector<SUMOTime>* exitTimes = new std::vector<SUMOTime>();
1677 for (const std::string& tStr : attrs.get<std::vector<std::string> >(SUMO_ATTR_EXITTIMES, nullptr, ok)) {
1678 exitTimes->push_back(string2time(tStr));
1679 }
1680 stage->setExitTimes(exitTimes);
1681 }
1684 }
1685 myActiveTransportablePlan->push_back(stage);
1686 myParamStack.push_back(stage);
1687 myActiveRoute.clear();
1688 } catch (ProcessError&) {
1690 throw;
1691 }
1692 } else { // parse walks from->to as person trips
1693 addPersonTrip(attrs);
1694 }
1695}
1696
1697double
1698MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1699 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1700 if (value == "") {
1701 return pos;
1702 }
1703 std::string error;
1705 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1706 if (dpd != DepartPosLatDefinition::GIVEN) {
1708 if (lane == nullptr) {
1709 throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1710 }
1711 const double usableWidth = lane->getWidth() - 0.5;
1712 switch (dpd) {
1714 pos = -usableWidth / 2;
1715 break;
1717 pos = usableWidth / 2;
1718 break;
1720 pos = 0;
1721 break;
1727 break;
1728 default:
1729 break;
1730 }
1731 }
1732 } else {
1733 throw ProcessError(error);
1734 }
1735 return pos;
1736}
1737
1738
1739void
1740MSRouteHandler::addTransportable(const SUMOSAXAttributes& /*attrs*/, const bool isPerson) {
1742 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1743 const std::string error = TLF("The type '%' for % '%' is not known.", myVehicleParameter->vtypeid, myActiveTypeName, myVehicleParameter->id);
1745 throw ProcessError(error);
1746 }
1748}
1749
1750
1751void
1753 try {
1754 myActiveRoute.clear();
1755 const std::string cid = myVehicleParameter->id;
1756 bool ok = true;
1757 const MSEdge* from = nullptr;
1758 const MSEdge* to = nullptr;
1759 MSStoppingPlace* cs = nullptr;
1760
1761 double speed;
1763 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1764 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1765 if (!ok) {
1766 throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1767 }
1768 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1769 speed = vtype->getMaxSpeed();
1770 } else { // default speed value
1772 }
1773 if (speed <= 0) {
1774 throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1775 }
1776 // values from preceding stage:
1777 const MSEdge* preEdge = nullptr;
1778 double prePos = 0;
1779 if (!myActiveTransportablePlan->empty()) {
1780 preEdge = myActiveTransportablePlan->back()->getDestination();
1781 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1782 }
1783 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1784 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1785
1786 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1787 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1788 } else {
1789 // set 'from':
1790 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1791 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1792 from = MSEdge::dictionary(fromID);
1793 if (from == nullptr) {
1794 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1795 }
1796 if (preEdge != nullptr && preEdge != from) {
1797 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1798 }
1799 } else if (preEdge == nullptr) {
1800 throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1801 } else {
1802 from = preEdge;
1803 }
1804 // set 'to':
1805 if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1806 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1807 to = MSEdge::dictionary(toID);
1808 if (to == nullptr) {
1809 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1810 }
1811 } else {
1812 const std::string description = "container '" + cid + "' transhipping from edge '" + from->getID() + "'";
1813 cs = retrieveStoppingPlace(attrs, " " + description);
1814 if (cs != nullptr) {
1815 to = &cs->getLane().getEdge();
1816 } else {
1817 throw ProcessError(TLF("Inconsistent tranship for container '%', needs either: 'edges', 'to', 'containerStop' (or any other stopping place)", cid));
1818 }
1819 }
1820 myActiveRoute.push_back(from);
1821 myActiveRoute.push_back(to);
1822 }
1823 if (myActiveRoute.empty()) {
1824 throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1825 }
1826 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1828 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1829 }
1830 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1831 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1832 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1833 myParamStack.push_back(myActiveTransportablePlan->back());
1834 myActiveRoute.clear();
1835 } catch (ProcessError&) {
1837 throw;
1838 }
1839}
1840
1841
1842void
1844 for (const auto& edge : MSEdge::getAllEdges()) {
1845 if (edge->isNormal() || MSGlobals::gUsingInternalLanes) {
1846 for (MSLane* lane : edge->getLanes()) {
1847 Boundary b = lane->getShape().getBoxBoundary();
1848 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1849 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1850 tree->Insert(cmin, cmax, lane);
1851 }
1852 }
1853 }
1854}
1855
1856
1857SumoRNG*
1859 return &myParsingRNG;
1860}
1861
1862
1863const SUMOVTypeParameter*
1864MSRouteHandler::getVTypeParameter(const std::string& refid) {
1865 const auto t = MSNet::getInstance()->getVehicleControl().getVType(refid);
1866 return t != nullptr ? &t->getParameter() : nullptr;
1867}
1868
1869
1870MSEdge*
1871MSRouteHandler::retrieveEdge(const std::string& id) {
1872 return MSEdge::dictionary(id);
1873}
1874
1875
1876/****************************************************************************/
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:287
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
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
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SUMOTime_MAX
Definition SUMOTime.h:34
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 std::string LINE_ANY
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_NOTHING
invalid tag, must be the last one
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ SUMO_TAG_TRANSPORT
@ SUMO_TAG_RIDE
@ 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_STARTED
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_VIA
@ SUMO_ATTR_REPLACED_AT_TIME
@ SUMO_ATTR_VIAXY
@ SUMO_ATTR_Y
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_DEPARTPOS_LAT
@ SUMO_ATTR_BUS_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_ROUTES
@ SUMO_ATTR_MODES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_EXITTIMES
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_GROUP
@ SUMO_ATTR_ENDED
@ 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_ROUTELENGTH
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_LAT
@ SUMO_ATTR_WALKFACTOR
@ SUMO_ATTR_VEHICLE
@ 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:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:127
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:115
PositionVector getShape(const bool closeShape) const
get position vector (shape) based on this boundary
Definition Boundary.cpp:444
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:133
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:121
Writes the state of the tls to a file (in each second)
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
const std::string & getFileName() const
returns the current file name
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
const MSParkingArea * getParkingArea() const
Get the parking area the charging station is placed on.
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1144
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:1168
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:1005
const MSJunction * getToJunction() const
Definition MSEdge.h:427
double getLength() const
return the length of the edge
Definition MSEdge.h:694
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:269
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:1105
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:995
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:632
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2528
bool isInternal() const
Definition MSLane.cpp:2659
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
double getWidth() const
Returns the lane's width.
Definition MSLane.h:661
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:201
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:495
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:505
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition MSNet.cpp:1320
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1521
bool hasContainers() const
Returns whether containers are simulated.
Definition MSNet.h:435
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:419
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:455
SUMOTime getStateLoaderTime() const
return the next time for route loading the time of state loading
Definition MSNet.h:358
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1311
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
A lane area vehicles can halt at.
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
Whether 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.
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.
SumoRNG * getRNG() override
const SUMOVTypeParameter * getVTypeParameter(const std::string &refid) override
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:224
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:128
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:209
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
static RandomDistributor< ConstMSRoutePtr > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition MSRoute.cpp:168
void setPeriod(SUMOTime period)
sets the period
Definition MSRoute.h:201
void setVehicleDistance(double dist)
restore further state during loading
void setVehicleID(const std::string vehID)
const MSEdge * getDestination() const
returns the destination edge
Definition MSStage.cpp:65
virtual double getArrivalPos() const
Definition MSStage.h:97
static const double ARRIVALPOS_UNSPECIFIED
sentinel value
Definition MSStage.h:72
void setDeparted(SUMOTime now)
logs beginning of stage
Definition MSStage.cpp:115
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition MSStage.h:88
MSStageType getStageType() const
Definition MSStage.h:138
void markSet(int what)
Definition MSStage.h:267
void setEnded(SUMOTime t)
sets end of stage
Definition MSStage.cpp:123
static const MSLane * checkDepartLane(const MSEdge *edge, SUMOVehicleClass svc, int laneIndex, const std::string &id)
interpret custom depart lane
void setTotalWaitingTime(SUMOTime t)
Restore waiting time when loading state.
const MSEdge * getEdge() const
Returns the current edge.
void setDepartPos(const double pos)
void setExitTimes(std::vector< SUMOTime > *exitTimes)
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.
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.
static MSVehicleType * build(SUMOVTypeParameter &from, const std::string &fileName="")
Builds the microsim vehicle type described by the given parameter.
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:48
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
const std::string & getID() const
Returns the id.
Definition Named.h:73
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::set< std::string > mySkippedVehicles
IDs of skipped vehicles to suppress errors for the triggered transportables within.
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
static SumoRNG myParsingRNG
A random number generator used to choose from vtype/route distributions and computing the speed facto...
StopParVector myActiveRouteStops
List of the stops on the parsed route.
std::string myCurrentVTypeRef
if the currently parsed vType is only a reference to an existing type, store the refId
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.
double myCurrentVTypeProbability
if the currently parsed vType is only a reference, store the probability here
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)
Structure representing possible vehicle parameter.
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:63
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.
ParkingType parking
whether the vehicle is removed from the net while stopping
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
int parametersSet
Information for the output which parameter were set.
SUMOTime jump
transfer time if there shall be a jump from this stop to the next route edge
SUMOTime until
The time at which the vehicle may continue its journey.
double endPos
The stopping position end.
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.
long long int repetitionsDone
The number of times the vehicle was already inserted.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
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 bool parseStopTag(const SUMOSAXAttributes &attrs, const SUMOVehicleParameter::Stop *stopParam, SumoXMLTag &tag, std::string &id)
parse named stopping place attrs (or use stopParam attrs) and return it's tag and id
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