Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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-2025 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// ===========================================================================
53
54
55// ===========================================================================
56// method definitions
57// ===========================================================================
58MSRouteHandler::MSRouteHandler(const std::string& file, bool addVehiclesDirectly) :
59 SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes", true),
60 MapMatcher(OptionsCont::getOptions().getBool("mapmatch.junctions"),
61 OptionsCont::getOptions().getBool("mapmatch.taz"),
62 OptionsCont::getOptions().getFloat("mapmatch.distance"),
63 MsgHandler::getErrorInstance()),
64 myActiveRouteRepeat(0),
65 myActiveRoutePeriod(0),
66 myActiveRoutePermanent(false),
67 myActiveType(ObjectTypeEnum::UNDEFINED),
68 myHaveVia(false),
69 myActiveTransportablePlan(nullptr),
70 myAddVehiclesDirectly(addVehiclesDirectly),
71 myCurrentVTypeDistribution(nullptr),
72 myCurrentRouteDistribution(nullptr),
73 myAmLoadingState(false),
74 myScaleSuffix(OptionsCont::getOptions().getString("scale-suffix")),
75 myReplayRerouting(OptionsCont::getOptions().getBool("replay-rerouting")),
76 myStartTriggeredInFlow(false) {
77 myActiveRoute.reserve(100);
78}
79
80
82
83
84void
95
96
97void
103
104
105void
107 const std::string element = toString(tag);
108 myActiveRoute.clear();
109 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
111 WRITE_WARNINGF(TL("Taz usage was requested but no taz present in % '%'!"), element, myVehicleParameter->id);
112 useTaz = false;
113 }
114 bool ok = true;
115 const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
118 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
119 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
120 if (type != nullptr) {
121 vClass = type->getParameter().vehicleClass;
122 }
123 }
124 // from-attributes
125 if ((useTaz || (!attrs.hasAttribute(SUMO_ATTR_FROM) && !attrs.hasAttribute(SUMO_ATTR_FROMXY) && !attrs.hasAttribute(SUMO_ATTR_FROMLONLAT))) &&
127 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION);
128 const std::string tazType = useJunction ? "junction" : "taz";
129 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROM_JUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok);
130 const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
131 if (fromTaz == nullptr) {
132 throw ProcessError("Source " + tazType + " '" + tazID + "' not known " + rid + "!"
133 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
134 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
135 throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges " + rid + "!");
136 } else {
137 myActiveRoute.push_back(fromTaz);
138 }
139 } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
140 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, vClass, myActiveRoute, rid, true, ok);
141 if (myMapMatchTAZ && ok) {
142 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
144 }
145 } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
146 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, myActiveRoute, rid, true, ok);
147 if (myMapMatchTAZ && ok) {
148 myVehicleParameter->fromTaz = myActiveRoute.back()->getID();
150 }
151 } else {
152 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok),
153 myActiveRoute, rid);
154 }
155 if (!ok) {
156 throw ProcessError();
157 }
158
159 // via-attributes
162 }
163 ConstMSEdgeVector viaEdges;
164 if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
165 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, vClass, viaEdges, rid, false, ok);
166 } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
167 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, viaEdges, rid, false, ok);
168 } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
169 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
170 const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
171 if (viaSink == nullptr) {
172 throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
173 } else {
174 viaEdges.push_back(viaSink);
175 }
176 }
177 } else {
178 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok),
179 viaEdges, rid);
180 }
181 if (!viaEdges.empty()) {
182 myHaveVia = true;
183 }
184 for (const MSEdge* e : viaEdges) {
185 myActiveRoute.push_back(e);
186 myVehicleParameter->via.push_back(e->getID());
187 }
188
189 // to-attributes
190 if ((useTaz || (!attrs.hasAttribute(SUMO_ATTR_TO) && !attrs.hasAttribute(SUMO_ATTR_TOXY) && !attrs.hasAttribute(SUMO_ATTR_TOLONLAT))) &&
192 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION);
193 const std::string tazType = useJunction ? "junction" : "taz";
194 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TO_JUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
195 const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
196 if (toTaz == nullptr) {
197 throw ProcessError("Sink " + tazType + " '" + tazID + "' not known " + rid + "!"
198 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
199 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
200 throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges " + rid + "!");
201 } else {
202 myActiveRoute.push_back(toTaz);
203 }
204 } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
205 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, vClass, myActiveRoute, rid, false, ok);
206 if (myMapMatchTAZ && ok) {
207 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
209 }
210 } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
211 parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, vClass, myActiveRoute, rid, false, ok);
212 if (myMapMatchTAZ && ok) {
213 myVehicleParameter->toTaz = myActiveRoute.back()->getID();
215 }
216 } else {
217 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
218 myActiveRoute, rid);
219 }
221 if (myVehicleParameter->routeid == "") {
223 }
224}
225
226
227void
229 try {
231 && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT && element != SUMO_TAG_PARAM) {
232 const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
233 throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
234 }
235 if (myVehicleParameter == nullptr) {
237 myHaveVia = false;
238 }
239 SUMORouteHandler::myStartElement(element, attrs);
240 switch (element) {
242 addTransportable(attrs, true);
243 break;
245 addTransportable(attrs, false);
246 break;
247 case SUMO_TAG_FLOW:
248 if (myVehicleParameter) {
249 parseFromViaTo((SumoXMLTag)element, attrs);
250 }
251 break;
252 case SUMO_TAG_TRIP:
253 parseFromViaTo((SumoXMLTag)element, attrs);
254 break;
255 default:
256 break;
257 }
258 } catch (ProcessError&) {
260 throw;
261 }
262}
263
264
265void
267 bool ok = true;
268 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
269 if (ok) {
271 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
272 std::vector<double> probs;
273 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
274 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
275 while (st.hasNext()) {
276 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
277 }
278 }
279 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
280 StringTokenizer st(vTypes);
281 int probIndex = 0;
282 while (st.hasNext()) {
283 const std::string& vtypeID = st.next();
285 if (dist != nullptr) {
286 const double distProb = ((int)probs.size() > probIndex ? probs[probIndex] : 1.) / dist->getOverallProb();
287 std::vector<double>::const_iterator probIt = dist->getProbs().begin();
288 for (MSVehicleType* const type : dist->getVals()) {
289 myCurrentVTypeDistribution->add(type, distProb * *probIt);
290 probIt++;
291 }
292 } else {
294 if (type == nullptr) {
295 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
296 }
297 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->getDefaultProbability());
298 myCurrentVTypeDistribution->add(type, prob);
299 }
300 probIndex++;
301 }
302 if (probs.size() > 0 && probIndex != (int)probs.size()) {
303 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
304 " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
305 }
306 }
307 }
308}
309
310
311void
313 if (myCurrentVTypeDistribution != nullptr) {
314 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
621 return;
622 }
623 }
624
625 // get the vehicle's type
626 MSVehicleType* vtype = nullptr;
627
628 try {
629 if (myVehicleParameter->vtypeid != "") {
630 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
631 if (vtype == nullptr) {
632 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
633 }
634 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
635 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
636 }
637 } else {
638 // there should be one (at least the default one)
639 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
640 }
642 // if the route id was given, prefer that one
643 if (route != nullptr && !myAmLoadingState) {
644 WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
645 }
647 }
648 if (route == nullptr) {
649 // nothing found? -> error
650 if (myVehicleParameter->routeid != "") {
651 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
652 } else {
653 throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
654 }
655 }
656 myActiveRouteID = "";
657
658 } catch (ProcessError&) {
660 throw;
661 }
662 if (route->mustReroute()) {
664 if (myVehicleParameter->stops.size() > 0) {
665 route = addVehicleStopsToImplicitRoute(route, false);
666 }
667 }
671 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
672 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
673 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
674 }
675 }
679 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
680 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
681 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
682 }
683 }
684
685 // try to build the vehicle
686 SUMOVehicle* vehicle = nullptr;
687 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
689 try {
690 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
691 } catch (const ProcessError& e) {
692 myVehicleParameter = nullptr;
694 WRITE_WARNING(e.what());
695 vehControl.deleteVehicle(vehicle, true);
696 myVehicleParameter = nullptr;
697 vehicle = nullptr;
698 return;
699 } else {
700 throw;
701 }
702 }
703 const SUMOTime origDepart = myVehicleParameter->depart;
704 // maybe we do not want this vehicle to be inserted due to scaling
705 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
706 if (quota > 0) {
709 vehControl.addVehicle(myVehicleParameter->id, vehicle);
710 if (myReplayRerouting) {
712 if (rDist != nullptr) {
713 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
714 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
715 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
716 if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
717 // routing in the insertion step happens *after* insertion
719 } else {
721 }
722 }
723 }
724 }
725 int offset = 0;
726 for (int i = 1; i < quota; i++) {
729 }
731 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
732 while (vehControl.getVehicle(newPars->id) != nullptr) {
733 offset += 1;
734 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
735 }
738 // resample type
739 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
740 }
741 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
742 vehControl.addVehicle(newPars->id, vehicle);
743 }
744 myVehicleParameter = nullptr;
745 } else {
746 vehControl.deleteVehicle(vehicle, true);
747 myVehicleParameter = nullptr;
748 vehicle = nullptr;
749 }
750 } else {
751 // strange: another vehicle with the same id already exists
753 // and was not loaded while loading a simulation state
754 // -> error
755 std::string veh_id = myVehicleParameter->id;
757 std::string scaleWarning = "";
758 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
759 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
760 }
761 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
762 } else {
763 // ok, it seems to be loaded previously while loading a simulation state
764 vehicle = nullptr;
765 }
766 }
767 // check whether the vehicle shall be added directly to the network or
768 // shall stay in the internal buffer
769 if (vehicle != nullptr) {
772 }
773 }
774}
775
776
779 // the route was defined without edges and its current edges were
780 // derived from route-stops.
781 // We may need to add additional edges for the vehicle-stops
783 assert(route->getStops().size() > 0);
784 ConstMSEdgeVector edges = route->getEdges();
786 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
787 if (stop.index == 0) {
788 if (edges.front() != stopEdge ||
789 route->getStops().front().endPos < stop.endPos) {
790 edges.insert(edges.begin(), stopEdge);
791 }
792 } else if (stop.index == STOP_INDEX_END) {
793 if (edges.back() != stopEdge ||
794 route->getStops().back().endPos > stop.endPos) {
795 edges.push_back(stopEdge);
796 }
797 } else {
798 WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
799 }
800 }
801 ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
802 isPermanent, new RGBColor(route->getColor()), route->getStops());
803 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
804 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
805 }
806 return newRoute;
807}
808
809
810void
812 try {
813 if (myActiveTransportablePlan->size() == 0) {
814 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
815 error[0] = (char)::toupper((char)error[0]);
816 throw ProcessError(error);
817 }
818 // let's check whether this transportable had to depart before the simulation starts
822 return;
823 }
824 // type existence has been checked on opening
827 && type->getVehicleClass() != SVC_PEDESTRIAN
829 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
830 }
833 if (created > 0) {
835 } else {
837 }
838 } catch (ProcessError&) {
840 throw;
841 }
842}
843
844
845void
849
850
851void
855
856
857void
861
862
863void
867
868
869void
871 try {
872 const std::string fid = myVehicleParameter->id;
873 if (myActiveTransportablePlan->size() == 0) {
874 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
875 }
876 // let's check whether this transportable (person/container) had to depart before the simulation starts
880 return;
881 }
882 // instantiate all persons/containers of this flow
883 int i = 0;
885 std::string baseID = myVehicleParameter->id;
888 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
889 } else {
892 // type existence has been checked on opening
894 addFlowTransportable(t, type, baseID, i++);
895 }
896 }
897 }
898 } else {
901 // poisson: randomize first depart
903 }
904 for (; i < myVehicleParameter->repetitionNumber && (myVehicleParameter->repetitionNumber != std::numeric_limits<int>::max()
906 // type existence has been checked on opening
910 }
911 }
913 } catch (ProcessError&) {
915 throw;
916 }
918}
919
920
921int
922MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
923 try {
924 int numCreated = 0;
925 MSNet* const net = MSNet::getInstance();
928 //MSTransportableControl& pc = net->getPersonControl();
929 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
930 if (quota == 0) {
931 tc.addDiscarded();
932 }
933 for (int j = 0; j < quota; j++) {
934 if (i > 0 || j > 0) {
935 // copy parameter and plan because the transportable takes over responsibility
937 *copyParam = *myVehicleParameter;
938 myVehicleParameter = copyParam;
940 MSStage* lastStage = nullptr;
941 for (MSStage* const s : *myActiveTransportablePlan) {
942 copyPlan->push_back(s->clone());
943 if (lastStage != nullptr && s->getStageType() == MSStageType::WALKING && lastStage->getDestinationStop() != nullptr) {
944 MSStageMoving* walk = static_cast<MSStageMoving*>(copyPlan->back());
945 walk->setDepartPos(lastStage->getDestinationStop()->getAccessPos(walk->getEdge(), &myParsingRNG));
946 }
947 lastStage = s;
948 }
949 myActiveTransportablePlan = copyPlan;
951 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
952 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
953 }
954 }
955 myVehicleParameter->id = (baseID
956 + (i >= 0 ? "." + toString(i) : "")
957 + (j > 0 ? "." + toString(j) : ""));
962 numCreated++;
963 if (!tc.add(transportable)) {
964 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
965 delete transportable;
968 throw ProcessError(error);
969 }
970 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
971 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
972 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);
973 }
974 }
975 return numCreated;
976 } catch (ProcessError&) {
978 throw;
979 }
980}
981
982
983void
986 vehType->check();
987 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
988 const std::string id = vehType->getID();
989 delete vehType;
991 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
992 }
993 } else {
994 if (myCurrentVTypeDistribution != nullptr) {
996 }
997 }
998}
999
1000
1001void
1005 delete myVehicleParameter;
1006 myVehicleParameter = nullptr;
1007 return;
1008 }
1009 // let's check whether vehicles had to depart before the simulation starts
1012 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
1013 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
1016 delete myVehicleParameter;
1017 myVehicleParameter = nullptr;
1018 return;
1019 }
1020 }
1021 }
1022 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
1023 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1024 }
1027 closeRoute(true);
1028 }
1030 if (route == nullptr) {
1031 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1032 }
1033 if (route->mustReroute()) {
1035 if (myVehicleParameter->stops.size() > 0) {
1036 route = addVehicleStopsToImplicitRoute(route, true);
1037 myVehicleParameter->routeid = route->getID();
1038 }
1039 }
1043 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
1044 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
1045 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1046 }
1047 }
1051 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
1052 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
1053 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1054 }
1055 }
1056 myActiveRouteID = "";
1057
1058 // check whether the vehicle shall be added directly to the network or
1059 // shall stay in the internal buffer
1061 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
1063 } else {
1065 delete myVehicleParameter;
1066 } else {
1067 throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
1068 }
1069 }
1070 }
1071 myVehicleParameter = nullptr;
1072}
1073
1074
1075void
1081
1082void
1086
1087void
1091
1092void
1094 if (myVehicleParameter == nullptr) {
1095 throw ProcessError(TLF("Cannot define % stage without %.", toString(modeTag), toString(modeTag)));
1096 }
1097 try {
1098 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1099 std::string agent = "person";
1100 std::string stop = "bus stop";
1102 agent = "container";
1103 stop = "container stop";
1104 }
1105
1106 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1108 throw ProcessError("Found " + mode + " inside " + agent + " element");
1109 }
1110 const std::string aid = myVehicleParameter->id;
1111 bool ok = true;
1112 const MSEdge* from = nullptr;
1113 const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, LINE_ANY);
1114 StringTokenizer st(desc);
1115 MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1116 MSEdge* to = nullptr;
1117 if (s != nullptr) {
1118 to = &s->getLane().getEdge();
1119 }
1120 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1121 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1122
1123 const SUMOVehicleParameter* startVeh = nullptr;
1124 const MSEdge* startVehFrom = nullptr;
1126 if (st.size() != 1) {
1127 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1128 }
1129 // agent starts
1131 const std::string vehID = st.front();
1132 SUMOVehicle* sVeh = vehControl.getVehicle(vehID);
1133 if (sVeh == nullptr) {
1134 if (MSNet::getInstance()->hasFlow(vehID)) {
1135 startVeh = MSNet::getInstance()->getInsertionControl().getFlowPars(vehID);
1136 if (startVeh != nullptr) {
1137 ConstMSRoutePtr const route = MSRoute::dictionary(startVeh->routeid);
1138 startVehFrom = route->getEdges().front();
1139 // flows are inserted at the end of the time step so we
1140 // do delay the pedestrian event by one time step
1141 myVehicleParameter->depart = startVeh->depart + DELTA_T;
1143 }
1144 }
1145 } else {
1146 startVeh = &sVeh->getParameter();
1147 startVehFrom = sVeh->getRoute().getEdges().front();
1148 myVehicleParameter->depart = startVeh->depart;
1149 }
1150 if (startVeh == nullptr) {
1151 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1152 }
1153 if (startVeh->departProcedure == DepartDefinition::TRIGGERED) {
1154 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1155 }
1156 }
1157
1158 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1159 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1160 from = MSEdge::dictionary(fromID);
1161 if (from == nullptr) {
1162 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1163 }
1164 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1165 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1166 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1167 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1168 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1169 if (!(stopWithAccess || transferAtJunction)) {
1170 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1171 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1172 }
1173 }
1174 if (startVeh != nullptr && startVehFrom != from) {
1175 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1176 "' (edge '" + fromID + "' != edge '" + startVehFrom->getID() + "').");
1177 }
1178 } else if (startVeh != nullptr) {
1179 from = startVehFrom;
1180 }
1181 if (myActiveTransportablePlan->empty()) {
1182 if (from == nullptr) {
1183 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1184 } else {
1186 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1187 }
1188 }
1189 // given attribute may override given stopping place due access requirements
1190 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1191 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1192 to = MSEdge::dictionary(toID);
1193 if (to == nullptr) {
1194 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1195 }
1196 }
1197 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1198 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1199 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1200 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1201 myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, 0.0, st.getVector(), group, intendedVeh, intendedDepart));
1202 myParamStack.push_back(myActiveTransportablePlan->back());
1203 } catch (ProcessError&) {
1205 throw;
1206 }
1207}
1208
1210MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1211 bool ok = true;
1212 // dummy stop parameter to hold the attributes
1214 if (stopParam != nullptr) {
1215 stop = *stopParam;
1216 } else {
1217 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1218 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1219 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1220 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1221 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1222 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1223 }
1224 MSStoppingPlace* toStop = nullptr;
1225 if (stop.busstop != "") {
1227 if (toStop == nullptr) {
1228 ok = false;
1229 WRITE_ERROR(TLF("The busStop '%' is not known%.", stop.busstop, errorSuffix));
1230 }
1231 } else if (stop.containerstop != "") {
1233 if (toStop == nullptr) {
1234 ok = false;
1235 WRITE_ERROR(TLF("The containerStop '%' is not known%.", stop.containerstop, errorSuffix));
1236 }
1237 } else if (stop.parkingarea != "") {
1239 if (toStop == nullptr) {
1240 ok = false;
1241 WRITE_ERROR(TLF("The parkingArea '%' is not known%.", stop.parkingarea, errorSuffix));
1242 }
1243 } else if (stop.chargingStation != "") {
1244 // ok, we have a charging station
1246 if (toStop == nullptr) {
1247 ok = false;
1248 WRITE_ERROR(TLF("The chargingStation '%' is not known%.", stop.chargingStation, errorSuffix));
1249 }
1250 } else if (stop.overheadWireSegment != "") {
1251 // ok, we have an overhead wire segment
1253 if (toStop == nullptr) {
1254 ok = false;
1255 WRITE_ERROR(TLF("The overhead wire segment '%' is not known%.", stop.overheadWireSegment, errorSuffix));
1256 }
1257 }
1258 if (!ok && MSGlobals::gCheckRoutes) {
1259 throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1260 }
1261 return toStop;
1262}
1263
1266 Parameterised* result = nullptr;
1267 try {
1268 std::string errorSuffix;
1270 errorSuffix = " in person '" + myVehicleParameter->id + "'";
1272 errorSuffix = " in container '" + myVehicleParameter->id + "'";
1273 } else if (myVehicleParameter != nullptr) {
1274 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'";
1275 } else {
1276 errorSuffix = " in route '" + myActiveRouteID + "'";
1277 }
1279 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1280 if (!ok) {
1282 throw ProcessError();
1283 }
1284 return result;
1285 }
1286 const MSEdge* edge = nullptr;
1287 // patch chargingStation stop on a parkingArea
1288 if (stop.chargingStation != "") {
1290 const MSParkingArea* pa = cs->getParkingArea();
1291 if (pa != nullptr) {
1292 stop.parkingarea = pa->getID();
1294 }
1295 }
1296 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1297 // if one of the previous stops is defined
1298 if (toStop != nullptr) {
1299 const MSLane& l = toStop->getLane();
1300 stop.lane = l.getID();
1301 if ((stop.parametersSet & STOP_END_SET) == 0) {
1302 stop.endPos = toStop->getEndLanePosition();
1303 } else {
1304 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1305 }
1306 stop.startPos = toStop->getBeginLanePosition();
1307 edge = &l.getEdge();
1308 } else {
1309 // no, the lane and the position should be given directly
1310 // get the lane
1311 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1312 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1313 if (ok && stop.edge != "") { // edge is given directly
1314 edge = MSEdge::dictionary(stop.edge);
1315 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1316 throw ProcessError(TLF("The edge '%' for a stop is not known%.", stop.edge, errorSuffix));
1317 }
1318 } else if (ok && stop.lane != "") { // lane is given directly
1319 MSLane* stopLane = MSLane::dictionary(stop.lane);
1320 if (stopLane == nullptr) {
1321 // check for opposite-direction stop
1322 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1323 if (stopLane != nullptr) {
1324 edge = MSEdge::dictionary(stop.edge);
1325 }
1326 } else {
1327 edge = &stopLane->getEdge();
1328 }
1329 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1330 throw ProcessError(TLF("The lane '%' for a stop is not known%.", stop.lane, errorSuffix));
1331 }
1332 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
1333 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
1334 Position pos;
1335 bool geo = false;
1336 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
1337 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
1338 } else {
1339 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
1340 geo = true;
1341 }
1342 PositionVector positions;
1343 positions.push_back(pos);
1344 ConstMSEdgeVector geoEdges;
1346 auto& vc = MSNet::getInstance()->getVehicleControl();
1347 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
1348 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1349 if (type != nullptr) {
1350 vClass = type->getParameter().vehicleClass;
1351 }
1352 }
1353 parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok, true);
1354 if (ok) {
1355 edge = geoEdges.front();
1356 if (geo) {
1358 }
1360 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
1361 } else {
1362 throw ProcessError(TLF("Could not map stop position '%' to the network%.", pos, errorSuffix));
1363 }
1364 } else {
1365 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1366 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1367 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1368 edge = &toStop->getLane().getEdge();
1369 stop.lane = toStop->getLane().getID();
1370 stop.endPos = toStop->getEndLanePosition();
1371 stop.startPos = toStop->getBeginLanePosition();
1372 } else { // use end of movement before definied as lane/edge
1373 edge = myActiveTransportablePlan->back()->getDestination();
1374 stop.lane = edge->getLanes()[0]->getID();
1375 stop.endPos = myActiveTransportablePlan->back()->unspecifiedArrivalPos() ?
1377 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1378 }
1379 } else {
1380 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);
1382 throw ProcessError(msg);
1383 } else {
1384 WRITE_WARNING(msg);
1385 return result;
1386 }
1387 }
1388 }
1389 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1390 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1391 WRITE_WARNINGF(TL("Deprecated attribute 'pos' in description of stop%."), errorSuffix);
1392 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1393 }
1394 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1395 if (!myAmLoadingState) {
1396 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1398 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1399 throw ProcessError(TLF("Invalid start or end position for stop on %'%.",
1400 stop.lane != "" ? ("lane '" + stop.lane) : ("edge '" + stop.edge), errorSuffix));
1401 }
1402 }
1403 }
1404 stop.edge = edge->getID();
1406 if (myActiveTransportablePlan->empty()) {
1407 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1409 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1411 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1412 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1413 if (myActiveTransportablePlan->back()->getDestination()->isTazConnector()) {
1414 myActiveTransportablePlan->back()->setDestination(edge, toStop);
1415 } else if (myActiveTransportablePlan->back()->getJumpDuration() < 0) {
1416 throw ProcessError(TLF("Disconnected plan for % '%' (%!=%).", myActiveTypeName, myVehicleParameter->id,
1417 edge->getID(), myActiveTransportablePlan->back()->getDestination()->getID()));
1418 }
1419 }
1420 // transporting veh stops somewhere
1421 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1423 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1424 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1425 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1426 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1427 WRITE_WARNINGF(TL("Disconnected plan for % '%' (stop range %-% does not cover previous arrival position %)."),
1429 }
1430 }
1431 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1432 double pos = (stop.startPos + stop.endPos) / 2.;
1433 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getJumpDuration() < 0) {
1434 pos = myActiveTransportablePlan->back()->unspecifiedArrivalPos() ?
1436 }
1437 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false, stop.jump));
1438 result = myActiveTransportablePlan->back();
1439
1440 } else if (myVehicleParameter != nullptr) {
1441 myVehicleParameter->stops.push_back(stop);
1442 result = &myVehicleParameter->stops.back();
1443 } else {
1444 myActiveRouteStops.push_back(stop);
1445 result = &myActiveRouteStops.back();
1446 }
1447 if (myInsertStopEdgesAt >= 0) {
1448 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1449 if (edge->isInternal()) {
1450 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1453 }
1456 } else {
1457 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1459 }
1460 } else if (myHaveVia) {
1461 // vias were loaded, check for consistency
1462 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1463 WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'."),
1465 }
1466 }
1467 } catch (ProcessError&) {
1469 throw;
1470 }
1471 return result;
1472}
1473
1474
1475void
1476MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1477 const MSEdge* fromEdge, const MSEdge*& toEdge,
1478 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1479 const MSStage* const lastStage, bool& ok) {
1480 try {
1481 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1482
1483 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1484 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."));
1485 }
1486 departPos = 0.;
1487 if (lastStage != nullptr) {
1488 if (lastStage->getDestinationStop() != nullptr) {
1489 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge, &myParsingRNG);
1490 } else if (lastStage->getDestination() == fromEdge) {
1491 departPos = lastStage->getArrivalPos();
1492 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1493 departPos = fromEdge->getLength();
1494 }
1495 }
1496
1497 bs = retrieveStoppingPlace(attrs, " " + description);
1498 if (bs != nullptr) {
1499 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1500 if (arrivalPos < 0) {
1501 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1502 }
1504 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1505 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1506 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1507 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1508 arrivalPos = arrPos;
1509 } else {
1510 WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1511 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1512 }
1513 }
1514 } else {
1515 if (toEdge == nullptr) {
1516 throw ProcessError(TLF("No destination edge for %.", description));
1517 }
1520 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1521 } else {
1522 arrivalPos = toEdge->getLength() / 2.;
1523 }
1524 }
1525 } catch (ProcessError&) {
1527 throw;
1528 }
1529}
1530
1531
1532void
1534 if (myVehicleParameter == nullptr) {
1535 throw ProcessError(TL("Cannot define person stage without person."));
1536 }
1537 try {
1538 myActiveRoute.clear();
1539 bool ok = true;
1540 const char* const id = myVehicleParameter->id.c_str();
1541 const MSEdge* from = nullptr;
1542 const MSEdge* to = nullptr;
1547 from = myActiveRoute.front();
1548 } else if (myActiveTransportablePlan->empty()) {
1549 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1550 } else {
1551 from = myActiveTransportablePlan->back()->getDestination();
1552 }
1555 to = myActiveRoute.back();
1556 } // else, to may also be derived from stopping place
1557
1558 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1559 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1560 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1561 }
1562
1563 double departPos = 0;
1564 double arrivalPos = 0;
1565 MSStoppingPlace* stoppingPlace = nullptr;
1566 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1567
1568 SVCPermissions modeSet = 0;
1569 if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
1570 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1571 std::string errorMsg;
1572 // try to parse person modes
1573 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1574 throw InvalidArgument(errorMsg);
1575 }
1576 } else {
1577 modeSet = myVehicleParameter->modes;
1578 }
1579 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1581 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, myVehicleParameter->vTypes);
1582 for (StringTokenizer st(types); st.hasNext();) {
1583 const std::string vtypeid = st.next();
1584 const MSVehicleType* const vType = vehControl.getVType(vtypeid);
1585 if (vType == nullptr) {
1586 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1587 }
1588 modeSet |= (vType->getVehicleClass() == SVC_BICYCLE) ? SVC_BICYCLE : SVC_PASSENGER;
1589 }
1590 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1591 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1592 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1593 }
1594 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1595 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1596 if (ok) {
1597 if (myActiveTransportablePlan->empty()) {
1598 double initialDepartPos = myVehicleParameter->departPos;
1600 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1601 }
1602 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1603 }
1605 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1606 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1607 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1608 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1609 myParamStack.push_back(myActiveTransportablePlan->back());
1612 }
1613 }
1614 myActiveRoute.clear();
1615 } catch (ProcessError&) {
1617 throw;
1618 }
1619}
1620
1621
1622void
1624 if (myVehicleParameter == nullptr) {
1625 throw ProcessError(TL("Cannot define person stage without person."));
1626 }
1627 myActiveRouteID = "";
1629 try {
1630 myActiveRoute.clear();
1631 bool ok = true;
1632 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1633 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1634 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1635 }
1636 double speed = -1; // default to vType speed
1637 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1638 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1639 if (speed <= 0) {
1640 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1641 }
1642 }
1643 double departPos = 0;
1644 double arrivalPos = 0;
1645 MSStoppingPlace* bs = nullptr;
1646 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1647 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1649 if (route == nullptr) {
1650 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1651 }
1652 myActiveRoute = route->getEdges();
1653 } else {
1655 }
1656 if (myActiveTransportablePlan->empty()) {
1657 double initialDepartPos = myVehicleParameter->departPos;
1659 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1660 }
1661 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1662 }
1663 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1664 if (myActiveRoute.empty()) {
1665 throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1666 }
1667 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1668 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1669 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1670 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1671 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1672 }
1673 }
1674 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1675 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1676 myActiveTransportablePlan->push_back(new MSStageWalking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1677 myParamStack.push_back(myActiveTransportablePlan->back());
1680 }
1681 myActiveRoute.clear();
1682 } catch (ProcessError&) {
1684 throw;
1685 }
1686 } else { // parse walks from->to as person trips
1687 addPersonTrip(attrs);
1688 }
1689}
1690
1691double
1692MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1693 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1694 if (value == "") {
1695 return pos;
1696 }
1697 std::string error;
1699 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1700 if (dpd != DepartPosLatDefinition::GIVEN) {
1702 if (lane == nullptr) {
1703 throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1704 }
1705 const double usableWidth = lane->getWidth() - 0.5;
1706 switch (dpd) {
1708 pos = -usableWidth / 2;
1709 break;
1711 pos = usableWidth / 2;
1712 break;
1714 pos = 0;
1715 break;
1721 break;
1722 default:
1723 break;
1724 }
1725 }
1726 } else {
1727 throw ProcessError(error);
1728 }
1729 return pos;
1730}
1731
1732
1733void
1734MSRouteHandler::addTransportable(const SUMOSAXAttributes& /*attrs*/, const bool isPerson) {
1736 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1737 const std::string error = TLF("The type '%' for % '%' is not known.", myVehicleParameter->vtypeid, myActiveTypeName, myVehicleParameter->id);
1739 throw ProcessError(error);
1740 }
1742}
1743
1744
1745void
1747 try {
1748 myActiveRoute.clear();
1749 const std::string cid = myVehicleParameter->id;
1750 bool ok = true;
1751 const MSEdge* from = nullptr;
1752 const MSEdge* to = nullptr;
1753 MSStoppingPlace* cs = nullptr;
1754
1755 double speed;
1757 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1758 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1759 if (!ok) {
1760 throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1761 }
1762 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1763 speed = vtype->getMaxSpeed();
1764 } else { // default speed value
1766 }
1767 if (speed <= 0) {
1768 throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1769 }
1770 // values from preceding stage:
1771 const MSEdge* preEdge = nullptr;
1772 double prePos = 0;
1773 if (!myActiveTransportablePlan->empty()) {
1774 preEdge = myActiveTransportablePlan->back()->getDestination();
1775 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1776 }
1777 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1778 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1779
1780 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1781 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1782 } else {
1783 // set 'from':
1784 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1785 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1786 from = MSEdge::dictionary(fromID);
1787 if (from == nullptr) {
1788 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1789 }
1790 if (preEdge != nullptr && preEdge != from) {
1791 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1792 }
1793 } else if (preEdge == nullptr) {
1794 throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1795 } else {
1796 from = preEdge;
1797 }
1798 // set 'to':
1799 if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1800 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1801 to = MSEdge::dictionary(toID);
1802 if (to == nullptr) {
1803 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1804 }
1805 } else {
1806 const std::string description = "container '" + cid + "' transhipping from edge '" + from->getID() + "'";
1807 cs = retrieveStoppingPlace(attrs, " " + description);
1808 if (cs != nullptr) {
1809 to = &cs->getLane().getEdge();
1810 } else {
1811 throw ProcessError(TLF("Inconsistent tranship for container '%', needs either: 'edges', 'to', 'containerStop' (or any other stopping place)", cid));
1812 }
1813 }
1814 myActiveRoute.push_back(from);
1815 myActiveRoute.push_back(to);
1816 }
1817 if (myActiveRoute.empty()) {
1818 throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1819 }
1820 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1822 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1823 }
1824 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1825 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1826 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1827 myParamStack.push_back(myActiveTransportablePlan->back());
1828 myActiveRoute.clear();
1829 } catch (ProcessError&) {
1831 throw;
1832 }
1833}
1834
1835
1836void
1838 for (const auto& edge : MSEdge::getAllEdges()) {
1839 if (edge->isNormal() || MSGlobals::gUsingInternalLanes) {
1840 for (MSLane* lane : edge->getLanes()) {
1841 Boundary b = lane->getShape().getBoxBoundary();
1842 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1843 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1844 tree->Insert(cmin, cmax, lane);
1845 }
1846 }
1847 }
1848}
1849
1850
1851SumoRNG*
1853 return &myParsingRNG;
1854}
1855
1856
1857MSEdge*
1858MSRouteHandler::retrieveEdge(const std::string& id) {
1859 return MSEdge::dictionary(id);
1860}
1861
1862
1863/****************************************************************************/
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:288
#define WRITE_ERROR(msg)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
#define TLF(string,...)
Definition MsgHandler.h:307
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 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_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: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: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:2463
bool isInternal() const
Definition MSLane.cpp:2594
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:186
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:476
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:486
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition MSNet.cpp:1210
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1404
bool hasContainers() const
Returns whether containers are simulated.
Definition MSNet.h:416
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:400
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:436
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:383
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1201
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
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.
SumoRNG * getRNG() 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: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:97
static const double ARRIVALPOS_UNSPECIFIED
sentinel value
Definition MSStage.h:72
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition MSStage.h:88
MSStageType getStageType() const
Definition MSStage.h:138
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.
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: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.
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
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 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.
std::string busstop
(Optional) bus stop if one is assigned to the stop
std::string containerstop
(Optional) container stop if one is assigned to the stop
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
void incrementFlow(double scale, SumoRNG *rng=nullptr)
increment flow
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
int repetitionsDone
The number of times the vehicle was already inserted.
SUMOTime repetitionTotalOffset
The offset between depart and the time for the next vehicle insertions.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
SVCPermissions modes
The modes a person or container can use.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
std::string vTypes
The types of usable (auto-generated) vehicles for a person / container.
double departPos
(optional) The position the vehicle shall depart from
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
static bool parsePersonModes(const std::string &modes, const std::string &element, const std::string &id, SVCPermissions &modeSet, std::string &error)
Validates a given person modes value.
static bool parseDepartPosLat(const std::string &val, const std::string &element, const std::string &id, double &pos, DepartPosLatDefinition &dpd, std::string &error)
Validates a given departPosLat value.
std::string toTaz
The vehicle's destination zone (district)
static double interpretEdgePos(double pos, double maximumValue, SumoXMLAttr attr, const std::string &id, bool silent=false)
Interprets negative edge positions and fits them onto a given edge.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int arrivalEdge
(optional) The final edge within the route of the vehicle
std::string fromTaz
The vehicle's origin zone (district)
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static double parseWalkPos(SumoXMLAttr attr, const bool hardFail, const std::string &id, double maxPos, const std::string &val, SumoRNG *rng=0)
parse departPos or arrivalPos for a walk
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it