Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSRouteHandler.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
23// Parser and container for routes during their loading
24/****************************************************************************/
25#include <config.h>
26
27#include "MSRouteHandler.h"
35#include <microsim/MSEdge.h>
36#include <microsim/MSLane.h>
48
49// ===========================================================================
50// static members
51// ===========================================================================
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)) {
317 return;
318 }
321 throw ProcessError(TLF("Vehicle type distribution '%' is empty.", myCurrentVTypeDistributionID));
322 }
323 if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
325 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", myCurrentVTypeDistributionID));
326 }
328 }
329}
330
331
332void
336 // check whether the id is really necessary
337 std::string rid;
338 if (myCurrentRouteDistribution != nullptr) {
340 rid = "distribution '" + myCurrentRouteDistributionID + "'";
341 } else if (myVehicleParameter != nullptr) {
342 // ok, a vehicle is wrapping the route,
343 // we may use this vehicle's id as default
344 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
345 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
346 WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
347 }
348 } else {
349 bool ok = true;
350 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
351 if (!ok) {
352 return;
353 }
354 rid = "'" + myActiveRouteID + "'";
355 }
356 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
357 rid = "for vehicle '" + myVehicleParameter->id + "'";
358 }
359 bool ok = true;
360 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
361 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
362 }
363 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
365 throw ProcessError(TLF("Invalid reference to route '%' in route %.", myActiveRouteRefID, rid));
366 }
369 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
373 // handle obsolete attribute name
375 myActiveRoutePermanent = attrs.getOpt<bool>(SUMO_ATTR_STATE, myActiveRouteID.c_str(), ok, false);
376 if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
377 WRITE_WARNING(TL("Attribute 'period' is deprecated for route. Use 'cycleTime' instead."));
378 }
379 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
380 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
381 WRITE_WARNING(TLF("Invalid cost for route '%'.", myActiveRouteID));
382 }
383}
384
385
386void
388 // Currently unused
389}
390
391
392void
394 // Currently unused
395}
396
397
398void
400 // Currently unsued
401}
402
403
404void
405MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
406 std::string type = "vehicle";
407 if (mayBeDisconnected) {
409 type = "flow";
410 } else {
411 type = "trip";
412 }
413 }
414
415 try {
416 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
417 if (mustReroute) {
418 // implicit route from stops
420 myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
421 }
422 }
423 if (myActiveRoute.size() == 0) {
424 delete myActiveRouteColor;
425 myActiveRouteColor = nullptr;
426 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
428 if (route != nullptr) {
430 }
431 myActiveRouteID = "";
433 return;
434 }
435 if (myVehicleParameter != nullptr) {
436 throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
437 } else {
438 throw ProcessError(TLF("Route '%' has no edges.", myActiveRouteID));
439 }
440 }
441 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
442 throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
443 }
444 if (myActiveRouteRepeat > 0) {
445 // duplicate route
447 auto tmpStops = myActiveRouteStops;
448
451 std::string errSuffix = ".";
452 if (myVehicleParameter != nullptr) {
455 if (vtype != nullptr) {
456 vClass = vtype->getVehicleClass();
457 errSuffix = TLF(" for vehicle '%' with vClass %.", myVehicleParameter->id, getVehicleClassNames(vClass));
458 }
459 }
460 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
461 if (tmpStops.size() == 0 || tmpStops.back().jump < 0) {
462 throw ProcessError(TLF("Disconnected route '%' when repeating. Last edge '%' is not connected to first edge '%'%",
463 myActiveRouteID, myActiveRoute.back()->getID(), myActiveRoute.front()->getID(), errSuffix));
464 }
465 }
466 }
467 for (int i = 0; i < myActiveRouteRepeat; i++) {
468 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
469 for (SUMOVehicleParameter::Stop stop : tmpStops) {
470 if (stop.until > 0) {
471 if (myActiveRoutePeriod <= 0) {
472 const std::string description = myVehicleParameter != nullptr
473 ? "for " + type + " '" + myVehicleParameter->id + "'"
474 : "'" + myActiveRouteID + "'";
475 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
476 }
477 stop.until += myActiveRoutePeriod * (i + 1);
478 }
479 if (stop.arrival > 0) {
480 if (myActiveRoutePeriod <= 0) {
481 const std::string description = myVehicleParameter != nullptr
482 ? "for " + type + " '" + myVehicleParameter->id + "'"
483 : "'" + myActiveRouteID + "'";
484 throw ProcessError(TLF("Cannot repeat stops with 'arrival' in route % because no cycleTime is defined.", description));
485 }
486 stop.arrival += myActiveRoutePeriod * (i + 1);
487 }
488 stop.index = STOP_INDEX_REPEAT;
489 myActiveRouteStops.push_back(stop);
490 }
491 }
492 if (myActiveRouteStops.size() > 0) {
493 // never jump on the last stop of a repeating route
494 myActiveRouteStops.back().jump = -1;
495 }
496 }
497 MSRoute* const route = new MSRoute(myActiveRouteID, myActiveRoute,
502 route->setCosts(myCurrentCosts);
503 route->setReroute(mustReroute);
504 myActiveRoute.clear();
505 ConstMSRoutePtr constRoute = std::shared_ptr<const MSRoute>(route);
506 if (!MSRoute::dictionary(myActiveRouteID, constRoute)) {
508 if (myVehicleParameter != nullptr) {
509 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
510 throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
511 } else {
512 throw ProcessError(TLF("A vehicle with id '%' already exists.", myVehicleParameter->id));
513 }
514 } else {
515 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myActiveRouteID));
516 }
517 }
518 } else {
519 if (myCurrentRouteDistribution != nullptr) {
521 }
522 }
523 myActiveRouteID = "";
524 myActiveRouteColor = nullptr;
525 myActiveRouteStops.clear();
527 } catch (ProcessError&) {
529 throw;
530 }
531}
532
533
534void
536 // check whether the id is really necessary
537 if (myVehicleParameter != nullptr) {
538 // ok, a vehicle is wrapping the route,
539 // we may use this vehicle's id as default
540 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
541 // we have to record this or we cannot remove the distribution later
543 } else {
544 bool ok = true;
545 myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
546 if (!ok) {
547 return;
548 }
549 }
551 std::vector<double> probs;
552 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
553 bool ok = true;
554 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
555 while (st.hasNext()) {
556 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
557 }
558 }
559 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
560 bool ok = true;
561 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
562 int probIndex = 0;
563 while (st.hasNext()) {
564 std::string routeID = st.next();
566 if (route == nullptr) {
567 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
568 }
569 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
570 myCurrentRouteDistribution->add(route, prob, false);
571 probIndex++;
572 }
573 if (probs.size() > 0 && probIndex != (int)probs.size()) {
574 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
575 " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
576 }
577 }
578}
579
580
581void
583 if (myCurrentRouteDistribution != nullptr) {
584 const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
585 if (MSGlobals::gStateLoaded && haveSameID) {
588 return;
589 }
590 if (haveSameID) {
592 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myCurrentRouteDistributionID));
593 }
596 throw ProcessError(TLF("Route distribution '%' is empty.", myCurrentRouteDistributionID));
597 }
600 }
601}
602
603
604void
606 // get nested route
607 const std::string embeddedRouteID = "!" + myVehicleParameter->id;
608 ConstMSRoutePtr route = nullptr;
609 if (myReplayRerouting) {
611 if (rDist != nullptr && rDist->getVals().size() > 0) {
612 route = rDist->getVals().front();
613 }
614 }
615 if (route == nullptr) {
616 route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
617 }
620 // let's check whether this vehicle had to depart before the simulation starts
623 return;
624 }
625 }
626
627 // get the vehicle's type
628 MSVehicleType* vtype = nullptr;
629
630 try {
631 if (myVehicleParameter->vtypeid != "") {
632 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
633 if (vtype == nullptr) {
634 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
635 }
636 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
637 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
638 }
639 } else {
640 // there should be one (at least the default one)
641 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
642 }
644 // if the route id was given, prefer that one
645 if (route != nullptr && !myAmLoadingState) {
646 WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
647 }
649 }
650 if (route == nullptr) {
651 // nothing found? -> error
652 if (myVehicleParameter->routeid != "") {
653 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
654 } else {
655 throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
656 }
657 }
658 myActiveRouteID = "";
659
660 } catch (ProcessError&) {
662 throw;
663 }
664 if (route->mustReroute()) {
666 if (myVehicleParameter->stops.size() > 0) {
667 route = addVehicleStopsToImplicitRoute(route, false);
668 }
669 }
673 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
674 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
675 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
676 }
677 }
681 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
682 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
683 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
684 }
685 }
686
687 // try to build the vehicle
688 SUMOVehicle* vehicle = nullptr;
689 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
691 try {
692 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
693 } catch (const ProcessError& e) {
694 myVehicleParameter = nullptr;
696 WRITE_WARNING(e.what());
697 vehControl.deleteVehicle(vehicle, true);
698 myVehicleParameter = nullptr;
699 vehicle = nullptr;
700 return;
701 } else {
702 throw;
703 }
704 }
705 const SUMOTime origDepart = myVehicleParameter->depart;
706 // maybe we do not want this vehicle to be inserted due to scaling
707 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
708 if (quota > 0) {
711 vehControl.addVehicle(myVehicleParameter->id, vehicle);
712 if (myReplayRerouting) {
714 if (rDist != nullptr) {
715 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
716 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
717 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
718 if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
719 // routing in the insertion step happens *after* insertion
721 } else {
723 }
724 }
725 }
726 }
727 int offset = 0;
728 for (int i = 1; i < quota; i++) {
731 }
733 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
734 while (vehControl.getVehicle(newPars->id) != nullptr) {
735 offset += 1;
736 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
737 }
740 // resample type
741 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
742 }
743 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
744 vehControl.addVehicle(newPars->id, vehicle);
745 }
746 myVehicleParameter = nullptr;
747 } else {
748 vehControl.deleteVehicle(vehicle, true);
749 myVehicleParameter = nullptr;
750 vehicle = nullptr;
751 }
752 } else {
753 // strange: another vehicle with the same id already exists
755 // and was not loaded while loading a simulation state
756 // -> error
757 std::string veh_id = myVehicleParameter->id;
759 std::string scaleWarning = "";
760 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
761 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
762 }
763 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
764 } else {
765 // ok, it seems to be loaded previously while loading a simulation state
766 vehicle = nullptr;
767 }
768 }
769 // check whether the vehicle shall be added directly to the network or
770 // shall stay in the internal buffer
771 if (vehicle != nullptr) {
774 }
775 }
776}
777
778
781 // the route was defined without edges and its current edges were
782 // derived from route-stops.
783 // We may need to add additional edges for the vehicle-stops
785 assert(route->getStops().size() > 0);
786 ConstMSEdgeVector edges = route->getEdges();
788 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
789 if (stop.index == 0) {
790 if (edges.front() != stopEdge ||
791 route->getStops().front().endPos < stop.endPos) {
792 edges.insert(edges.begin(), stopEdge);
793 }
794 } else if (stop.index == STOP_INDEX_END) {
795 if (edges.back() != stopEdge ||
796 route->getStops().back().endPos > stop.endPos) {
797 edges.push_back(stopEdge);
798 }
799 } else {
800 WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
801 }
802 }
803 ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
804 isPermanent, new RGBColor(route->getColor()), route->getStops());
805 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
806 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
807 }
808 return newRoute;
809}
810
811
812void
814 try {
815 if (myActiveTransportablePlan->size() == 0) {
816 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
817 error[0] = (char)::toupper((char)error[0]);
818 throw ProcessError(error);
819 }
820 // let's check whether this transportable had to depart before the simulation starts
824 return;
825 }
826 // type existence has been checked on opening
829 && type->getVehicleClass() != SVC_PEDESTRIAN
831 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
832 }
835 if (created > 0) {
837 } else {
839 }
840 } catch (ProcessError&) {
842 throw;
843 }
844}
845
846
847void
851
852
853void
857
858
859void
863
864
865void
869
870
871void
873 try {
874 const std::string fid = myVehicleParameter->id;
875 if (myActiveTransportablePlan->size() == 0) {
876 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
877 }
878 // let's check whether this transportable (person/container) had to depart before the simulation starts
882 return;
883 }
884 // instantiate all persons/containers of this flow
885 int i = 0;
887 std::string baseID = myVehicleParameter->id;
890 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
891 } else {
894 // type existence has been checked on opening
896 addFlowTransportable(t, type, baseID, i++);
897 }
898 }
899 }
900 } else {
903 // poisson: randomize first depart
905 }
906 for (; i < myVehicleParameter->repetitionNumber && (myVehicleParameter->repetitionNumber != std::numeric_limits<long long int>::max()
908 // type existence has been checked on opening
912 }
913 }
915 } catch (ProcessError&) {
917 throw;
918 }
920}
921
922
923int
924MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
925 try {
926 int numCreated = 0;
927 MSNet* const net = MSNet::getInstance();
930 //MSTransportableControl& pc = net->getPersonControl();
931 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
932 if (quota == 0) {
933 tc.addDiscarded();
934 }
935 for (int j = 0; j < quota; j++) {
936 if (i > 0 || j > 0) {
937 // copy parameter and plan because the transportable takes over responsibility
939 *copyParam = *myVehicleParameter;
940 myVehicleParameter = copyParam;
942 MSStage* lastStage = nullptr;
943 for (MSStage* const s : *myActiveTransportablePlan) {
944 copyPlan->push_back(s->clone());
945 if (lastStage != nullptr && s->getStageType() == MSStageType::WALKING && lastStage->getDestinationStop() != nullptr) {
946 MSStageMoving* walk = static_cast<MSStageMoving*>(copyPlan->back());
947 walk->setDepartPos(lastStage->getDestinationStop()->getAccessPos(walk->getEdge(), &myParsingRNG));
948 }
949 lastStage = s;
950 }
951 myActiveTransportablePlan = copyPlan;
953 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
954 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
955 }
956 }
957 myVehicleParameter->id = (baseID
958 + (i >= 0 ? "." + toString(i) : "")
959 + (j > 0 ? "." + toString(j) : ""));
960 if (MSGlobals::gStateLoaded && tc.get(myVehicleParameter->id) != nullptr) {
961 return numCreated;
962 }
967 numCreated++;
968 if (!tc.add(transportable)) {
969 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
970 delete transportable;
972 throw ProcessError(error);
973 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
974 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
975 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);
976 }
977 }
978 return numCreated;
979 } catch (ProcessError&) {
981 throw;
982 }
983}
984
985
986void
988 MSVehicleType* vehType = nullptr;
989 if (myCurrentVTypeRef.empty()) {
991 vehType->check();
992 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
993 const std::string id = vehType->getID();
994 delete vehType;
996 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
997 }
998 }
999 }
1000 if (myCurrentVTypeDistribution != nullptr) {
1001 if (!myCurrentVTypeRef.empty()) {
1003 if (dist != nullptr) {
1004 const double distProb = (myCurrentVTypeProbability >= 0 ? myCurrentVTypeProbability : 1) / dist->getOverallProb();
1005 std::vector<double>::const_iterator probIt = dist->getProbs().begin();
1006 for (MSVehicleType* const type : dist->getVals()) {
1007 myCurrentVTypeDistribution->add(type, distProb * *probIt);
1008 probIt++;
1009 }
1010 return;
1011 } else {
1013 }
1014 }
1015 double probability = myCurrentVTypeProbability >= 0 ? myCurrentVTypeProbability : vehType->getDefaultProbability();
1016 myCurrentVTypeDistribution->add(vehType, probability);
1017 }
1018}
1019
1020
1021void
1025 delete myVehicleParameter;
1026 myVehicleParameter = nullptr;
1027 return;
1028 }
1029 // let's check whether vehicles had to depart before the simulation starts
1032 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
1033 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
1036 delete myVehicleParameter;
1037 myVehicleParameter = nullptr;
1038 return;
1039 }
1040 }
1041 }
1042 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
1043 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1044 }
1047 closeRoute(true);
1048 }
1050 if (route == nullptr) {
1051 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1052 }
1053 if (route->mustReroute()) {
1055 if (myVehicleParameter->stops.size() > 0) {
1056 route = addVehicleStopsToImplicitRoute(route, true);
1057 myVehicleParameter->routeid = route->getID();
1058 }
1059 }
1063 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
1064 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
1065 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1066 }
1067 }
1071 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
1072 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
1073 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1074 }
1075 }
1076 myActiveRouteID = "";
1077
1078 // check whether the vehicle shall be added directly to the network or
1079 // shall stay in the internal buffer
1081 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
1083 } else {
1085 delete myVehicleParameter;
1086 } else {
1087 throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
1088 }
1089 }
1090 }
1091 myVehicleParameter = nullptr;
1092}
1093
1094
1095void
1101
1102void
1106
1107void
1111
1112void
1114 if (myVehicleParameter == nullptr) {
1115 throw ProcessError(TLF("Cannot define % stage without %.", toString(modeTag), toString(modeTag)));
1116 }
1117 try {
1118 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1119 std::string agent = "person";
1120 std::string stop = "bus stop";
1122 agent = "container";
1123 stop = "container stop";
1124 }
1125
1126 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1128 throw ProcessError("Found " + mode + " inside " + agent + " element");
1129 }
1130 const std::string aid = myVehicleParameter->id;
1131 bool ok = true;
1132 const MSEdge* from = nullptr;
1133 const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, LINE_ANY);
1134 StringTokenizer st(desc);
1135 MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1136 MSEdge* to = nullptr;
1137 if (s != nullptr) {
1138 to = &s->getLane().getEdge();
1139 }
1140 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1141 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1142
1143 const SUMOVehicleParameter* startVeh = nullptr;
1144 const MSEdge* startVehFrom = nullptr;
1146 if (st.size() != 1) {
1147 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1148 }
1149 // agent starts
1151 const std::string vehID = st.front();
1152 SUMOVehicle* sVeh = vehControl.getVehicle(vehID);
1153 if (sVeh == nullptr) {
1154 if (MSNet::getInstance()->hasFlow(vehID)) {
1155 startVeh = MSNet::getInstance()->getInsertionControl().getFlowPars(vehID);
1156 if (startVeh != nullptr) {
1157 ConstMSRoutePtr const route = MSRoute::dictionary(startVeh->routeid);
1158 startVehFrom = route->getEdges().front();
1159 // flows are inserted at the end of the time step so we
1160 // do delay the pedestrian event by one time step
1161 myVehicleParameter->depart = startVeh->depart + DELTA_T;
1163 }
1164 }
1165 } else {
1166 startVeh = &sVeh->getParameter();
1167 startVehFrom = sVeh->getRoute().getEdges().front();
1168 myVehicleParameter->depart = startVeh->depart;
1169 }
1170 if (startVeh == nullptr) {
1171 if (mySkippedVehicles.count(vehID) == 0) {
1172 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1173 }
1174 // we cannot simply throw here because we need to parse the rest of the person (just to discard it)
1175 from = MSEdge::getAllEdges().front(); // a dummy edge to keep parsing active
1176 } else if (startVeh->departProcedure == DepartDefinition::TRIGGERED) {
1177 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1178 }
1179 }
1180
1181 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1182 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1183 from = MSEdge::dictionary(fromID);
1184 if (from == nullptr) {
1185 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1186 }
1187 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1188 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1189 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1190 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1191 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1192 if (!(stopWithAccess || transferAtJunction)) {
1193 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1194 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1195 }
1196 }
1197 if (startVeh != nullptr && startVehFrom != from) {
1198 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1199 "' (edge '" + fromID + "' != edge '" + startVehFrom->getID() + "').");
1200 }
1201 } else if (startVeh != nullptr) {
1202 from = startVehFrom;
1203 }
1204 if (myActiveTransportablePlan->empty()) {
1205 if (from == nullptr) {
1206 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1207 } else {
1209 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1210 }
1211 }
1212 // given attribute may override given stopping place due access requirements
1213 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1214 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1215 to = MSEdge::dictionary(toID);
1216 if (to == nullptr) {
1217 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1218 }
1219 }
1220 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1221 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1222 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1223 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1224 MSStageDriving* stage = new MSStageDriving(from, to, s, arrivalPos, 0.0, st.getVector(), group, intendedVeh, intendedDepart);
1225 // for loading from saved state
1226 stage->setDeparted(attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1));
1227 stage->setEnded(attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1));
1228 stage->setVehicleID(attrs.getOpt<std::string>(SUMO_ATTR_VEHICLE, nullptr, ok, ""));
1229 stage->setVehicleDistance(attrs.getOpt<double>(SUMO_ATTR_ROUTELENGTH, nullptr, ok, -1));
1230 myActiveTransportablePlan->push_back(stage);
1231 myParamStack.push_back(stage);
1232 } catch (ProcessError&) {
1234 throw;
1235 }
1236}
1237
1239MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1240 bool ok = true;
1241 // dummy stop parameter to hold the attributes
1243 if (stopParam != nullptr) {
1244 stop = *stopParam;
1245 } else {
1246 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1247 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1248 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1249 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1250 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1251 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1252 }
1253 MSStoppingPlace* toStop = nullptr;
1254 if (stop.busstop != "") {
1256 if (toStop == nullptr) {
1257 ok = false;
1258 WRITE_ERROR(TLF("The busStop '%' is not known%.", stop.busstop, errorSuffix));
1259 }
1260 } else if (stop.containerstop != "") {
1262 if (toStop == nullptr) {
1263 ok = false;
1264 WRITE_ERROR(TLF("The containerStop '%' is not known%.", stop.containerstop, errorSuffix));
1265 }
1266 } else if (stop.parkingarea != "") {
1268 if (toStop == nullptr) {
1269 ok = false;
1270 WRITE_ERROR(TLF("The parkingArea '%' is not known%.", stop.parkingarea, errorSuffix));
1271 }
1272 } else if (stop.chargingStation != "") {
1273 // ok, we have a charging station
1275 if (toStop == nullptr) {
1276 ok = false;
1277 WRITE_ERROR(TLF("The chargingStation '%' is not known%.", stop.chargingStation, errorSuffix));
1278 }
1279 } else if (stop.overheadWireSegment != "") {
1280 // ok, we have an overhead wire segment
1282 if (toStop == nullptr) {
1283 ok = false;
1284 WRITE_ERROR(TLF("The overhead wire segment '%' is not known%.", stop.overheadWireSegment, errorSuffix));
1285 }
1286 }
1287 if (!ok && MSGlobals::gCheckRoutes) {
1288 throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1289 }
1290 return toStop;
1291}
1292
1295 Parameterised* result = nullptr;
1296 try {
1297 std::string errorSuffix;
1299 errorSuffix = " in person '" + myVehicleParameter->id + "'";
1301 errorSuffix = " in container '" + myVehicleParameter->id + "'";
1302 } else if (myVehicleParameter != nullptr) {
1303 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'";
1304 } else {
1305 errorSuffix = " in route '" + myActiveRouteID + "'";
1306 }
1308 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1309 if (!ok) {
1311 throw ProcessError();
1312 }
1313 return result;
1314 }
1315 const MSEdge* edge = nullptr;
1316 // patch chargingStation stop on a parkingArea
1317 if (stop.chargingStation != "") {
1319 const MSParkingArea* pa = cs->getParkingArea();
1320 if (pa != nullptr) {
1321 stop.parkingarea = pa->getID();
1323 }
1324 }
1325 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1326 // if one of the previous stops is defined
1327 if (toStop != nullptr) {
1328 const MSLane& l = toStop->getLane();
1329 stop.lane = l.getID();
1330 if ((stop.parametersSet & STOP_END_SET) == 0) {
1331 stop.endPos = toStop->getEndLanePosition();
1332 } else {
1333 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1334 }
1335 stop.startPos = toStop->getBeginLanePosition();
1336 edge = &l.getEdge();
1337 } else {
1338 // no, the lane and the position should be given directly
1339 // get the lane
1340 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1341 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1342 if (ok && stop.edge != "") { // edge is given directly
1343 edge = MSEdge::dictionary(stop.edge);
1344 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1345 throw ProcessError(TLF("The edge '%' for a stop is not known%.", stop.edge, errorSuffix));
1346 }
1347 } else if (ok && stop.lane != "") { // lane is given directly
1348 MSLane* stopLane = MSLane::dictionary(stop.lane);
1349 if (stopLane == nullptr) {
1350 // check for opposite-direction stop
1351 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1352 if (stopLane != nullptr) {
1353 edge = MSEdge::dictionary(stop.edge);
1354 }
1355 } else {
1356 edge = &stopLane->getEdge();
1357 }
1358 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1359 throw ProcessError(TLF("The lane '%' for a stop is not known%.", stop.lane, errorSuffix));
1360 }
1361 } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
1362 || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
1363 Position pos;
1364 bool geo = false;
1365 if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
1366 pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
1367 } else {
1368 pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
1369 geo = true;
1370 }
1371 PositionVector positions;
1372 positions.push_back(pos);
1373 ConstMSEdgeVector geoEdges;
1375 auto& vc = MSNet::getInstance()->getVehicleControl();
1376 if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
1377 MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1378 if (type != nullptr) {
1379 vClass = type->getParameter().vehicleClass;
1380 }
1381 }
1382 parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok, true);
1383 if (ok) {
1384 edge = geoEdges.front();
1385 if (geo) {
1387 }
1389 stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
1390 } else {
1391 throw ProcessError(TLF("Could not map stop position '%' to the network%.", pos, errorSuffix));
1392 }
1393 } else {
1394 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1395 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1396 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1397 edge = &toStop->getLane().getEdge();
1398 stop.lane = toStop->getLane().getID();
1399 stop.endPos = toStop->getEndLanePosition();
1400 stop.startPos = toStop->getBeginLanePosition();
1401 } else { // use end of movement before definied as lane/edge
1402 edge = myActiveTransportablePlan->back()->getDestination();
1403 stop.lane = edge->getLanes()[0]->getID();
1404 stop.endPos = myActiveTransportablePlan->back()->unspecifiedArrivalPos() ?
1406 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1407 }
1408 } else {
1409 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);
1411 throw ProcessError(msg);
1412 } else {
1413 WRITE_WARNING(msg);
1414 return result;
1415 }
1416 }
1417 }
1418 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1419 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1420 WRITE_WARNINGF(TL("Deprecated attribute 'pos' in description of stop%."), errorSuffix);
1421 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1422 }
1423 if (stop.endPos < 0) {
1424 stop.endPos += edge->getLength();
1425 }
1426 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1427 if (!myAmLoadingState) {
1428 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1430 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1431 throw ProcessError(TLF("Invalid start or end position for stop on %'%.",
1432 stop.lane != "" ? ("lane '" + stop.lane) : ("edge '" + stop.edge), errorSuffix));
1433 }
1434 }
1435 }
1436 stop.edge = edge->getID();
1438 if (myActiveTransportablePlan->empty()) {
1439 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1441 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1443 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1444 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1445 if (myActiveTransportablePlan->back()->getDestination()->isTazConnector()) {
1446 myActiveTransportablePlan->back()->setDestination(edge, toStop);
1447 } else if (myActiveTransportablePlan->back()->getJumpDuration() < 0) {
1448 throw ProcessError(TLF("Disconnected plan for % '%' (%!=%).", myActiveTypeName, myVehicleParameter->id,
1449 edge->getID(), myActiveTransportablePlan->back()->getDestination()->getID()));
1450 }
1451 }
1452 // transporting veh stops somewhere
1453 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1455 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1456 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1457 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1458 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1459 WRITE_WARNINGF(TL("Disconnected plan for % '%' (stop range %-% does not cover previous arrival position %)."),
1461 }
1462 }
1463 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1464 double pos = (stop.startPos + stop.endPos) / 2.;
1465 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getJumpDuration() < 0) {
1466 pos = myActiveTransportablePlan->back()->unspecifiedArrivalPos() ?
1468 }
1469 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false, stop.jump));
1470 result = myActiveTransportablePlan->back();
1471
1472 } else if (myVehicleParameter != nullptr) {
1473 myVehicleParameter->stops.push_back(stop);
1474 result = &myVehicleParameter->stops.back();
1475 } else {
1476 myActiveRouteStops.push_back(stop);
1477 result = &myActiveRouteStops.back();
1478 }
1479 if (myInsertStopEdgesAt >= 0) {
1480 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1481 if (edge->isInternal()) {
1482 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1485 }
1488 } else {
1489 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1491 }
1492 } else if (myHaveVia) {
1493 // vias were loaded, check for consistency
1494 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1495 WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'."),
1497 }
1498 }
1499 } catch (ProcessError&) {
1501 throw;
1502 }
1503 return result;
1504}
1505
1506
1507void
1508MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1509 const MSEdge* fromEdge, const MSEdge*& toEdge,
1510 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1511 const MSStage* const lastStage, bool& ok) {
1512 try {
1513 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1514
1515 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1516 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."));
1517 }
1518 departPos = 0.;
1519 if (lastStage != nullptr) {
1520 if (lastStage->getDestinationStop() != nullptr) {
1521 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge, &myParsingRNG);
1522 } else if (lastStage->getDestination() == fromEdge) {
1523 departPos = lastStage->getArrivalPos();
1524 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1525 departPos = fromEdge->getLength();
1526 }
1527 }
1528
1529 bs = retrieveStoppingPlace(attrs, " " + description);
1530 if (bs != nullptr) {
1531 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1532 if (arrivalPos < 0) {
1533 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1534 }
1536 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1537 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1538 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1539 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1540 arrivalPos = arrPos;
1541 } else {
1542 WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1543 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1544 }
1545 }
1546 } else {
1547 if (toEdge == nullptr) {
1548 throw ProcessError(TLF("No destination edge for %.", description));
1549 }
1552 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1553 } else {
1554 arrivalPos = toEdge->getLength() / 2.;
1555 }
1556 }
1557 } catch (ProcessError&) {
1559 throw;
1560 }
1561}
1562
1563
1564void
1566 if (myVehicleParameter == nullptr) {
1567 throw ProcessError(TL("Cannot define person stage without person."));
1568 }
1569 try {
1570 myActiveRoute.clear();
1571 bool ok = true;
1572 const char* const id = myVehicleParameter->id.c_str();
1573 const MSEdge* from = nullptr;
1574 const MSEdge* to = nullptr;
1579 from = myActiveRoute.front();
1580 } else if (myActiveTransportablePlan->empty()) {
1581 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1582 } else {
1583 from = myActiveTransportablePlan->back()->getDestination();
1584 }
1587 to = myActiveRoute.back();
1588 } // else, to may also be derived from stopping place
1589
1590 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1591 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1592 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1593 }
1594
1595 double departPos = 0;
1596 double arrivalPos = 0;
1597 MSStoppingPlace* stoppingPlace = nullptr;
1598 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1599
1600 SVCPermissions modeSet = 0;
1601 if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
1602 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1603 std::string errorMsg;
1604 // try to parse person modes
1605 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1606 throw InvalidArgument(errorMsg);
1607 }
1608 } else {
1609 modeSet = myVehicleParameter->modes;
1610 }
1611 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1613 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, myVehicleParameter->vTypes);
1614 for (StringTokenizer st(types); st.hasNext();) {
1615 const std::string vtypeid = st.next();
1616 const MSVehicleType* const vType = vehControl.getVType(vtypeid);
1617 if (vType == nullptr) {
1618 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1619 }
1620 modeSet |= (vType->getVehicleClass() == SVC_BICYCLE) ? SVC_BICYCLE : SVC_PASSENGER;
1621 }
1622 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1623 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1624 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1625 }
1626 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1627 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1628 if (ok) {
1629 if (myActiveTransportablePlan->empty()) {
1630 double initialDepartPos = myVehicleParameter->departPos;
1632 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1633 }
1634 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1635 }
1637 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1638 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1639 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1640 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1641 myParamStack.push_back(myActiveTransportablePlan->back());
1644 }
1645 }
1646 myActiveRoute.clear();
1647 } catch (ProcessError&) {
1649 throw;
1650 }
1651}
1652
1653
1654void
1656 if (myVehicleParameter == nullptr) {
1657 throw ProcessError(TL("Cannot define person stage without person."));
1658 }
1659 myActiveRouteID = "";
1661 try {
1662 myActiveRoute.clear();
1663 bool ok = true;
1664 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1665 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1666 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1667 }
1668 double speed = -1; // default to vType speed
1669 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1670 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1671 if (speed <= 0) {
1672 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1673 }
1674 }
1675 double departPos = 0;
1676 double arrivalPos = 0;
1677 MSStoppingPlace* bs = nullptr;
1678 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1679 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1681 if (route == nullptr) {
1682 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1683 }
1684 myActiveRoute = route->getEdges();
1685 } else {
1687 }
1688 if (myActiveTransportablePlan->empty()) {
1689 double initialDepartPos = myVehicleParameter->departPos;
1691 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1692 }
1693 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1694 }
1695 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1696 if (myActiveRoute.empty()) {
1697 throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1698 }
1699 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1700 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1701 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1702 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1703 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1704 }
1705 }
1706 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1707 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1708 MSStageWalking* stage = new MSStageWalking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID);
1709 stage->setDeparted(attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1));
1710 stage->setEnded(attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1));
1712 if (attrs.hasAttribute(SUMO_ATTR_EXITTIMES) && OptionsCont::getOptions().getBool("vehroute-output.exit-times")) {
1713 std::vector<SUMOTime>* exitTimes = new std::vector<SUMOTime>();
1714 for (const std::string& tStr : attrs.get<std::vector<std::string> >(SUMO_ATTR_EXITTIMES, nullptr, ok)) {
1715 exitTimes->push_back(string2time(tStr));
1716 }
1717 stage->setExitTimes(exitTimes);
1718 }
1721 }
1722 myActiveTransportablePlan->push_back(stage);
1723 myParamStack.push_back(stage);
1724 myActiveRoute.clear();
1725 } catch (ProcessError&) {
1727 throw;
1728 }
1729 } else { // parse walks from->to as person trips
1730 addPersonTrip(attrs);
1731 }
1732}
1733
1734double
1735MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1736 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1737 if (value == "") {
1738 return pos;
1739 }
1740 std::string error;
1742 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1743 if (dpd != DepartPosLatDefinition::GIVEN) {
1745 if (lane == nullptr) {
1746 throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1747 }
1748 const double usableWidth = lane->getWidth() - 0.5;
1749 switch (dpd) {
1751 pos = -usableWidth / 2;
1752 break;
1754 pos = usableWidth / 2;
1755 break;
1757 pos = 0;
1758 break;
1764 break;
1765 default:
1766 break;
1767 }
1768 }
1769 } else {
1770 throw ProcessError(error);
1771 }
1772 return pos;
1773}
1774
1775
1776void
1777MSRouteHandler::addTransportable(const SUMOSAXAttributes& /*attrs*/, const bool isPerson) {
1779 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1780 const std::string error = TLF("The type '%' for % '%' is not known.", myVehicleParameter->vtypeid, myActiveTypeName, myVehicleParameter->id);
1782 throw ProcessError(error);
1783 }
1785}
1786
1787
1788void
1790 try {
1791 myActiveRoute.clear();
1792 const std::string cid = myVehicleParameter->id;
1793 bool ok = true;
1794 const MSEdge* from = nullptr;
1795 const MSEdge* to = nullptr;
1796 MSStoppingPlace* cs = nullptr;
1797
1798 double speed;
1800 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1801 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1802 if (!ok) {
1803 throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1804 }
1805 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1806 speed = vtype->getMaxSpeed();
1807 } else { // default speed value
1809 }
1810 if (speed <= 0) {
1811 throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1812 }
1813 // values from preceding stage:
1814 const MSEdge* preEdge = nullptr;
1815 double prePos = 0;
1816 if (!myActiveTransportablePlan->empty()) {
1817 preEdge = myActiveTransportablePlan->back()->getDestination();
1818 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1819 }
1820 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1821 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1822
1823 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1824 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1825 } else {
1826 // set 'from':
1827 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1828 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1829 from = MSEdge::dictionary(fromID);
1830 if (from == nullptr) {
1831 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1832 }
1833 if (preEdge != nullptr && preEdge != from) {
1834 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1835 }
1836 } else if (preEdge == nullptr) {
1837 throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1838 } else {
1839 from = preEdge;
1840 }
1841 // set 'to':
1842 if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1843 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1844 to = MSEdge::dictionary(toID);
1845 if (to == nullptr) {
1846 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1847 }
1848 } else {
1849 const std::string description = "container '" + cid + "' transhipping from edge '" + from->getID() + "'";
1850 cs = retrieveStoppingPlace(attrs, " " + description);
1851 if (cs != nullptr) {
1852 to = &cs->getLane().getEdge();
1853 } else {
1854 throw ProcessError(TLF("Inconsistent tranship for container '%', needs either: 'edges', 'to', 'containerStop' (or any other stopping place)", cid));
1855 }
1856 }
1857 myActiveRoute.push_back(from);
1858 myActiveRoute.push_back(to);
1859 }
1860 if (myActiveRoute.empty()) {
1861 throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1862 }
1863 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1865 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1866 }
1867 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1868 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1869 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1870 myParamStack.push_back(myActiveTransportablePlan->back());
1871 myActiveRoute.clear();
1872 } catch (ProcessError&) {
1874 throw;
1875 }
1876}
1877
1878
1879void
1881 for (const auto& edge : MSEdge::getAllEdges()) {
1882 if (edge->isNormal() || MSGlobals::gUsingInternalLanes) {
1883 for (MSLane* lane : edge->getLanes()) {
1884 Boundary b = lane->getShape().getBoxBoundary();
1885 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1886 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1887 tree->Insert(cmin, cmax, lane);
1888 }
1889 }
1890 }
1891}
1892
1893
1894SumoRNG*
1896 return &myParsingRNG;
1897}
1898
1899
1900const SUMOVTypeParameter*
1901MSRouteHandler::getVTypeParameter(const std::string& refid) {
1902 const auto t = MSNet::getInstance()->getVehicleControl().getVType(refid);
1903 return t != nullptr ? &t->getParameter() : nullptr;
1904}
1905
1906
1907MSEdge*
1908MSRouteHandler::retrieveEdge(const std::string& id) {
1909 return MSEdge::dictionary(id);
1910}
1911
1912
1913/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
#define JUNCTION_TAZ_MISSING_HELP
Definition MapMatcher.h:30
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define TIME2STEPS(x)
Definition SUMOTime.h:60
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_STARTED
@ SUMO_ATTR_WAITINGTIME
@ 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_EXITTIMES
@ SUMO_ATTR_OVERHEAD_WIRE_SEGMENT
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_GROUP
@ SUMO_ATTR_ENDED
@ SUMO_ATTR_COST
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_REPLACED_ON_INDEX
@ SUMO_ATTR_VIAJUNCTIONS
@ SUMO_ATTR_FROMXY
@ SUMO_ATTR_ROUTELENGTH
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_LAT
@ SUMO_ATTR_WALKFACTOR
@ SUMO_ATTR_VEHICLE
@ SUMO_ATTR_TOXY
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_FROMLONLAT
@ SUMO_ATTR_REPEAT
@ SUMO_ATTR_INTENDED
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_CYCLETIME
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:127
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:115
PositionVector getShape(const bool closeShape) const
get position vector (shape) based on this boundary
Definition Boundary.cpp:444
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:133
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:121
Writes the state of the tls to a file (in each second)
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
const std::string & getFileName() const
returns the current file name
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
const MSParkingArea * getParkingArea() const
Get the parking area the charging station is placed on.
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1120
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:1144
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:981
const MSJunction * getToJunction() const
Definition MSEdge.h:427
double getLength() const
return the length of the edge
Definition MSEdge.h:694
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:269
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1081
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:971
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gCheckRoutes
Definition MSGlobals.h:91
static bool gStateLoaded
Information whether a state has been loaded.
Definition MSGlobals.h:103
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
const SUMOVehicleParameter * getFlowPars(const std::string &id) const
return parameters for the given flow
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
SUMOTime computeRandomDepartOffset() const
compute (optional) random offset to the departure time
Representation of a lane in the micro simulation.
Definition MSLane.h:84
double getLength() const
Returns the lane's length.
Definition MSLane.h:632
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2521
bool isInternal() const
Definition MSLane.cpp:2652
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
double getWidth() const
Returns the lane's width.
Definition MSLane.h:661
The simulated network and simulation perfomer.
Definition MSNet.h:89
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:199
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:495
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:505
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition MSNet.cpp:1300
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1501
bool hasContainers() const
Returns whether containers are simulated.
Definition MSNet.h:435
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:419
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:455
SUMOTime getStateLoaderTime() const
return the next time for route loading the time of state loading
Definition MSNet.h:358
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1291
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
const SUMOVTypeParameter * getVTypeParameter(const std::string &refid) override
void closePersonFlow() override
Ends the processing of a personFlow.
int myActiveRouteReplacedIndex
The index at which this route was replaced (from vehroute-output)
void closeRouteDistribution() override
closes (ends) the building of a distribution
MSRouteHandler(const std::string &file, bool addVehiclesDirectly)
standard constructor
std::string myScaleSuffix
prefix when copying vehicles with –scale
ObjectTypeEnum
enum for object type
double interpretDepartPosLat(const std::string &value, int departLane, const std::string &element)
virtual ~MSRouteHandler()
standard destructor
bool myAddVehiclesDirectly
Information whether vehicles shall be directly added to the network or kept within the buffer.
bool myReplayRerouting
whether loaded rerouting events shall be replayed
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs) override
opens a type distribution for reading
Parameterised * addStop(const SUMOSAXAttributes &attrs) override
Processing of a stop.
virtual void closeVehicle() override
Ends the processing of a vehicle (note: is virtual because is reimplemented in MSStateHandler)
void openRouteFlow(const SUMOSAXAttributes &attrs) override
opens a route flow for reading
void openRouteDistribution(const SUMOSAXAttributes &attrs) override
opens a route distribution for reading
void addRide(const SUMOSAXAttributes &attrs) override
Processing of a ride.
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const MSEdge *fromEdge, const MSEdge *&toEdge, double &departPos, double &arrivalPos, MSStoppingPlace *&bs, const MSStage *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
bool myActiveRoutePermanent
whether the active route is stored indefinitely (used by state loader)
std::string myActiveTypeName
The name of the current object type.
void closeVType() override
Ends the processing of a vehicle type.
void addTransportable(const SUMOSAXAttributes &attrs, const bool isPerson) override
Processing of a person.
void closeTransportableFlow()
ends the flow of a transportable
void setReroute(bool reroute=true)
Definition MSRoute.h:224
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:128
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:209
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
static RandomDistributor< ConstMSRoutePtr > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition MSRoute.cpp:168
void setPeriod(SUMOTime period)
sets the period
Definition MSRoute.h:201
void setVehicleDistance(double dist)
restore further state during loading
void setVehicleID(const std::string vehID)
const MSEdge * getDestination() const
returns the destination edge
Definition MSStage.cpp:65
virtual double getArrivalPos() const
Definition MSStage.h:97
static const double ARRIVALPOS_UNSPECIFIED
sentinel value
Definition MSStage.h:72
void setDeparted(SUMOTime now)
logs beginning of stage
Definition MSStage.cpp:115
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition MSStage.h:88
MSStageType getStageType() const
Definition MSStage.h:138
void markSet(int what)
Definition MSStage.h:267
void setEnded(SUMOTime t)
sets end of stage
Definition MSStage.cpp:123
static const MSLane * checkDepartLane(const MSEdge *edge, SUMOVehicleClass svc, int laneIndex, const std::string &id)
interpret custom depart lane
void setTotalWaitingTime(SUMOTime t)
Restore waiting time when loading state.
const MSEdge * getEdge() const
Returns the current edge.
void setDepartPos(const double pos)
void setExitTimes(std::vector< SUMOTime > *exitTimes)
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
double getAccessPos(const MSEdge *edge, SumoRNG *rng=nullptr) const
the position on the given edge which is connected to this stop, -1 on failure
int getLoadedNumber() const
Returns the number of build transportables.
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, SumoRNG *rng) const
Builds a new person.
bool add(MSTransportable *transportable)
Adds a single transportable, returns false if an id clash occurred.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
The class responsible for building and deletion of vehicles.
VehicleDefinitionSource
possible origins of a vehicle definition
double getScale() const
sets the demand scaling factor
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
int getQuota(double frac=-1, int loaded=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, ConstMSRoutePtr route, MSVehicleType *type, const bool ignoreStopErrors, const VehicleDefinitionSource source=ROUTEFILE, bool addRouteStops=true)
Builds a vehicle, increases the number of built vehicles.
const RandomDistributor< MSVehicleType * > * getVTypeDistribution(const std::string &typeDistID) const
return the vehicle type distribution with the given id
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false, bool wasKept=false)
Deletes the vehicle.
The car-following model and parameter.
double getDefaultProbability() const
Get the default probability of this vehicle type.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
const std::string & getID() const
Returns the name of the vehicle type.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
static MSVehicleType * build(SUMOVTypeParameter &from, const std::string &fileName="")
Builds the microsim vehicle type described by the given parameter.
const SUMOVTypeParameter & getParameter() const
void check()
Checks whether vehicle type parameters may be problematic (Currently, only the value for the action s...
Provides utility functions for matching locations to edges (during route parsing)
Definition MapMatcher.h:45
void parseGeoEdges(const PositionVector &positions, bool geo, SUMOVehicleClass vClass, std::vector< const MSEdge * > &into, const std::string &rid, bool isFrom, bool &ok, bool forceEdge=false)
Definition MapMatcher.h:48
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
const std::string & getID() const
Returns the id.
Definition Named.h:73
A RT-tree for efficient storing of SUMO's Named objects.
Definition NamedRTree.h:61
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition NamedRTree.h:79
A storage for options typed value containers)
Definition OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
An upper class for objects with additional parameters.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Represents a generic random distribution.
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
const std::vector< T > & getVals() const
Returns the members of the distribution.
void clear()
Clears the distribution.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
Parser for routes during their loading.
bool parseStop(SUMOVehicleParameter::Stop &stop, const SUMOSAXAttributes &attrs, std::string errorSuffix, MsgHandler *const errorOutput)
parses attributes common to all stops
std::set< std::string > mySkippedVehicles
IDs of skipped vehicles to suppress errors for the triggered transportables within.
void registerLastDepart()
save last depart (only to be used if vehicle is not discarded)
double myCurrentCosts
The currently parsed route costs.
std::string myActiveRouteID
The id of the current route.
std::vector< Parameterised * > myParamStack
The stack of currently parsed parameterised objects.
SUMOVehicleParameter * myVehicleParameter
Parameter of the current vehicle, trip, person, container or flow.
const bool myHardFail
flag to enable or disable hard fails
StopParVector myActiveRouteStops
List of the stops on the parsed route.
std::string myCurrentVTypeRef
if the currently parsed vType is only a reference to an existing type, store the refId
SUMOVTypeParameter * myCurrentVType
The currently parsed vehicle type.
static StopPos checkStopPos(double &startPos, double &endPos, const double laneLength, const double minLength, const bool friendlyPos)
check start and end position of a stop
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
double myActiveRouteProbability
The probability of the current route.
double myCurrentVTypeProbability
if the currently parsed vType is only a reference, store the probability here
int myInsertStopEdgesAt
where stop edges can be inserted into the current route (-1 means no insertion)
std::string myActiveRouteRefID
The id of the route the current route references to.
const RGBColor * myActiveRouteColor
The currently parsed route's color.
virtual bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
Structure representing possible vehicle parameter.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double scale
individual scaling factor (-1 for undefined)
SUMOVehicleClass vehicleClass
The vehicle's class.
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual const MSRoute & getRoute() const =0
Returns the current route.
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
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.
long long int repetitionsDone
The number of times the vehicle was already inserted.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
SUMOTime repetitionTotalOffset
The offset between depart and the time for the next vehicle insertions.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
SVCPermissions modes
The modes a person or container can use.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
std::string vTypes
The types of usable (auto-generated) vehicles for a person / container.
double departPos
(optional) The position the vehicle shall depart from
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
static bool parsePersonModes(const std::string &modes, const std::string &element, const std::string &id, SVCPermissions &modeSet, std::string &error)
Validates a given person modes value.
static bool parseDepartPosLat(const std::string &val, const std::string &element, const std::string &id, double &pos, DepartPosLatDefinition &dpd, std::string &error)
Validates a given departPosLat value.
std::string toTaz
The vehicle's destination zone (district)
static double interpretEdgePos(double pos, double maximumValue, SumoXMLAttr attr, const std::string &id, bool silent=false)
Interprets negative edge positions and fits them onto a given edge.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int arrivalEdge
(optional) The final edge within the route of the vehicle
std::string fromTaz
The vehicle's origin zone (district)
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static 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