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-2022 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 MSTransportable::MSTransportablePlan::iterator i;
79 if (myActiveTransportablePlan != nullptr) {
80 for (i = myActiveTransportablePlan->begin(); i != myActiveTransportablePlan->end(); i++) {
81 delete *i;
82 }
84 }
85 delete myVehicleParameter;
87}
88
89
90void
92 myVehicleParameter = nullptr;
95}
96
97
98void
100 const std::string element = toString(tag);
101 myActiveRoute.clear();
102 bool useTaz = OptionsCont::getOptions().getBool("with-taz");
104 WRITE_WARNING("Taz usage was requested but no taz present in " + element + " '" + myVehicleParameter->id + "'!");
105 useTaz = false;
106 }
107 bool ok = true;
108 // from-attributes
109 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
111 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROMJUNCTION);
112 const std::string tazType = useJunction ? "junction" : "taz";
113 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROMJUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok);
114 const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
115 if (fromTaz == nullptr) {
116 throw ProcessError("Source " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
117 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
118 } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
119 throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
120 } else {
121 myActiveRoute.push_back(fromTaz);
122 }
123 } else {
124 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok),
125 myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
126 }
127
128 // via-attributes
131 }
132 ConstMSEdgeVector viaEdges;
134 for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
135 const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
136 if (viaSink == nullptr) {
137 throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
138 } else {
139 viaEdges.push_back(viaSink);
140 }
141 }
142 } else {
143 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok),
144 viaEdges, "for " + element + " '" + myVehicleParameter->id + "'");
145 }
146 if (!viaEdges.empty()) {
147 myHaveVia = true;
148 }
149 for (const MSEdge* e : viaEdges) {
150 myActiveRoute.push_back(e);
151 myVehicleParameter->via.push_back(e->getID());
152 }
153
154 // to-attributes
155 if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
157 const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TOJUNCTION);
158 const std::string tazType = useJunction ? "junction" : "taz";
159 const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TOJUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
160 const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
161 if (toTaz == nullptr) {
162 throw ProcessError("Sink " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
163 + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
164 } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
165 throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
166 } else {
167 myActiveRoute.push_back(toTaz);
168 }
169 } else {
170 MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
171 myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
172 }
174 if (myVehicleParameter->routeid == "") {
176 }
177}
178
179
180void
182 try {
184 && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT) {
185 const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
186 throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
187 }
188 if (myVehicleParameter == nullptr) {
190 myHaveVia = false;
191 }
192 SUMORouteHandler::myStartElement(element, attrs);
193 switch (element) {
195 addPerson(attrs);
196 break;
198 addContainer(attrs);
199 break;
200 case SUMO_TAG_FLOW:
201 if (myVehicleParameter) {
202 parseFromViaTo((SumoXMLTag)element, attrs);
203 }
204 break;
205 case SUMO_TAG_TRIP:
206 parseFromViaTo((SumoXMLTag)element, attrs);
207 break;
208 default:
209 break;
210 }
211 } catch (ProcessError&) {
213 throw;
214 }
215}
216
217
218void
220 bool ok = true;
221 myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
222 if (ok) {
224 if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
225 const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
226 StringTokenizer st(vTypes);
227 while (st.hasNext()) {
228 std::string vtypeID = st.next();
230 if (type == nullptr) {
231 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
232 }
234 }
235 }
236 }
237}
238
239
240void
242 if (myCurrentVTypeDistribution != nullptr) {
243 if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
245 return;
246 }
249 throw ProcessError("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
250 }
251 if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
253 throw ProcessError("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
254 }
256 }
257}
258
259
260void
262 myActiveRoute.clear();
264 // check whether the id is really necessary
265 std::string rid;
266 if (myCurrentRouteDistribution != nullptr) {
268 rid = "distribution '" + myCurrentRouteDistributionID + "'";
269 } else if (myVehicleParameter != nullptr) {
270 // ok, a vehicle is wrapping the route,
271 // we may use this vehicle's id as default
272 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
273 if (attrs.hasAttribute(SUMO_ATTR_ID)) {
274 WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "').");
275 }
276 } else {
277 bool ok = true;
278 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
279 if (!ok) {
280 return;
281 }
282 rid = "'" + myActiveRouteID + "'";
283 }
284 if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
285 rid = "for vehicle '" + myVehicleParameter->id + "'";
286 }
287 bool ok = true;
288 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
289 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
290 }
291 myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
293 WRITE_ERROR("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
294 }
297 myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
301 // handle obsolete attribute name
303 if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
304 WRITE_WARNING(TL("Attribute 'period' is deprecated for route. Use 'cycleTime' instead."));
305 }
306 if (myActiveRouteRepeat > 0) {
309 if (myVehicleParameter != nullptr) {
312 if (vtype != nullptr) {
313 vClass = vtype->getVehicleClass();
314 }
315 }
316 if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
317 WRITE_ERROR("Disconnected route " + rid + " when repeating.");
318 }
319 }
320 }
321 myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
322 if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
323 WRITE_ERROR("Invalid cost for route '" + myActiveRouteID + "'.");
324 }
325}
326
327
328void
330 // Currently unused
331}
332
333
334void
336 // Currently unused
337}
338
339
340void
342 // Currently unsued
343}
344
345
346void
347MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
348 std::string type = "vehicle";
349 if (mayBeDisconnected) {
351 type = "flow";
352 } else {
353 type = "trip";
354 }
355 }
356
357 try {
358 const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
359 if (mustReroute) {
360 // implicit route from stops
362 myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
363 }
364 }
365 if (myActiveRoute.size() == 0) {
366 delete myActiveRouteColor;
367 myActiveRouteColor = nullptr;
368 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
370 if (route != nullptr) {
372 route->addReference();
373 }
374 }
375 myActiveRouteID = "";
377 return;
378 }
379 if (myVehicleParameter != nullptr) {
380 throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
381 } else {
382 throw ProcessError("Route '" + myActiveRouteID + "' has no edges.");
383 }
384 }
385 if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
386 throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
387 }
388 if (myActiveRouteRepeat > 0) {
389 // duplicate route
391 auto tmpStops = myActiveRouteStops;
392 for (int i = 0; i < myActiveRouteRepeat; i++) {
393 myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
394 for (SUMOVehicleParameter::Stop stop : tmpStops) {
395 if (stop.until > 0) {
396 if (myActiveRoutePeriod <= 0) {
397 const std::string description = myVehicleParameter != nullptr
398 ? "for " + type + " '" + myVehicleParameter->id + "'"
399 : "'" + myActiveRouteID + "'";
400 throw ProcessError("Cannot repeat stops with 'until' in route " + description + " because no cycleTime is defined.");
401 }
402 stop.until += myActiveRoutePeriod * (i + 1);
403 }
404 if (stop.arrival > 0) {
405 if (myActiveRoutePeriod <= 0) {
406 const std::string description = myVehicleParameter != nullptr
407 ? "for " + type + " '" + myVehicleParameter->id + "'"
408 : "'" + myActiveRouteID + "'";
409 throw ProcessError("Cannot repeat stops with 'arrival' in route " + description + " because no cycleTime is defined.");
410 }
411 stop.arrival += myActiveRoutePeriod * (i + 1);
412 }
413 myActiveRouteStops.push_back(stop);
414 }
415 }
416 }
422 route->setCosts(myCurrentCosts);
423 route->setReroute(mustReroute);
424 myActiveRoute.clear();
426 delete route;
428 if (myVehicleParameter != nullptr) {
429 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
430 throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
431 } else {
432 throw ProcessError("A vehicle with id '" + myVehicleParameter->id + "' already exists.");
433 }
434 } else {
435 throw ProcessError("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
436 }
437 }
438 } else {
439 if (myCurrentRouteDistribution != nullptr) {
441 route->addReference();
442 }
443 }
444 }
445 myActiveRouteID = "";
446 myActiveRouteColor = nullptr;
447 myActiveRouteStops.clear();
448 } catch (ProcessError&) {
450 throw;
451 }
452}
453
454
455void
457 // check whether the id is really necessary
458 if (myVehicleParameter != nullptr) {
459 // ok, a vehicle is wrapping the route,
460 // we may use this vehicle's id as default
461 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
462 } else {
463 bool ok = true;
464 myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
465 if (!ok) {
466 return;
467 }
468 }
470 std::vector<double> probs;
471 if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
472 bool ok = true;
473 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
474 while (st.hasNext()) {
475 probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
476 }
477 }
478 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
479 bool ok = true;
480 StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
481 int probIndex = 0;
482 while (st.hasNext()) {
483 std::string routeID = st.next();
484 const MSRoute* route = MSRoute::dictionary(routeID, &myParsingRNG);
485 if (route == nullptr) {
486 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
487 }
488 const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
489 if (myCurrentRouteDistribution->add(route, prob, false)) {
490 route->addReference();
491 }
492 probIndex++;
493 }
494 if (probs.size() > 0 && probIndex != (int)probs.size()) {
495 WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
496 " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
497 }
498 }
499}
500
501
502void
504 if (myCurrentRouteDistribution != nullptr) {
505 const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
506 if (MSGlobals::gStateLoaded && haveSameID) {
509 return;
510 }
511 if (haveSameID) {
513 throw ProcessError("Another route (or distribution) with the id '" + myCurrentRouteDistributionID + "' exists.");
514 }
517 throw ProcessError("Route distribution '" + myCurrentRouteDistributionID + "' is empty.");
518 }
521 }
522}
523
524
525void
527 // get nested route
528 const std::string embeddedRouteID = "!" + myVehicleParameter->id;
529 const MSRoute* route = nullptr;
530 if (myReplayRerouting) {
532 if (rDist != nullptr && rDist->getVals().size() > 0) {
533 route = rDist->getVals().front();
534 }
535 }
536 if (route == nullptr) {
537 route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
538 }
541 // let's check whether this vehicle had to depart before the simulation starts
543 if (route != nullptr) {
544 route->addReference();
545 route->release();
546 }
547 return;
548 }
549 }
550
551 // get the vehicle's type
552 MSVehicleType* vtype = nullptr;
553
554 try {
555 if (myVehicleParameter->vtypeid != "") {
556 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
557 if (vtype == nullptr) {
558 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
559 }
560 if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
561 WRITE_WARNING("Vehicle type '" + vtype->getID() + "' with vClass=pedestrian should only be used for persons and not for vehicle '" + myVehicleParameter->id + "'.");
562 }
563 } else {
564 // there should be one (at least the default one)
565 vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
566 }
568 // if the route id was given, prefer that one
569 if (route != nullptr && !myAmLoadingState) {
570 WRITE_WARNING("Ignoring child element 'route' for vehicle '" + myVehicleParameter->id + "' because attribute 'route' is set.");
571 }
573 }
574 if (route == nullptr) {
575 // nothing found? -> error
576 if (myVehicleParameter->routeid != "") {
577 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
578 } else {
579 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route.");
580 }
581 }
582 myActiveRouteID = "";
583
584 } catch (ProcessError&) {
586 throw;
587 }
588 if (route->mustReroute()) {
590 if (myVehicleParameter->stops.size() > 0) {
591 route = addVehicleStopsToImplicitRoute(route, false);
592 }
593 }
597 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
598 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
599 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
600 }
601 }
605 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
606 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
607 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
608 }
609 }
610
611 // try to build the vehicle
612 SUMOVehicle* vehicle = nullptr;
613 if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
614 try {
615 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
616 } catch (const ProcessError& e) {
617 myVehicleParameter = nullptr;
619 WRITE_WARNING(e.what());
620 vehControl.fixVehicleCounts();
621 return;
622 } else {
623 throw e;
624 }
625 }
626 const SUMOTime origDepart = myVehicleParameter->depart;
627 // maybe we do not want this vehicle to be inserted due to scaling
628 int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
629 if (quota > 0) {
632 vehControl.addVehicle(myVehicleParameter->id, vehicle);
633 if (myReplayRerouting) {
635 if (rDist != nullptr) {
636 for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
637 SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
638 auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
639 if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
640 // routing in the insertion step happens *after* insertion
642 } else {
644 }
645 }
646 }
647 }
648 int offset = 0;
649 for (int i = 1; i < quota; i++) {
652 }
654 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
655 while (vehControl.getVehicle(newPars->id) != nullptr) {
656 offset += 1;
657 newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
658 }
661 // resample type
662 vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
663 }
664 vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
665 vehControl.addVehicle(newPars->id, vehicle);
666 }
667 myVehicleParameter = nullptr;
668 } else {
669 vehControl.deleteVehicle(vehicle, true);
670 myVehicleParameter = nullptr;
671 vehicle = nullptr;
672 }
673 } else {
674 // strange: another vehicle with the same id already exists
676 // and was not loaded while loading a simulation state
677 // -> error
678 std::string veh_id = myVehicleParameter->id;
680 std::string scaleWarning = "";
681 if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
682 scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
683 }
684 throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
685 } else {
686 // ok, it seems to be loaded previously while loading a simulation state
687 vehicle = nullptr;
688 }
689 }
690 // check whether the vehicle shall be added directly to the network or
691 // shall stay in the internal buffer
692 if (vehicle != nullptr) {
695 }
696 }
697}
698
699
700MSRoute*
702 // the route was defined without edges and its current edges were
703 // derived from route-stops.
704 // We may need to add additional edges for the vehicle-stops
706 assert(route->getStops().size() > 0);
707 ConstMSEdgeVector edges = route->getEdges();
709 MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
710 if (stop.index == 0) {
711 if (edges.front() != stopEdge ||
712 route->getStops().front().endPos < stop.endPos) {
713 edges.insert(edges.begin(), stopEdge);
714 }
715 } else if (stop.index == STOP_INDEX_END) {
716 if (edges.back() != stopEdge ||
717 route->getStops().back().endPos > stop.endPos) {
718 edges.push_back(stopEdge);
719 }
720 } else {
721 WRITE_WARNING("Could not merge vehicle stops for vehicle '" + myVehicleParameter->id + "' into implicitly defined route '" + route->getID() + "'");
722 }
723 }
724 MSRoute* newRoute = new MSRoute("!" + myVehicleParameter->id, edges,
725 isPermanent, new RGBColor(route->getColor()), route->getStops());
726 if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
727 delete newRoute;
728 throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
729 }
730 return newRoute;
731}
732
733
734void
736 try {
737 if (myActiveTransportablePlan->size() == 0) {
738 std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
739 error[0] = (char)::toupper((char)error[0]);
740 throw ProcessError(error);
741 }
742 // let's check whether this transportable had to depart before the simulation starts
746 return;
747 }
748 // type existence has been checked on opening
751 && type->getVehicleClass() != SVC_PEDESTRIAN
753 WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
754 }
757 if (created > 0) {
759 } else {
761 }
762 } catch (ProcessError&) {
764 throw;
765 }
766}
767
768
769void
772}
773
774
775void
778}
779
780
781void
784}
785
786
787void
790}
791
792
793void
795 try {
796 const std::string fid = myVehicleParameter->id;
797 if (myActiveTransportablePlan->size() == 0) {
798 throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
799 }
800 // let's check whether this transportable (person/container) had to depart before the simulation starts
804 return;
805 }
806 // type existence has been checked on opening
808 // instantiate all persons/containers of this flow
809 int i = 0;
811 std::string baseID = myVehicleParameter->id;
814 throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
815 } else {
816 for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
818 addFlowTransportable(t, type, baseID, i++);
819 }
820 }
821 }
822 } else {
826 // poisson: randomize first depart
828 }
833 }
834 }
835 }
837 } catch (ProcessError&) {
839 throw;
840 }
841}
842
843
844int
845MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
846 try {
847 int numCreated = 0;
848 MSNet* const net = MSNet::getInstance();
851 //MSTransportableControl& pc = net->getPersonControl();
852 const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
853 if (quota == 0) {
854 tc.addDiscarded();
855 }
856 for (int j = 0; j < quota; j++) {
857 if (i > 0 || j > 0) {
858 // copy parameter and plan because the transportable takes over responsibility
860 *copyParam = *myVehicleParameter;
861 myVehicleParameter = copyParam;
864 copyPlan->push_back(s->clone());
865 }
866 myActiveTransportablePlan = copyPlan;
868 const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
869 myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
870 }
871 }
872 myVehicleParameter->id = (baseID
873 + (i >= 0 ? "." + toString(i) : "")
874 + (j > 0 ? "." + toString(j) : ""));
879 numCreated++;
880 if (!tc.add(transportable)) {
881 std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
882 delete transportable;
885 throw ProcessError(error);
886 }
887 } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
888 && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
889 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);
890 }
891 }
892 return numCreated;
893 } catch (ProcessError&) {
895 throw;
896 }
897}
898
899
900void
903 vehType->check();
904 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
905 const std::string id = vehType->getID();
906 delete vehType;
908 throw ProcessError("Another vehicle type (or distribution) with the id '" + id + "' exists.");
909 }
910 } else {
911 if (myCurrentVTypeDistribution != nullptr) {
913 }
914 }
915}
916
917
918void
922 delete myVehicleParameter;
923 myVehicleParameter = nullptr;
924 return;
925 }
926 // let's check whether vehicles had to depart before the simulation starts
929 const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
930 while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
933 delete myVehicleParameter;
934 myVehicleParameter = nullptr;
935 return;
936 }
937 }
938 }
939 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
940 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
941 }
944 closeRoute(true);
945 }
947 if (route == nullptr) {
948 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
949 }
950 if (route->mustReroute()) {
952 if (myVehicleParameter->stops.size() > 0) {
953 route = addVehicleStopsToImplicitRoute(route, true);
954 myVehicleParameter->routeid = route->getID();
955 }
956 }
960 myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
961 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
962 + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
963 }
964 }
968 myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
969 throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
970 + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
971 }
972 }
973 myActiveRouteID = "";
974
975 // check whether the vehicle shall be added directly to the network or
976 // shall stay in the internal buffer
978 if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
980 } else {
982 delete myVehicleParameter;
983 } else {
984 throw ProcessError("Another flow with the id '" + myVehicleParameter->id + "' exists.");
985 }
986 }
987 }
988 myVehicleParameter = nullptr;
989}
990
991
992void
995 closeRoute(true);
996 closeVehicle();
997}
998
999void
1002}
1003
1004void
1007}
1008
1009void
1011 try {
1012 const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1013 std::string agent = "person";
1014 std::string stop = "bus stop";
1016 agent = "container";
1017 stop = "container stop";
1018 }
1019
1020 if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1022 throw ProcessError("Found " + mode + " inside " + agent + " element");
1023 }
1024 const std::string aid = myVehicleParameter->id;
1025 bool ok = true;
1026 const MSEdge* from = nullptr;
1027 const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok);
1028 StringTokenizer st(desc);
1029 MSStoppingPlace* s = retrieveStoppingPlace(attrs, "in " + agent + " '" + aid + "'");
1030 MSEdge* to = nullptr;
1031 if (s != nullptr) {
1032 to = &s->getLane().getEdge();
1033 }
1034 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1035 s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1036
1037 SUMOVehicle* startVeh = nullptr;
1039 if (st.size() != 1) {
1040 throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1041 }
1042 // agent starts
1044 const std::string vehID = st.front();
1045 startVeh = vehControl.getVehicle(vehID);
1046 if (startVeh == nullptr) {
1047 throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1048 }
1049 if (startVeh->getParameter().departProcedure == DepartDefinition::TRIGGERED) {
1050 throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1051 }
1052 myVehicleParameter->depart = startVeh->getParameter().depart;
1053 }
1054
1055 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1056 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1057 from = MSEdge::dictionary(fromID);
1058 if (from == nullptr) {
1059 throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1060 }
1061 if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1062 const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1063 && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1064 const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1065 || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1066 if (!(stopWithAccess || transferAtJunction)) {
1067 throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1068 "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1069 }
1070 }
1071 if (startVeh != nullptr && startVeh->getRoute().getEdges().front() != from) {
1072 throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1073 "' (edge '" + fromID + "' != edge '" + startVeh->getRoute().getEdges().front()->getID() + "').");
1074 }
1075 } else if (startVeh != nullptr) {
1076 from = startVeh->getRoute().getEdges().front();
1077 }
1078 if (myActiveTransportablePlan->empty()) {
1079 if (from == nullptr) {
1080 throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1081 } else {
1083 from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1084 }
1085 }
1086 // given attribute may override given stopping place due access requirements
1087 if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1088 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1089 to = MSEdge::dictionary(toID);
1090 if (to == nullptr) {
1091 throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1092 }
1093 }
1094 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1095 const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1096 const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1097 arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1098 myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, st.getVector(), group, intendedVeh, intendedDepart));
1099 } catch (ProcessError&) {
1101 throw;
1102 }
1103}
1104
1106MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1107 // dummy stop parameter to hold the attributes
1109 if (stopParam != nullptr) {
1110 stop = *stopParam;
1111 } else {
1112 bool ok = true;
1113 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1114 stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1115 stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1116 stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1117 stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1118 stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1119 }
1120 MSStoppingPlace* toStop = nullptr;
1121 if (stop.busstop != "") {
1123 if (toStop == nullptr) {
1124 WRITE_ERROR("The busStop '" + stop.busstop + "' is not known " + errorSuffix + ".");
1125 }
1126 } else if (stop.containerstop != "") {
1128 if (toStop == nullptr) {
1129 WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known " + errorSuffix + ".");
1130 }
1131 } else if (stop.parkingarea != "") {
1133 if (toStop == nullptr) {
1134 WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known " + errorSuffix + ".");
1135 }
1136 } else if (stop.chargingStation != "") {
1137 // ok, we have a charging station
1139 if (toStop == nullptr) {
1140 WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known " + errorSuffix + ".");
1141 }
1142 } else if (stop.overheadWireSegment != "") {
1143 // ok, we have an overhead wire segment
1145 if (toStop == nullptr) {
1146 WRITE_ERROR("The overhead wire segment '" + stop.overheadWireSegment + "' is not known " + errorSuffix + ".");
1147 }
1148 }
1149 return toStop;
1150}
1151
1152void
1154 try {
1155 std::string errorSuffix;
1157 errorSuffix = " in person '" + myVehicleParameter->id + "'.";
1159 errorSuffix = " in container '" + myVehicleParameter->id + "'.";
1160 } else if (myVehicleParameter != nullptr) {
1161 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
1162 } else {
1163 errorSuffix = " in route '" + myActiveRouteID + "'.";
1164 }
1166 bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1167 if (!ok) {
1168 return;
1169 }
1170 const MSEdge* edge = nullptr;
1171 MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1172 // if one of the previous stops is defined
1173 if (toStop != nullptr) {
1174 const MSLane& l = toStop->getLane();
1175 stop.lane = l.getID();
1176 if ((stop.parametersSet & STOP_END_SET) == 0) {
1177 stop.endPos = toStop->getEndLanePosition();
1178 } else {
1179 stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1180 }
1181 stop.startPos = toStop->getBeginLanePosition();
1182 edge = &l.getEdge();
1183 } else {
1184 // no, the lane and the position should be given directly
1185 // get the lane
1186 stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1187 stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1188 if (ok && stop.edge != "") { // edge is given directly
1189 edge = MSEdge::dictionary(stop.edge);
1190 if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1191 WRITE_ERROR("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
1192 return;
1193 }
1194 } else if (ok && stop.lane != "") { // lane is given directly
1195 MSLane* stopLane = MSLane::dictionary(stop.lane);
1196 if (stopLane == nullptr) {
1197 // check for opposite-direction stop
1198 stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1199 if (stopLane != nullptr) {
1200 edge = MSEdge::dictionary(stop.edge);
1201 }
1202 } else {
1203 edge = &stopLane->getEdge();
1204 }
1205 if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1206 WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
1207 return;
1208 }
1209 } else {
1210 if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1211 toStop = myActiveTransportablePlan->back()->getDestinationStop();
1212 if (toStop != nullptr) { // use end of movement before definied as a stopping place
1213 edge = &toStop->getLane().getEdge();
1214 stop.lane = toStop->getLane().getID();
1215 stop.endPos = toStop->getEndLanePosition();
1216 stop.startPos = toStop->getBeginLanePosition();
1217 } else { // use end of movement before definied as lane/edge
1218 edge = myActiveTransportablePlan->back()->getDestination();
1219 stop.lane = edge->getLanes()[0]->getID();
1220 stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1221 stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1222 }
1223 } else {
1224 WRITE_ERROR("A stop must be placed on a busStop, a chargingStation, an overheadWireSegment, a containerStop, a parkingArea, an edge or a lane" + errorSuffix);
1225 return;
1226 }
1227 }
1228 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1229 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1230 WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix);
1231 stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1232 }
1233 stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1234 if (!myAmLoadingState) {
1235 const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS));
1236 if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1237 WRITE_ERROR("Invalid start or end position for stop on "
1238 + (stop.lane != ""
1239 ? ("lane '" + stop.lane)
1240 : ("edge '" + stop.edge)) + "'" + errorSuffix);
1241 return;
1242 }
1243 }
1244 }
1245 stop.edge = edge->getID();
1247 if (myActiveTransportablePlan->empty()) {
1248 double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1250 : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1252 edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1253 } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1254 throw ProcessError("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id + "' (" + edge->getID() + "!=" + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1255 }
1256 // transporting veh stops somewhere
1257 else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1259 const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1260 const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1261 const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1262 if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1263 WRITE_WARNING("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id
1264 + "' (stop range " + toString(start) + "-" + toString(end) + " does not cover previous arrival position " + toString(prevAr) + + ").");
1265 }
1266 }
1267 std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1268 double pos = (stop.startPos + stop.endPos) / 2.;
1269 if (!myActiveTransportablePlan->empty()) {
1270 pos = myActiveTransportablePlan->back()->getArrivalPos();
1271 }
1272 myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1273
1274 } else if (myVehicleParameter != nullptr) {
1275 myVehicleParameter->stops.push_back(stop);
1276 } else {
1277 myActiveRouteStops.push_back(stop);
1278 }
1279 if (myInsertStopEdgesAt >= 0) {
1280 //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1281 if (edge->isInternal()) {
1282 if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1285 }
1288 } else {
1289 myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1291 }
1292 } else if (myHaveVia) {
1293 // vias were loaded, check for consistency
1294 if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1295 WRITE_WARNING("Stop edge '" + edge->getID() + "' missing in attribute 'via' for " + myActiveTypeName + " '" + myVehicleParameter->id + "'");
1296 }
1297 }
1298 } catch (ProcessError&) {
1300 throw;
1301 }
1302}
1303
1304
1305void
1306MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1307 const MSEdge* fromEdge, const MSEdge*& toEdge,
1308 double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1309 const MSStage* const lastStage, bool& ok) {
1310 try {
1311 const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1312
1313 if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1314 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."));
1315 }
1316 departPos = 0.;
1317 if (lastStage != nullptr) {
1318 if (lastStage->getDestinationStop() != nullptr) {
1319 departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge);
1320 } else if (lastStage->getDestination() == fromEdge) {
1321 departPos = lastStage->getArrivalPos();
1322 } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1323 departPos = fromEdge->getLength();
1324 }
1325 }
1326
1327 bs = retrieveStoppingPlace(attrs, description);
1328 if (bs != nullptr) {
1329 arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1330 if (arrivalPos < 0) {
1331 throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1332 }
1334 const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1335 const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1336 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1337 if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1338 arrivalPos = arrPos;
1339 } else {
1340 WRITE_WARNING("Ignoring arrivalPos for " + description + " because it is outside the given stop '" + toString(SUMO_ATTR_BUS_STOP) + "'.");
1341 arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1342 }
1343 }
1344 } else {
1345 if (toEdge == nullptr) {
1346 throw ProcessError("No destination edge for " + description + ".");
1347 }
1350 attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1351 } else {
1352 arrivalPos = toEdge->getLength() / 2.;
1353 }
1354 }
1355 } catch (ProcessError&) {
1357 throw;
1358 }
1359}
1360
1361
1362void
1364 try {
1365 myActiveRoute.clear();
1366 bool ok = true;
1367 const char* const id = myVehicleParameter->id.c_str();
1368 const MSEdge* from = nullptr;
1369 const MSEdge* to = nullptr;
1373 from = myActiveRoute.front();
1374 } else if (myActiveTransportablePlan->empty()) {
1375 throw ProcessError("Start edge not defined for person '" + myVehicleParameter->id + "'.");
1376 } else {
1377 from = myActiveTransportablePlan->back()->getDestination();
1378 }
1380 to = myActiveRoute.back();
1381 } // else, to may also be derived from stopping place
1382
1383 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1384 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1385 throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1386 }
1387
1388 double departPos = 0;
1389 double arrivalPos = 0;
1390 MSStoppingPlace* stoppingPlace = nullptr;
1391 parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1392
1393 const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1394 const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1395 SVCPermissions modeSet = 0;
1396 std::string errorMsg;
1397 // try to parse person modes
1398 if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1399 throw InvalidArgument(errorMsg);
1400 }
1402 const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1403 for (StringTokenizer st(types); st.hasNext();) {
1404 const std::string vtypeid = st.next();
1405 if (vehControl.getVType(vtypeid) == nullptr) {
1406 throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1407 }
1408 modeSet |= SVC_PASSENGER;
1409 }
1410 const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1411 if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1412 throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1413 }
1414 const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1415 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1416 if (ok) {
1417 if (myActiveTransportablePlan->empty()) {
1418 double initialDepartPos = myVehicleParameter->departPos;
1420 initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1421 }
1422 myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1423 }
1425 MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1426 myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1427 stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1428 departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1431 }
1432 }
1433 myActiveRoute.clear();
1434 } catch (ProcessError&) {
1436 throw;
1437 }
1438}
1439
1440
1441void
1443 myActiveRouteID = "";
1445 try {
1446 myActiveRoute.clear();
1447 bool ok = true;
1448 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1449 if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1450 throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1451 }
1452 double speed = -1; // default to vType speed
1453 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1454 speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1455 if (speed <= 0) {
1456 throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1457 }
1458 }
1459 double departPos = 0;
1460 double arrivalPos = 0;
1461 MSStoppingPlace* bs = nullptr;
1462 if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1463 myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1465 if (route == nullptr) {
1466 throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1467 }
1468 myActiveRoute = route->getEdges();
1469 } else {
1471 }
1472 if (myActiveTransportablePlan->empty()) {
1473 double initialDepartPos = myVehicleParameter->departPos;
1475 initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1476 }
1477 myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1478 }
1479 parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1480 if (myActiveRoute.empty()) {
1481 throw ProcessError("No edges to walk for person '" + myVehicleParameter->id + "'.");
1482 }
1483 if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1484 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1485 myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1486 if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1487 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1488 }
1489 }
1490 const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1491 const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1492 myActiveTransportablePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1495 }
1496 myActiveRoute.clear();
1497 } catch (ProcessError&) {
1499 throw;
1500 }
1501 } else { // parse walks from->to as person trips
1502 addPersonTrip(attrs);
1503 }
1504}
1505
1506double
1507MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1508 double pos = MSPModel::UNSPECIFIED_POS_LAT;
1509 if (value == "") {
1510 return pos;
1511 }
1512 std::string error;
1514 if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1515 if (dpd != DepartPosLatDefinition::GIVEN) {
1517 if (lane == nullptr) {
1518 throw ProcessError("Could not find departure lane for walk of person '" + myVehicleParameter->id + "' when interpreting departPosLat");
1519 }
1520 const double usableWidth = lane->getWidth() - 0.5;
1521 switch (dpd) {
1523 pos = -usableWidth / 2;
1524 break;
1526 pos = usableWidth / 2;
1527 break;
1529 pos = 0;
1530 break;
1536 break;
1537 default:
1538 break;
1539 }
1540 }
1541 } else {
1542 throw ProcessError(error);
1543 }
1544 return pos;
1545}
1546
1547void
1552}
1553
1554
1555void
1560}
1561
1562void
1564 try {
1565 if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1566 const std::string error = "The type '" + myVehicleParameter->vtypeid + "' for " + myActiveTypeName + " '" + myVehicleParameter->id + "' is not known.";
1567 throw ProcessError(error);
1568 }
1569 } catch (ProcessError&) {
1571 throw;
1572 }
1573}
1574
1575void
1577 try {
1578 myActiveRoute.clear();
1579 const std::string cid = myVehicleParameter->id;
1580 bool ok = true;
1581 const MSEdge* from = nullptr;
1582 const MSEdge* to = nullptr;
1583 MSStoppingPlace* cs = nullptr;
1584
1585 double speed;
1587 if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1588 speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1589 if (!ok) {
1590 throw ProcessError("Could not read tranship speed for container '" + cid + "'.");
1591 }
1592 } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1593 speed = vtype->getMaxSpeed();
1594 } else { // default speed value
1596 }
1597 if (speed <= 0) {
1598 throw ProcessError("Non-positive tranship speed for container '" + cid + "'.");
1599 }
1600 // values from preceding stage:
1601 const MSEdge* preEdge = nullptr;
1602 double prePos = 0;
1603 if (!myActiveTransportablePlan->empty()) {
1604 preEdge = myActiveTransportablePlan->back()->getDestination();
1605 prePos = myActiveTransportablePlan->back()->getArrivalPos();
1606 }
1607 // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1608 double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1609
1610 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1611 MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1612 } else {
1613 // set 'from':
1614 if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1615 const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1616 from = MSEdge::dictionary(fromID);
1617 if (from == nullptr) {
1618 throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1619 }
1620 if (preEdge != nullptr && preEdge != from) {
1621 throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1622 }
1623 } else if (preEdge == nullptr) {
1624 throw ProcessError("The start edge for container '" + cid + "' is not known.");
1625 } else {
1626 from = preEdge;
1627 }
1628 // set 'to':
1630 std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1632 if (cs == nullptr) {
1633 throw ProcessError("Unknown container stop '" + csID + "' for container '" + cid + "'.");
1634 }
1635 to = &cs->getLane().getEdge();
1636 } else if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1637 const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1638 to = MSEdge::dictionary(toID);
1639 if (to == nullptr) {
1640 throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1641 }
1642 } else {
1643 throw ProcessError("Inconsistent tranship for container '" + cid + "', only one option is allowed: 'edges', 'to', 'containerStop'");
1644 }
1645 myActiveRoute.push_back(from);
1646 myActiveRoute.push_back(to);
1647 }
1648 if (myActiveRoute.empty()) {
1649 throw ProcessError("No edges to tranship container '" + cid + "'.");
1650 }
1651 if (preEdge == nullptr) { // additional 'stop' to start the container plan
1653 myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1654 }
1655 double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1656 cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1657 myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1658 myActiveRoute.clear();
1659 } catch (ProcessError&) {
1661 throw;
1662 }
1663}
1664
1665/****************************************************************************/
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:266
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:274
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
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
@ 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 definitio nusing a from-to edges instead of a route (used by router)
@ 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:77
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:575
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2199
bool isInternal() const
Definition: MSLane.cpp:2330
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:713
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:590
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:472
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:482
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1105
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1287
bool hasContainers() const
Returns whether containers are simulated.
Definition: MSNet.h:412
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:396
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:432
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:379
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1096
static const double RANDOM_POS_LAT
magic value to encode randomized lateral offset for persons when starting a walk
Definition: MSPModel.h:131
static const double UNSPECIFIED_POS_LAT
the default lateral offset for persons when starting a walk
Definition: MSPModel.h:128
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;.
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.
RandomDistributor< const MSRoute * > * myCurrentRouteDistribution
The currently parsed distribution of routes (probability->route)
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)
MSRoute * addVehicleStopsToImplicitRoute(const MSRoute *route, bool isPermanent)
adapt implicit route (edges derived from stops) to additional vehicle-stops
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 addReference() const
increments the reference counter for the route
Definition: MSRoute.cpp:99
void setReroute(bool reroute=true)
Definition: MSRoute.h:214
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:415
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:118
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:199
void release() const
deletes the route if there are no further references to it
Definition: MSRoute.cpp:105
static RandomDistributor< const MSRoute * > * distDictionary(const std::string &id)
Returns the named route distribution.
Definition: MSRoute.cpp:170
const RGBColor & getColor() const
Returns the color.
Definition: MSRoute.cpp:406
void setPeriod(SUMOTime period)
sets the period
Definition: MSRoute.h:191
bool mustReroute() const
Definition: MSRoute.h:210
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.
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.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true, bool addRouteStops=true)
Builds a vehicle, increases the number of built vehicles.
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:79
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:60
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