Eclipse SUMO - Simulation of Urban MObility
MSRouteHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 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"
34 #include <microsim/MSEdge.h>
35 #include <microsim/MSLane.h>
45 
46 // ===========================================================================
47 // static members
48 // ===========================================================================
50 
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 MSRouteHandler::MSRouteHandler(const std::string& file, bool addVehiclesDirectly) :
56  SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes", true),
57  MapMatcher(OptionsCont::getOptions().getBool("mapmatch.junctions"),
58  OptionsCont::getOptions().getFloat("mapmatch.distance"),
59  MsgHandler::getErrorInstance()),
60  myActiveRouteRepeat(0),
61  myActiveRoutePeriod(0),
62  myActiveRoutePermanent(false),
63  myActiveType(ObjectTypeEnum::UNDEFINED),
64  myHaveVia(false),
65  myActiveTransportablePlan(nullptr),
66  myAddVehiclesDirectly(addVehiclesDirectly),
67  myCurrentVTypeDistribution(nullptr),
68  myCurrentRouteDistribution(nullptr),
69  myAmLoadingState(false),
70  myScaleSuffix(OptionsCont::getOptions().getString("scale-suffix")),
71  myReplayRerouting(OptionsCont::getOptions().getBool("replay-rerouting")),
72  myStartTriggeredInFlow(false) {
73  myActiveRoute.reserve(100);
74 }
75 
76 
78 
79 
80 void
82  if (myActiveTransportablePlan != nullptr) {
83  for (MSStage* const s : *myActiveTransportablePlan) {
84  delete s;
85  }
87  }
88  delete myVehicleParameter;
90 }
91 
92 
93 void
95  myVehicleParameter = nullptr;
96  myActiveTransportablePlan = nullptr;
98 }
99 
100 
101 void
103  const std::string element = toString(tag);
104  myActiveRoute.clear();
105  bool useTaz = OptionsCont::getOptions().getBool("with-taz");
107  WRITE_WARNINGF(TL("Taz usage was requested but no taz present in % '%'!"), element, myVehicleParameter->id);
108  useTaz = false;
109  }
110  bool ok = true;
111  const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
113  auto& vc = MSNet::getInstance()->getVehicleControl();
114  if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
115  MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
116  if (type != nullptr) {
117  vClass = type->getParameter().vehicleClass;
118  }
119  }
120  // from-attributes
121  if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
123  const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION);
124  const std::string tazType = useJunction ? "junction" : "taz";
125  const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROM_JUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok);
126  const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
127  if (fromTaz == nullptr) {
128  throw ProcessError("Source " + tazType + " '" + tazID + "' not known " + rid + "!"
129  + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
130  } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
131  throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges " + rid + "!");
132  } else {
133  myActiveRoute.push_back(fromTaz);
134  }
135  } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
136  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok), false, vClass, myActiveRoute, rid, true, ok);
137  } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
138  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, myActiveRoute, rid, true, ok);
139  } else {
140  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok),
141  myActiveRoute, rid);
142  }
143  if (!ok) {
144  throw ProcessError();
145  }
146 
147  // via-attributes
148  if (!attrs.hasAttribute(SUMO_ATTR_VIA) && !attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
149  myInsertStopEdgesAt = (int)myActiveRoute.size();
150  }
151  ConstMSEdgeVector viaEdges;
152  if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
153  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok), false, vClass, viaEdges, rid, false, ok);
154  } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
155  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok), true, vClass, viaEdges, rid, false, ok);
156  } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
157  for (std::string junctionID : attrs.get<std::vector<std::string> >(SUMO_ATTR_VIAJUNCTIONS, myVehicleParameter->id.c_str(), ok)) {
158  const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
159  if (viaSink == nullptr) {
160  throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
161  } else {
162  viaEdges.push_back(viaSink);
163  }
164  }
165  } else {
166  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok),
167  viaEdges, rid);
168  }
169  if (!viaEdges.empty()) {
170  myHaveVia = true;
171  }
172  for (const MSEdge* e : viaEdges) {
173  myActiveRoute.push_back(e);
174  myVehicleParameter->via.push_back(e->getID());
175  }
176 
177  // to-attributes
178  if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
180  const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION);
181  const std::string tazType = useJunction ? "junction" : "taz";
182  const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TO_JUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
183  const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
184  if (toTaz == nullptr) {
185  throw ProcessError("Sink " + tazType + " '" + tazID + "' not known " + rid + "!"
186  + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
187  } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
188  throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges " + rid + "!");
189  } else {
190  myActiveRoute.push_back(toTaz);
191  }
192  } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
193  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, vClass, myActiveRoute, rid, false, ok);
194  } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
195  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, vClass, myActiveRoute, rid, false, ok);
196  } else {
197  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
198  myActiveRoute, rid);
199  }
201  if (myVehicleParameter->routeid == "") {
203  }
204 }
205 
206 
207 void
209  try {
211  && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT && element != SUMO_TAG_PARAM) {
212  const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
213  throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
214  }
215  if (myVehicleParameter == nullptr) {
217  myHaveVia = false;
218  }
219  SUMORouteHandler::myStartElement(element, attrs);
220  switch (element) {
221  case SUMO_TAG_PERSONFLOW:
222  addTransportable(attrs, true);
223  break;
225  addTransportable(attrs, false);
226  break;
227  case SUMO_TAG_FLOW:
228  if (myVehicleParameter) {
229  parseFromViaTo((SumoXMLTag)element, attrs);
230  }
231  break;
232  case SUMO_TAG_TRIP:
233  parseFromViaTo((SumoXMLTag)element, attrs);
234  break;
235  default:
236  break;
237  }
238  } catch (ProcessError&) {
240  throw;
241  }
242 }
243 
244 
245 void
247  bool ok = true;
248  myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
249  if (ok) {
251  if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
252  std::vector<double> probs;
253  if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
254  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentVTypeDistributionID.c_str(), ok));
255  while (st.hasNext()) {
256  probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
257  }
258  }
259  const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
260  StringTokenizer st(vTypes);
261  int probIndex = 0;
262  while (st.hasNext()) {
263  const std::string& vtypeID = st.next();
265  if (dist != nullptr) {
266  const double distProb = ((int)probs.size() > probIndex ? probs[probIndex] : 1.) / dist->getOverallProb();
267  std::vector<double>::const_iterator probIt = dist->getProbs().begin();
268  for (MSVehicleType* const type : dist->getVals()) {
269  myCurrentVTypeDistribution->add(type, distProb * *probIt);
270  probIt++;
271  }
272  } else {
274  if (type == nullptr) {
275  throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
276  }
277  const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : type->getDefaultProbability());
278  myCurrentVTypeDistribution->add(type, prob);
279  }
280  probIndex++;
281  }
282  if (probs.size() > 0 && probIndex != (int)probs.size()) {
283  WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
284  " types in vTypeDistribution '" + myCurrentVTypeDistributionID + "'");
285  }
286  }
287  }
288 }
289 
290 
291 void
293  if (myCurrentVTypeDistribution != nullptr) {
294  if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
296  return;
297  }
300  throw ProcessError(TLF("Vehicle type distribution '%' is empty.", myCurrentVTypeDistributionID));
301  }
302  if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
304  throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", myCurrentVTypeDistributionID));
305  }
306  myCurrentVTypeDistribution = nullptr;
307  }
308 }
309 
310 
311 void
313  myActiveRoute.clear();
314  myInsertStopEdgesAt = -1;
315  // check whether the id is really necessary
316  std::string rid;
317  if (myCurrentRouteDistribution != nullptr) {
319  rid = "distribution '" + myCurrentRouteDistributionID + "'";
320  } else if (myVehicleParameter != nullptr) {
321  // ok, a vehicle is wrapping the route,
322  // we may use this vehicle's id as default
323  myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
324  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
325  WRITE_WARNINGF(TL("Ids of internal routes are ignored (vehicle '%')."), myVehicleParameter->id);
326  }
327  } else {
328  bool ok = true;
329  myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
330  if (!ok) {
331  return;
332  }
333  rid = "'" + myActiveRouteID + "'";
334  }
335  if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
336  rid = "for vehicle '" + myVehicleParameter->id + "'";
337  }
338  bool ok = true;
339  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
340  MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
341  }
342  myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
344  throw ProcessError(TLF("Invalid reference to route '%' in route %.", myActiveRouteRefID, rid));
345  }
348  myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
352  // handle obsolete attribute name
354  myActiveRoutePermanent = attrs.getOpt<bool>(SUMO_ATTR_STATE, myActiveRouteID.c_str(), ok, false);
355  if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
356  WRITE_WARNING(TL("Attribute 'period' is deprecated for route. Use 'cycleTime' instead."));
357  }
358  myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
359  if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
360  WRITE_WARNING(TLF("Invalid cost for route '%'.", myActiveRouteID));
361  }
362 }
363 
364 
365 void
367  // Currently unused
368 }
369 
370 
371 void
373  // Currently unused
374 }
375 
376 
377 void
379  // Currently unsued
380 }
381 
382 
383 void
384 MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
385  std::string type = "vehicle";
386  if (mayBeDisconnected) {
388  type = "flow";
389  } else {
390  type = "trip";
391  }
392  }
393 
394  try {
395  const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
396  if (mustReroute) {
397  // implicit route from stops
398  for (const SUMOVehicleParameter::Stop& stop : myActiveRouteStops) {
399  myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
400  }
401  }
402  if (myActiveRoute.size() == 0) {
403  delete myActiveRouteColor;
404  myActiveRouteColor = nullptr;
405  if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
407  if (route != nullptr) {
409  }
410  myActiveRouteID = "";
411  myActiveRouteRefID = "";
412  return;
413  }
414  if (myVehicleParameter != nullptr) {
415  throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
416  } else {
417  throw ProcessError(TLF("Route '%' has no edges.", myActiveRouteID));
418  }
419  }
420  if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
421  throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
422  }
423  if (myActiveRouteRepeat > 0) {
424  // duplicate route
425  ConstMSEdgeVector tmpEdges = myActiveRoute;
426  auto tmpStops = myActiveRouteStops;
427 
430  std::string errSuffix = ".";
431  if (myVehicleParameter != nullptr) {
434  if (vtype != nullptr) {
435  vClass = vtype->getVehicleClass();
436  errSuffix = TLF(" for vehicle '%' with vClass %.", myVehicleParameter->id, getVehicleClassNames(vClass));
437  }
438  }
439  if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
440  if (tmpStops.size() == 0 || tmpStops.back().jump < 0) {
441  throw ProcessError(TLF("Disconnected route '%' when repeating. Last edge '%' is not connected to first edge '%'%",
442  myActiveRouteID, myActiveRoute.back()->getID(), myActiveRoute.front()->getID(), errSuffix));
443  }
444  }
445  }
446  for (int i = 0; i < myActiveRouteRepeat; i++) {
447  myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
448  for (SUMOVehicleParameter::Stop stop : tmpStops) {
449  if (stop.until > 0) {
450  if (myActiveRoutePeriod <= 0) {
451  const std::string description = myVehicleParameter != nullptr
452  ? "for " + type + " '" + myVehicleParameter->id + "'"
453  : "'" + myActiveRouteID + "'";
454  throw ProcessError(TLF("Cannot repeat stops with 'until' in route % because no cycleTime is defined.", description));
455  }
456  stop.until += myActiveRoutePeriod * (i + 1);
457  }
458  if (stop.arrival > 0) {
459  if (myActiveRoutePeriod <= 0) {
460  const std::string description = myVehicleParameter != nullptr
461  ? "for " + type + " '" + myVehicleParameter->id + "'"
462  : "'" + myActiveRouteID + "'";
463  throw ProcessError(TLF("Cannot repeat stops with 'arrival' in route % because no cycleTime is defined.", description));
464  }
465  stop.arrival += myActiveRoutePeriod * (i + 1);
466  }
467  stop.index = STOP_INDEX_REPEAT;
468  myActiveRouteStops.push_back(stop);
469  }
470  }
471  if (myActiveRouteStops.size() > 0) {
472  // never jump on the last stop of a repeating route
473  myActiveRouteStops.back().jump = -1;
474  }
475  }
476  MSRoute* const route = new MSRoute(myActiveRouteID, myActiveRoute,
481  route->setCosts(myCurrentCosts);
482  route->setReroute(mustReroute);
483  myActiveRoute.clear();
484  ConstMSRoutePtr constRoute = std::shared_ptr<const MSRoute>(route);
485  if (!MSRoute::dictionary(myActiveRouteID, constRoute)) {
487  if (myVehicleParameter != nullptr) {
488  if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
489  throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
490  } else {
491  throw ProcessError(TLF("A vehicle with id '%' already exists.", myVehicleParameter->id));
492  }
493  } else {
494  throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myActiveRouteID));
495  }
496  }
497  } else {
498  if (myCurrentRouteDistribution != nullptr) {
500  }
501  }
502  myActiveRouteID = "";
503  myActiveRouteColor = nullptr;
504  myActiveRouteStops.clear();
506  } catch (ProcessError&) {
508  throw;
509  }
510 }
511 
512 
513 void
515  // check whether the id is really necessary
516  if (myVehicleParameter != nullptr) {
517  // ok, a vehicle is wrapping the route,
518  // we may use this vehicle's id as default
519  myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
520  // we have to record this or we cannot remove the distribution later
522  } else {
523  bool ok = true;
524  myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
525  if (!ok) {
526  return;
527  }
528  }
530  std::vector<double> probs;
531  if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
532  bool ok = true;
533  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
534  while (st.hasNext()) {
535  probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
536  }
537  }
538  if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
539  bool ok = true;
540  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
541  int probIndex = 0;
542  while (st.hasNext()) {
543  std::string routeID = st.next();
545  if (route == nullptr) {
546  throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
547  }
548  const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
549  myCurrentRouteDistribution->add(route, prob, false);
550  probIndex++;
551  }
552  if (probs.size() > 0 && probIndex != (int)probs.size()) {
553  WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
554  " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
555  }
556  }
557 }
558 
559 
560 void
562  if (myCurrentRouteDistribution != nullptr) {
563  const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
564  if (MSGlobals::gStateLoaded && haveSameID) {
566  myCurrentRouteDistribution = nullptr;
567  return;
568  }
569  if (haveSameID) {
571  throw ProcessError(TLF("Another route (or distribution) with the id '%' exists.", myCurrentRouteDistributionID));
572  }
575  throw ProcessError(TLF("Route distribution '%' is empty.", myCurrentRouteDistributionID));
576  }
578  myCurrentRouteDistribution = nullptr;
579  }
580 }
581 
582 
583 void
585  // get nested route
586  const std::string embeddedRouteID = "!" + myVehicleParameter->id;
587  ConstMSRoutePtr route = nullptr;
588  if (myReplayRerouting) {
590  if (rDist != nullptr && rDist->getVals().size() > 0) {
591  route = rDist->getVals().front();
592  }
593  }
594  if (route == nullptr) {
595  route = MSRoute::dictionary(embeddedRouteID, &myParsingRNG);
596  }
599  // let's check whether this vehicle had to depart before the simulation starts
601  return;
602  }
603  }
604 
605  // get the vehicle's type
606  MSVehicleType* vtype = nullptr;
607 
608  try {
609  if (myVehicleParameter->vtypeid != "") {
610  vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
611  if (vtype == nullptr) {
612  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
613  }
614  if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
615  WRITE_WARNINGF(TL("Vehicle type '%' with vClass=pedestrian should only be used for persons and not for vehicle '%'."), vtype->getID(), myVehicleParameter->id);
616  }
617  } else {
618  // there should be one (at least the default one)
619  vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
620  }
622  // if the route id was given, prefer that one
623  if (route != nullptr && !myAmLoadingState) {
624  WRITE_WARNINGF(TL("Ignoring child element 'route' for vehicle '%' because attribute 'route' is set."), myVehicleParameter->id);
625  }
627  }
628  if (route == nullptr) {
629  // nothing found? -> error
630  if (myVehicleParameter->routeid != "") {
631  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
632  } else {
633  throw ProcessError(TLF("Vehicle '%' has no route.", myVehicleParameter->id));
634  }
635  }
636  myActiveRouteID = "";
637 
638  } catch (ProcessError&) {
640  throw;
641  }
642  if (route->mustReroute()) {
644  if (myVehicleParameter->stops.size() > 0) {
645  route = addVehicleStopsToImplicitRoute(route, false);
646  }
647  }
651  myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
652  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
653  + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
654  }
655  }
659  myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
660  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
661  + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
662  }
663  }
664 
665  // try to build the vehicle
666  SUMOVehicle* vehicle = nullptr;
667  if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
668  MSVehicleControl::VehicleDefinitionSource source = (myAmLoadingState) ? MSVehicleControl::VehicleDefinitionSource::STATE : MSVehicleControl::VehicleDefinitionSource::ROUTEFILE;
669  try {
670  vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
671  } catch (const ProcessError& e) {
672  myVehicleParameter = nullptr;
674  WRITE_WARNING(e.what());
675  vehControl.fixVehicleCounts();
676  return;
677  } else {
678  throw e;
679  }
680  }
681  const SUMOTime origDepart = myVehicleParameter->depart;
682  // maybe we do not want this vehicle to be inserted due to scaling
683  int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
684  if (quota > 0) {
687  vehControl.addVehicle(myVehicleParameter->id, vehicle);
688  if (myReplayRerouting) {
690  if (rDist != nullptr) {
691  for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
692  SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
693  auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
694  if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
695  // routing in the insertion step happens *after* insertion
696  MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(cmd, replacedAt);
697  } else {
699  }
700  }
701  }
702  }
703  int offset = 0;
704  for (int i = 1; i < quota; i++) {
707  }
709  newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
710  while (vehControl.getVehicle(newPars->id) != nullptr) {
711  offset += 1;
712  newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
713  }
716  // resample type
717  vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
718  }
719  vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, source, !myAmLoadingState);
720  vehControl.addVehicle(newPars->id, vehicle);
721  }
722  myVehicleParameter = nullptr;
723  } else {
724  vehControl.deleteVehicle(vehicle, true);
725  myVehicleParameter = nullptr;
726  vehicle = nullptr;
727  }
728  } else {
729  // strange: another vehicle with the same id already exists
731  // and was not loaded while loading a simulation state
732  // -> error
733  std::string veh_id = myVehicleParameter->id;
735  std::string scaleWarning = "";
736  if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
737  scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
738  }
739  throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
740  } else {
741  // ok, it seems to be loaded previously while loading a simulation state
742  vehicle = nullptr;
743  }
744  }
745  // check whether the vehicle shall be added directly to the network or
746  // shall stay in the internal buffer
747  if (vehicle != nullptr) {
750  }
751  }
752 }
753 
754 
757  // the route was defined without edges and its current edges were
758  // derived from route-stops.
759  // We may need to add additional edges for the vehicle-stops
761  assert(route->getStops().size() > 0);
762  ConstMSEdgeVector edges = route->getEdges();
764  MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
765  if (stop.index == 0) {
766  if (edges.front() != stopEdge ||
767  route->getStops().front().endPos < stop.endPos) {
768  edges.insert(edges.begin(), stopEdge);
769  }
770  } else if (stop.index == STOP_INDEX_END) {
771  if (edges.back() != stopEdge ||
772  route->getStops().back().endPos > stop.endPos) {
773  edges.push_back(stopEdge);
774  }
775  } else {
776  WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
777  }
778  }
779  ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
780  isPermanent, new RGBColor(route->getColor()), route->getStops());
781  if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
782  throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
783  }
784  return newRoute;
785 }
786 
787 
788 void
790  try {
791  if (myActiveTransportablePlan->size() == 0) {
792  std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
793  error[0] = (char)::toupper((char)error[0]);
794  throw ProcessError(error);
795  }
796  // let's check whether this transportable had to depart before the simulation starts
800  return;
801  }
802  // type existence has been checked on opening
805  && type->getVehicleClass() != SVC_PEDESTRIAN
807  WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
808  }
811  if (created > 0) {
813  } else {
815  }
816  } catch (ProcessError&) {
818  throw;
819  }
820 }
821 
822 
823 void
826 }
827 
828 
829 void
832 }
833 
834 
835 void
838 }
839 
840 
841 void
844 }
845 
846 
847 void
849  try {
850  const std::string fid = myVehicleParameter->id;
851  if (myActiveTransportablePlan->size() == 0) {
852  throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
853  }
854  // let's check whether this transportable (person/container) had to depart before the simulation starts
858  return;
859  }
860  // instantiate all persons/containers of this flow
861  int i = 0;
863  std::string baseID = myVehicleParameter->id;
866  throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
867  } else {
868  for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
870  // type existence has been checked on opening
872  addFlowTransportable(t, type, baseID, i++);
873  }
874  }
875  }
876  } else {
879  // poisson: randomize first depart
881  }
882  for (; i < myVehicleParameter->repetitionNumber && (myVehicleParameter->repetitionNumber != std::numeric_limits<int>::max()
884  // type existence has been checked on opening
888  }
889  }
891  } catch (ProcessError&) {
893  throw;
894  }
895  myStartTriggeredInFlow = false;
896 }
897 
898 
899 int
900 MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
901  try {
902  int numCreated = 0;
903  MSNet* const net = MSNet::getInstance();
906  //MSTransportableControl& pc = net->getPersonControl();
907  const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
908  if (quota == 0) {
909  tc.addDiscarded();
910  }
911  for (int j = 0; j < quota; j++) {
912  if (i > 0 || j > 0) {
913  // copy parameter and plan because the transportable takes over responsibility
914  SUMOVehicleParameter* copyParam = new SUMOVehicleParameter();
915  *copyParam = *myVehicleParameter;
916  myVehicleParameter = copyParam;
918  MSStage* lastStage = nullptr;
919  for (MSStage* const s : *myActiveTransportablePlan) {
920  copyPlan->push_back(s->clone());
921  if (lastStage != nullptr && s->getStageType() == MSStageType::WALKING && lastStage->getDestinationStop() != nullptr) {
922  MSStageMoving* walk = static_cast<MSStageMoving*>(copyPlan->back());
923  walk->setDepartPos(lastStage->getDestinationStop()->getAccessPos(walk->getEdge(), &myParsingRNG));
924  }
925  lastStage = s;
926  }
927  myActiveTransportablePlan = copyPlan;
929  const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
930  myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
931  }
932  }
933  myVehicleParameter->id = (baseID
934  + (i >= 0 ? "." + toString(i) : "")
935  + (j > 0 ? "." + toString(j) : ""));
940  numCreated++;
941  if (!tc.add(transportable)) {
942  std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
943  delete transportable;
946  throw ProcessError(error);
947  }
948  } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
949  && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
950  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);
951  }
952  }
953  return numCreated;
954  } catch (ProcessError&) {
956  throw;
957  }
958 }
959 
960 
961 void
964  vehType->check();
965  if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
966  const std::string id = vehType->getID();
967  delete vehType;
969  throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
970  }
971  } else {
972  if (myCurrentVTypeDistribution != nullptr) {
974  }
975  }
976 }
977 
978 
979 void
981  myInsertStopEdgesAt = -1;
983  delete myVehicleParameter;
984  myVehicleParameter = nullptr;
985  return;
986  }
987  // let's check whether vehicles had to depart before the simulation starts
990  const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
991  while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
994  delete myVehicleParameter;
995  myVehicleParameter = nullptr;
996  return;
997  }
998  }
999  }
1000  if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
1001  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1002  }
1005  closeRoute(true);
1006  }
1008  if (route == nullptr) {
1009  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1010  }
1011  if (route->mustReroute()) {
1013  if (myVehicleParameter->stops.size() > 0) {
1014  route = addVehicleStopsToImplicitRoute(route, true);
1015  myVehicleParameter->routeid = route->getID();
1016  }
1017  }
1021  myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
1022  throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
1023  + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1024  }
1025  }
1029  myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
1030  throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
1031  + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1032  }
1033  }
1034  myActiveRouteID = "";
1035 
1036  // check whether the vehicle shall be added directly to the network or
1037  // shall stay in the internal buffer
1039  if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
1041  } else {
1043  delete myVehicleParameter;
1044  } else {
1045  throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
1046  }
1047  }
1048  }
1049  myVehicleParameter = nullptr;
1050 }
1051 
1052 
1053 void
1056  closeRoute(true);
1057  closeVehicle();
1058 }
1059 
1060 void
1063 }
1064 
1065 void
1068 }
1069 
1070 void
1072  if (myVehicleParameter == nullptr) {
1073  throw ProcessError(TLF("Cannot define % stage without %.", toString(modeTag), toString(modeTag)));
1074  }
1075  try {
1076  const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1077  std::string agent = "person";
1078  std::string stop = "bus stop";
1080  agent = "container";
1081  stop = "container stop";
1082  }
1083 
1084  if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1086  throw ProcessError("Found " + mode + " inside " + agent + " element");
1087  }
1088  const std::string aid = myVehicleParameter->id;
1089  bool ok = true;
1090  const MSEdge* from = nullptr;
1091  const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, "ANY");
1092  StringTokenizer st(desc);
1093  MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1094  MSEdge* to = nullptr;
1095  if (s != nullptr) {
1096  to = &s->getLane().getEdge();
1097  }
1098  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1099  s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1100 
1101  const SUMOVehicleParameter* startVeh = nullptr;
1102  const MSEdge* startVehFrom = nullptr;
1104  if (st.size() != 1) {
1105  throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1106  }
1107  // agent starts
1109  const std::string vehID = st.front();
1110  SUMOVehicle* sVeh = vehControl.getVehicle(vehID);
1111  if (sVeh == nullptr) {
1112  if (MSNet::getInstance()->hasFlow(vehID)) {
1113  startVeh = MSNet::getInstance()->getInsertionControl().getFlowPars(vehID);
1114  if (startVeh != nullptr) {
1115  ConstMSRoutePtr const route = MSRoute::dictionary(startVeh->routeid);
1116  startVehFrom = route->getEdges().front();
1117  // flows are inserted at the end of the time step so we
1118  // do delay the pedestrian event by one time step
1119  myVehicleParameter->depart = startVeh->depart + DELTA_T;
1120  myStartTriggeredInFlow = true;
1121  }
1122  }
1123  } else {
1124  startVeh = &sVeh->getParameter();
1125  startVehFrom = sVeh->getRoute().getEdges().front();
1126  myVehicleParameter->depart = startVeh->depart;
1127  }
1128  if (startVeh == nullptr) {
1129  throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1130  }
1131  if (startVeh->departProcedure == DepartDefinition::TRIGGERED) {
1132  throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1133  }
1134  }
1135 
1136  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1137  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1138  from = MSEdge::dictionary(fromID);
1139  if (from == nullptr) {
1140  throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1141  }
1142  if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1143  const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1144  && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1145  const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1146  || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1147  if (!(stopWithAccess || transferAtJunction)) {
1148  throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1149  "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1150  }
1151  }
1152  if (startVeh != nullptr && startVehFrom != from) {
1153  throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1154  "' (edge '" + fromID + "' != edge '" + startVehFrom->getID() + "').");
1155  }
1156  } else if (startVeh != nullptr) {
1157  from = startVehFrom;
1158  }
1159  if (myActiveTransportablePlan->empty()) {
1160  if (from == nullptr) {
1161  throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1162  } else {
1164  from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1165  }
1166  }
1167  // given attribute may override given stopping place due access requirements
1168  if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1169  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1170  to = MSEdge::dictionary(toID);
1171  if (to == nullptr) {
1172  throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1173  }
1174  }
1175  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1176  const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1177  const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1178  arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1179  myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, 0.0, st.getVector(), group, intendedVeh, intendedDepart));
1180  myParamStack.push_back(myActiveTransportablePlan->back());
1181  } catch (ProcessError&) {
1183  throw;
1184  }
1185 }
1186 
1188 MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1189  bool ok = true;
1190  // dummy stop parameter to hold the attributes
1192  if (stopParam != nullptr) {
1193  stop = *stopParam;
1194  } else {
1195  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1196  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1197  stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1198  stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1199  stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1200  stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1201  }
1202  MSStoppingPlace* toStop = nullptr;
1203  if (stop.busstop != "") {
1205  if (toStop == nullptr) {
1206  ok = false;
1207  WRITE_ERROR(TLF("The busStop '%' is not known%.", stop.busstop, errorSuffix));
1208  }
1209  } else if (stop.containerstop != "") {
1211  if (toStop == nullptr) {
1212  ok = false;
1213  WRITE_ERROR(TLF("The containerStop '%' is not known%.", stop.containerstop, errorSuffix));
1214  }
1215  } else if (stop.parkingarea != "") {
1217  if (toStop == nullptr) {
1218  ok = false;
1219  WRITE_ERROR(TLF("The parkingArea '%' is not known%.", stop.parkingarea, errorSuffix));
1220  }
1221  } else if (stop.chargingStation != "") {
1222  // ok, we have a charging station
1224  if (toStop == nullptr) {
1225  ok = false;
1226  WRITE_ERROR(TLF("The chargingStation '%' is not known%.", stop.chargingStation, errorSuffix));
1227  }
1228  } else if (stop.overheadWireSegment != "") {
1229  // ok, we have an overhead wire segment
1231  if (toStop == nullptr) {
1232  ok = false;
1233  WRITE_ERROR(TLF("The overhead wire segment '%' is not known%.", stop.overheadWireSegment, errorSuffix));
1234  }
1235  }
1236  if (!ok && MSGlobals::gCheckRoutes) {
1237  throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1238  }
1239  return toStop;
1240 }
1241 
1244  Parameterised* result = nullptr;
1245  try {
1246  std::string errorSuffix;
1248  errorSuffix = " in person '" + myVehicleParameter->id + "'";
1249  } else if (myActiveType == ObjectTypeEnum::CONTAINER) {
1250  errorSuffix = " in container '" + myVehicleParameter->id + "'";
1251  } else if (myVehicleParameter != nullptr) {
1252  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'";
1253  } else {
1254  errorSuffix = " in route '" + myActiveRouteID + "'";
1255  }
1257  bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1258  if (!ok) {
1260  throw ProcessError();
1261  }
1262  return result;
1263  }
1264  const MSEdge* edge = nullptr;
1265  MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1266  // if one of the previous stops is defined
1267  if (toStop != nullptr) {
1268  const MSLane& l = toStop->getLane();
1269  stop.lane = l.getID();
1270  if ((stop.parametersSet & STOP_END_SET) == 0) {
1271  stop.endPos = toStop->getEndLanePosition();
1272  } else {
1273  stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1274  }
1275  stop.startPos = toStop->getBeginLanePosition();
1276  edge = &l.getEdge();
1277  } else {
1278  // no, the lane and the position should be given directly
1279  // get the lane
1280  stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1281  stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1282  if (ok && stop.edge != "") { // edge is given directly
1283  edge = MSEdge::dictionary(stop.edge);
1284  if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1285  throw ProcessError(TLF("The edge '%' for a stop is not known%.", stop.edge, errorSuffix));
1286  }
1287  } else if (ok && stop.lane != "") { // lane is given directly
1288  MSLane* stopLane = MSLane::dictionary(stop.lane);
1289  if (stopLane == nullptr) {
1290  // check for opposite-direction stop
1291  stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1292  if (stopLane != nullptr) {
1293  edge = MSEdge::dictionary(stop.edge);
1294  }
1295  } else {
1296  edge = &stopLane->getEdge();
1297  }
1298  if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1299  throw ProcessError(TLF("The lane '%' for a stop is not known%.", stop.lane, errorSuffix));
1300  }
1301  } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
1302  || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
1303  Position pos;
1304  bool geo = false;
1305  if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
1306  pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
1307  } else {
1308  pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
1309  geo = true;
1310  }
1311  PositionVector positions;
1312  positions.push_back(pos);
1313  ConstMSEdgeVector geoEdges;
1315  auto& vc = MSNet::getInstance()->getVehicleControl();
1316  if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
1317  MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1318  if (type != nullptr) {
1319  vClass = type->getParameter().vehicleClass;
1320  }
1321  }
1322  parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok);
1323  if (ok) {
1324  edge = geoEdges.front();
1325  if (geo) {
1327  }
1328  stop.parametersSet |= STOP_END_SET;
1329  stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
1330  } else {
1331  throw ProcessError(TLF("Could not map stop position '%' to the network%.", pos, errorSuffix));
1332  }
1333  } else {
1334  if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1335  toStop = myActiveTransportablePlan->back()->getDestinationStop();
1336  if (toStop != nullptr) { // use end of movement before definied as a stopping place
1337  edge = &toStop->getLane().getEdge();
1338  stop.lane = toStop->getLane().getID();
1339  stop.endPos = toStop->getEndLanePosition();
1340  stop.startPos = toStop->getBeginLanePosition();
1341  } else { // use end of movement before definied as lane/edge
1342  edge = myActiveTransportablePlan->back()->getDestination();
1343  stop.lane = edge->getLanes()[0]->getID();
1344  stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1345  stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1346  }
1347  } else {
1348  const std::string msg = TLF("A stop must be placed on a busStop, a chargingStation, an overheadWireSegment, a containerStop, a parkingArea, an edge or a lane%.", errorSuffix);
1350  throw ProcessError(msg);
1351  } else {
1352  WRITE_WARNING(msg);
1353  return result;
1354  }
1355  }
1356  }
1357  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1358  if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1359  WRITE_WARNINGF(TL("Deprecated attribute 'pos' in description of stop%."), errorSuffix);
1360  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1361  }
1362  stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1363  if (!myAmLoadingState) {
1364  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1366  if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1367  throw ProcessError(TLF("Invalid start or end position for stop on %'%.",
1368  stop.lane != "" ? ("lane '" + stop.lane) : ("edge '" + stop.edge), errorSuffix));
1369  }
1370  }
1371  }
1372  stop.edge = edge->getID();
1374  if (myActiveTransportablePlan->empty()) {
1375  double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1377  : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1379  edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1380  } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1381  throw ProcessError(TLF("Disconnected plan for % '%' (%!=%).", myActiveTypeName, myVehicleParameter->id,
1382  edge->getID(), myActiveTransportablePlan->back()->getDestination()->getID()));
1383  }
1384  // transporting veh stops somewhere
1385  else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1387  const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1388  const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1389  const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1390  if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1391  WRITE_WARNINGF(TL("Disconnected plan for % '%' (stop range %-% does not cover previous arrival position %)."),
1392  myActiveTypeName, myVehicleParameter->id, toString(start), toString(end), toString(prevAr));
1393  }
1394  }
1395  std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1396  double pos = (stop.startPos + stop.endPos) / 2.;
1397  if (!myActiveTransportablePlan->empty()) {
1398  pos = myActiveTransportablePlan->back()->getArrivalPos();
1399  }
1400  myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1401  result = myActiveTransportablePlan->back();
1402 
1403  } else if (myVehicleParameter != nullptr) {
1404  myVehicleParameter->stops.push_back(stop);
1405  result = &myVehicleParameter->stops.back();
1406  } else {
1407  myActiveRouteStops.push_back(stop);
1408  result = &myActiveRouteStops.back();
1409  }
1410  if (myInsertStopEdgesAt >= 0) {
1411  //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1412  if (edge->isInternal()) {
1413  if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1416  }
1419  } else {
1420  myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1422  }
1423  } else if (myHaveVia) {
1424  // vias were loaded, check for consistency
1425  if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1426  WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'."),
1428  }
1429  }
1430  } catch (ProcessError&) {
1432  throw;
1433  }
1434  return result;
1435 }
1436 
1437 
1438 void
1439 MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1440  const MSEdge* fromEdge, const MSEdge*& toEdge,
1441  double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1442  const MSStage* const lastStage, bool& ok) {
1443  try {
1444  const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1445 
1446  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1447  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."));
1448  }
1449  departPos = 0.;
1450  if (lastStage != nullptr) {
1451  if (lastStage->getDestinationStop() != nullptr) {
1452  departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge, &myParsingRNG);
1453  } else if (lastStage->getDestination() == fromEdge) {
1454  departPos = lastStage->getArrivalPos();
1455  } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1456  departPos = fromEdge->getLength();
1457  }
1458  }
1459 
1460  bs = retrieveStoppingPlace(attrs, " " + description);
1461  if (bs != nullptr) {
1462  arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1463  if (arrivalPos < 0) {
1464  throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1465  }
1466  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1467  const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1468  const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1469  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1470  if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1471  arrivalPos = arrPos;
1472  } else {
1473  WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1474  arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1475  }
1476  }
1477  } else {
1478  if (toEdge == nullptr) {
1479  throw ProcessError(TLF("No destination edge for %.", description));
1480  }
1481  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1483  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1484  } else {
1485  arrivalPos = toEdge->getLength() / 2.;
1486  }
1487  }
1488  } catch (ProcessError&) {
1490  throw;
1491  }
1492 }
1493 
1494 
1495 void
1497  if (myVehicleParameter == nullptr) {
1498  throw ProcessError(TL("Cannot define person stage without person."));
1499  }
1500  try {
1501  myActiveRoute.clear();
1502  bool ok = true;
1503  const char* const id = myVehicleParameter->id.c_str();
1504  const MSEdge* from = nullptr;
1505  const MSEdge* to = nullptr;
1507  myInsertStopEdgesAt = -1;
1509  from = myActiveRoute.front();
1510  } else if (myActiveTransportablePlan->empty()) {
1511  throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1512  } else {
1513  from = myActiveTransportablePlan->back()->getDestination();
1514  }
1516  to = myActiveRoute.back();
1517  } // else, to may also be derived from stopping place
1518 
1519  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1520  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1521  throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1522  }
1523 
1524  double departPos = 0;
1525  double arrivalPos = 0;
1526  MSStoppingPlace* stoppingPlace = nullptr;
1527  parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1528 
1529  SVCPermissions modeSet = 0;
1530  if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
1531  const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1532  std::string errorMsg;
1533  // try to parse person modes
1534  if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1535  throw InvalidArgument(errorMsg);
1536  }
1537  } else {
1538  modeSet = myVehicleParameter->modes;
1539  }
1540  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1542  const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, myVehicleParameter->vTypes);
1543  for (StringTokenizer st(types); st.hasNext();) {
1544  const std::string vtypeid = st.next();
1545  const MSVehicleType* const vType = vehControl.getVType(vtypeid);
1546  if (vType == nullptr) {
1547  throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1548  }
1549  modeSet |= (vType->getVehicleClass() == SVC_BICYCLE) ? SVC_BICYCLE : SVC_PASSENGER;
1550  }
1551  const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1552  if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1553  throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1554  }
1555  const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1556  const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1557  if (ok) {
1558  if (myActiveTransportablePlan->empty()) {
1559  double initialDepartPos = myVehicleParameter->departPos;
1561  initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1562  }
1563  myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1564  }
1566  MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1567  myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1568  stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1569  departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1570  myParamStack.push_back(myActiveTransportablePlan->back());
1571  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1573  }
1574  }
1575  myActiveRoute.clear();
1576  } catch (ProcessError&) {
1578  throw;
1579  }
1580 }
1581 
1582 
1583 void
1585  if (myVehicleParameter == nullptr) {
1586  throw ProcessError(TL("Cannot define person stage without person."));
1587  }
1588  myActiveRouteID = "";
1590  try {
1591  myActiveRoute.clear();
1592  bool ok = true;
1593  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1594  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1595  throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1596  }
1597  double speed = -1; // default to vType speed
1598  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1599  speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1600  if (speed <= 0) {
1601  throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1602  }
1603  }
1604  double departPos = 0;
1605  double arrivalPos = 0;
1606  MSStoppingPlace* bs = nullptr;
1607  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1608  myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1610  if (route == nullptr) {
1611  throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1612  }
1613  myActiveRoute = route->getEdges();
1614  } else {
1616  }
1617  if (myActiveTransportablePlan->empty()) {
1618  double initialDepartPos = myVehicleParameter->departPos;
1620  initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1621  }
1622  myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1623  }
1624  parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1625  if (myActiveRoute.empty()) {
1626  throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1627  }
1628  if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1629  myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1630  myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1631  if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1632  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1633  }
1634  }
1635  const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1636  const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1637  myActiveTransportablePlan->push_back(new MSStageWalking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1638  myParamStack.push_back(myActiveTransportablePlan->back());
1639  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1641  }
1642  myActiveRoute.clear();
1643  } catch (ProcessError&) {
1645  throw;
1646  }
1647  } else { // parse walks from->to as person trips
1648  addPersonTrip(attrs);
1649  }
1650 }
1651 
1652 double
1653 MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1654  double pos = MSPModel::UNSPECIFIED_POS_LAT;
1655  if (value == "") {
1656  return pos;
1657  }
1658  std::string error;
1660  if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1661  if (dpd != DepartPosLatDefinition::GIVEN) {
1663  if (lane == nullptr) {
1664  throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1665  }
1666  const double usableWidth = lane->getWidth() - 0.5;
1667  switch (dpd) {
1669  pos = -usableWidth / 2;
1670  break;
1672  pos = usableWidth / 2;
1673  break;
1675  pos = 0;
1676  break;
1682  break;
1683  default:
1684  break;
1685  }
1686  }
1687  } else {
1688  throw ProcessError(error);
1689  }
1690  return pos;
1691 }
1692 
1693 
1694 void
1695 MSRouteHandler::addTransportable(const SUMOSAXAttributes& /*attrs*/, const bool isPerson) {
1697  if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1698  const std::string error = TLF("The type '%' for % '%' is not known.", myVehicleParameter->vtypeid, myActiveTypeName, myVehicleParameter->id);
1700  throw ProcessError(error);
1701  }
1703 }
1704 
1705 
1706 void
1708  try {
1709  myActiveRoute.clear();
1710  const std::string cid = myVehicleParameter->id;
1711  bool ok = true;
1712  const MSEdge* from = nullptr;
1713  const MSEdge* to = nullptr;
1714  MSStoppingPlace* cs = nullptr;
1715 
1716  double speed;
1718  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1719  speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1720  if (!ok) {
1721  throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1722  }
1723  } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1724  speed = vtype->getMaxSpeed();
1725  } else { // default speed value
1727  }
1728  if (speed <= 0) {
1729  throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1730  }
1731  // values from preceding stage:
1732  const MSEdge* preEdge = nullptr;
1733  double prePos = 0;
1734  if (!myActiveTransportablePlan->empty()) {
1735  preEdge = myActiveTransportablePlan->back()->getDestination();
1736  prePos = myActiveTransportablePlan->back()->getArrivalPos();
1737  }
1738  // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1739  double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1740 
1741  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1742  MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1743  } else {
1744  // set 'from':
1745  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1746  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1747  from = MSEdge::dictionary(fromID);
1748  if (from == nullptr) {
1749  throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1750  }
1751  if (preEdge != nullptr && preEdge != from) {
1752  throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1753  }
1754  } else if (preEdge == nullptr) {
1755  throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1756  } else {
1757  from = preEdge;
1758  }
1759  // set 'to':
1760  if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1761  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1762  to = MSEdge::dictionary(toID);
1763  if (to == nullptr) {
1764  throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1765  }
1766  } else {
1767  const std::string description = "container '" + cid + "' transhipping from edge '" + from->getID() + "'";
1768  cs = retrieveStoppingPlace(attrs, " " + description);
1769  if (cs != nullptr) {
1770  to = &cs->getLane().getEdge();
1771  } else {
1772  throw ProcessError(TLF("Inconsistent tranship for container '%', needs either: 'edges', 'to', 'containerStop' (or any other stopping place)", cid));
1773  }
1774  }
1775  myActiveRoute.push_back(from);
1776  myActiveRoute.push_back(to);
1777  }
1778  if (myActiveRoute.empty()) {
1779  throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1780  }
1781  if (preEdge == nullptr) { // additional 'stop' to start the container plan
1783  myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1784  }
1785  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1786  cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1787  myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1788  myParamStack.push_back(myActiveTransportablePlan->back());
1789  myActiveRoute.clear();
1790  } catch (ProcessError&) {
1792  throw;
1793  }
1794 }
1795 
1796 
1797 void
1799  for (const auto& edge : MSEdge::getAllEdges()) {
1800  for (MSLane* lane : edge->getLanes()) {
1801  Boundary b = lane->getShape().getBoxBoundary();
1802  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1803  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1804  tree->Insert(cmin, cmax, lane);
1805  }
1806  }
1807 }
1808 
1809 
1810 MSEdge*
1811 MSRouteHandler::retrieveEdge(const std::string& id) {
1812  return MSEdge::dictionary(id);
1813 }
1814 
1815 
1816 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
#define JUNCTION_TAZ_MISSING_HELP
Definition: MapMatcher.h:29
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:31
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:46
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
const long long int VTYPEPARS_MAXSPEED_SET
const long long int VTYPEPARS_VEHICLECLASS_SET
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const double DEFAULT_VEH_PROB
const std::string DEFAULT_VTYPE_ID
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
const double DEFAULT_CONTAINER_TRANSHIP_SPEED
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const 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
A random position is chosen.
const int VEHPARS_DEPARTPOS_SET
const int VEHPARS_FROM_TAZ_SET
const int STOP_INDEX_REPEAT
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_PARAM
parameter associated to a certain key
@ SUMO_TAG_PERSON
@ SUMO_TAG_PERSONFLOW
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_ATTR_STARTPOS
@ SUMO_ATTR_LINES
@ SUMO_ATTR_LANE
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_LON
@ SUMO_ATTR_REFID
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_VIALONLAT
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_REPLACED_AT_TIME
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_VIAXY
@ SUMO_ATTR_Y
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_DEPARTPOS_LAT
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_TO_JUNCTION
@ SUMO_ATTR_X
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_ACTTYPE
@ SUMO_ATTR_PROBS
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_TOLONLAT
@ SUMO_ATTR_CHARGING_STATION
@ SUMO_ATTR_ROUTES
@ SUMO_ATTR_MODES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_OVERHEAD_WIRE_SEGMENT
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_GROUP
@ SUMO_ATTR_COST
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_REPLACED_ON_INDEX
@ SUMO_ATTR_VIAJUNCTIONS
@ SUMO_ATTR_FROMXY
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_LAT
@ SUMO_ATTR_WALKFACTOR
@ SUMO_ATTR_TOXY
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_FROMLONLAT
@ SUMO_ATTR_REPEAT
@ SUMO_ATTR_INTENDED
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_CYCLETIME
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:118
PositionVector getShape(const bool closeShape) const
get position vector (shape) based on this boundary
Definition: Boundary.cpp:423
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:124
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 const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
A road/street connecting two junctions.
Definition: MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition: MSEdge.cpp:1034
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:1058
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition: MSEdge.cpp:895
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
double getLength() const
return the length of the edge
Definition: MSEdge.h:670
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:268
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition: MSEdge.cpp:995
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: MSEdge.cpp:885
const MSJunction * getToJunction() const
Definition: MSEdge.h:418
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
const SUMOVehicleParameter * getFlowPars(const std::string &id) const
return parameters for the given flow
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
SUMOTime computeRandomDepartOffset() const
compute (optional) random offset to the departure time
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2395
bool isInternal() const
Definition: MSLane.cpp:2526
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:627
The simulated network and simulation perfomer.
Definition: MSNet.h:89
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1191
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:481
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1373
bool hasContainers() const
Returns whether containers are simulated.
Definition: MSNet.h:411
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:431
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:471
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:395
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1182
static const double RANDOM_POS_LAT
magic value to encode randomized lateral offset for persons when starting a walk
Definition: MSPModel.h:68
static const double UNSPECIFIED_POS_LAT
the default lateral offset for persons when starting a walk
Definition: MSPModel.h:65
void closePerson() override
Ends the processing of a person.
RandomDistributor< ConstMSRoutePtr > * myCurrentRouteDistribution
The currently parsed distribution of routes (probability->route)
void addRideOrTransport(const SUMOSAXAttributes &attrs, const SumoXMLTag modeTag)
Processing of a transport.
void closeContainerFlow() override
Ends the processing of a containerFlow.
void openFlow(const SUMOSAXAttributes &attrs) override
opens a flow for reading
ConstMSRoutePtr addVehicleStopsToImplicitRoute(ConstMSRoutePtr route, bool isPermanent)
adapt implicit route (edges derived from stops) to additional vehicle-stops
void addWalk(const SUMOSAXAttributes &attrs) override
add a fully specified walk
void addTransport(const SUMOSAXAttributes &attrs) override
Processing of a transport.
void deleteActivePlanAndVehicleParameter()
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void initLaneTree(NamedRTree *tree) override
bool myAmLoadingState
whether a state file is being loaded
bool myStartTriggeredInFlow
whether we are loading a personFlow that is starting triggered in a vehicle flow
void resetActivePlanAndVehicleParameter()
reset MSTransportablePlans after transportable tag closes
SUMOTime myActiveRoutePeriod
bool myHaveVia
Wether an object with 'via'-attribute is being parsed.
int addFlowTransportable(SUMOTime depart, MSVehicleType *type, const std::string &baseID, int i)
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void closeTransportable()
ends the processing of a transportable (as person or container)
MSEdge * retrieveEdge(const std::string &id) override
MSStoppingPlace * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, SUMOVehicleParameter::Stop *stopParam=nullptr)
Parse destination stop.
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
void openRoute(const SUMOSAXAttributes &attrs) override
opens a route for reading
void closeVehicleTypeDistribution() override
closes (ends) the building of a distribution
void addTranship(const SUMOSAXAttributes &attrs) override
Processing of a tranship.
void closeRoute(const bool mayBeDisconnected=false) override
closes (ends) the building of a route.
static SumoRNG myParsingRNG
A random number generator used to choose from vtype/route distributions and computing the speed facto...
void parseFromViaTo(SumoXMLTag tag, const SUMOSAXAttributes &attrs)
Called for parsing from and to and the corresponding taz attributes.
void closeFlow() override
Ends the processing of a flow.
MSTransportable::MSTransportablePlan * myActiveTransportablePlan
The plan of the current transportable (person or container)
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
std::string myCurrentRouteDistributionID
The id of the currently parsed route distribution.
RandomDistributor< MSVehicleType * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
void closeContainer() override
Ends the processing of a container.
SUMOTime myActiveRouteReplacedAtTime
The time at which this route was replaced (from vehroute-output)
void closeTrip() override
Ends the processing of a trip.
void openTrip(const SUMOSAXAttributes &attrs) override
opens a trip for reading
void addPersonTrip(const SUMOSAXAttributes &attrs) override
add a routing request for a walking or intermodal person
ConstMSEdgeVector myActiveRoute
The current route.
int myActiveRouteRepeat
number of repetitions of the active route
ObjectTypeEnum myActiveType
The type of the current object.
void closePersonFlow() override
Ends the processing of a personFlow.
int myActiveRouteReplacedIndex
The index at which this route was replaced (from vehroute-output)
void closeRouteDistribution() override
closes (ends) the building of a distribution
MSRouteHandler(const std::string &file, bool addVehiclesDirectly)
standard constructor
std::string myScaleSuffix
prefix when copying vehicles with –scale
ObjectTypeEnum
enum for object type
double interpretDepartPosLat(const std::string &value, int departLane, const std::string &element)
virtual ~MSRouteHandler()
standard destructor
bool myAddVehiclesDirectly
Information whether vehicles shall be directly added to the network or kept within the buffer.
bool myReplayRerouting
whether loaded rerouting events shall be replayed
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs) override
opens a type distribution for reading
Parameterised * addStop(const SUMOSAXAttributes &attrs) override
Processing of a stop.
virtual void closeVehicle() override
Ends the processing of a vehicle (note: is virtual because is reimplemented in MSStateHandler)
void openRouteFlow(const SUMOSAXAttributes &attrs) override
opens a route flow for reading
void openRouteDistribution(const SUMOSAXAttributes &attrs) override
opens a route distribution for reading
void addRide(const SUMOSAXAttributes &attrs) override
Processing of a ride.
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const MSEdge *fromEdge, const MSEdge *&toEdge, double &departPos, double &arrivalPos, MSStoppingPlace *&bs, const MSStage *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
bool myActiveRoutePermanent
whether the active route is stored indefinitely (used by state loader)
std::string myActiveTypeName
The name of the current object type.
void closeVType() override
Ends the processing of a vehicle type.
void addTransportable(const SUMOSAXAttributes &attrs, const bool isPerson) override
Processing of a person.
void closeTransportableFlow()
ends the flow of a transportable
void setReroute(bool reroute=true)
Definition: MSRoute.h:220
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:205
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:197
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
const MSEdge * getDestination() const
returns the destination edge
Definition: MSStage.cpp:65
virtual double getArrivalPos() const
Definition: MSStage.h:94
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition: MSStage.h:85
MSStageType getStageType() const
Definition: MSStage.h:127
static const MSLane * checkDepartLane(const MSEdge *edge, SUMOVehicleClass svc, int laneIndex, const std::string &id)
interpret custom depart lane
const MSEdge * getEdge() const
Returns the current edge.
void setDepartPos(const double pos)
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
double getAccessPos(const MSEdge *edge, SumoRNG *rng=nullptr) const
the position on the given edge which is connected to this stop, -1 on failure
int getLoadedNumber() const
Returns the number of build transportables.
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, SumoRNG *rng) const
Builds a new person.
bool add(MSTransportable *transportable)
Adds a single transportable, returns false if an id clash occurred.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
The class responsible for building and deletion of vehicles.
VehicleDefinitionSource
possible origins of a vehicle definition
double getScale() const
sets the demand scaling factor
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
int getQuota(double frac=-1, int loaded=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, ConstMSRoutePtr route, MSVehicleType *type, const bool ignoreStopErrors, const VehicleDefinitionSource source=ROUTEFILE, bool addRouteStops=true)
Builds a vehicle, increases the number of built vehicles.
const RandomDistributor< MSVehicleType * > * getVTypeDistribution(const std::string &typeDistID) const
return the vehicle type distribution with the given id
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false, bool wasKept=false)
Deletes the vehicle.
The car-following model and parameter.
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].
bool wasSet(long long int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:80
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
const SUMOVTypeParameter & getParameter() const
void check()
Checks whether vehicle type parameters may be problematic (Currently, only the value for the action s...
Provides utility functions for matching locations to edges (during route parsing)
Definition: MapMatcher.h:44
void parseGeoEdges(const PositionVector &positions, bool geo, SUMOVehicleClass vClass, std::vector< const MSEdge * > &into, const std::string &rid, bool isFrom, bool &ok)
Definition: MapMatcher.h:56
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:92
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A RT-tree for efficient storing of SUMO's Named objects.
Definition: NamedRTree.h:61
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition: NamedRTree.h:79
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
An upper class for objects with additional parameters.
Definition: Parameterised.h:41
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
A list of positions.
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
const std::vector< T > & getVals() const
Returns the members of the distribution.
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
Parser for routes during their loading.
bool parseStop(SUMOVehicleParameter::Stop &stop, const SUMOSAXAttributes &attrs, std::string errorSuffix, MsgHandler *const errorOutput)
parses attributes common to all stops
std::vector< SUMOVehicleParameter::Stop > myActiveRouteStops
List of the stops on the parsed route.
void registerLastDepart()
save last depart (only to be used if vehicle is not discarded)
double myCurrentCosts
The currently parsed route costs.
std::string myActiveRouteID
The id of the current route.
std::vector< Parameterised * > myParamStack
The stack of currently parsed parameterised objects.
SUMOVehicleParameter * myVehicleParameter
Parameter of the current vehicle, trip, person, container or flow.
const bool myHardFail
flag to enable or disable hard fails
SUMOVTypeParameter * myCurrentVType
The currently parsed vehicle type.
static StopPos checkStopPos(double &startPos, double &endPos, const double laneLength, const double minLength, const bool friendlyPos)
check start and end position of a stop
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
double myActiveRouteProbability
The probability of the current route.
int myInsertStopEdgesAt
where stop edges can be inserted into the current route (-1 means no insertion)
std::string myActiveRouteRefID
The id of the route the current route references to.
const RGBColor * myActiveRouteColor
The currently parsed route's color.
virtual bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double scale
individual scaling factor (-1 for undefined)
SUMOVehicleClass vehicleClass
The vehicle's class.
Representation of a vehicle.
Definition: SUMOVehicle.h:62
virtual const MSRoute & getRoute() const =0
Returns the current route.
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
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.
SVCPermissions modes
The modes a person or container can use.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
std::string vTypes
The types of usable (auto-generated) vehicles for a person / container.
double departPos
(optional) The position the vehicle shall depart from
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
static bool parsePersonModes(const std::string &modes, const std::string &element, const std::string &id, SVCPermissions &modeSet, std::string &error)
Validates a given person modes value.
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