Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSRouteHandler.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
22// Parser and container for routes during their loading
23/****************************************************************************/
24#include <config.h>
25
26#include "MSRouteHandler.h"
34#include <microsim/MSEdge.h>
35#include <microsim/MSLane.h>
45
46// ===========================================================================
47// static members
48// ===========================================================================
50
51
52// ===========================================================================
53// method definitions
54// ===========================================================================
55MSRouteHandler::MSRouteHandler(const std::string& file, bool addVehiclesDirectly) :
56 SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes", true),
57 MapMatcher(OptionsCont::getOptions().getBool("mapmatch.junctions"),
58 OptionsCont::getOptions().getFloat("mapmatch.distance"),
59 MsgHandler::getErrorInstance()),
60 myActiveRouteRepeat(0),
61 myActiveRoutePeriod(0),
62 myActiveRoutePermanent(false),
63 myActiveType(ObjectTypeEnum::UNDEFINED),
64 myHaveVia(false),
65 myActiveTransportablePlan(nullptr),
66 myAddVehiclesDirectly(addVehiclesDirectly),
67 myCurrentVTypeDistribution(nullptr),
68 myCurrentRouteDistribution(nullptr),
69 myAmLoadingState(false),
70 myScaleSuffix(OptionsCont::getOptions().getString("scale-suffix")),
71 myReplayRerouting(OptionsCont::getOptions().getBool("replay-rerouting")),
72 myStartTriggeredInFlow(false) {
73 myActiveRoute.reserve(100);
74}
75
76
78
79
80void
91
92
93void
99
100
101void
103 const std::string element = toString(tag);
104 myActiveRoute.clear();
105 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
107 WRITE_WARNINGF(TL("Taz usage was requested but no taz present in % '%'!"), element, myVehicleParameter->id);
108 useTaz = false;
109 }
110 bool ok = true;
111 const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
114 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
115 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
116 if (type != nullptr) {
117 vClass = type->getParameter().vehicleClass;
118 }
119 }
120 // from-attributes
121 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
123 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION);
124 const std::string tazType = useJunction ? "junction" : "taz";
125 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROM_JUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok);
126 const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
127 if (fromTaz == nullptr) {
128 throw ProcessError("Source " + tazType + " '" + tazID + "' not known " + rid + "!"
129 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
130 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
131 throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges " + rid + "!");
132 } else {
133 myActiveRoute.push_back(fromTaz);
134 }
135 } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
136 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, vClass, myActiveRoute, rid, true, ok);
137 } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
138 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, myActiveRoute, rid, true, ok);
139 } else {
140 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok),
141 myActiveRoute, rid);
142 }
143 if (!ok) {
144 throw ProcessError();
145 }
146
147 // via-attributes
150 }
151 ConstMSEdgeVector viaEdges;
152 if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
153 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, vClass, viaEdges, rid, false, ok);
154 } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
155 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, viaEdges, rid, false, ok);
156 } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
157 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
158 const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
159 if (viaSink == nullptr) {
160 throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
161 } else {
162 viaEdges.push_back(viaSink);
163 }
164 }
165 } else {
166 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok),
167 viaEdges, rid);
168 }
169 if (!viaEdges.empty()) {
170 myHaveVia = true;
171 }
172 for (const MSEdge* e : viaEdges) {
173 myActiveRoute.push_back(e);
174 myVehicleParameter->via.push_back(e->getID());
175 }
176
177 // to-attributes
178 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
180 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION);
181 const std::string tazType = useJunction ? "junction" : "taz";
182 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TO_JUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
183 const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
184 if (toTaz == nullptr) {
185 throw ProcessError("Sink " + tazType + " '" + tazID + "' not known " + rid + "!"
186 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
187 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
188 throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges " + rid + "!");
189 } else {
190 myActiveRoute.push_back(toTaz);
191 }
192 } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
193 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, vClass, myActiveRoute, rid, false, ok);
194 } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
195 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, vClass, myActiveRoute, rid, false, ok);
196 } else {
197 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
198 myActiveRoute, rid);
199 }
201 if (myVehicleParameter->routeid == "") {
203 }
204}
205
206
207void
209 try {
211 && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT && element != SUMO_TAG_PARAM) {
212 const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
213 throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
214 }
215 if (myVehicleParameter == nullptr) {
217 myHaveVia = false;
218 }
219 SUMORouteHandler::myStartElement(element, attrs);
220 switch (element) {
222 addTransportable(attrs, true);
223 break;
225 addTransportable(attrs, false);
226 break;
227 case SUMO_TAG_FLOW:
228 if (myVehicleParameter) {
229 parseFromViaTo((SumoXMLTag)element, attrs);
230 }
231 break;
232 case SUMO_TAG_TRIP:
233 parseFromViaTo((SumoXMLTag)element, attrs);
234 break;
235 default:
236 break;
237 }
238 } catch (ProcessError&) {
240 throw;
241 }
242}
243
244
245void
247 bool ok = true;
248 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
249 if (ok) {
251 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
252 std::vector<double> probs;
253 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
254 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
255 while (st.hasNext()) {
256 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
257 }
258 }
259 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
260 StringTokenizer st(vTypes);
261 int probIndex = 0;
262 while (st.hasNext()) {
263 const std::string& vtypeID = st.next();
265 if (dist != nullptr) {
266 const double distProb = ((int)probs.size() > probIndex ? probs[probIndex] : 1.) / dist->getOverallProb();
267 std::vector<double>::const_iterator probIt = dist->getProbs().begin();
268 for (MSVehicleType* const type : dist->getVals()) {
269 myCurrentVTypeDistribution->add(type, distProb * *probIt);
270 probIt++;
271 }
272 } else {
274 if (type == nullptr) {
275 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
276 }
277 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->getDefaultProbability());
278 myCurrentVTypeDistribution->add(type, prob);
279 }
280 probIndex++;
281 }
282 if (probs.size() > 0 && probIndex != (int)probs.size()) {
283 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
284 " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
285 }
286 }
287 }
288}
289
290
291void
293 if (myCurrentVTypeDistribution != nullptr) {
294 if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
296 return;
297 }
300 throw ProcessError(TLF("Vehicle type distribution '%' is empty.", myCurrentVTypeDistributionID));
301 }
302 if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
304 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", myCurrentVTypeDistributionID));
305 }
307 }
308}
309
310
311void
315 // check whether the id is really necessary
316 std::string rid;
317 if (myCurrentRouteDistribution != nullptr) {
319 rid = "distribution '" + myCurrentRouteDistributionID + "'";
320 } else if (myVehicleParameter != nullptr) {
321 // ok, a vehicle is wrapping the route,
322 // we may use this vehicle's id as default
323 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
324 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
325 WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
326 }
327 } else {
328 bool ok = true;
329 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
330 if (!ok) {
331 return;
332 }
333 rid = "'" + myActiveRouteID + "'";
334 }
335 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
336 rid = "for vehicle '" + myVehicleParameter->id + "'";
337 }
338 bool ok = true;
339 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
340 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
341 }
342 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
344 throw ProcessError(TLF("Invalid reference to route '%' in route %.", myActiveRouteRefID, rid));
345 }
348 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
352 // handle obsolete attribute name
354 myActiveRoutePermanent = attrs.getOpt<bool>(SUMO_ATTR_STATE, myActiveRouteID.c_str(), ok, false);
355 if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
356 WRITE_WARNING(TL("Attribute 'period' is deprecated for route. Use 'cycleTime' instead."));
357 }
358 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
359 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
360 WRITE_WARNING(TLF("Invalid cost for route '%'.", myActiveRouteID));
361 }
362}
363
364
365void
367 // Currently unused
368}
369
370
371void
373 // Currently unused
374}
375
376
377void
379 // Currently unsued
380}
381
382
383void
384MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
385 std::string type = "vehicle";
386 if (mayBeDisconnected) {
388 type = "flow";
389 } else {
390 type = "trip";
391 }
392 }
393
394 try {
395 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
396 if (mustReroute) {
397 // implicit route from stops
399 myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
400 }
401 }
402 if (myActiveRoute.size() == 0) {
403 delete myActiveRouteColor;
404 myActiveRouteColor = nullptr;
405 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
407 if (route != nullptr) {
409 }
410 myActiveRouteID = "";
412 return;
413 }
414 if (myVehicleParameter != nullptr) {
415 throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
416 } else {
417 throw ProcessError(TLF("Route '%' has no edges.", myActiveRouteID));
418 }
419 }
420 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
421 throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
422 }
423 if (myActiveRouteRepeat > 0) {
424 // duplicate route
426 auto tmpStops = myActiveRouteStops;
427
430 std::string errSuffix = ".";
431 if (myVehicleParameter != nullptr) {
434 if (vtype != nullptr) {
435 vClass = vtype->getVehicleClass();
436 errSuffix = TLF(" for vehicle '%' with vClass %.", myVehicleParameter->id, getVehicleClassNames(vClass));
437 }
438 }
439 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
440 if (tmpStops.size() == 0 || tmpStops.back().jump < 0) {
441 throw ProcessError(TLF("Disconnected route '%' when repeating. Last edge '%' is not connected to first edge '%'%",
442 myActiveRouteID, myActiveRoute.back()->getID(), myActiveRoute.front()->getID(), errSuffix));
443 }
444 }
445 }
446 for (int i = 0; i < myActiveRouteRepeat; i++) {
447 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
448 for (SUMOVehicleParameter::Stop stop : tmpStops) {
449 if (stop.until > 0) {
450 if (myActiveRoutePeriod <= 0) {
451 const std::string description = myVehicleParameter != nullptr
452 ? "for " + type + " '" + myVehicleParameter->id + "'"
453 : "'" + myActiveRouteID + "'";
454 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
455 }
456 stop.until += myActiveRoutePeriod * (i + 1);
457 }
458 if (stop.arrival > 0) {
459 if (myActiveRoutePeriod <= 0) {
460 const std::string description = myVehicleParameter != nullptr
461 ? "for " + type + " '" + myVehicleParameter->id + "'"
462 : "'" + myActiveRouteID + "'";
463 throw ProcessError(TLF("Cannot repeat stops with 'arrival' in route % because no cycleTime is defined.", description));
464 }
465 stop.arrival += myActiveRoutePeriod * (i + 1);
466 }
467 stop.index = STOP_INDEX_REPEAT;
468 myActiveRouteStops.push_back(stop);
469 }
470 }
471 if (myActiveRouteStops.size() > 0) {
472 // never jump on the last stop of a repeating route
473 myActiveRouteStops.back().jump = -1;
474 }
475 }
476 MSRoute* const route = new MSRoute(myActiveRouteID, myActiveRoute,
481 route->setCosts(myCurrentCosts);
482 route->setReroute(mustReroute);
483 myActiveRoute.clear();
484 ConstMSRoutePtr constRoute = std::shared_ptr<const MSRoute>(route);
485 if (!MSRoute::dictionary(myActiveRouteID, constRoute)) {
487 if (myVehicleParameter != nullptr) {
488 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
489 throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
490 } else {
491 throw ProcessError(TLF("A vehicle with id '%' already exists.", myVehicleParameter->id));
492 }
493 } else {
494 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myActiveRouteID));
495 }
496 }
497 } else {
498 if (myCurrentRouteDistribution != nullptr) {
500 }
501 }
502 myActiveRouteID = "";
503 myActiveRouteColor = nullptr;
504 myActiveRouteStops.clear();
506 } catch (ProcessError&) {
508 throw;
509 }
510}
511
512
513void
515 // check whether the id is really necessary
516 if (myVehicleParameter != nullptr) {
517 // ok, a vehicle is wrapping the route,
518 // we may use this vehicle's id as default
519 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
520 // we have to record this or we cannot remove the distribution later
522 } else {
523 bool ok = true;
524 myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
525 if (!ok) {
526 return;
527 }
528 }
530 std::vector<double> probs;
531 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
532 bool ok = true;
533 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
534 while (st.hasNext()) {
535 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
536 }
537 }
538 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
539 bool ok = true;
540 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
541 int probIndex = 0;
542 while (st.hasNext()) {
543 std::string routeID = st.next();
545 if (route == nullptr) {
546 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
547 }
548 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
549 myCurrentRouteDistribution->add(route, prob, false);
550 probIndex++;
551 }
552 if (probs.size() > 0 && probIndex != (int)probs.size()) {
553 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
554 " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
555 }
556 }
557}
558
559
560void
562 if (myCurrentRouteDistribution != nullptr) {
563 const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
564 if (MSGlobals::gStateLoaded && haveSameID) {
567 return;
568 }
569 if (haveSameID) {
571 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myCurrentRouteDistributionID));
572 }
575 throw ProcessError(TLF("Route distribution '%' is empty.", myCurrentRouteDistributionID));
576 }
579 }
580}
581
582
583void
585 // get nested route
586 const std::string embeddedRouteID = "!" + myVehicleParameter->id;
587 ConstMSRoutePtr route = nullptr;
588 if (myReplayRerouting) {
590 if (rDist != nullptr && rDist->getVals().size() > 0) {
591 route = rDist->getVals().front();
592 }
593 }
594 if (route == nullptr) {
595 route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
596 }
599 // let's check whether this vehicle had to depart before the simulation starts
601 return;
602 }
603 }
604
605 // get the vehicle's type
606 MSVehicleType* vtype = nullptr;
607
608 try {
609 if (myVehicleParameter->vtypeid != "") {
610 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
611 if (vtype == nullptr) {
612 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
613 }
614 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
615 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
616 }
617 } else {
618 // there should be one (at least the default one)
619 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
620 }
622 // if the route id was given, prefer that one
623 if (route != nullptr && !myAmLoadingState) {
624 WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
625 }
627 }
628 if (route == nullptr) {
629 // nothing found? -> error
630 if (myVehicleParameter->routeid != "") {
631 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
632 } else {
633 throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
634 }
635 }
636 myActiveRouteID = "";
637
638 } catch (ProcessError&) {
640 throw;
641 }
642 if (route->mustReroute()) {
644 if (myVehicleParameter->stops.size() > 0) {
645 route = addVehicleStopsToImplicitRoute(route, false);
646 }
647 }
651 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
652 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
653 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
654 }
655 }
659 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
660 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
661 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
662 }
663 }
664
665 // try to build the vehicle
666 SUMOVehicle* vehicle = nullptr;
667 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
669 try {
670 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
671 } catch (const ProcessError& e) {
672 myVehicleParameter = nullptr;
674 WRITE_WARNING(e.what());
675 vehControl.fixVehicleCounts();
676 return;
677 } else {
678 throw e;
679 }
680 }
681 const SUMOTime origDepart = myVehicleParameter->depart;
682 // maybe we do not want this vehicle to be inserted due to scaling
683 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
684 if (quota > 0) {
687 vehControl.addVehicle(myVehicleParameter->id, vehicle);
688 if (myReplayRerouting) {
690 if (rDist != nullptr) {
691 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
692 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
693 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
694 if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
695 // routing in the insertion step happens *after* insertion
697 } else {
699 }
700 }
701 }
702 }
703 int offset = 0;
704 for (int i = 1; i < quota; i++) {
707 }
709 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
710 while (vehControl.getVehicle(newPars->id) != nullptr) {
711 offset += 1;
712 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
713 }
716 // resample type
717 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
718 }
719 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
720 vehControl.addVehicle(newPars->id, vehicle);
721 }
722 myVehicleParameter = nullptr;
723 } else {
724 vehControl.deleteVehicle(vehicle, true);
725 myVehicleParameter = nullptr;
726 vehicle = nullptr;
727 }
728 } else {
729 // strange: another vehicle with the same id already exists
731 // and was not loaded while loading a simulation state
732 // -> error
733 std::string veh_id = myVehicleParameter->id;
735 std::string scaleWarning = "";
736 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
737 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
738 }
739 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
740 } else {
741 // ok, it seems to be loaded previously while loading a simulation state
742 vehicle = nullptr;
743 }
744 }
745 // check whether the vehicle shall be added directly to the network or
746 // shall stay in the internal buffer
747 if (vehicle != nullptr) {
750 }
751 }
752}
753
754
757 // the route was defined without edges and its current edges were
758 // derived from route-stops.
759 // We may need to add additional edges for the vehicle-stops
761 assert(route->getStops().size() > 0);
762 ConstMSEdgeVector edges = route->getEdges();
764 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
765 if (stop.index == 0) {
766 if (edges.front() != stopEdge ||
767 route->getStops().front().endPos < stop.endPos) {
768 edges.insert(edges.begin(), stopEdge);
769 }
770 } else if (stop.index == STOP_INDEX_END) {
771 if (edges.back() != stopEdge ||
772 route->getStops().back().endPos > stop.endPos) {
773 edges.push_back(stopEdge);
774 }
775 } else {
776 WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
777 }
778 }
779 ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
780 isPermanent, new RGBColor(route->getColor()), route->getStops());
781 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
782 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
783 }
784 return newRoute;
785}
786
787
788void
790 try {
791 if (myActiveTransportablePlan->size() == 0) {
792 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
793 error[0] = (char)::toupper((char)error[0]);
794 throw ProcessError(error);
795 }
796 // let's check whether this transportable had to depart before the simulation starts
800 return;
801 }
802 // type existence has been checked on opening
805 && type->getVehicleClass() != SVC_PEDESTRIAN
807 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
808 }
811 if (created > 0) {
813 } else {
815 }
816 } catch (ProcessError&) {
818 throw;
819 }
820}
821
822
823void
827
828
829void
833
834
835void
839
840
841void
845
846
847void
849 try {
850 const std::string fid = myVehicleParameter->id;
851 if (myActiveTransportablePlan->size() == 0) {
852 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
853 }
854 // let's check whether this transportable (person/container) had to depart before the simulation starts
858 return;
859 }
860 // instantiate all persons/containers of this flow
861 int i = 0;
863 std::string baseID = myVehicleParameter->id;
866 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
867 } else {
870 // type existence has been checked on opening
872 addFlowTransportable(t, type, baseID, i++);
873 }
874 }
875 }
876 } else {
879 // poisson: randomize first depart
881 }
882 for (; i < myVehicleParameter->repetitionNumber && (myVehicleParameter->repetitionNumber != std::numeric_limits<int>::max()
884 // type existence has been checked on opening
888 }
889 }
891 } catch (ProcessError&) {
893 throw;
894 }
896}
897
898
899int
900MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
901 try {
902 int numCreated = 0;
903 MSNet* const net = MSNet::getInstance();
906 //MSTransportableControl& pc = net->getPersonControl();
907 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
908 if (quota == 0) {
909 tc.addDiscarded();
910 }
911 for (int j = 0; j < quota; j++) {
912 if (i > 0 || j > 0) {
913 // copy parameter and plan because the transportable takes over responsibility
915 *copyParam = *myVehicleParameter;
916 myVehicleParameter = copyParam;
918 MSStage* lastStage = nullptr;
919 for (MSStage* const s : *myActiveTransportablePlan) {
920 copyPlan->push_back(s->clone());
921 if (lastStage != nullptr && s->getStageType() == MSStageType::WALKING && lastStage->getDestinationStop() != nullptr) {
922 MSStageMoving* walk = static_cast<MSStageMoving*>(copyPlan->back());
923 walk->setDepartPos(lastStage->getDestinationStop()->getAccessPos(walk->getEdge(), &myParsingRNG));
924 }
925 lastStage = s;
926 }
927 myActiveTransportablePlan = copyPlan;
929 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
930 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
931 }
932 }
933 myVehicleParameter->id = (baseID
934 + (i >= 0 ? "." + toString(i) : "")
935 + (j > 0 ? "." + toString(j) : ""));
940 numCreated++;
941 if (!tc.add(transportable)) {
942 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
943 delete transportable;
946 throw ProcessError(error);
947 }
948 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
949 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
950 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);
951 }
952 }
953 return numCreated;
954 } catch (ProcessError&) {
956 throw;
957 }
958}
959
960
961void
964 vehType->check();
965 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
966 const std::string id = vehType->getID();
967 delete vehType;
969 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
970 }
971 } else {
972 if (myCurrentVTypeDistribution != nullptr) {
974 }
975 }
976}
977
978
979void
983 delete myVehicleParameter;
984 myVehicleParameter = nullptr;
985 return;
986 }
987 // let's check whether vehicles had to depart before the simulation starts
990 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
991 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
994 delete myVehicleParameter;
995 myVehicleParameter = nullptr;
996 return;
997 }
998 }
999 }
1000 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
1001 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1002 }
1005 closeRoute(true);
1006 }
1008 if (route == nullptr) {
1009 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1010 }
1011 if (route->mustReroute()) {
1013 if (myVehicleParameter->stops.size() > 0) {
1014 route = addVehicleStopsToImplicitRoute(route, true);
1015 myVehicleParameter->routeid = route->getID();
1016 }
1017 }
1021 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
1022 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
1023 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1024 }
1025 }
1029 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
1030 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
1031 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1032 }
1033 }
1034 myActiveRouteID = "";
1035
1036 // check whether the vehicle shall be added directly to the network or
1037 // shall stay in the internal buffer
1039 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
1041 } else {
1043 delete myVehicleParameter;
1044 } else {
1045 throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
1046 }
1047 }
1048 }
1049 myVehicleParameter = nullptr;
1050}
1051
1052
1053void
1059
1060void
1064
1065void
1069
1070void
1072 if (myVehicleParameter == nullptr) {
1073 throw ProcessError(TLF("Cannot define % stage without %.", toString(modeTag), toString(modeTag)));
1074 }
1075 try {
1076 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1077 std::string agent = "person";
1078 std::string stop = "bus stop";
1080 agent = "container";
1081 stop = "container stop";
1082 }
1083
1084 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1086 throw ProcessError("Found " + mode + " inside " + agent + " element");
1087 }
1088 const std::string aid = myVehicleParameter->id;
1089 bool ok = true;
1090 const MSEdge* from = nullptr;
1091 const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, "ANY");
1092 StringTokenizer st(desc);
1093 MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1094 MSEdge* to = nullptr;
1095 if (s != nullptr) {
1096 to = &s->getLane().getEdge();
1097 }
1098 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1099 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1100
1101 const SUMOVehicleParameter* startVeh = nullptr;
1102 const MSEdge* startVehFrom = nullptr;
1104 if (st.size() != 1) {
1105 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1106 }
1107 // agent starts
1109 const std::string vehID = st.front();
1110 SUMOVehicle* sVeh = vehControl.getVehicle(vehID);
1111 if (sVeh == nullptr) {
1112 if (MSNet::getInstance()->hasFlow(vehID)) {
1113 startVeh = MSNet::getInstance()->getInsertionControl().getFlowPars(vehID);
1114 if (startVeh != nullptr) {
1115 ConstMSRoutePtr const route = MSRoute::dictionary(startVeh->routeid);
1116 startVehFrom = route->getEdges().front();
1117 // flows are inserted at the end of the time step so we
1118 // do delay the pedestrian event by one time step
1119 myVehicleParameter->depart = startVeh->depart + DELTA_T;
1121 }
1122 }
1123 } else {
1124 startVeh = &sVeh->getParameter();
1125 startVehFrom = sVeh->getRoute().getEdges().front();
1126 myVehicleParameter->depart = startVeh->depart;
1127 }
1128 if (startVeh == nullptr) {
1129 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1130 }
1131 if (startVeh->departProcedure == DepartDefinition::TRIGGERED) {
1132 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1133 }
1134 }
1135
1136 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1137 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1138 from = MSEdge::dictionary(fromID);
1139 if (from == nullptr) {
1140 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1141 }
1142 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1143 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1144 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1145 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1146 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1147 if (!(stopWithAccess || transferAtJunction)) {
1148 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1149 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1150 }
1151 }
1152 if (startVeh != nullptr && startVehFrom != from) {
1153 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1154 "' (edge '" + fromID + "' != edge '" + startVehFrom->getID() + "').");
1155 }
1156 } else if (startVeh != nullptr) {
1157 from = startVehFrom;
1158 }
1159 if (myActiveTransportablePlan->empty()) {
1160 if (from == nullptr) {
1161 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1162 } else {
1164 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1165 }
1166 }
1167 // given attribute may override given stopping place due access requirements
1168 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1169 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1170 to = MSEdge::dictionary(toID);
1171 if (to == nullptr) {
1172 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1173 }
1174 }
1175 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1176 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1177 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1178 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1179 myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, 0.0, st.getVector(), group, intendedVeh, intendedDepart));
1180 myParamStack.push_back(myActiveTransportablePlan->back());
1181 } catch (ProcessError&) {
1183 throw;
1184 }
1185}
1186
1188MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1189 bool ok = true;
1190 // dummy stop parameter to hold the attributes
1192 if (stopParam != nullptr) {
1193 stop = *stopParam;
1194 } else {
1195 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1196 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1197 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1198 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1199 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1200 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1201 }
1202 MSStoppingPlace* toStop = nullptr;
1203 if (stop.busstop != "") {
1205 if (toStop == nullptr) {
1206 ok = false;
1207 WRITE_ERROR(TLF("The busStop '%' is not known%.", stop.busstop, errorSuffix));
1208 }
1209 } else if (stop.containerstop != "") {
1211 if (toStop == nullptr) {
1212 ok = false;
1213 WRITE_ERROR(TLF("The containerStop '%' is not known%.", stop.containerstop, errorSuffix));
1214 }
1215 } else if (stop.parkingarea != "") {
1217 if (toStop == nullptr) {
1218 ok = false;
1219 WRITE_ERROR(TLF("The parkingArea '%' is not known%.", stop.parkingarea, errorSuffix));
1220 }
1221 } else if (stop.chargingStation != "") {
1222 // ok, we have a charging station
1224 if (toStop == nullptr) {
1225 ok = false;
1226 WRITE_ERROR(TLF("The chargingStation '%' is not known%.", stop.chargingStation, errorSuffix));
1227 }
1228 } else if (stop.overheadWireSegment != "") {
1229 // ok, we have an overhead wire segment
1231 if (toStop == nullptr) {
1232 ok = false;
1233 WRITE_ERROR(TLF("The overhead wire segment '%' is not known%.", stop.overheadWireSegment, errorSuffix));
1234 }
1235 }
1236 if (!ok && MSGlobals::gCheckRoutes) {
1237 throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1238 }
1239 return toStop;
1240}
1241
1244 Parameterised* result = nullptr;
1245 try {
1246 std::string errorSuffix;
1248 errorSuffix = " in person '" + myVehicleParameter->id + "'";
1250 errorSuffix = " in container '" + myVehicleParameter->id + "'";
1251 } else if (myVehicleParameter != nullptr) {
1252 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'";
1253 } else {
1254 errorSuffix = " in route '" + myActiveRouteID + "'";
1255 }
1257 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1258 if (!ok) {
1260 throw ProcessError();
1261 }
1262 return result;
1263 }
1264 const MSEdge* edge = nullptr;
1265 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1266 // if one of the previous stops is defined
1267 if (toStop != nullptr) {
1268 const MSLane& l = toStop->getLane();
1269 stop.lane = l.getID();
1270 if ((stop.parametersSet & STOP_END_SET) == 0) {
1271 stop.endPos = toStop->getEndLanePosition();
1272 } else {
1273 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1274 }
1275 stop.startPos = toStop->getBeginLanePosition();
1276 edge = &l.getEdge();
1277 } else {
1278 // no, the lane and the position should be given directly
1279 // get the lane
1280 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1281 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1282 if (ok && stop.edge != "") { // edge is given directly
1283 edge = MSEdge::dictionary(stop.edge);
1284 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1285 throw ProcessError(TLF("The edge '%' for a stop is not known%.", stop.edge, errorSuffix));
1286 }
1287 } else if (ok && stop.lane != "") { // lane is given directly
1288 MSLane* stopLane = MSLane::dictionary(stop.lane);
1289 if (stopLane == nullptr) {
1290 // check for opposite-direction stop
1291 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1292 if (stopLane != nullptr) {
1293 edge = MSEdge::dictionary(stop.edge);
1294 }
1295 } else {
1296 edge = &stopLane->getEdge();
1297 }
1298 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1299 throw ProcessError(TLF("The lane '%' for a stop is not known%.", stop.lane, errorSuffix));
1300 }
1301 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
1302 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
1303 Position pos;
1304 bool geo = false;
1305 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
1306 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
1307 } else {
1308 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
1309 geo = true;
1310 }
1311 PositionVector positions;
1312 positions.push_back(pos);
1313 ConstMSEdgeVector geoEdges;
1315 auto& vc = MSNet::getInstance()->getVehicleControl();
1316 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
1317 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1318 if (type != nullptr) {
1319 vClass = type->getParameter().vehicleClass;
1320 }
1321 }
1322 parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok);
1323 if (ok) {
1324 edge = geoEdges.front();
1325 if (geo) {
1327 }
1329 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
1330 } else {
1331 throw ProcessError(TLF("Could not map stop position '%' to the network%.", pos, errorSuffix));
1332 }
1333 } else {
1334 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1335 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1336 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1337 edge = &toStop->getLane().getEdge();
1338 stop.lane = toStop->getLane().getID();
1339 stop.endPos = toStop->getEndLanePosition();
1340 stop.startPos = toStop->getBeginLanePosition();
1341 } else { // use end of movement before definied as lane/edge
1342 edge = myActiveTransportablePlan->back()->getDestination();
1343 stop.lane = edge->getLanes()[0]->getID();
1344 stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1345 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1346 }
1347 } else {
1348 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);
1350 throw ProcessError(msg);
1351 } else {
1352 WRITE_WARNING(msg);
1353 return result;
1354 }
1355 }
1356 }
1357 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1358 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1359 WRITE_WARNINGF(TL("Deprecated attribute 'pos' in description of stop%."), errorSuffix);
1360 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1361 }
1362 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1363 if (!myAmLoadingState) {
1364 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1366 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1367 throw ProcessError(TLF("Invalid start or end position for stop on %'%.",
1368 stop.lane != "" ? ("lane '" + stop.lane) : ("edge '" + stop.edge), errorSuffix));
1369 }
1370 }
1371 }
1372 stop.edge = edge->getID();
1374 if (myActiveTransportablePlan->empty()) {
1375 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1377 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1379 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1380 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1381 throw ProcessError(TLF("Disconnected plan for % '%' (%!=%).", myActiveTypeName, myVehicleParameter->id,
1382 edge->getID(), myActiveTransportablePlan->back()->getDestination()->getID()));
1383 }
1384 // transporting veh stops somewhere
1385 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1387 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1388 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1389 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1390 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1391 WRITE_WARNINGF(TL("Disconnected plan for % '%' (stop range %-% does not cover previous arrival position %)."),
1393 }
1394 }
1395 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1396 double pos = (stop.startPos + stop.endPos) / 2.;
1397 if (!myActiveTransportablePlan->empty()) {
1398 pos = myActiveTransportablePlan->back()->getArrivalPos();
1399 }
1400 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1401 result = myActiveTransportablePlan->back();
1402
1403 } else if (myVehicleParameter != nullptr) {
1404 myVehicleParameter->stops.push_back(stop);
1405 result = &myVehicleParameter->stops.back();
1406 } else {
1407 myActiveRouteStops.push_back(stop);
1408 result = &myActiveRouteStops.back();
1409 }
1410 if (myInsertStopEdgesAt >= 0) {
1411 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1412 if (edge->isInternal()) {
1413 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1416 }
1419 } else {
1420 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1422 }
1423 } else if (myHaveVia) {
1424 // vias were loaded, check for consistency
1425 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1426 WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'."),
1428 }
1429 }
1430 } catch (ProcessError&) {
1432 throw;
1433 }
1434 return result;
1435}
1436
1437
1438void
1439MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1440 const MSEdge* fromEdge, const MSEdge*& toEdge,
1441 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1442 const MSStage* const lastStage, bool& ok) {
1443 try {
1444 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1445
1446 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1447 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."));
1448 }
1449 departPos = 0.;
1450 if (lastStage != nullptr) {
1451 if (lastStage->getDestinationStop() != nullptr) {
1452 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge, &myParsingRNG);
1453 } else if (lastStage->getDestination() == fromEdge) {
1454 departPos = lastStage->getArrivalPos();
1455 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1456 departPos = fromEdge->getLength();
1457 }
1458 }
1459
1460 bs = retrieveStoppingPlace(attrs, " " + description);
1461 if (bs != nullptr) {
1462 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1463 if (arrivalPos < 0) {
1464 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1465 }
1467 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1468 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1469 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1470 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1471 arrivalPos = arrPos;
1472 } else {
1473 WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1474 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1475 }
1476 }
1477 } else {
1478 if (toEdge == nullptr) {
1479 throw ProcessError(TLF("No destination edge for %.", description));
1480 }
1483 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1484 } else {
1485 arrivalPos = toEdge->getLength() / 2.;
1486 }
1487 }
1488 } catch (ProcessError&) {
1490 throw;
1491 }
1492}
1493
1494
1495void
1497 if (myVehicleParameter == nullptr) {
1498 throw ProcessError(TL("Cannot define person stage without person."));
1499 }
1500 try {
1501 myActiveRoute.clear();
1502 bool ok = true;
1503 const char* const id = myVehicleParameter->id.c_str();
1504 const MSEdge* from = nullptr;
1505 const MSEdge* to = nullptr;
1509 from = myActiveRoute.front();
1510 } else if (myActiveTransportablePlan->empty()) {
1511 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1512 } else {
1513 from = myActiveTransportablePlan->back()->getDestination();
1514 }
1516 to = myActiveRoute.back();
1517 } // else, to may also be derived from stopping place
1518
1519 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1520 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1521 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1522 }
1523
1524 double departPos = 0;
1525 double arrivalPos = 0;
1526 MSStoppingPlace* stoppingPlace = nullptr;
1527 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1528
1529 SVCPermissions modeSet = 0;
1530 if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
1531 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1532 std::string errorMsg;
1533 // try to parse person modes
1534 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1535 throw InvalidArgument(errorMsg);
1536 }
1537 } else {
1538 modeSet = myVehicleParameter->modes;
1539 }
1540 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1542 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, myVehicleParameter->vTypes);
1543 for (StringTokenizer st(types); st.hasNext();) {
1544 const std::string vtypeid = st.next();
1545 const MSVehicleType* const vType = vehControl.getVType(vtypeid);
1546 if (vType == nullptr) {
1547 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1548 }
1549 modeSet |= (vType->getVehicleClass() == SVC_BICYCLE) ? SVC_BICYCLE : SVC_PASSENGER;
1550 }
1551 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1552 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1553 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1554 }
1555 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1556 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1557 if (ok) {
1558 if (myActiveTransportablePlan->empty()) {
1559 double initialDepartPos = myVehicleParameter->departPos;
1561 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1562 }
1563 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1564 }
1566 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1567 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1568 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1569 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1570 myParamStack.push_back(myActiveTransportablePlan->back());
1573 }
1574 }
1575 myActiveRoute.clear();
1576 } catch (ProcessError&) {
1578 throw;
1579 }
1580}
1581
1582
1583void
1585 if (myVehicleParameter == nullptr) {
1586 throw ProcessError(TL("Cannot define person stage without person."));
1587 }
1588 myActiveRouteID = "";
1590 try {
1591 myActiveRoute.clear();
1592 bool ok = true;
1593 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1594 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1595 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1596 }
1597 double speed = -1; // default to vType speed
1598 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1599 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1600 if (speed <= 0) {
1601 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1602 }
1603 }
1604 double departPos = 0;
1605 double arrivalPos = 0;
1606 MSStoppingPlace* bs = nullptr;
1607 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1608 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1610 if (route == nullptr) {
1611 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1612 }
1613 myActiveRoute = route->getEdges();
1614 } else {
1616 }
1617 if (myActiveTransportablePlan->empty()) {
1618 double initialDepartPos = myVehicleParameter->departPos;
1620 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1621 }
1622 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1623 }
1624 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1625 if (myActiveRoute.empty()) {
1626 throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1627 }
1628 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1629 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1630 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1631 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1632 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1633 }
1634 }
1635 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1636 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1637 myActiveTransportablePlan->push_back(new MSStageWalking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1638 myParamStack.push_back(myActiveTransportablePlan->back());
1641 }
1642 myActiveRoute.clear();
1643 } catch (ProcessError&) {
1645 throw;
1646 }
1647 } else { // parse walks from->to as person trips
1648 addPersonTrip(attrs);
1649 }
1650}
1651
1652double
1653MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1654 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1655 if (value == "") {
1656 return pos;
1657 }
1658 std::string error;
1660 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1661 if (dpd != DepartPosLatDefinition::GIVEN) {
1663 if (lane == nullptr) {
1664 throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1665 }
1666 const double usableWidth = lane->getWidth() - 0.5;
1667 switch (dpd) {
1669 pos = -usableWidth / 2;
1670 break;
1672 pos = usableWidth / 2;
1673 break;
1675 pos = 0;
1676 break;
1682 break;
1683 default:
1684 break;
1685 }
1686 }
1687 } else {
1688 throw ProcessError(error);
1689 }
1690 return pos;
1691}
1692
1693
1694void
1695MSRouteHandler::addTransportable(const SUMOSAXAttributes& /*attrs*/, const bool isPerson) {
1697 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1698 const std::string error = TLF("The type '%' for % '%' is not known.", myVehicleParameter->vtypeid, myActiveTypeName, myVehicleParameter->id);
1700 throw ProcessError(error);
1701 }
1703}
1704
1705
1706void
1708 try {
1709 myActiveRoute.clear();
1710 const std::string cid = myVehicleParameter->id;
1711 bool ok = true;
1712 const MSEdge* from = nullptr;
1713 const MSEdge* to = nullptr;
1714 MSStoppingPlace* cs = nullptr;
1715
1716 double speed;
1718 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1719 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1720 if (!ok) {
1721 throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1722 }
1723 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1724 speed = vtype->getMaxSpeed();
1725 } else { // default speed value
1727 }
1728 if (speed <= 0) {
1729 throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1730 }
1731 // values from preceding stage:
1732 const MSEdge* preEdge = nullptr;
1733 double prePos = 0;
1734 if (!myActiveTransportablePlan->empty()) {
1735 preEdge = myActiveTransportablePlan->back()->getDestination();
1736 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1737 }
1738 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1739 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1740
1741 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1742 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1743 } else {
1744 // set 'from':
1745 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1746 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1747 from = MSEdge::dictionary(fromID);
1748 if (from == nullptr) {
1749 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1750 }
1751 if (preEdge != nullptr && preEdge != from) {
1752 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1753 }
1754 } else if (preEdge == nullptr) {
1755 throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1756 } else {
1757 from = preEdge;
1758 }
1759 // set 'to':
1760 if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1761 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1762 to = MSEdge::dictionary(toID);
1763 if (to == nullptr) {
1764 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1765 }
1766 } else {
1767 const std::string description = "container '" + cid + "' transhipping from edge '" + from->getID() + "'";
1768 cs = retrieveStoppingPlace(attrs, " " + description);
1769 if (cs != nullptr) {
1770 to = &cs->getLane().getEdge();
1771 } else {
1772 throw ProcessError(TLF("Inconsistent tranship for container '%', needs either: 'edges', 'to', 'containerStop' (or any other stopping place)", cid));
1773 }
1774 }
1775 myActiveRoute.push_back(from);
1776 myActiveRoute.push_back(to);
1777 }
1778 if (myActiveRoute.empty()) {
1779 throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1780 }
1781 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1783 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1784 }
1785 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1786 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1787 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1788 myParamStack.push_back(myActiveTransportablePlan->back());
1789 myActiveRoute.clear();
1790 } catch (ProcessError&) {
1792 throw;
1793 }
1794}
1795
1796
1797void
1799 for (const auto& edge : MSEdge::getAllEdges()) {
1800 for (MSLane* lane : edge->getLanes()) {
1801 Boundary b = lane->getShape().getBoxBoundary();
1802 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1803 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1804 tree->Insert(cmin, cmax, lane);
1805 }
1806 }
1807}
1808
1809
1810MSEdge*
1811MSRouteHandler::retrieveEdge(const std::string& id) {
1812 return MSEdge::dictionary(id);
1813}
1814
1815
1816/****************************************************************************/
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:29
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define TIME2STEPS(x)
Definition SUMOTime.h:57
const long long int VTYPEPARS_MAXSPEED_SET
const long long int VTYPEPARS_VEHICLECLASS_SET
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const double DEFAULT_VEH_PROB
const std::string DEFAULT_VTYPE_ID
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
const double DEFAULT_CONTAINER_TRANSHIP_SPEED
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const long long int VEHPARS_FORCE_REROUTE
DepartPosLatDefinition
Possible ways to choose the lateral departure position.
@ RANDOM
The lateral position is chosen randomly.
@ RIGHT
At the rightmost side of the lane.
@ GIVEN
The position is given.
@ LEFT
At the leftmost side of the lane.
@ FREE
A free lateral position is chosen.
@ CENTER
At the center of the lane.
@ RANDOM_FREE
If a fixed number of random choices fails, a free lateral position is chosen.
@ RANDOM
A random position is chosen.
const long long int VEHPARS_ROUTE_SET
const long long int VEHPARS_TO_TAZ_SET
const long long int VEHPARS_DEPARTPOS_SET
const long long int VEHPARS_ARRIVALPOS_SET
const int STOP_INDEX_REPEAT
const long long int VEHPARS_FROM_TAZ_SET
const int STOP_END_SET
const double MIN_STOP_LENGTH
@ BEGIN
The departure is at simulation start.
@ GIVEN
The time is given.
@ TRIGGERED
The departure is person triggered.
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_TRANSPORT
@ SUMO_TAG_RIDE
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_TAG_PERSON
@ SUMO_TAG_PERSONFLOW
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_ATTR_STARTPOS
@ SUMO_ATTR_LINES
@ SUMO_ATTR_LANE
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_LON
@ SUMO_ATTR_REFID
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_VIALONLAT
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_REPLACED_AT_TIME
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_VIAXY
@ SUMO_ATTR_Y
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_DEPARTPOS_LAT
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_TO_JUNCTION
@ SUMO_ATTR_X
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_ACTTYPE
@ SUMO_ATTR_PROBS
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_TOLONLAT
@ SUMO_ATTR_CHARGING_STATION
@ SUMO_ATTR_ROUTES
@ SUMO_ATTR_MODES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_OVERHEAD_WIRE_SEGMENT
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_GROUP
@ SUMO_ATTR_COST
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_REPLACED_ON_INDEX
@ SUMO_ATTR_VIAJUNCTIONS
@ SUMO_ATTR_FROMXY
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_LAT
@ SUMO_ATTR_WALKFACTOR
@ SUMO_ATTR_TOXY
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_FROMLONLAT
@ SUMO_ATTR_REPEAT
@ SUMO_ATTR_INTENDED
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_CYCLETIME
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:118
PositionVector getShape(const bool closeShape) const
get position vector (shape) based on this boundary
Definition Boundary.cpp:447
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:124
Writes the state of the tls to a file (in each second)
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1086
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
static void parseEdgesList(const std::string &desc, ConstMSEdgeVector &into, const std::string &rid)
Parses the given string assuming it contains a list of edge ids divided by spaces.
Definition MSEdge.cpp:1110
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:947
const MSJunction * getToJunction() const
Definition MSEdge.h:418
double getLength() const
return the length of the edge
Definition MSEdge.h:685
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1047
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:937
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gCheckRoutes
Definition MSGlobals.h:91
static bool gStateLoaded
Information whether a state has been loaded.
Definition MSGlobals.h:103
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
const SUMOVehicleParameter * getFlowPars(const std::string &id) const
return parameters for the given flow
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
SUMOTime computeRandomDepartOffset() const
compute (optional) random offset to the departure time
Representation of a lane in the micro simulation.
Definition MSLane.h:84
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2414
bool isInternal() const
Definition MSLane.cpp:2545
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
double getWidth() const
Returns the lane's width.
Definition MSLane.h:635
The simulated network and simulation perfomer.
Definition MSNet.h:89
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:185
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:471
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:481
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition MSNet.cpp:1198
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1380
bool hasContainers() const
Returns whether containers are simulated.
Definition MSNet.h:411
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:395
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:431
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:378
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1189
static const double RANDOM_POS_LAT
magic value to encode randomized lateral offset for persons when starting a walk
Definition MSPModel.h:68
static const double UNSPECIFIED_POS_LAT
the default lateral offset for persons when starting a walk
Definition MSPModel.h:65
void closePerson() override
Ends the processing of a person.
RandomDistributor< ConstMSRoutePtr > * myCurrentRouteDistribution
The currently parsed distribution of routes (probability->route)
void addRideOrTransport(const SUMOSAXAttributes &attrs, const SumoXMLTag modeTag)
Processing of a transport.
void closeContainerFlow() override
Ends the processing of a containerFlow.
void openFlow(const SUMOSAXAttributes &attrs) override
opens a flow for reading
ConstMSRoutePtr addVehicleStopsToImplicitRoute(ConstMSRoutePtr route, bool isPermanent)
adapt implicit route (edges derived from stops) to additional vehicle-stops
void addWalk(const SUMOSAXAttributes &attrs) override
add a fully specified walk
void addTransport(const SUMOSAXAttributes &attrs) override
Processing of a transport.
void deleteActivePlanAndVehicleParameter()
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void initLaneTree(NamedRTree *tree) override
bool myAmLoadingState
whether a state file is being loaded
bool myStartTriggeredInFlow
whether we are loading a personFlow that is starting triggered in a vehicle flow
void resetActivePlanAndVehicleParameter()
reset MSTransportablePlans after transportable tag closes
SUMOTime myActiveRoutePeriod
bool myHaveVia
Wether an object with 'via'-attribute is being parsed.
int addFlowTransportable(SUMOTime depart, MSVehicleType *type, const std::string &baseID, int i)
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void closeTransportable()
ends the processing of a transportable (as person or container)
MSEdge * retrieveEdge(const std::string &id) override
MSStoppingPlace * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, SUMOVehicleParameter::Stop *stopParam=nullptr)
Parse destination stop.
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
void openRoute(const SUMOSAXAttributes &attrs) override
opens a route for reading
void closeVehicleTypeDistribution() override
closes (ends) the building of a distribution
void addTranship(const SUMOSAXAttributes &attrs) override
Processing of a tranship.
void closeRoute(const bool mayBeDisconnected=false) override
closes (ends) the building of a route.
static SumoRNG myParsingRNG
A random number generator used to choose from vtype/route distributions and computing the speed facto...
void parseFromViaTo(SumoXMLTag tag, const SUMOSAXAttributes &attrs)
Called for parsing from and to and the corresponding taz attributes.
void closeFlow() override
Ends the processing of a flow.
MSTransportable::MSTransportablePlan * myActiveTransportablePlan
The plan of the current transportable (person or container)
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
std::string myCurrentRouteDistributionID
The id of the currently parsed route distribution.
RandomDistributor< MSVehicleType * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
void closeContainer() override
Ends the processing of a container.
SUMOTime myActiveRouteReplacedAtTime
The time at which this route was replaced (from vehroute-output)
void closeTrip() override
Ends the processing of a trip.
void openTrip(const SUMOSAXAttributes &attrs) override
opens a trip for reading
void addPersonTrip(const SUMOSAXAttributes &attrs) override
add a routing request for a walking or intermodal person
ConstMSEdgeVector myActiveRoute
The current route.
int myActiveRouteRepeat
number of repetitions of the active route
ObjectTypeEnum myActiveType
The type of the current object.
void closePersonFlow() override
Ends the processing of a personFlow.
int myActiveRouteReplacedIndex
The index at which this route was replaced (from vehroute-output)
void closeRouteDistribution() override
closes (ends) the building of a distribution
MSRouteHandler(const std::string &file, bool addVehiclesDirectly)
standard constructor
std::string myScaleSuffix
prefix when copying vehicles with –scale
ObjectTypeEnum
enum for object type
double interpretDepartPosLat(const std::string &value, int departLane, const std::string &element)
virtual ~MSRouteHandler()
standard destructor
bool myAddVehiclesDirectly
Information whether vehicles shall be directly added to the network or kept within the buffer.
bool myReplayRerouting
whether loaded rerouting events shall be replayed
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs) override
opens a type distribution for reading
Parameterised * addStop(const SUMOSAXAttributes &attrs) override
Processing of a stop.
virtual void closeVehicle() override
Ends the processing of a vehicle (note: is virtual because is reimplemented in MSStateHandler)
void openRouteFlow(const SUMOSAXAttributes &attrs) override
opens a route flow for reading
void openRouteDistribution(const SUMOSAXAttributes &attrs) override
opens a route distribution for reading
void addRide(const SUMOSAXAttributes &attrs) override
Processing of a ride.
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const MSEdge *fromEdge, const MSEdge *&toEdge, double &departPos, double &arrivalPos, MSStoppingPlace *&bs, const MSStage *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
bool myActiveRoutePermanent
whether the active route is stored indefinitely (used by state loader)
std::string myActiveTypeName
The name of the current object type.
void closeVType() override
Ends the processing of a vehicle type.
void addTransportable(const SUMOSAXAttributes &attrs, const bool isPerson) override
Processing of a person.
void closeTransportableFlow()
ends the flow of a transportable
void setReroute(bool reroute=true)
Definition MSRoute.h:221
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:125
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:206
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:109
static RandomDistributor< ConstMSRoutePtr > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition MSRoute.cpp:161
void setPeriod(SUMOTime period)
sets the period
Definition MSRoute.h:198
const MSEdge * getDestination() const
returns the destination edge
Definition MSStage.cpp:65
virtual double getArrivalPos() const
Definition MSStage.h:94
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition MSStage.h:85
MSStageType getStageType() const
Definition MSStage.h:127
static const MSLane * checkDepartLane(const MSEdge *edge, SUMOVehicleClass svc, int laneIndex, const std::string &id)
interpret custom depart lane
const MSEdge * getEdge() const
Returns the current edge.
void setDepartPos(const double pos)
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
double getAccessPos(const MSEdge *edge, SumoRNG *rng=nullptr) const
the position on the given edge which is connected to this stop, -1 on failure
int getLoadedNumber() const
Returns the number of build transportables.
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, SumoRNG *rng) const
Builds a new person.
bool add(MSTransportable *transportable)
Adds a single transportable, returns false if an id clash occurred.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
The class responsible for building and deletion of vehicles.
VehicleDefinitionSource
possible origins of a vehicle definition
double getScale() const
sets the demand scaling factor
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
int getQuota(double frac=-1, int loaded=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, ConstMSRoutePtr route, MSVehicleType *type, const bool ignoreStopErrors, const VehicleDefinitionSource source=ROUTEFILE, bool addRouteStops=true)
Builds a vehicle, increases the number of built vehicles.
const RandomDistributor< MSVehicleType * > * getVTypeDistribution(const std::string &typeDistID) const
return the vehicle type distribution with the given id
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false, bool wasKept=false)
Deletes the vehicle.
The car-following model and parameter.
double getDefaultProbability() const
Get the default probability of this vehicle type.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
static MSVehicleType * build(SUMOVTypeParameter &from)
Builds the microsim vehicle type described by the given parameter.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
const std::string & getID() const
Returns the name of the vehicle type.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
const SUMOVTypeParameter & getParameter() const
void check()
Checks whether vehicle type parameters may be problematic (Currently, only the value for the action s...
Provides utility functions for matching locations to edges (during route parsing)
Definition MapMatcher.h:44
void parseGeoEdges(const PositionVector &positions, bool geo, SUMOVehicleClass vClass, std::vector< const MSEdge * > &into, const std::string &rid, bool isFrom, bool &ok)
Definition MapMatcher.h:56
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
const std::string & getID() const
Returns the id.
Definition Named.h:74
A RT-tree for efficient storing of SUMO's Named objects.
Definition NamedRTree.h:61
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition NamedRTree.h:79
A storage for options typed value containers)
Definition OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
An upper class for objects with additional parameters.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Represents a generic random distribution.
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
const std::vector< T > & getVals() const
Returns the members of the distribution.
void clear()
Clears the distribution.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
Parser for routes during their loading.
bool parseStop(SUMOVehicleParameter::Stop &stop, const SUMOSAXAttributes &attrs, std::string errorSuffix, MsgHandler *const errorOutput)
parses attributes common to all stops
std::vector< SUMOVehicleParameter::Stop > myActiveRouteStops
List of the stops on the parsed route.
void registerLastDepart()
save last depart (only to be used if vehicle is not discarded)
double myCurrentCosts
The currently parsed route costs.
std::string myActiveRouteID
The id of the current route.
std::vector< Parameterised * > myParamStack
The stack of currently parsed parameterised objects.
SUMOVehicleParameter * myVehicleParameter
Parameter of the current vehicle, trip, person, container or flow.
const bool myHardFail
flag to enable or disable hard fails
SUMOVTypeParameter * myCurrentVType
The currently parsed vehicle type.
static StopPos checkStopPos(double &startPos, double &endPos, const double laneLength, const double minLength, const bool friendlyPos)
check start and end position of a stop
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
double myActiveRouteProbability
The probability of the current route.
int myInsertStopEdgesAt
where stop edges can be inserted into the current route (-1 means no insertion)
std::string myActiveRouteRefID
The id of the route the current route references to.
const RGBColor * myActiveRouteColor
The currently parsed route's color.
virtual bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double scale
individual scaling factor (-1 for undefined)
SUMOVehicleClass vehicleClass
The vehicle's class.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual const MSRoute & getRoute() const =0
Returns the current route.
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
std::string overheadWireSegment
(Optional) overhead line segment if one is assigned to the stop
int parametersSet
Information for the output which parameter were set.
SUMOTime until
The time at which the vehicle may continue its journey.
double endPos
The stopping position end.
std::string busstop
(Optional) bus stop if one is assigned to the stop
std::string containerstop
(Optional) container stop if one is assigned to the stop
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
void incrementFlow(double scale, SumoRNG *rng=nullptr)
increment flow
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
int repetitionsDone
The number of times the vehicle was already inserted.
SUMOTime repetitionTotalOffset
The offset between depart and the time for the next vehicle insertions.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
SVCPermissions modes
The modes a person or container can use.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
std::string vTypes
The types of usable (auto-generated) vehicles for a person / container.
double departPos
(optional) The position the vehicle shall depart from
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
static bool parsePersonModes(const std::string &modes, const std::string &element, const std::string &id, SVCPermissions &modeSet, std::string &error)
Validates a given person modes value.
static bool parseDepartPosLat(const std::string &val, const std::string &element, const std::string &id, double &pos, DepartPosLatDefinition &dpd, std::string &error)
Validates a given departPosLat value.
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
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static double parseWalkPos(SumoXMLAttr attr, const bool hardFail, const std::string &id, double maxPos, const std::string &val, SumoRNG *rng=0)
parse departPos or arrivalPos for a walk
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it