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.org/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 WRITE_ERRORF(TL("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 if (myVehicleParameter != nullptr) {
325 if (vtype != nullptr) {
326 vClass = vtype->getVehicleClass();
327 }
328 }
329 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
330 WRITE_ERRORF(TL("Disconnected route % when repeating."), rid);
331 }
332 }
333 }
334 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
335 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
336 WRITE_ERRORF(TL("Invalid cost for route '%'."), myActiveRouteID);
337 }
338}
339
340
341void
343 // Currently unused
344}
345
346
347void
349 // Currently unused
350}
351
352
353void
355 // Currently unsued
356}
357
358
359void
360MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
361 std::string type = "vehicle";
362 if (mayBeDisconnected) {
364 type = "flow";
365 } else {
366 type = "trip";
367 }
368 }
369
370 try {
371 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
372 if (mustReroute) {
373 // implicit route from stops
375 myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
376 }
377 }
378 if (myActiveRoute.size() == 0) {
379 delete myActiveRouteColor;
380 myActiveRouteColor = nullptr;
381 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
383 if (route != nullptr) {
385 }
386 myActiveRouteID = "";
388 return;
389 }
390 if (myVehicleParameter != nullptr) {
391 throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
392 } else {
393 throw ProcessError(TLF("Route '%' has no edges.", myActiveRouteID));
394 }
395 }
396 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
397 throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
398 }
399 if (myActiveRouteRepeat > 0) {
400 // duplicate route
402 auto tmpStops = myActiveRouteStops;
403 for (int i = 0; i < myActiveRouteRepeat; i++) {
404 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
405 for (SUMOVehicleParameter::Stop stop : tmpStops) {
406 if (stop.until > 0) {
407 if (myActiveRoutePeriod <= 0) {
408 const std::string description = myVehicleParameter != nullptr
409 ? "for " + type + " '" + myVehicleParameter->id + "'"
410 : "'" + myActiveRouteID + "'";
411 throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
412 }
413 stop.until += myActiveRoutePeriod * (i + 1);
414 }
415 if (stop.arrival > 0) {
416 if (myActiveRoutePeriod <= 0) {
417 const std::string description = myVehicleParameter != nullptr
418 ? "for " + type + " '" + myVehicleParameter->id + "'"
419 : "'" + myActiveRouteID + "'";
420 throw ProcessError(TLF("Cannot repeat stops with 'arrival' in route % because no cycleTime is defined.", description));
421 }
422 stop.arrival += myActiveRoutePeriod * (i + 1);
423 }
424 myActiveRouteStops.push_back(stop);
425 }
426 }
427 }
433 route->setCosts(myCurrentCosts);
434 route->setReroute(mustReroute);
435 myActiveRoute.clear();
436 ConstMSRoutePtr constRoute = std::shared_ptr<const MSRoute>(route);
437 if (!MSRoute::dictionary(myActiveRouteID, constRoute)) {
439 if (myVehicleParameter != nullptr) {
440 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
441 throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
442 } else {
443 throw ProcessError(TLF("A vehicle with id '%' already exists.", myVehicleParameter->id));
444 }
445 } else {
446 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myActiveRouteID));
447 }
448 }
449 } else {
450 if (myCurrentRouteDistribution != nullptr) {
452 }
453 }
454 myActiveRouteID = "";
455 myActiveRouteColor = nullptr;
456 myActiveRouteStops.clear();
457 } catch (ProcessError&) {
459 throw;
460 }
461}
462
463
464void
466 // check whether the id is really necessary
467 if (myVehicleParameter != nullptr) {
468 // ok, a vehicle is wrapping the route,
469 // we may use this vehicle's id as default
470 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
471 } else {
472 bool ok = true;
473 myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
474 if (!ok) {
475 return;
476 }
477 }
479 std::vector<double> probs;
480 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
481 bool ok = true;
482 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
483 while (st.hasNext()) {
484 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
485 }
486 }
487 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
488 bool ok = true;
489 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
490 int probIndex = 0;
491 while (st.hasNext()) {
492 std::string routeID = st.next();
494 if (route == nullptr) {
495 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
496 }
497 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
498 myCurrentRouteDistribution->add(route, prob, false);
499 probIndex++;
500 }
501 if (probs.size() > 0 && probIndex != (int)probs.size()) {
502 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
503 " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
504 }
505 }
506}
507
508
509void
511 if (myCurrentRouteDistribution != nullptr) {
512 const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
513 if (MSGlobals::gStateLoaded && haveSameID) {
516 return;
517 }
518 if (haveSameID) {
520 throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myCurrentRouteDistributionID));
521 }
524 throw ProcessError(TLF("Route distribution '%' is empty.", myCurrentRouteDistributionID));
525 }
528 }
529}
530
531
532void
534 // get nested route
535 const std::string embeddedRouteID = "!" + myVehicleParameter->id;
536 ConstMSRoutePtr route = nullptr;
537 if (myReplayRerouting) {
539 if (rDist != nullptr && rDist->getVals().size() > 0) {
540 route = rDist->getVals().front();
541 }
542 }
543 if (route == nullptr) {
544 route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
545 }
548 // let's check whether this vehicle had to depart before the simulation starts
550 return;
551 }
552 }
553
554 // get the vehicle's type
555 MSVehicleType* vtype = nullptr;
556
557 try {
558 if (myVehicleParameter->vtypeid != "") {
559 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
560 if (vtype == nullptr) {
561 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
562 }
563 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
564 WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
565 }
566 } else {
567 // there should be one (at least the default one)
568 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
569 }
571 // if the route id was given, prefer that one
572 if (route != nullptr && !myAmLoadingState) {
573 WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
574 }
576 }
577 if (route == nullptr) {
578 // nothing found? -> error
579 if (myVehicleParameter->routeid != "") {
580 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
581 } else {
582 throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
583 }
584 }
585 myActiveRouteID = "";
586
587 } catch (ProcessError&) {
589 throw;
590 }
591 if (route->mustReroute()) {
593 if (myVehicleParameter->stops.size() > 0) {
594 route = addVehicleStopsToImplicitRoute(route, false);
595 }
596 }
600 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
601 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
602 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
603 }
604 }
608 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
609 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
610 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
611 }
612 }
613
614 // try to build the vehicle
615 SUMOVehicle* vehicle = nullptr;
616 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
617 try {
618 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
619 } catch (const ProcessError& e) {
620 myVehicleParameter = nullptr;
622 WRITE_WARNING(e.what());
623 vehControl.fixVehicleCounts();
624 return;
625 } else {
626 throw e;
627 }
628 }
629 const SUMOTime origDepart = myVehicleParameter->depart;
630 // maybe we do not want this vehicle to be inserted due to scaling
631 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
632 if (quota > 0) {
635 vehControl.addVehicle(myVehicleParameter->id, vehicle);
636 if (myReplayRerouting) {
638 if (rDist != nullptr) {
639 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
640 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
641 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
642 if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
643 // routing in the insertion step happens *after* insertion
645 } else {
647 }
648 }
649 }
650 }
651 int offset = 0;
652 for (int i = 1; i < quota; i++) {
655 }
657 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
658 while (vehControl.getVehicle(newPars->id) != nullptr) {
659 offset += 1;
660 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
661 }
664 // resample type
665 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
666 }
667 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
668 vehControl.addVehicle(newPars->id, vehicle);
669 }
670 myVehicleParameter = nullptr;
671 } else {
672 vehControl.deleteVehicle(vehicle, true);
673 myVehicleParameter = nullptr;
674 vehicle = nullptr;
675 }
676 } else {
677 // strange: another vehicle with the same id already exists
679 // and was not loaded while loading a simulation state
680 // -> error
681 std::string veh_id = myVehicleParameter->id;
683 std::string scaleWarning = "";
684 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
685 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
686 }
687 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
688 } else {
689 // ok, it seems to be loaded previously while loading a simulation state
690 vehicle = nullptr;
691 }
692 }
693 // check whether the vehicle shall be added directly to the network or
694 // shall stay in the internal buffer
695 if (vehicle != nullptr) {
698 }
699 }
700}
701
702
705 // the route was defined without edges and its current edges were
706 // derived from route-stops.
707 // We may need to add additional edges for the vehicle-stops
709 assert(route->getStops().size() > 0);
710 ConstMSEdgeVector edges = route->getEdges();
712 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
713 if (stop.index == 0) {
714 if (edges.front() != stopEdge ||
715 route->getStops().front().endPos < stop.endPos) {
716 edges.insert(edges.begin(), stopEdge);
717 }
718 } else if (stop.index == STOP_INDEX_END) {
719 if (edges.back() != stopEdge ||
720 route->getStops().back().endPos > stop.endPos) {
721 edges.push_back(stopEdge);
722 }
723 } else {
724 WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
725 }
726 }
727 ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
728 isPermanent, new RGBColor(route->getColor()), route->getStops());
729 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
730 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
731 }
732 return newRoute;
733}
734
735
736void
738 try {
739 if (myActiveTransportablePlan->size() == 0) {
740 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
741 error[0] = (char)::toupper((char)error[0]);
742 throw ProcessError(error);
743 }
744 // let's check whether this transportable had to depart before the simulation starts
748 return;
749 }
750 // type existence has been checked on opening
753 && type->getVehicleClass() != SVC_PEDESTRIAN
755 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
756 }
759 if (created > 0) {
761 } else {
763 }
764 } catch (ProcessError&) {
766 throw;
767 }
768}
769
770
771void
774}
775
776
777void
780}
781
782
783void
786}
787
788
789void
792}
793
794
795void
797 try {
798 const std::string fid = myVehicleParameter->id;
799 if (myActiveTransportablePlan->size() == 0) {
800 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
801 }
802 // let's check whether this transportable (person/container) had to depart before the simulation starts
806 return;
807 }
808 // type existence has been checked on opening
810 // instantiate all persons/containers of this flow
811 int i = 0;
813 std::string baseID = myVehicleParameter->id;
816 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
817 } else {
818 for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
820 addFlowTransportable(t, type, baseID, i++);
821 }
822 }
823 }
824 } else {
828 // poisson: randomize first depart
830 }
835 }
836 }
837 }
839 } catch (ProcessError&) {
841 throw;
842 }
843}
844
845
846int
847MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
848 try {
849 int numCreated = 0;
850 MSNet* const net = MSNet::getInstance();
853 //MSTransportableControl& pc = net->getPersonControl();
854 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
855 if (quota == 0) {
856 tc.addDiscarded();
857 }
858 for (int j = 0; j < quota; j++) {
859 if (i > 0 || j > 0) {
860 // copy parameter and plan because the transportable takes over responsibility
862 *copyParam = *myVehicleParameter;
863 myVehicleParameter = copyParam;
866 copyPlan->push_back(s->clone());
867 }
868 myActiveTransportablePlan = copyPlan;
870 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
871 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
872 }
873 }
874 myVehicleParameter->id = (baseID
875 + (i >= 0 ? "." + toString(i) : "")
876 + (j > 0 ? "." + toString(j) : ""));
881 numCreated++;
882 if (!tc.add(transportable)) {
883 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
884 delete transportable;
887 throw ProcessError(error);
888 }
889 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
890 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
891 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);
892 }
893 }
894 return numCreated;
895 } catch (ProcessError&) {
897 throw;
898 }
899}
900
901
902void
905 vehType->check();
906 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
907 const std::string id = vehType->getID();
908 delete vehType;
910 throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
911 }
912 } else {
913 if (myCurrentVTypeDistribution != nullptr) {
915 }
916 }
917}
918
919
920void
924 delete myVehicleParameter;
925 myVehicleParameter = nullptr;
926 return;
927 }
928 // let's check whether vehicles had to depart before the simulation starts
931 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
932 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
935 delete myVehicleParameter;
936 myVehicleParameter = nullptr;
937 return;
938 }
939 }
940 }
941 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
942 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
943 }
946 closeRoute(true);
947 }
949 if (route == nullptr) {
950 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
951 }
952 if (route->mustReroute()) {
954 if (myVehicleParameter->stops.size() > 0) {
955 route = addVehicleStopsToImplicitRoute(route, true);
956 myVehicleParameter->routeid = route->getID();
957 }
958 }
962 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
963 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
964 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
965 }
966 }
970 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
971 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
972 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
973 }
974 }
975 myActiveRouteID = "";
976
977 // check whether the vehicle shall be added directly to the network or
978 // shall stay in the internal buffer
980 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
982 } else {
984 delete myVehicleParameter;
985 } else {
986 throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
987 }
988 }
989 }
990 myVehicleParameter = nullptr;
991}
992
993
994void
997 closeRoute(true);
998 closeVehicle();
999}
1000
1001void
1004}
1005
1006void
1009}
1010
1011void
1013 try {
1014 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1015 std::string agent = "person";
1016 std::string stop = "bus stop";
1018 agent = "container";
1019 stop = "container stop";
1020 }
1021
1022 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1024 throw ProcessError("Found " + mode + " inside " + agent + " element");
1025 }
1026 const std::string aid = myVehicleParameter->id;
1027 bool ok = true;
1028 const MSEdge* from = nullptr;
1029 const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, "ANY");
1030 StringTokenizer st(desc);
1031 MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1032 MSEdge* to = nullptr;
1033 if (s != nullptr) {
1034 to = &s->getLane().getEdge();
1035 }
1036 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1037 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1038
1039 SUMOVehicle* startVeh = nullptr;
1041 if (st.size() != 1) {
1042 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1043 }
1044 // agent starts
1046 const std::string vehID = st.front();
1047 startVeh = vehControl.getVehicle(vehID);
1048 if (startVeh == nullptr) {
1049 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1050 }
1051 if (startVeh->getParameter().departProcedure == DepartDefinition::TRIGGERED) {
1052 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1053 }
1054 myVehicleParameter->depart = startVeh->getParameter().depart;
1055 }
1056
1057 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1058 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1059 from = MSEdge::dictionary(fromID);
1060 if (from == nullptr) {
1061 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1062 }
1063 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1064 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1065 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1066 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1067 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1068 if (!(stopWithAccess || transferAtJunction)) {
1069 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1070 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1071 }
1072 }
1073 if (startVeh != nullptr && startVeh->getRoute().getEdges().front() != from) {
1074 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1075 "' (edge '" + fromID + "' != edge '" + startVeh->getRoute().getEdges().front()->getID() + "').");
1076 }
1077 } else if (startVeh != nullptr) {
1078 from = startVeh->getRoute().getEdges().front();
1079 }
1080 if (myActiveTransportablePlan->empty()) {
1081 if (from == nullptr) {
1082 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1083 } else {
1085 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1086 }
1087 }
1088 // given attribute may override given stopping place due access requirements
1089 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1090 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1091 to = MSEdge::dictionary(toID);
1092 if (to == nullptr) {
1093 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1094 }
1095 }
1096 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1097 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1098 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1099 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1100 myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, st.getVector(), group, intendedVeh, intendedDepart));
1101 } catch (ProcessError&) {
1103 throw;
1104 }
1105}
1106
1108MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1109 bool ok = true;
1110 // dummy stop parameter to hold the attributes
1112 if (stopParam != nullptr) {
1113 stop = *stopParam;
1114 } else {
1115 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1116 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1117 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1118 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1119 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1120 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1121 }
1122 MSStoppingPlace* toStop = nullptr;
1123 if (stop.busstop != "") {
1125 if (toStop == nullptr) {
1126 ok = false;
1127 WRITE_ERRORF(TL("The busStop '%' is not known%."), stop.busstop, errorSuffix);
1128 }
1129 } else if (stop.containerstop != "") {
1131 if (toStop == nullptr) {
1132 ok = false;
1133 WRITE_ERRORF(TL("The containerStop '%' is not known%."), stop.containerstop, errorSuffix);
1134 }
1135 } else if (stop.parkingarea != "") {
1137 if (toStop == nullptr) {
1138 ok = false;
1139 WRITE_ERRORF(TL("The parkingArea '%' is not known%."), stop.parkingarea, errorSuffix);
1140 }
1141 } else if (stop.chargingStation != "") {
1142 // ok, we have a charging station
1144 if (toStop == nullptr) {
1145 ok = false;
1146 WRITE_ERRORF(TL("The chargingStation '%' is not known%."), stop.chargingStation, errorSuffix);
1147 }
1148 } else if (stop.overheadWireSegment != "") {
1149 // ok, we have an overhead wire segment
1151 if (toStop == nullptr) {
1152 ok = false;
1153 WRITE_ERRORF(TL("The overhead wire segment '%' is not known%."), stop.overheadWireSegment, errorSuffix);
1154 }
1155 }
1156 if (!ok && MSGlobals::gCheckRoutes) {
1157 throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1158 }
1159 return toStop;
1160}
1161
1162void
1164 try {
1165 std::string errorSuffix;
1167 errorSuffix = " in person '" + myVehicleParameter->id + "'.";
1169 errorSuffix = " in container '" + myVehicleParameter->id + "'.";
1170 } else if (myVehicleParameter != nullptr) {
1171 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
1172 } else {
1173 errorSuffix = " in route '" + myActiveRouteID + "'.";
1174 }
1176 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1177 if (!ok) {
1178 return;
1179 }
1180 const MSEdge* edge = nullptr;
1181 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1182 // if one of the previous stops is defined
1183 if (toStop != nullptr) {
1184 const MSLane& l = toStop->getLane();
1185 stop.lane = l.getID();
1186 if ((stop.parametersSet & STOP_END_SET) == 0) {
1187 stop.endPos = toStop->getEndLanePosition();
1188 } else {
1189 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1190 }
1191 stop.startPos = toStop->getBeginLanePosition();
1192 edge = &l.getEdge();
1193 } else {
1194 // no, the lane and the position should be given directly
1195 // get the lane
1196 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1197 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1198 if (ok && stop.edge != "") { // edge is given directly
1199 edge = MSEdge::dictionary(stop.edge);
1200 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1201 WRITE_ERROR("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
1202 return;
1203 }
1204 } else if (ok && stop.lane != "") { // lane is given directly
1205 MSLane* stopLane = MSLane::dictionary(stop.lane);
1206 if (stopLane == nullptr) {
1207 // check for opposite-direction stop
1208 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1209 if (stopLane != nullptr) {
1210 edge = MSEdge::dictionary(stop.edge);
1211 }
1212 } else {
1213 edge = &stopLane->getEdge();
1214 }
1215 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1216 WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
1217 return;
1218 }
1219 } else {
1220 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1221 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1222 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1223 edge = &toStop->getLane().getEdge();
1224 stop.lane = toStop->getLane().getID();
1225 stop.endPos = toStop->getEndLanePosition();
1226 stop.startPos = toStop->getBeginLanePosition();
1227 } else { // use end of movement before definied as lane/edge
1228 edge = myActiveTransportablePlan->back()->getDestination();
1229 stop.lane = edge->getLanes()[0]->getID();
1230 stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1231 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1232 }
1233 } else {
1234 WRITE_ERROR("A stop must be placed on a busStop, a chargingStation, an overheadWireSegment, a containerStop, a parkingArea, an edge or a lane" + errorSuffix);
1235 return;
1236 }
1237 }
1238 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1239 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1240 WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix);
1241 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1242 }
1243 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1244 if (!myAmLoadingState) {
1245 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS));
1246 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1247 WRITE_ERROR("Invalid start or end position for stop on "
1248 + (stop.lane != ""
1249 ? ("lane '" + stop.lane)
1250 : ("edge '" + stop.edge)) + "'" + errorSuffix);
1251 return;
1252 }
1253 }
1254 }
1255 stop.edge = edge->getID();
1257 if (myActiveTransportablePlan->empty()) {
1258 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1260 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1262 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1263 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1264 throw ProcessError("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id + "' (" + edge->getID() + "!=" + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1265 }
1266 // transporting veh stops somewhere
1267 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1269 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1270 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1271 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1272 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1273 WRITE_WARNING("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id
1274 + "' (stop range " + toString(start) + "-" + toString(end) + " does not cover previous arrival position " + toString(prevAr) + + ").");
1275 }
1276 }
1277 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1278 double pos = (stop.startPos + stop.endPos) / 2.;
1279 if (!myActiveTransportablePlan->empty()) {
1280 pos = myActiveTransportablePlan->back()->getArrivalPos();
1281 }
1282 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1283
1284 } else if (myVehicleParameter != nullptr) {
1285 myVehicleParameter->stops.push_back(stop);
1286 } else {
1287 myActiveRouteStops.push_back(stop);
1288 }
1289 if (myInsertStopEdgesAt >= 0) {
1290 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1291 if (edge->isInternal()) {
1292 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1295 }
1298 } else {
1299 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1301 }
1302 } else if (myHaveVia) {
1303 // vias were loaded, check for consistency
1304 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1305 WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'"), edge->getID(), myActiveTypeName, myVehicleParameter->id);
1306 }
1307 }
1308 } catch (ProcessError&) {
1310 throw;
1311 }
1312}
1313
1314
1315void
1316MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1317 const MSEdge* fromEdge, const MSEdge*& toEdge,
1318 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1319 const MSStage* const lastStage, bool& ok) {
1320 try {
1321 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1322
1323 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1324 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."));
1325 }
1326 departPos = 0.;
1327 if (lastStage != nullptr) {
1328 if (lastStage->getDestinationStop() != nullptr) {
1329 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge);
1330 } else if (lastStage->getDestination() == fromEdge) {
1331 departPos = lastStage->getArrivalPos();
1332 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1333 departPos = fromEdge->getLength();
1334 }
1335 }
1336
1337 bs = retrieveStoppingPlace(attrs, " " + description);
1338 if (bs != nullptr) {
1339 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1340 if (arrivalPos < 0) {
1341 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1342 }
1344 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1345 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1346 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1347 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1348 arrivalPos = arrPos;
1349 } else {
1350 WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1351 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1352 }
1353 }
1354 } else {
1355 if (toEdge == nullptr) {
1356 throw ProcessError(TLF("No destination edge for %.", description));
1357 }
1360 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1361 } else {
1362 arrivalPos = toEdge->getLength() / 2.;
1363 }
1364 }
1365 } catch (ProcessError&) {
1367 throw;
1368 }
1369}
1370
1371
1372void
1374 try {
1375 myActiveRoute.clear();
1376 bool ok = true;
1377 const char* const id = myVehicleParameter->id.c_str();
1378 const MSEdge* from = nullptr;
1379 const MSEdge* to = nullptr;
1383 from = myActiveRoute.front();
1384 } else if (myActiveTransportablePlan->empty()) {
1385 throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1386 } else {
1387 from = myActiveTransportablePlan->back()->getDestination();
1388 }
1390 to = myActiveRoute.back();
1391 } // else, to may also be derived from stopping place
1392
1393 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1394 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1395 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1396 }
1397
1398 double departPos = 0;
1399 double arrivalPos = 0;
1400 MSStoppingPlace* stoppingPlace = nullptr;
1401 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1402
1403 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1404 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1405 SVCPermissions modeSet = 0;
1406 std::string errorMsg;
1407 // try to parse person modes
1408 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1409 throw InvalidArgument(errorMsg);
1410 }
1412 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1413 for (StringTokenizer st(types); st.hasNext();) {
1414 const std::string vtypeid = st.next();
1415 if (vehControl.getVType(vtypeid) == nullptr) {
1416 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1417 }
1418 modeSet |= SVC_PASSENGER;
1419 }
1420 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1421 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1422 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1423 }
1424 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1425 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1426 if (ok) {
1427 if (myActiveTransportablePlan->empty()) {
1428 double initialDepartPos = myVehicleParameter->departPos;
1430 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1431 }
1432 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1433 }
1435 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1436 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1437 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1438 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1441 }
1442 }
1443 myActiveRoute.clear();
1444 } catch (ProcessError&) {
1446 throw;
1447 }
1448}
1449
1450
1451void
1453 myActiveRouteID = "";
1455 try {
1456 myActiveRoute.clear();
1457 bool ok = true;
1458 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1459 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1460 throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1461 }
1462 double speed = -1; // default to vType speed
1463 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1464 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1465 if (speed <= 0) {
1466 throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1467 }
1468 }
1469 double departPos = 0;
1470 double arrivalPos = 0;
1471 MSStoppingPlace* bs = nullptr;
1472 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1473 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1475 if (route == nullptr) {
1476 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1477 }
1478 myActiveRoute = route->getEdges();
1479 } else {
1481 }
1482 if (myActiveTransportablePlan->empty()) {
1483 double initialDepartPos = myVehicleParameter->departPos;
1485 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1486 }
1487 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1488 }
1489 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1490 if (myActiveRoute.empty()) {
1491 throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1492 }
1493 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1494 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1495 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1496 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1497 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1498 }
1499 }
1500 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1501 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1502 myActiveTransportablePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1505 }
1506 myActiveRoute.clear();
1507 } catch (ProcessError&) {
1509 throw;
1510 }
1511 } else { // parse walks from->to as person trips
1512 addPersonTrip(attrs);
1513 }
1514}
1515
1516double
1517MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1518 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1519 if (value == "") {
1520 return pos;
1521 }
1522 std::string error;
1524 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1525 if (dpd != DepartPosLatDefinition::GIVEN) {
1527 if (lane == nullptr) {
1528 throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1529 }
1530 const double usableWidth = lane->getWidth() - 0.5;
1531 switch (dpd) {
1533 pos = -usableWidth / 2;
1534 break;
1536 pos = usableWidth / 2;
1537 break;
1539 pos = 0;
1540 break;
1546 break;
1547 default:
1548 break;
1549 }
1550 }
1551 } else {
1552 throw ProcessError(error);
1553 }
1554 return pos;
1555}
1556
1557void
1562}
1563
1564
1565void
1570}
1571
1572void
1574 try {
1575 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1576 const std::string error = "The type '" + myVehicleParameter->vtypeid + "' for " + myActiveTypeName + " '" + myVehicleParameter->id + "' is not known.";
1577 throw ProcessError(error);
1578 }
1579 } catch (ProcessError&) {
1581 throw;
1582 }
1583}
1584
1585void
1587 try {
1588 myActiveRoute.clear();
1589 const std::string cid = myVehicleParameter->id;
1590 bool ok = true;
1591 const MSEdge* from = nullptr;
1592 const MSEdge* to = nullptr;
1593 MSStoppingPlace* cs = nullptr;
1594
1595 double speed;
1597 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1598 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1599 if (!ok) {
1600 throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1601 }
1602 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1603 speed = vtype->getMaxSpeed();
1604 } else { // default speed value
1606 }
1607 if (speed <= 0) {
1608 throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1609 }
1610 // values from preceding stage:
1611 const MSEdge* preEdge = nullptr;
1612 double prePos = 0;
1613 if (!myActiveTransportablePlan->empty()) {
1614 preEdge = myActiveTransportablePlan->back()->getDestination();
1615 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1616 }
1617 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1618 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1619
1620 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1621 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1622 } else {
1623 // set 'from':
1624 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1625 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1626 from = MSEdge::dictionary(fromID);
1627 if (from == nullptr) {
1628 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1629 }
1630 if (preEdge != nullptr && preEdge != from) {
1631 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1632 }
1633 } else if (preEdge == nullptr) {
1634 throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1635 } else {
1636 from = preEdge;
1637 }
1638 // set 'to':
1640 std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1642 if (cs == nullptr) {
1643 throw ProcessError("Unknown container stop '" + csID + "' for container '" + cid + "'.");
1644 }
1645 to = &cs->getLane().getEdge();
1646 } else if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1647 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1648 to = MSEdge::dictionary(toID);
1649 if (to == nullptr) {
1650 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1651 }
1652 } else {
1653 throw ProcessError(TLF("Inconsistent tranship for container '%', only one option is allowed: 'edges', 'to', 'containerStop'", cid));
1654 }
1655 myActiveRoute.push_back(from);
1656 myActiveRoute.push_back(to);
1657 }
1658 if (myActiveRoute.empty()) {
1659 throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1660 }
1661 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1663 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1664 }
1665 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1666 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1667 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1668 myActiveRoute.clear();
1669 } catch (ProcessError&) {
1671 throw;
1672 }
1673}
1674
1675/****************************************************************************/
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:268
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:277
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:276
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:267
#define TL(string)
Definition: MsgHandler.h:284
#define TLF(string,...)
Definition: MsgHandler.h:285
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:32
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
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:2234
bool isInternal() const
Definition: MSLane.cpp:2365
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:471
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:481
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1168
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1350
bool hasContainers() const
Returns whether containers are simulated.
Definition: MSNet.h:411
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:395
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:431
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1159
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...
void addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
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.
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:59
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