Eclipse SUMO - Simulation of Urban MObility
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-2023 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
22// Parser and container for routes during their loading
23/****************************************************************************/
24#include <config.h>
25
26#include "MSRouteHandler.h"
33#include <microsim/MSEdge.h>
34#include <microsim/MSLane.h>
44
45#define JUNCTION_TAZ_MISSING_HELP "\nSet option '--junction-taz' or load a TAZ-file"
46
47
48// ===========================================================================
49// static members
50// ===========================================================================
52
53// ===========================================================================
54// method definitions
55// ===========================================================================
56MSRouteHandler::MSRouteHandler(const std::string& file, bool addVehiclesDirectly) :
57 SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes", true),
58 myActiveRouteRepeat(0),
59 myActiveRoutePeriod(0),
60 myActiveType(ObjectTypeEnum::UNDEFINED),
61 myHaveVia(false),
62 myActiveTransportablePlan(nullptr),
63 myAddVehiclesDirectly(addVehiclesDirectly),
64 myCurrentVTypeDistribution(nullptr),
65 myCurrentRouteDistribution(nullptr),
66 myAmLoadingState(false),
67 myScaleSuffix(OptionsCont::getOptions().getString("scale-suffix")),
68 myReplayRerouting(OptionsCont::getOptions().getBool("replay-rerouting")) {
69 myActiveRoute.reserve(100);
70}
71
72
74
75
76void
78 if (myActiveTransportablePlan != nullptr) {
79 for (MSStage* const s : *myActiveTransportablePlan) {
80 delete s;
81 }
83 }
84 delete myVehicleParameter;
86}
87
88
89void
91 myVehicleParameter = nullptr;
94}
95
96
97void
99 const std::string element = toString(tag);
100 myActiveRoute.clear();
101 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
103 WRITE_WARNINGF(TL("Taz usage was requested but no taz present in % '%'!"), element, myVehicleParameter->id);
104 useTaz = false;
105 }
106 bool ok = true;
107 // from-attributes
108 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
110 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROMJUNCTION);
111 const std::string tazType = useJunction ? "junction" : "taz";
112 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROMJUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok);
113 const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
114 if (fromTaz == nullptr) {
115 throw ProcessError("Source " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
116 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
117 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
118 throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
119 } else {
120 myActiveRoute.push_back(fromTaz);
121 }
122 } else {
123 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok),
124 myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
125 }
126
127 // via-attributes
130 }
131 ConstMSEdgeVector viaEdges;
133 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
134 const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
135 if (viaSink == nullptr) {
136 throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
137 } else {
138 viaEdges.push_back(viaSink);
139 }
140 }
141 } else {
142 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok),
143 viaEdges, "for " + element + " '" + myVehicleParameter->id + "'");
144 }
145 if (!viaEdges.empty()) {
146 myHaveVia = true;
147 }
148 for (const MSEdge* e : viaEdges) {
149 myActiveRoute.push_back(e);
150 myVehicleParameter->via.push_back(e->getID());
151 }
152
153 // to-attributes
154 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
156 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TOJUNCTION);
157 const std::string tazType = useJunction ? "junction" : "taz";
158 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TOJUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
159 const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
160 if (toTaz == nullptr) {
161 throw ProcessError("Sink " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
162 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
163 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
164 throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
165 } else {
166 myActiveRoute.push_back(toTaz);
167 }
168 } else {
169 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
170 myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
171 }
173 if (myVehicleParameter->routeid == "") {
175 }
176}
177
178
179void
181 try {
183 && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT) {
184 const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
185 throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
186 }
187 if (myVehicleParameter == nullptr) {
189 myHaveVia = false;
190 }
191 SUMORouteHandler::myStartElement(element, attrs);
192 switch (element) {
194 addPerson(attrs);
195 break;
197 addContainer(attrs);
198 break;
199 case SUMO_TAG_FLOW:
200 if (myVehicleParameter) {
201 parseFromViaTo((SumoXMLTag)element, attrs);
202 }
203 break;
204 case SUMO_TAG_TRIP:
205 parseFromViaTo((SumoXMLTag)element, attrs);
206 break;
207 default:
208 break;
209 }
210 } catch (ProcessError&) {
212 throw;
213 }
214}
215
216
217void
219 bool ok = true;
220 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
221 if (ok) {
223 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
224 std::vector<double> probs;
225 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
226 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
227 while (st.hasNext()) {
228 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
229 }
230 }
231 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
232 StringTokenizer st(vTypes);
233 int probIndex = 0;
234 while (st.hasNext()) {
235 std::string vtypeID = st.next();
237 if (type == nullptr) {
238 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
239 }
240 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->getDefaultProbability());
241 myCurrentVTypeDistribution->add(type, prob);
242 probIndex++;
243 }
244 if (probs.size() > 0 && probIndex != (int)probs.size()) {
245 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
246 " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
247 }
248 }
249 }
250}
251
252
253void
255 if (myCurrentVTypeDistribution != nullptr) {
256 if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
258 return;
259 }
262 throw ProcessError(TLF("Vehicle type distribution '%' is empty.", myCurrentVTypeDistributionID));
263 }
264 if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
266 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", myCurrentVTypeDistributionID));
267 }
269 }
270}
271
272
273void
275 myActiveRoute.clear();
277 // check whether the id is really necessary
278 std::string rid;
279 if (myCurrentRouteDistribution != nullptr) {
281 rid = "distribution '" + myCurrentRouteDistributionID + "'";
282 } else if (myVehicleParameter != nullptr) {
283 // ok, a vehicle is wrapping the route,
284 // we may use this vehicle's id as default
285 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
286 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
287 WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
288 }
289 } else {
290 bool ok = true;
291 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
292 if (!ok) {
293 return;
294 }
295 rid = "'" + myActiveRouteID + "'";
296 }
297 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
298 rid = "for vehicle '" + myVehicleParameter->id + "'";
299 }
300 bool ok = true;
301 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
302 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
303 }
304 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
306 throw ProcessError(TLF("Invalid reference to route '%' in route %.", myActiveRouteRefID, rid));
307 }
310 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
314 // handle obsolete attribute name
316 if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
317 WRITE_WARNING(TL("Attribute 'period' is deprecated for route. Use 'cycleTime' instead."));
318 }
319 if (myActiveRouteRepeat > 0) {
322 std::string errSuffix = ".";
323 if (myVehicleParameter != nullptr) {
326 if (vtype != nullptr) {
327 vClass = vtype->getVehicleClass();
328 errSuffix = TLF(" for vehicle '%' with vClass %.", myVehicleParameter->id, vClass);
329 }
330 }
331 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
332 throw ProcessError(TLF("Disconnected route % when repeating. Last edge '%' is not connected to first edge '%'%",
333 rid, myActiveRoute.back()->getID(), myActiveRoute.front()->getID(), errSuffix));
334 }
335 }
336 }
337 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
338 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
339 WRITE_WARNING(TLF("Invalid cost for route '%'.", myActiveRouteID));
340 }
341}
342
343
344void
346 // Currently unused
347}
348
349
350void
352 // Currently unused
353}
354
355
356void
358 // Currently unsued
359}
360
361
362void
363MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
364 std::string type = "vehicle";
365 if (mayBeDisconnected) {
367 type = "flow";
368 } else {
369 type = "trip";
370 }
371 }
372
373 try {
374 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
375 if (mustReroute) {
376 // implicit route from stops
378 myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
379 }
380 }
381 if (myActiveRoute.size() == 0) {
382 delete myActiveRouteColor;
383 myActiveRouteColor = nullptr;
384 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
386 if (route != nullptr) {
388 }
389 myActiveRouteID = "";
391 return;
392 }
393 if (myVehicleParameter != nullptr) {
394 throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
395 } else {
396 throw ProcessError(TLF("Route '%' has no edges.", myActiveRouteID));
397 }
398 }
399 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
400 throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
401 }
402 if (myActiveRouteRepeat > 0) {
403 // duplicate route
405 auto tmpStops = myActiveRouteStops;
406 for (int i = 0; i < myActiveRouteRepeat; i++) {
407 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
408 for (SUMOVehicleParameter::Stop stop : tmpStops) {
409 if (stop.until > 0) {
410 if (myActiveRoutePeriod <= 0) {
411 const std::string description = myVehicleParameter != nullptr
412 ? "for " + type + " '" + myVehicleParameter->id + "'"
413 : "'" + myActiveRouteID + "'";
414 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
415 }
416 stop.until += myActiveRoutePeriod * (i + 1);
417 }
418 if (stop.arrival > 0) {
419 if (myActiveRoutePeriod <= 0) {
420 const std::string description = myVehicleParameter != nullptr
421 ? "for " + type + " '" + myVehicleParameter->id + "'"
422 : "'" + myActiveRouteID + "'";
423 throw ProcessError(TLF("Cannot repeat stops with 'arrival' in route % because no cycleTime is defined.", description));
424 }
425 stop.arrival += myActiveRoutePeriod * (i + 1);
426 }
427 myActiveRouteStops.push_back(stop);
428 }
429 }
430 }
432 myVehicleParameter == nullptr,
436 route->setCosts(myCurrentCosts);
437 route->setReroute(mustReroute);
438 myActiveRoute.clear();
439 ConstMSRoutePtr constRoute = std::shared_ptr<const MSRoute>(route);
440 if (!MSRoute::dictionary(myActiveRouteID, constRoute)) {
442 if (myVehicleParameter != nullptr) {
443 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
444 throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
445 } else {
446 throw ProcessError(TLF("A vehicle with id '%' already exists.", myVehicleParameter->id));
447 }
448 } else {
449 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myActiveRouteID));
450 }
451 }
452 } else {
453 if (myCurrentRouteDistribution != nullptr) {
455 }
456 }
457 myActiveRouteID = "";
458 myActiveRouteColor = nullptr;
459 myActiveRouteStops.clear();
460 } catch (ProcessError&) {
462 throw;
463 }
464}
465
466
467void
469 // check whether the id is really necessary
470 if (myVehicleParameter != nullptr) {
471 // ok, a vehicle is wrapping the route,
472 // we may use this vehicle's id as default
473 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
474 // we have to record this or we cannot remove the distribution later
476 } else {
477 bool ok = true;
478 myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
479 if (!ok) {
480 return;
481 }
482 }
484 std::vector<double> probs;
485 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
486 bool ok = true;
487 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
488 while (st.hasNext()) {
489 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
490 }
491 }
492 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
493 bool ok = true;
494 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
495 int probIndex = 0;
496 while (st.hasNext()) {
497 std::string routeID = st.next();
499 if (route == nullptr) {
500 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
501 }
502 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
503 myCurrentRouteDistribution->add(route, prob, false);
504 probIndex++;
505 }
506 if (probs.size() > 0 && probIndex != (int)probs.size()) {
507 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
508 " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
509 }
510 }
511}
512
513
514void
516 if (myCurrentRouteDistribution != nullptr) {
517 const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
518 if (MSGlobals::gStateLoaded && haveSameID) {
521 return;
522 }
523 if (haveSameID) {
525 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myCurrentRouteDistributionID));
526 }
529 throw ProcessError(TLF("Route distribution '%' is empty.", myCurrentRouteDistributionID));
530 }
533 }
534}
535
536
537void
539 // get nested route
540 const std::string embeddedRouteID = "!" + myVehicleParameter->id;
541 ConstMSRoutePtr route = nullptr;
542 if (myReplayRerouting) {
544 if (rDist != nullptr && rDist->getVals().size() > 0) {
545 route = rDist->getVals().front();
546 }
547 }
548 if (route == nullptr) {
549 route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
550 }
553 // let's check whether this vehicle had to depart before the simulation starts
555 return;
556 }
557 }
558
559 // get the vehicle's type
560 MSVehicleType* vtype = nullptr;
561
562 try {
563 if (myVehicleParameter->vtypeid != "") {
564 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
565 if (vtype == nullptr) {
566 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
567 }
568 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
569 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
570 }
571 } else {
572 // there should be one (at least the default one)
573 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
574 }
576 // if the route id was given, prefer that one
577 if (route != nullptr && !myAmLoadingState) {
578 WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
579 }
581 }
582 if (route == nullptr) {
583 // nothing found? -> error
584 if (myVehicleParameter->routeid != "") {
585 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
586 } else {
587 throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
588 }
589 }
590 myActiveRouteID = "";
591
592 } catch (ProcessError&) {
594 throw;
595 }
596 if (route->mustReroute()) {
598 if (myVehicleParameter->stops.size() > 0) {
599 route = addVehicleStopsToImplicitRoute(route, false);
600 }
601 }
605 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
606 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
607 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
608 }
609 }
613 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
614 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
615 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
616 }
617 }
618
619 // try to build the vehicle
620 SUMOVehicle* vehicle = nullptr;
621 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
622 try {
623 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
624 } catch (const ProcessError& e) {
625 myVehicleParameter = nullptr;
627 WRITE_WARNING(e.what());
628 vehControl.fixVehicleCounts();
629 return;
630 } else {
631 throw e;
632 }
633 }
634 const SUMOTime origDepart = myVehicleParameter->depart;
635 // maybe we do not want this vehicle to be inserted due to scaling
636 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
637 if (quota > 0) {
640 vehControl.addVehicle(myVehicleParameter->id, vehicle);
641 if (myReplayRerouting) {
643 if (rDist != nullptr) {
644 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
645 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
646 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
647 if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
648 // routing in the insertion step happens *after* insertion
650 } else {
652 }
653 }
654 }
655 }
656 int offset = 0;
657 for (int i = 1; i < quota; i++) {
660 }
662 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
663 while (vehControl.getVehicle(newPars->id) != nullptr) {
664 offset += 1;
665 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
666 }
669 // resample type
670 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
671 }
672 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
673 vehControl.addVehicle(newPars->id, vehicle);
674 }
675 myVehicleParameter = nullptr;
676 } else {
677 vehControl.deleteVehicle(vehicle, true);
678 myVehicleParameter = nullptr;
679 vehicle = nullptr;
680 }
681 } else {
682 // strange: another vehicle with the same id already exists
684 // and was not loaded while loading a simulation state
685 // -> error
686 std::string veh_id = myVehicleParameter->id;
688 std::string scaleWarning = "";
689 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
690 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
691 }
692 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
693 } else {
694 // ok, it seems to be loaded previously while loading a simulation state
695 vehicle = nullptr;
696 }
697 }
698 // check whether the vehicle shall be added directly to the network or
699 // shall stay in the internal buffer
700 if (vehicle != nullptr) {
703 }
704 }
705}
706
707
710 // the route was defined without edges and its current edges were
711 // derived from route-stops.
712 // We may need to add additional edges for the vehicle-stops
714 assert(route->getStops().size() > 0);
715 ConstMSEdgeVector edges = route->getEdges();
717 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
718 if (stop.index == 0) {
719 if (edges.front() != stopEdge ||
720 route->getStops().front().endPos < stop.endPos) {
721 edges.insert(edges.begin(), stopEdge);
722 }
723 } else if (stop.index == STOP_INDEX_END) {
724 if (edges.back() != stopEdge ||
725 route->getStops().back().endPos > stop.endPos) {
726 edges.push_back(stopEdge);
727 }
728 } else {
729 WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
730 }
731 }
732 ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
733 isPermanent, new RGBColor(route->getColor()), route->getStops());
734 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
735 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
736 }
737 return newRoute;
738}
739
740
741void
743 try {
744 if (myActiveTransportablePlan->size() == 0) {
745 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
746 error[0] = (char)::toupper((char)error[0]);
747 throw ProcessError(error);
748 }
749 // let's check whether this transportable had to depart before the simulation starts
753 return;
754 }
755 // type existence has been checked on opening
758 && type->getVehicleClass() != SVC_PEDESTRIAN
760 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
761 }
764 if (created > 0) {
766 } else {
768 }
769 } catch (ProcessError&) {
771 throw;
772 }
773}
774
775
776void
779}
780
781
782void
785}
786
787
788void
791}
792
793
794void
797}
798
799
800void
802 try {
803 const std::string fid = myVehicleParameter->id;
804 if (myActiveTransportablePlan->size() == 0) {
805 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
806 }
807 // let's check whether this transportable (person/container) had to depart before the simulation starts
811 return;
812 }
813 // type existence has been checked on opening
815 // instantiate all persons/containers of this flow
816 int i = 0;
818 std::string baseID = myVehicleParameter->id;
821 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
822 } else {
823 for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
825 addFlowTransportable(t, type, baseID, i++);
826 }
827 }
828 }
829 } else {
833 // poisson: randomize first depart
835 }
840 }
841 }
842 }
844 } catch (ProcessError&) {
846 throw;
847 }
848}
849
850
851int
852MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
853 try {
854 int numCreated = 0;
855 MSNet* const net = MSNet::getInstance();
858 //MSTransportableControl& pc = net->getPersonControl();
859 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
860 if (quota == 0) {
861 tc.addDiscarded();
862 }
863 for (int j = 0; j < quota; j++) {
864 if (i > 0 || j > 0) {
865 // copy parameter and plan because the transportable takes over responsibility
867 *copyParam = *myVehicleParameter;
868 myVehicleParameter = copyParam;
871 copyPlan->push_back(s->clone());
872 }
873 myActiveTransportablePlan = copyPlan;
875 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
876 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
877 }
878 }
879 myVehicleParameter->id = (baseID
880 + (i >= 0 ? "." + toString(i) : "")
881 + (j > 0 ? "." + toString(j) : ""));
886 numCreated++;
887 if (!tc.add(transportable)) {
888 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
889 delete transportable;
892 throw ProcessError(error);
893 }
894 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
895 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
896 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);
897 }
898 }
899 return numCreated;
900 } catch (ProcessError&) {
902 throw;
903 }
904}
905
906
907void
910 vehType->check();
911 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
912 const std::string id = vehType->getID();
913 delete vehType;
915 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
916 }
917 } else {
918 if (myCurrentVTypeDistribution != nullptr) {
920 }
921 }
922}
923
924
925void
929 delete myVehicleParameter;
930 myVehicleParameter = nullptr;
931 return;
932 }
933 // let's check whether vehicles had to depart before the simulation starts
936 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
937 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
940 delete myVehicleParameter;
941 myVehicleParameter = nullptr;
942 return;
943 }
944 }
945 }
946 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
947 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
948 }
951 closeRoute(true);
952 }
954 if (route == nullptr) {
955 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
956 }
957 if (route->mustReroute()) {
959 if (myVehicleParameter->stops.size() > 0) {
960 route = addVehicleStopsToImplicitRoute(route, true);
961 myVehicleParameter->routeid = route->getID();
962 }
963 }
967 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
968 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
969 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
970 }
971 }
975 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
976 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
977 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
978 }
979 }
980 myActiveRouteID = "";
981
982 // check whether the vehicle shall be added directly to the network or
983 // shall stay in the internal buffer
985 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
987 } else {
989 delete myVehicleParameter;
990 } else {
991 throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
992 }
993 }
994 }
995 myVehicleParameter = nullptr;
996}
997
998
999void
1002 closeRoute(true);
1003 closeVehicle();
1004}
1005
1006void
1009}
1010
1011void
1014}
1015
1016void
1018 try {
1019 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1020 std::string agent = "person";
1021 std::string stop = "bus stop";
1023 agent = "container";
1024 stop = "container stop";
1025 }
1026
1027 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1029 throw ProcessError("Found " + mode + " inside " + agent + " element");
1030 }
1031 const std::string aid = myVehicleParameter->id;
1032 bool ok = true;
1033 const MSEdge* from = nullptr;
1034 const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, "ANY");
1035 StringTokenizer st(desc);
1036 MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1037 MSEdge* to = nullptr;
1038 if (s != nullptr) {
1039 to = &s->getLane().getEdge();
1040 }
1041 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1042 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1043
1044 SUMOVehicle* startVeh = nullptr;
1046 if (st.size() != 1) {
1047 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1048 }
1049 // agent starts
1051 const std::string vehID = st.front();
1052 startVeh = vehControl.getVehicle(vehID);
1053 if (startVeh == nullptr) {
1054 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1055 }
1056 if (startVeh->getParameter().departProcedure == DepartDefinition::TRIGGERED) {
1057 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1058 }
1059 myVehicleParameter->depart = startVeh->getParameter().depart;
1060 }
1061
1062 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1063 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1064 from = MSEdge::dictionary(fromID);
1065 if (from == nullptr) {
1066 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1067 }
1068 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1069 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1070 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1071 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1072 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1073 if (!(stopWithAccess || transferAtJunction)) {
1074 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1075 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1076 }
1077 }
1078 if (startVeh != nullptr && startVeh->getRoute().getEdges().front() != from) {
1079 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1080 "' (edge '" + fromID + "' != edge '" + startVeh->getRoute().getEdges().front()->getID() + "').");
1081 }
1082 } else if (startVeh != nullptr) {
1083 from = startVeh->getRoute().getEdges().front();
1084 }
1085 if (myActiveTransportablePlan->empty()) {
1086 if (from == nullptr) {
1087 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1088 } else {
1090 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1091 }
1092 }
1093 // given attribute may override given stopping place due access requirements
1094 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1095 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1096 to = MSEdge::dictionary(toID);
1097 if (to == nullptr) {
1098 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1099 }
1100 }
1101 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1102 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1103 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1104 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1105 myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, st.getVector(), group, intendedVeh, intendedDepart));
1106 } catch (ProcessError&) {
1108 throw;
1109 }
1110}
1111
1113MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1114 bool ok = true;
1115 // dummy stop parameter to hold the attributes
1117 if (stopParam != nullptr) {
1118 stop = *stopParam;
1119 } else {
1120 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1121 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1122 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1123 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1124 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1125 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1126 }
1127 MSStoppingPlace* toStop = nullptr;
1128 if (stop.busstop != "") {
1130 if (toStop == nullptr) {
1131 ok = false;
1132 WRITE_ERROR(TLF("The busStop '%' is not known%.", stop.busstop, errorSuffix));
1133 }
1134 } else if (stop.containerstop != "") {
1136 if (toStop == nullptr) {
1137 ok = false;
1138 WRITE_ERROR(TLF("The containerStop '%' is not known%.", stop.containerstop, errorSuffix));
1139 }
1140 } else if (stop.parkingarea != "") {
1142 if (toStop == nullptr) {
1143 ok = false;
1144 WRITE_ERROR(TLF("The parkingArea '%' is not known%.", stop.parkingarea, errorSuffix));
1145 }
1146 } else if (stop.chargingStation != "") {
1147 // ok, we have a charging station
1149 if (toStop == nullptr) {
1150 ok = false;
1151 WRITE_ERROR(TLF("The chargingStation '%' is not known%.", stop.chargingStation, errorSuffix));
1152 }
1153 } else if (stop.overheadWireSegment != "") {
1154 // ok, we have an overhead wire segment
1156 if (toStop == nullptr) {
1157 ok = false;
1158 WRITE_ERROR(TLF("The overhead wire segment '%' is not known%.", stop.overheadWireSegment, errorSuffix));
1159 }
1160 }
1161 if (!ok && MSGlobals::gCheckRoutes) {
1162 throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1163 }
1164 return toStop;
1165}
1166
1169 Parameterised* result = nullptr;
1170 try {
1171 std::string errorSuffix;
1173 errorSuffix = " in person '" + myVehicleParameter->id + "'.";
1175 errorSuffix = " in container '" + myVehicleParameter->id + "'.";
1176 } else if (myVehicleParameter != nullptr) {
1177 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
1178 } else {
1179 errorSuffix = " in route '" + myActiveRouteID + "'.";
1180 }
1182 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1183 if (!ok) {
1185 throw ProcessError();
1186 }
1187 return result;
1188 }
1189 const MSEdge* edge = nullptr;
1190 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1191 // if one of the previous stops is defined
1192 if (toStop != nullptr) {
1193 const MSLane& l = toStop->getLane();
1194 stop.lane = l.getID();
1195 if ((stop.parametersSet & STOP_END_SET) == 0) {
1196 stop.endPos = toStop->getEndLanePosition();
1197 } else {
1198 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1199 }
1200 stop.startPos = toStop->getBeginLanePosition();
1201 edge = &l.getEdge();
1202 } else {
1203 // no, the lane and the position should be given directly
1204 // get the lane
1205 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1206 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1207 if (ok && stop.edge != "") { // edge is given directly
1208 edge = MSEdge::dictionary(stop.edge);
1209 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1210 throw ProcessError("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
1211 }
1212 } else if (ok && stop.lane != "") { // lane is given directly
1213 MSLane* stopLane = MSLane::dictionary(stop.lane);
1214 if (stopLane == nullptr) {
1215 // check for opposite-direction stop
1216 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1217 if (stopLane != nullptr) {
1218 edge = MSEdge::dictionary(stop.edge);
1219 }
1220 } else {
1221 edge = &stopLane->getEdge();
1222 }
1223 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1224 throw ProcessError("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
1225 }
1226 } else {
1227 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1228 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1229 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1230 edge = &toStop->getLane().getEdge();
1231 stop.lane = toStop->getLane().getID();
1232 stop.endPos = toStop->getEndLanePosition();
1233 stop.startPos = toStop->getBeginLanePosition();
1234 } else { // use end of movement before definied as lane/edge
1235 edge = myActiveTransportablePlan->back()->getDestination();
1236 stop.lane = edge->getLanes()[0]->getID();
1237 stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1238 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1239 }
1240 } else {
1241 const std::string msg = TL("A stop must be placed on a busStop, a chargingStation, an overheadWireSegment, a containerStop, a parkingArea, an edge or a lane") + errorSuffix;
1243 throw ProcessError(msg);
1244 } else {
1245 WRITE_WARNING(msg);
1246 return result;
1247 }
1248 }
1249 }
1250 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1251 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1252 WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix);
1253 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1254 }
1255 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1256 if (!myAmLoadingState) {
1257 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1259 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1260 throw ProcessError("Invalid start or end position for stop on "
1261 + (stop.lane != ""
1262 ? ("lane '" + stop.lane)
1263 : ("edge '" + stop.edge)) + "'" + errorSuffix);
1264 }
1265 }
1266 }
1267 stop.edge = edge->getID();
1269 if (myActiveTransportablePlan->empty()) {
1270 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1272 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1274 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1275 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1276 throw ProcessError("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id + "' (" + edge->getID() + "!=" + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1277 }
1278 // transporting veh stops somewhere
1279 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1281 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1282 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1283 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1284 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1285 WRITE_WARNING("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id
1286 + "' (stop range " + toString(start) + "-" + toString(end) + " does not cover previous arrival position " + toString(prevAr) + + ").");
1287 }
1288 }
1289 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1290 double pos = (stop.startPos + stop.endPos) / 2.;
1291 if (!myActiveTransportablePlan->empty()) {
1292 pos = myActiveTransportablePlan->back()->getArrivalPos();
1293 }
1294 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1295 result = myActiveTransportablePlan->back();
1296
1297 } else if (myVehicleParameter != nullptr) {
1298 myVehicleParameter->stops.push_back(stop);
1299 result = &myVehicleParameter->stops.back();
1300 } else {
1301 myActiveRouteStops.push_back(stop);
1302 result = &myActiveRouteStops.back();
1303 }
1304 if (myInsertStopEdgesAt >= 0) {
1305 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1306 if (edge->isInternal()) {
1307 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1310 }
1313 } else {
1314 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1316 }
1317 } else if (myHaveVia) {
1318 // vias were loaded, check for consistency
1319 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1320 WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'"), edge->getID(), myActiveTypeName, myVehicleParameter->id);
1321 }
1322 }
1323 } catch (ProcessError&) {
1325 throw;
1326 }
1327 return result;
1328}
1329
1330
1331void
1332MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1333 const MSEdge* fromEdge, const MSEdge*& toEdge,
1334 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1335 const MSStage* const lastStage, bool& ok) {
1336 try {
1337 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1338
1339 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1340 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."));
1341 }
1342 departPos = 0.;
1343 if (lastStage != nullptr) {
1344 if (lastStage->getDestinationStop() != nullptr) {
1345 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge);
1346 } else if (lastStage->getDestination() == fromEdge) {
1347 departPos = lastStage->getArrivalPos();
1348 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1349 departPos = fromEdge->getLength();
1350 }
1351 }
1352
1353 bs = retrieveStoppingPlace(attrs, " " + description);
1354 if (bs != nullptr) {
1355 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1356 if (arrivalPos < 0) {
1357 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1358 }
1360 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1361 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1362 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1363 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1364 arrivalPos = arrPos;
1365 } else {
1366 WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1367 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1368 }
1369 }
1370 } else {
1371 if (toEdge == nullptr) {
1372 throw ProcessError(TLF("No destination edge for %.", description));
1373 }
1376 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1377 } else {
1378 arrivalPos = toEdge->getLength() / 2.;
1379 }
1380 }
1381 } catch (ProcessError&) {
1383 throw;
1384 }
1385}
1386
1387
1388void
1390 try {
1391 myActiveRoute.clear();
1392 bool ok = true;
1393 const char* const id = myVehicleParameter->id.c_str();
1394 const MSEdge* from = nullptr;
1395 const MSEdge* to = nullptr;
1399 from = myActiveRoute.front();
1400 } else if (myActiveTransportablePlan->empty()) {
1401 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1402 } else {
1403 from = myActiveTransportablePlan->back()->getDestination();
1404 }
1406 to = myActiveRoute.back();
1407 } // else, to may also be derived from stopping place
1408
1409 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1410 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1411 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1412 }
1413
1414 double departPos = 0;
1415 double arrivalPos = 0;
1416 MSStoppingPlace* stoppingPlace = nullptr;
1417 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1418
1419 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1420 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1421 SVCPermissions modeSet = 0;
1422 std::string errorMsg;
1423 // try to parse person modes
1424 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1425 throw InvalidArgument(errorMsg);
1426 }
1428 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1429 for (StringTokenizer st(types); st.hasNext();) {
1430 const std::string vtypeid = st.next();
1431 if (vehControl.getVType(vtypeid) == nullptr) {
1432 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1433 }
1434 modeSet |= SVC_PASSENGER;
1435 }
1436 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1437 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1438 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1439 }
1440 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1441 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1442 if (ok) {
1443 if (myActiveTransportablePlan->empty()) {
1444 double initialDepartPos = myVehicleParameter->departPos;
1446 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1447 }
1448 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1449 }
1451 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1452 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1453 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1454 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1457 }
1458 }
1459 myActiveRoute.clear();
1460 } catch (ProcessError&) {
1462 throw;
1463 }
1464}
1465
1466
1467void
1469 myActiveRouteID = "";
1471 try {
1472 myActiveRoute.clear();
1473 bool ok = true;
1474 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1475 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1476 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1477 }
1478 double speed = -1; // default to vType speed
1479 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1480 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1481 if (speed <= 0) {
1482 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1483 }
1484 }
1485 double departPos = 0;
1486 double arrivalPos = 0;
1487 MSStoppingPlace* bs = nullptr;
1488 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1489 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1491 if (route == nullptr) {
1492 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1493 }
1494 myActiveRoute = route->getEdges();
1495 } else {
1497 }
1498 if (myActiveTransportablePlan->empty()) {
1499 double initialDepartPos = myVehicleParameter->departPos;
1501 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1502 }
1503 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1504 }
1505 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1506 if (myActiveRoute.empty()) {
1507 throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1508 }
1509 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1510 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1511 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1512 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1513 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1514 }
1515 }
1516 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1517 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1518 myActiveTransportablePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1521 }
1522 myActiveRoute.clear();
1523 } catch (ProcessError&) {
1525 throw;
1526 }
1527 } else { // parse walks from->to as person trips
1528 addPersonTrip(attrs);
1529 }
1530}
1531
1532double
1533MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1534 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1535 if (value == "") {
1536 return pos;
1537 }
1538 std::string error;
1540 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1541 if (dpd != DepartPosLatDefinition::GIVEN) {
1543 if (lane == nullptr) {
1544 throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1545 }
1546 const double usableWidth = lane->getWidth() - 0.5;
1547 switch (dpd) {
1549 pos = -usableWidth / 2;
1550 break;
1552 pos = usableWidth / 2;
1553 break;
1555 pos = 0;
1556 break;
1562 break;
1563 default:
1564 break;
1565 }
1566 }
1567 } else {
1568 throw ProcessError(error);
1569 }
1570 return pos;
1571}
1572
1573void
1578}
1579
1580
1581void
1586}
1587
1588void
1590 try {
1591 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1592 const std::string error = "The type '" + myVehicleParameter->vtypeid + "' for " + myActiveTypeName + " '" + myVehicleParameter->id + "' is not known.";
1593 throw ProcessError(error);
1594 }
1595 } catch (ProcessError&) {
1597 throw;
1598 }
1599}
1600
1601void
1603 try {
1604 myActiveRoute.clear();
1605 const std::string cid = myVehicleParameter->id;
1606 bool ok = true;
1607 const MSEdge* from = nullptr;
1608 const MSEdge* to = nullptr;
1609 MSStoppingPlace* cs = nullptr;
1610
1611 double speed;
1613 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1614 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1615 if (!ok) {
1616 throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1617 }
1618 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1619 speed = vtype->getMaxSpeed();
1620 } else { // default speed value
1622 }
1623 if (speed <= 0) {
1624 throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1625 }
1626 // values from preceding stage:
1627 const MSEdge* preEdge = nullptr;
1628 double prePos = 0;
1629 if (!myActiveTransportablePlan->empty()) {
1630 preEdge = myActiveTransportablePlan->back()->getDestination();
1631 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1632 }
1633 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1634 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1635
1636 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1637 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1638 } else {
1639 // set 'from':
1640 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1641 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1642 from = MSEdge::dictionary(fromID);
1643 if (from == nullptr) {
1644 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1645 }
1646 if (preEdge != nullptr && preEdge != from) {
1647 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1648 }
1649 } else if (preEdge == nullptr) {
1650 throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1651 } else {
1652 from = preEdge;
1653 }
1654 // set 'to':
1656 std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1658 if (cs == nullptr) {
1659 throw ProcessError("Unknown container stop '" + csID + "' for container '" + cid + "'.");
1660 }
1661 to = &cs->getLane().getEdge();
1662 } else if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1663 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1664 to = MSEdge::dictionary(toID);
1665 if (to == nullptr) {
1666 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1667 }
1668 } else {
1669 throw ProcessError(TLF("Inconsistent tranship for container '%', only one option is allowed: 'edges', 'to', 'containerStop'", cid));
1670 }
1671 myActiveRoute.push_back(from);
1672 myActiveRoute.push_back(to);
1673 }
1674 if (myActiveRoute.empty()) {
1675 throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1676 }
1677 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1679 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1680 }
1681 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1682 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1683 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1684 myActiveRoute.clear();
1685 } catch (ProcessError&) {
1687 throw;
1688 }
1689}
1690
1691/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
#define JUNCTION_TAZ_MISSING_HELP
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:271
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:279
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:270
#define TL(string)
Definition: MsgHandler.h:287
#define TLF(string,...)
Definition: MsgHandler.h:288
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:32
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:46
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
const long long int VTYPEPARS_MAXSPEED_SET
const long long int VTYPEPARS_VEHICLECLASS_SET
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_PEDESTRIAN
pedestrian
const double DEFAULT_VEH_PROB
const std::string DEFAULT_VTYPE_ID
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const double DEFAULT_CONTAINER_TRANSHIP_SPEED
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const int VEHPARS_ROUTE_SET
const int VEHPARS_TO_TAZ_SET
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
The position is set by the vehroute device.
const int VEHPARS_DEPARTPOS_SET
const int VEHPARS_FROM_TAZ_SET
const int VEHPARS_FORCE_REROUTE
const int STOP_END_SET
const double MIN_STOP_LENGTH
const int VEHPARS_ARRIVALPOS_SET
@ 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_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_REFID
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_REPLACED_AT_TIME
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_FROMJUNCTION
@ SUMO_ATTR_DEPARTPOS_LAT
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_ACTTYPE
@ SUMO_ATTR_PROBS
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_CHARGING_STATION
@ SUMO_ATTR_ROUTES
@ SUMO_ATTR_MODES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_OVERHEAD_WIRE_SEGMENT
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_GROUP
@ SUMO_ATTR_COST
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_REPLACED_ON_INDEX
@ SUMO_ATTR_VIAJUNCTIONS
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_WALKFACTOR
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_REPEAT
@ SUMO_ATTR_INTENDED
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_CYCLETIME
@ SUMO_ATTR_TOJUNCTION
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
Writes the state of the tls to a file (in each second)
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
A road/street connecting two junctions.
Definition: MSEdge.h:77
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:1008
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition: MSEdge.cpp:845
const MSJunction * getToJunction() const
Definition: MSEdge.h:415
double getLength() const
return the length of the edge
Definition: MSEdge.h:658
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
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:945
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: MSEdge.cpp:835
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gCheckRoutes
Definition: MSGlobals.h:88
static bool gStateLoaded
Information whether a state has been loaded.
Definition: MSGlobals.h:100
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:78
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:593
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2325
bool isInternal() const
Definition: MSLane.cpp:2456
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:745
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:622
The simulated network and simulation perfomer.
Definition: MSNet.h:88
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:473
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:483
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1181
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1363
bool hasContainers() const
Returns whether containers are simulated.
Definition: MSNet.h:413
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:397
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:433
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:380
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1172
static const double RANDOM_POS_LAT
magic value to encode randomized lateral offset for persons when starting a walk
Definition: MSPModel.h:133
static const double UNSPECIFIED_POS_LAT
the default lateral offset for persons when starting a walk
Definition: MSPModel.h:130
RandomDistributor< ConstMSRoutePtr > * myCurrentRouteDistribution
The currently parsed distribution of routes (probability->route)
void addRideOrTransport(const SUMOSAXAttributes &attrs, const SumoXMLTag modeTag)
Processing of a transport.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
ConstMSRoutePtr addVehicleStopsToImplicitRoute(ConstMSRoutePtr route, bool isPermanent)
adapt implicit route (edges derived from stops) to additional vehicle-stops
void deleteActivePlanAndVehicleParameter()
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
bool myAmLoadingState
whether a state file is being loaded
void resetActivePlanAndVehicleParameter()
reset MSTransportablePlans after transportable tag closes
SUMOTime myActiveRoutePeriod
bool myHaveVia
Wether an object with 'via'-attribute is being parsed.
void closeContainerFlow()
Ends the processing of a containerFlow.
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)
void closeVType()
Ends the processing of a vehicle type.
void openTrip(const SUMOSAXAttributes &attrs)
opens a trip for reading
MSStoppingPlace * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, SUMOVehicleParameter::Stop *stopParam=nullptr)
Parse destination stop.
void closeVehicleTypeDistribution()
closes (ends) the building of a distribution
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
Parameterised * addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
void closeRouteDistribution()
closes (ends) the building of a distribution
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()
Ends the processing of a flow.
MSTransportable::MSTransportablePlan * myActiveTransportablePlan
The plan of the current transportable (person or container)
void closeContainer()
Ends the processing of a container.
std::string myCurrentRouteDistributionID
The id of the currently parsed route distribution.
void closePersonFlow()
Ends the processing of a personFlow.
void openRouteFlow(const SUMOSAXAttributes &attrs)
opens a route flow for reading
RandomDistributor< MSVehicleType * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
SUMOTime myActiveRouteReplacedAtTime
The time at which this route was replaced (from vehroute-output)
void closePerson()
Ends the processing of a person.
void closeTrip()
Ends the processing of a trip.
void openRouteDistribution(const SUMOSAXAttributes &attrs)
opens a route distribution for reading
ConstMSEdgeVector myActiveRoute
The current route.
int myActiveRouteRepeat
number of repetitions of the active route
ObjectTypeEnum myActiveType
The type of the current object.
void addPersonTrip(const SUMOSAXAttributes &attrs)
add a routing request for a walking or intermodal person
void addTranship(const SUMOSAXAttributes &attrs)
Processing of a tranship.
virtual void closeVehicle()
Ends the processing of a vehicle (note: is virtual because is reimplemented in MSStateHandler)
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs)
opens a type distribution for reading
int myActiveRouteReplacedIndex
The index at which this route was replaced (from vehroute-output)
void openFlow(const SUMOSAXAttributes &attrs)
opens a flow for reading
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.
void addWalk(const SUMOSAXAttributes &attrs)
add a fully specified walk
bool myReplayRerouting
whether loaded rerouting events shall be replayed
void openRoute(const SUMOSAXAttributes &attrs)
opens a route for reading
void addTransport(const SUMOSAXAttributes &attrs)
Processing of a transport.
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
void checkTransportableType()
Check if vtype of given transportable exists.
std::string myActiveTypeName
The name of the current object type.
void addRide(const SUMOSAXAttributes &attrs)
Processing of a ride.
void addPerson(const SUMOSAXAttributes &attrs)
Processing of a person.
void closeTransportableFlow()
ends the flow of a transportable
void closeRoute(const bool mayBeDisconnected=false)
closes (ends) the building of a route.
void addContainer(const SUMOSAXAttributes &attrs)
Processing of a container.
void setReroute(bool reroute=true)
Definition: MSRoute.h:214
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:199
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:109
static RandomDistributor< ConstMSRoutePtr > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition: MSRoute.cpp:161
void setPeriod(SUMOTime period)
sets the period
Definition: MSRoute.h:191
const MSEdge * getDestination() const
returns the destination edge
Definition: MSStage.cpp:61
virtual double getArrivalPos() const
Definition: MSStage.h:89
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition: MSStage.h:80
static const MSLane * checkDepartLane(const MSEdge *edge, SUMOVehicleClass svc, int laneIndex, const std::string &id)
interpret custom depart lane
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) 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.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, ConstMSRoutePtr route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true, bool addRouteStops=true)
Builds a vehicle, increases the number of built vehicles.
double getScale() const
sets the demand scaling factor
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
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.
The car-following model and parameter.
Definition: MSVehicleType.h:63
double getDefaultProbability() const
Get the default probability of this vehicle type.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
static MSVehicleType * build(SUMOVTypeParameter &from)
Builds the microsim vehicle type described by the given parameter.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
bool wasSet(int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:80
const SUMOVTypeParameter & getParameter() const
void check()
Checks whether vehicle type parameters may be problematic (Currently, only the value for the action s...
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
const std::string & getID() const
Returns the id.
Definition: Named.h:74
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.
Definition: OptionsCont.cpp:60
An upper class for objects with additional parameters.
Definition: Parameterised.h:41
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
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.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
Parser for routes during their loading.
bool parseStop(SUMOVehicleParameter::Stop &stop, const SUMOSAXAttributes &attrs, std::string errorSuffix, MsgHandler *const errorOutput)
parses attributes common to all stops
std::vector< SUMOVehicleParameter::Stop > myActiveRouteStops
List of the stops on the parsed route.
void registerLastDepart()
save last depart (only to be used if vehicle is not discarded)
double myCurrentCosts
The currently parsed route costs.
std::string myActiveRouteID
The id of the current route.
SUMOVehicleParameter * myVehicleParameter
Parameter of the current vehicle, trip, person, container or flow.
const bool myHardFail
flag to enable or disable hard fails
SUMOVTypeParameter * myCurrentVType
The currently parsed vehicle type.
static StopPos checkStopPos(double &startPos, double &endPos, const double laneLength, const double minLength, const bool friendlyPos)
check start and end position of a stop
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
double myActiveRouteProbability
The probability of the current route.
int myInsertStopEdgesAt
where stop edges can be inserted into the current route (-1 means no insertion)
std::string myActiveRouteRefID
The id of the route the current route references to.
const RGBColor * myActiveRouteColor
The currently parsed route's color.
virtual bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double scale
individual scaling factor (-1 for undefined)
Representation of a vehicle.
Definition: SUMOVehicle.h:62
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at (used only in netedit)
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.
int index
at which position in the stops list
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.
int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
void incrementFlow(double scale, SumoRNG *rng=nullptr)
increment flow
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
int repetitionsDone
The number of times the vehicle was already inserted.
SUMOTime repetitionTotalOffset
The offset between depart and the time for the next vehicle insertions.
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
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.
bool wasSet(int what) const
Returns whether the given parameter was set.
static bool parseDepartPosLat(const std::string &val, const std::string &element, const std::string &id, double &pos, DepartPosLatDefinition &dpd, std::string &error)
Validates a given departPosLat value.
static double interpretEdgePos(double pos, double maximumValue, SumoXMLAttr attr, const std::string &id, bool silent=false)
Interprets negative edge positions and fits them onto a given edge.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int arrivalEdge
(optional) The final edge within the route of the vehicle
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static double parseWalkPos(SumoXMLAttr attr, const bool hardFail, const std::string &id, double maxPos, const std::string &val, SumoRNG *rng=0)
parse departPos or arrivalPos for a walk
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it