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  try {
669  vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
670  } catch (const ProcessError& e) {
671  myVehicleParameter = nullptr;
673  WRITE_WARNING(e.what());
674  vehControl.fixVehicleCounts();
675  return;
676  } else {
677  throw e;
678  }
679  }
680  const SUMOTime origDepart = myVehicleParameter->depart;
681  // maybe we do not want this vehicle to be inserted due to scaling
682  int quota = myAmLoadingState ? 1 : vehControl.getQuota(vehControl.getScale() * vtype->getParameter().scale);
683  if (quota > 0) {
686  vehControl.addVehicle(myVehicleParameter->id, vehicle);
687  if (myReplayRerouting) {
689  if (rDist != nullptr) {
690  for (int i = 0; i < (int)rDist->getVals().size() - 1; i++) {
691  SUMOTime replacedAt = rDist->getVals()[i]->getReplacedTime();
692  auto* cmd = new Command_RouteReplacement(vehicle->getID(), rDist->getVals()[i + 1]);
693  if (i == 0 && replacedAt >= 0 && replacedAt == myVehicleParameter->depart) {
694  // routing in the insertion step happens *after* insertion
695  MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(cmd, replacedAt);
696  } else {
698  }
699  }
700  }
701  }
702  int offset = 0;
703  for (int i = 1; i < quota; i++) {
706  }
708  newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
709  while (vehControl.getVehicle(newPars->id) != nullptr) {
710  offset += 1;
711  newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
712  }
715  // resample type
716  vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
717  }
718  vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes, true, !myAmLoadingState);
719  vehControl.addVehicle(newPars->id, vehicle);
720  }
721  myVehicleParameter = nullptr;
722  } else {
723  vehControl.deleteVehicle(vehicle, true);
724  myVehicleParameter = nullptr;
725  vehicle = nullptr;
726  }
727  } else {
728  // strange: another vehicle with the same id already exists
730  // and was not loaded while loading a simulation state
731  // -> error
732  std::string veh_id = myVehicleParameter->id;
734  std::string scaleWarning = "";
735  if (vehControl.getScale() * vtype->getParameter().scale > 1 && veh_id.find(myScaleSuffix) != std::string::npos) {
736  scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
737  }
738  throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
739  } else {
740  // ok, it seems to be loaded previously while loading a simulation state
741  vehicle = nullptr;
742  }
743  }
744  // check whether the vehicle shall be added directly to the network or
745  // shall stay in the internal buffer
746  if (vehicle != nullptr) {
749  }
750  }
751 }
752 
753 
756  // the route was defined without edges and its current edges were
757  // derived from route-stops.
758  // We may need to add additional edges for the vehicle-stops
760  assert(route->getStops().size() > 0);
761  ConstMSEdgeVector edges = route->getEdges();
763  MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
764  if (stop.index == 0) {
765  if (edges.front() != stopEdge ||
766  route->getStops().front().endPos < stop.endPos) {
767  edges.insert(edges.begin(), stopEdge);
768  }
769  } else if (stop.index == STOP_INDEX_END) {
770  if (edges.back() != stopEdge ||
771  route->getStops().back().endPos > stop.endPos) {
772  edges.push_back(stopEdge);
773  }
774  } else {
775  WRITE_WARNINGF(TL("Could not merge vehicle stops for vehicle '%' into implicitly defined route '%'"), myVehicleParameter->id, route->getID());
776  }
777  }
778  ConstMSRoutePtr newRoute = std::make_shared<MSRoute>("!" + myVehicleParameter->id, edges,
779  isPermanent, new RGBColor(route->getColor()), route->getStops());
780  if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
781  throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
782  }
783  return newRoute;
784 }
785 
786 
787 void
789  try {
790  if (myActiveTransportablePlan->size() == 0) {
791  std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
792  error[0] = (char)::toupper((char)error[0]);
793  throw ProcessError(error);
794  }
795  // let's check whether this transportable had to depart before the simulation starts
799  return;
800  }
801  // type existence has been checked on opening
804  && type->getVehicleClass() != SVC_PEDESTRIAN
806  WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
807  }
810  if (created > 0) {
812  } else {
814  }
815  } catch (ProcessError&) {
817  throw;
818  }
819 }
820 
821 
822 void
825 }
826 
827 
828 void
831 }
832 
833 
834 void
837 }
838 
839 
840 void
843 }
844 
845 
846 void
848  try {
849  const std::string fid = myVehicleParameter->id;
850  if (myActiveTransportablePlan->size() == 0) {
851  throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
852  }
853  // let's check whether this transportable (person/container) had to depart before the simulation starts
857  return;
858  }
859  // instantiate all persons/containers of this flow
860  int i = 0;
862  std::string baseID = myVehicleParameter->id;
865  throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
866  } else {
867  for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
869  // type existence has been checked on opening
871  addFlowTransportable(t, type, baseID, i++);
872  }
873  }
874  }
875  } else {
878  // poisson: randomize first depart
880  }
881  for (; i < myVehicleParameter->repetitionNumber && (myVehicleParameter->repetitionNumber != std::numeric_limits<int>::max()
883  // type existence has been checked on opening
887  }
888  }
890  } catch (ProcessError&) {
892  throw;
893  }
894  myStartTriggeredInFlow = false;
895 }
896 
897 
898 int
899 MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
900  try {
901  int numCreated = 0;
902  MSNet* const net = MSNet::getInstance();
905  //MSTransportableControl& pc = net->getPersonControl();
906  const int quota = vc.getQuota(vc.getScale() * type->getParameter().scale, tc.getLoadedNumber());
907  if (quota == 0) {
908  tc.addDiscarded();
909  }
910  for (int j = 0; j < quota; j++) {
911  if (i > 0 || j > 0) {
912  // copy parameter and plan because the transportable takes over responsibility
913  SUMOVehicleParameter* copyParam = new SUMOVehicleParameter();
914  *copyParam = *myVehicleParameter;
915  myVehicleParameter = copyParam;
917  MSStage* lastStage = nullptr;
918  for (MSStage* const s : *myActiveTransportablePlan) {
919  copyPlan->push_back(s->clone());
920  if (lastStage != nullptr && s->getStageType() == MSStageType::WALKING && lastStage->getDestinationStop() != nullptr) {
921  MSStageMoving* walk = static_cast<MSStageMoving*>(copyPlan->back());
922  walk->setDepartPos(lastStage->getDestinationStop()->getAccessPos(walk->getEdge(), &myParsingRNG));
923  }
924  lastStage = s;
925  }
926  myActiveTransportablePlan = copyPlan;
928  const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
929  myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
930  }
931  }
932  myVehicleParameter->id = (baseID
933  + (i >= 0 ? "." + toString(i) : "")
934  + (j > 0 ? "." + toString(j) : ""));
939  numCreated++;
940  if (!tc.add(transportable)) {
941  std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
942  delete transportable;
945  throw ProcessError(error);
946  }
947  } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
948  && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
949  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);
950  }
951  }
952  return numCreated;
953  } catch (ProcessError&) {
955  throw;
956  }
957 }
958 
959 
960 void
963  vehType->check();
964  if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
965  const std::string id = vehType->getID();
966  delete vehType;
968  throw ProcessError(TLF("Another vehicle type (or distribution) with the id '%' exists.", id));
969  }
970  } else {
971  if (myCurrentVTypeDistribution != nullptr) {
973  }
974  }
975 }
976 
977 
978 void
980  myInsertStopEdgesAt = -1;
982  delete myVehicleParameter;
983  myVehicleParameter = nullptr;
984  return;
985  }
986  // let's check whether vehicles had to depart before the simulation starts
989  const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
990  while (myVehicleParameter->repetitionTotalOffset < offsetToBegin) {
993  delete myVehicleParameter;
994  myVehicleParameter = nullptr;
995  return;
996  }
997  }
998  }
999  if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
1000  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1001  }
1004  closeRoute(true);
1005  }
1007  if (route == nullptr) {
1008  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
1009  }
1010  if (route->mustReroute()) {
1012  if (myVehicleParameter->stops.size() > 0) {
1013  route = addVehicleStopsToImplicitRoute(route, true);
1014  myVehicleParameter->routeid = route->getID();
1015  }
1016  }
1020  myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
1021  throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
1022  + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1023  }
1024  }
1028  myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
1029  throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
1030  + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
1031  }
1032  }
1033  myActiveRouteID = "";
1034 
1035  // check whether the vehicle shall be added directly to the network or
1036  // shall stay in the internal buffer
1038  if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
1040  } else {
1042  delete myVehicleParameter;
1043  } else {
1044  throw ProcessError(TLF("Another flow with the id '%' exists.", myVehicleParameter->id));
1045  }
1046  }
1047  }
1048  myVehicleParameter = nullptr;
1049 }
1050 
1051 
1052 void
1055  closeRoute(true);
1056  closeVehicle();
1057 }
1058 
1059 void
1062 }
1063 
1064 void
1067 }
1068 
1069 void
1071  if (myVehicleParameter == nullptr) {
1072  throw ProcessError(TLF("Cannot define % stage without %.", toString(modeTag), toString(modeTag)));
1073  }
1074  try {
1075  const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
1076  std::string agent = "person";
1077  std::string stop = "bus stop";
1079  agent = "container";
1080  stop = "container stop";
1081  }
1082 
1083  if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
1085  throw ProcessError("Found " + mode + " inside " + agent + " element");
1086  }
1087  const std::string aid = myVehicleParameter->id;
1088  bool ok = true;
1089  const MSEdge* from = nullptr;
1090  const std::string desc = attrs.getOpt<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok, "ANY");
1091  StringTokenizer st(desc);
1092  MSStoppingPlace* s = retrieveStoppingPlace(attrs, " in " + agent + " '" + aid + "'");
1093  MSEdge* to = nullptr;
1094  if (s != nullptr) {
1095  to = &s->getLane().getEdge();
1096  }
1097  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
1098  s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
1099 
1100  const SUMOVehicleParameter* startVeh = nullptr;
1101  const MSEdge* startVehFrom = nullptr;
1103  if (st.size() != 1) {
1104  throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
1105  }
1106  // agent starts
1108  const std::string vehID = st.front();
1109  SUMOVehicle* sVeh = vehControl.getVehicle(vehID);
1110  if (sVeh == nullptr) {
1111  if (MSNet::getInstance()->hasFlow(vehID)) {
1112  startVeh = MSNet::getInstance()->getInsertionControl().getFlowPars(vehID);
1113  if (startVeh != nullptr) {
1114  ConstMSRoutePtr const route = MSRoute::dictionary(startVeh->routeid);
1115  startVehFrom = route->getEdges().front();
1116  // flows are inserted at the end of the time step so we
1117  // do delay the pedestrian event by one time step
1118  myVehicleParameter->depart = startVeh->depart + DELTA_T;
1119  myStartTriggeredInFlow = true;
1120  }
1121  }
1122  } else {
1123  startVeh = &sVeh->getParameter();
1124  startVehFrom = sVeh->getRoute().getEdges().front();
1125  myVehicleParameter->depart = startVeh->depart;
1126  }
1127  if (startVeh == nullptr) {
1128  throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1129  }
1130  if (startVeh->departProcedure == DepartDefinition::TRIGGERED) {
1131  throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
1132  }
1133  }
1134 
1135  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1136  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
1137  from = MSEdge::dictionary(fromID);
1138  if (from == nullptr) {
1139  throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1140  }
1141  if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1142  const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1143  && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1144  const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1145  || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1146  if (!(stopWithAccess || transferAtJunction)) {
1147  throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1148  "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1149  }
1150  }
1151  if (startVeh != nullptr && startVehFrom != from) {
1152  throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1153  "' (edge '" + fromID + "' != edge '" + startVehFrom->getID() + "').");
1154  }
1155  } else if (startVeh != nullptr) {
1156  from = startVehFrom;
1157  }
1158  if (myActiveTransportablePlan->empty()) {
1159  if (from == nullptr) {
1160  throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1161  } else {
1163  from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1164  }
1165  }
1166  // given attribute may override given stopping place due access requirements
1167  if (to == nullptr || attrs.hasAttribute(SUMO_ATTR_TO)) {
1168  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1169  to = MSEdge::dictionary(toID);
1170  if (to == nullptr) {
1171  throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1172  }
1173  }
1174  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1175  const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1176  const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1177  arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1178  myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, 0.0, st.getVector(), group, intendedVeh, intendedDepart));
1179  myParamStack.push_back(myActiveTransportablePlan->back());
1180  } catch (ProcessError&) {
1182  throw;
1183  }
1184 }
1185 
1187 MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1188  bool ok = true;
1189  // dummy stop parameter to hold the attributes
1191  if (stopParam != nullptr) {
1192  stop = *stopParam;
1193  } else {
1194  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1195  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1196  stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1197  stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1198  stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1199  stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1200  }
1201  MSStoppingPlace* toStop = nullptr;
1202  if (stop.busstop != "") {
1204  if (toStop == nullptr) {
1205  ok = false;
1206  WRITE_ERROR(TLF("The busStop '%' is not known%.", stop.busstop, errorSuffix));
1207  }
1208  } else if (stop.containerstop != "") {
1210  if (toStop == nullptr) {
1211  ok = false;
1212  WRITE_ERROR(TLF("The containerStop '%' is not known%.", stop.containerstop, errorSuffix));
1213  }
1214  } else if (stop.parkingarea != "") {
1216  if (toStop == nullptr) {
1217  ok = false;
1218  WRITE_ERROR(TLF("The parkingArea '%' is not known%.", stop.parkingarea, errorSuffix));
1219  }
1220  } else if (stop.chargingStation != "") {
1221  // ok, we have a charging station
1223  if (toStop == nullptr) {
1224  ok = false;
1225  WRITE_ERROR(TLF("The chargingStation '%' is not known%.", stop.chargingStation, errorSuffix));
1226  }
1227  } else if (stop.overheadWireSegment != "") {
1228  // ok, we have an overhead wire segment
1230  if (toStop == nullptr) {
1231  ok = false;
1232  WRITE_ERROR(TLF("The overhead wire segment '%' is not known%.", stop.overheadWireSegment, errorSuffix));
1233  }
1234  }
1235  if (!ok && MSGlobals::gCheckRoutes) {
1236  throw ProcessError(TLF("Invalid stop definition%.", errorSuffix));
1237  }
1238  return toStop;
1239 }
1240 
1243  Parameterised* result = nullptr;
1244  try {
1245  std::string errorSuffix;
1247  errorSuffix = " in person '" + myVehicleParameter->id + "'";
1248  } else if (myActiveType == ObjectTypeEnum::CONTAINER) {
1249  errorSuffix = " in container '" + myVehicleParameter->id + "'";
1250  } else if (myVehicleParameter != nullptr) {
1251  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'";
1252  } else {
1253  errorSuffix = " in route '" + myActiveRouteID + "'";
1254  }
1256  bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1257  if (!ok) {
1259  throw ProcessError();
1260  }
1261  return result;
1262  }
1263  const MSEdge* edge = nullptr;
1264  MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1265  // if one of the previous stops is defined
1266  if (toStop != nullptr) {
1267  const MSLane& l = toStop->getLane();
1268  stop.lane = l.getID();
1269  if ((stop.parametersSet & STOP_END_SET) == 0) {
1270  stop.endPos = toStop->getEndLanePosition();
1271  } else {
1272  stop.endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, nullptr, ok);
1273  }
1274  stop.startPos = toStop->getBeginLanePosition();
1275  edge = &l.getEdge();
1276  } else {
1277  // no, the lane and the position should be given directly
1278  // get the lane
1279  stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1280  stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1281  if (ok && stop.edge != "") { // edge is given directly
1282  edge = MSEdge::dictionary(stop.edge);
1283  if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1284  throw ProcessError(TLF("The edge '%' for a stop is not known%.", stop.edge, errorSuffix));
1285  }
1286  } else if (ok && stop.lane != "") { // lane is given directly
1287  MSLane* stopLane = MSLane::dictionary(stop.lane);
1288  if (stopLane == nullptr) {
1289  // check for opposite-direction stop
1290  stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1291  if (stopLane != nullptr) {
1292  edge = MSEdge::dictionary(stop.edge);
1293  }
1294  } else {
1295  edge = &stopLane->getEdge();
1296  }
1297  if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1298  throw ProcessError(TLF("The lane '%' for a stop is not known%.", stop.lane, errorSuffix));
1299  }
1300  } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
1301  || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
1302  Position pos;
1303  bool geo = false;
1304  if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
1305  pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
1306  } else {
1307  pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
1308  geo = true;
1309  }
1310  PositionVector positions;
1311  positions.push_back(pos);
1312  ConstMSEdgeVector geoEdges;
1314  auto& vc = MSNet::getInstance()->getVehicleControl();
1315  if (!vc.getVTypeDistribution(myVehicleParameter->vtypeid)) {
1316  MSVehicleType* const type = vc.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1317  if (type != nullptr) {
1318  vClass = type->getParameter().vehicleClass;
1319  }
1320  }
1321  parseGeoEdges(positions, geo, vClass, geoEdges, myVehicleParameter->id, true, ok);
1322  if (ok) {
1323  edge = geoEdges.front();
1324  if (geo) {
1326  }
1327  stop.parametersSet |= STOP_END_SET;
1328  stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
1329  } else {
1330  throw ProcessError(TLF("Could not map stop position '%' to the network%.", pos, errorSuffix));
1331  }
1332  } else {
1333  if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1334  toStop = myActiveTransportablePlan->back()->getDestinationStop();
1335  if (toStop != nullptr) { // use end of movement before definied as a stopping place
1336  edge = &toStop->getLane().getEdge();
1337  stop.lane = toStop->getLane().getID();
1338  stop.endPos = toStop->getEndLanePosition();
1339  stop.startPos = toStop->getBeginLanePosition();
1340  } else { // use end of movement before definied as lane/edge
1341  edge = myActiveTransportablePlan->back()->getDestination();
1342  stop.lane = edge->getLanes()[0]->getID();
1343  stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1344  stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1345  }
1346  } else {
1347  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);
1349  throw ProcessError(msg);
1350  } else {
1351  WRITE_WARNING(msg);
1352  return result;
1353  }
1354  }
1355  }
1356  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1357  if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1358  WRITE_WARNINGF(TL("Deprecated attribute 'pos' in description of stop%."), errorSuffix);
1359  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1360  }
1361  stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1362  if (!myAmLoadingState) {
1363  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS))
1365  if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), 0, friendlyPos) != StopPos::STOPPOS_VALID)) {
1366  throw ProcessError(TLF("Invalid start or end position for stop on %'%.",
1367  stop.lane != "" ? ("lane '" + stop.lane) : ("edge '" + stop.edge), errorSuffix));
1368  }
1369  }
1370  }
1371  stop.edge = edge->getID();
1373  if (myActiveTransportablePlan->empty()) {
1374  double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1376  : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1378  edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1379  } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1380  throw ProcessError(TLF("Disconnected plan for % '%' (%!=%).", myActiveTypeName, myVehicleParameter->id,
1381  edge->getID(), myActiveTransportablePlan->back()->getDestination()->getID()));
1382  }
1383  // transporting veh stops somewhere
1384  else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1386  const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1387  const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1388  const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1389  if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1390  WRITE_WARNINGF(TL("Disconnected plan for % '%' (stop range %-% does not cover previous arrival position %)."),
1391  myActiveTypeName, myVehicleParameter->id, toString(start), toString(end), toString(prevAr));
1392  }
1393  }
1394  std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1395  double pos = (stop.startPos + stop.endPos) / 2.;
1396  if (!myActiveTransportablePlan->empty()) {
1397  pos = myActiveTransportablePlan->back()->getArrivalPos();
1398  }
1399  myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1400  result = myActiveTransportablePlan->back();
1401 
1402  } else if (myVehicleParameter != nullptr) {
1403  myVehicleParameter->stops.push_back(stop);
1404  result = &myVehicleParameter->stops.back();
1405  } else {
1406  myActiveRouteStops.push_back(stop);
1407  result = &myActiveRouteStops.back();
1408  }
1409  if (myInsertStopEdgesAt >= 0) {
1410  //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1411  if (edge->isInternal()) {
1412  if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1415  }
1418  } else {
1419  myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1421  }
1422  } else if (myHaveVia) {
1423  // vias were loaded, check for consistency
1424  if (std::find(myActiveRoute.begin(), myActiveRoute.end(), edge) == myActiveRoute.end()) {
1425  WRITE_WARNINGF(TL("Stop edge '%' missing in attribute 'via' for % '%'."),
1427  }
1428  }
1429  } catch (ProcessError&) {
1431  throw;
1432  }
1433  return result;
1434 }
1435 
1436 
1437 void
1438 MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1439  const MSEdge* fromEdge, const MSEdge*& toEdge,
1440  double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1441  const MSStage* const lastStage, bool& ok) {
1442  try {
1443  const std::string description = "person '" + personID + "' walking from edge '" + fromEdge->getID() + "'";
1444 
1445  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1446  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."));
1447  }
1448  departPos = 0.;
1449  if (lastStage != nullptr) {
1450  if (lastStage->getDestinationStop() != nullptr) {
1451  departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge, &myParsingRNG);
1452  } else if (lastStage->getDestination() == fromEdge) {
1453  departPos = lastStage->getArrivalPos();
1454  } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1455  departPos = fromEdge->getLength();
1456  }
1457  }
1458 
1459  bs = retrieveStoppingPlace(attrs, " " + description);
1460  if (bs != nullptr) {
1461  arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1462  if (arrivalPos < 0) {
1463  throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1464  }
1465  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1466  const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1467  const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1468  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1469  if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1470  arrivalPos = arrPos;
1471  } else {
1472  WRITE_WARNINGF(TL("Ignoring arrivalPos for % because it is outside the given stop '%'."), description, toString(SUMO_ATTR_BUS_STOP));
1473  arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1474  }
1475  }
1476  } else {
1477  if (toEdge == nullptr) {
1478  throw ProcessError(TLF("No destination edge for %.", description));
1479  }
1480  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1482  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1483  } else {
1484  arrivalPos = toEdge->getLength() / 2.;
1485  }
1486  }
1487  } catch (ProcessError&) {
1489  throw;
1490  }
1491 }
1492 
1493 
1494 void
1496  if (myVehicleParameter == nullptr) {
1497  throw ProcessError(TL("Cannot define person stage without person."));
1498  }
1499  try {
1500  myActiveRoute.clear();
1501  bool ok = true;
1502  const char* const id = myVehicleParameter->id.c_str();
1503  const MSEdge* from = nullptr;
1504  const MSEdge* to = nullptr;
1506  myInsertStopEdgesAt = -1;
1508  from = myActiveRoute.front();
1509  } else if (myActiveTransportablePlan->empty()) {
1510  throw ProcessError(TLF("Start edge not defined for person '%'.", myVehicleParameter->id));
1511  } else {
1512  from = myActiveTransportablePlan->back()->getDestination();
1513  }
1515  to = myActiveRoute.back();
1516  } // else, to may also be derived from stopping place
1517 
1518  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1519  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1520  throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1521  }
1522 
1523  double departPos = 0;
1524  double arrivalPos = 0;
1525  MSStoppingPlace* stoppingPlace = nullptr;
1526  parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1527 
1528  const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1529  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1530  SVCPermissions modeSet = 0;
1531  std::string errorMsg;
1532  // try to parse person modes
1533  if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1534  throw InvalidArgument(errorMsg);
1535  }
1537  const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1538  for (StringTokenizer st(types); st.hasNext();) {
1539  const std::string vtypeid = st.next();
1540  if (vehControl.getVType(vtypeid) == nullptr) {
1541  throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1542  }
1543  modeSet |= SVC_PASSENGER;
1544  }
1545  const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1546  if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1547  throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1548  }
1549  const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1550  const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), -1, "personTrip");
1551  if (ok) {
1552  if (myActiveTransportablePlan->empty()) {
1553  double initialDepartPos = myVehicleParameter->departPos;
1555  initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1556  }
1557  myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1558  }
1560  MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1561  myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1562  stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1563  departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1564  myParamStack.push_back(myActiveTransportablePlan->back());
1565  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1567  }
1568  }
1569  myActiveRoute.clear();
1570  } catch (ProcessError&) {
1572  throw;
1573  }
1574 }
1575 
1576 
1577 void
1579  if (myVehicleParameter == nullptr) {
1580  throw ProcessError(TL("Cannot define person stage without person."));
1581  }
1582  myActiveRouteID = "";
1584  try {
1585  myActiveRoute.clear();
1586  bool ok = true;
1587  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1588  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1589  throw ProcessError(TLF("Non-positive walking duration for '%'.", myVehicleParameter->id));
1590  }
1591  double speed = -1; // default to vType speed
1592  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1593  speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1594  if (speed <= 0) {
1595  throw ProcessError(TLF("Non-positive walking speed for '%'.", myVehicleParameter->id));
1596  }
1597  }
1598  double departPos = 0;
1599  double arrivalPos = 0;
1600  MSStoppingPlace* bs = nullptr;
1601  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1602  myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1604  if (route == nullptr) {
1605  throw ProcessError("The route '" + myActiveRouteID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1606  }
1607  myActiveRoute = route->getEdges();
1608  } else {
1610  }
1611  if (myActiveTransportablePlan->empty()) {
1612  double initialDepartPos = myVehicleParameter->departPos;
1614  initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1615  }
1616  myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1617  }
1618  parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1619  if (myActiveRoute.empty()) {
1620  throw ProcessError(TLF("No edges to walk for person '%'.", myVehicleParameter->id));
1621  }
1622  if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1623  myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1624  myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1625  if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1626  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1627  }
1628  }
1629  const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1630  const double departPosLat = interpretDepartPosLat(attrs.getOpt<std::string>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, ""), departLane, "walk");
1631  myActiveTransportablePlan->push_back(new MSStageWalking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane, myActiveRouteID));
1632  myParamStack.push_back(myActiveTransportablePlan->back());
1633  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1635  }
1636  myActiveRoute.clear();
1637  } catch (ProcessError&) {
1639  throw;
1640  }
1641  } else { // parse walks from->to as person trips
1642  addPersonTrip(attrs);
1643  }
1644 }
1645 
1646 double
1647 MSRouteHandler::interpretDepartPosLat(const std::string& value, int departLane, const std::string& element) {
1648  double pos = MSPModel::UNSPECIFIED_POS_LAT;
1649  if (value == "") {
1650  return pos;
1651  }
1652  std::string error;
1654  if (SUMOVehicleParameter::parseDepartPosLat(value, element, myVehicleParameter->id, pos, dpd, error)) {
1655  if (dpd != DepartPosLatDefinition::GIVEN) {
1657  if (lane == nullptr) {
1658  throw ProcessError(TLF("Could not find departure lane for walk of person '%' when interpreting departPosLat", myVehicleParameter->id));
1659  }
1660  const double usableWidth = lane->getWidth() - 0.5;
1661  switch (dpd) {
1663  pos = -usableWidth / 2;
1664  break;
1666  pos = usableWidth / 2;
1667  break;
1669  pos = 0;
1670  break;
1676  break;
1677  default:
1678  break;
1679  }
1680  }
1681  } else {
1682  throw ProcessError(error);
1683  }
1684  return pos;
1685 }
1686 
1687 
1688 void
1689 MSRouteHandler::addTransportable(const SUMOSAXAttributes& /*attrs*/, const bool isPerson) {
1691  if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1692  const std::string error = TLF("The type '%' for % '%' is not known.", myVehicleParameter->vtypeid, myActiveTypeName, myVehicleParameter->id);
1694  throw ProcessError(error);
1695  }
1697 }
1698 
1699 
1700 void
1702  try {
1703  myActiveRoute.clear();
1704  const std::string cid = myVehicleParameter->id;
1705  bool ok = true;
1706  const MSEdge* from = nullptr;
1707  const MSEdge* to = nullptr;
1708  MSStoppingPlace* cs = nullptr;
1709 
1710  double speed;
1712  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1713  speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1714  if (!ok) {
1715  throw ProcessError(TLF("Could not read tranship speed for container '%'.", cid));
1716  }
1717  } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1718  speed = vtype->getMaxSpeed();
1719  } else { // default speed value
1721  }
1722  if (speed <= 0) {
1723  throw ProcessError(TLF("Non-positive tranship speed for container '%'.", cid));
1724  }
1725  // values from preceding stage:
1726  const MSEdge* preEdge = nullptr;
1727  double prePos = 0;
1728  if (!myActiveTransportablePlan->empty()) {
1729  preEdge = myActiveTransportablePlan->back()->getDestination();
1730  prePos = myActiveTransportablePlan->back()->getArrivalPos();
1731  }
1732  // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1733  double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1734 
1735  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1736  MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1737  } else {
1738  // set 'from':
1739  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1740  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1741  from = MSEdge::dictionary(fromID);
1742  if (from == nullptr) {
1743  throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1744  }
1745  if (preEdge != nullptr && preEdge != from) {
1746  throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1747  }
1748  } else if (preEdge == nullptr) {
1749  throw ProcessError(TLF("The start edge for container '%' is not known.", cid));
1750  } else {
1751  from = preEdge;
1752  }
1753  // set 'to':
1755  std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1757  if (cs == nullptr) {
1758  throw ProcessError("Unknown container stop '" + csID + "' for container '" + cid + "'.");
1759  }
1760  to = &cs->getLane().getEdge();
1761  } else if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1762  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1763  to = MSEdge::dictionary(toID);
1764  if (to == nullptr) {
1765  throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1766  }
1767  } else {
1768  throw ProcessError(TLF("Inconsistent tranship for container '%', only one option is allowed: 'edges', 'to', 'containerStop'", cid));
1769  }
1770  myActiveRoute.push_back(from);
1771  myActiveRoute.push_back(to);
1772  }
1773  if (myActiveRoute.empty()) {
1774  throw ProcessError(TLF("No edges to tranship container '%'.", cid));
1775  }
1776  if (preEdge == nullptr) { // additional 'stop' to start the container plan
1778  myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1779  }
1780  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1781  cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1782  myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1783  myParamStack.push_back(myActiveTransportablePlan->back());
1784  myActiveRoute.clear();
1785  } catch (ProcessError&) {
1787  throw;
1788  }
1789 }
1790 
1791 
1792 void
1794  for (const auto& edge : MSEdge::getAllEdges()) {
1795  for (MSLane* lane : edge->getLanes()) {
1796  Boundary b = lane->getShape().getBoxBoundary();
1797  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1798  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1799  tree->Insert(cmin, cmax, lane);
1800  }
1801  }
1802 }
1803 
1804 
1805 MSEdge*
1806 MSRouteHandler::retrieveEdge(const std::string& id) {
1807  return MSEdge::dictionary(id);
1808 }
1809 
1810 /****************************************************************************/
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_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:1022
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:1046
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition: MSEdge.cpp:883
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:662
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition: MSEdge.cpp:983
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: MSEdge.cpp:873
const MSJunction * getToJunction() const
Definition: MSEdge.h:415
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:2385
bool isInternal() const
Definition: MSLane.cpp:2516
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:182
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1182
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:1364
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:1173
static const double RANDOM_POS_LAT
magic value to encode randomized lateral offset for persons when starting a walk
Definition: MSPModel.h:133
static const double UNSPECIFIED_POS_LAT
the default lateral offset for persons when starting a walk
Definition: MSPModel.h:130
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:93
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition: MSStage.h:84
MSStageType getStageType() const
Definition: MSStage.h:126
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.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, ConstMSRoutePtr route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true, bool addRouteStops=true)
Builds a vehicle, increases the number of built vehicles.
double getScale() const
sets the demand scaling factor
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
virtual 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.
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:60
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.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
double departPos
(optional) The position the vehicle shall depart from
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
static bool parsePersonModes(const std::string &modes, const std::string &element, const std::string &id, SVCPermissions &modeSet, std::string &error)
Validates a given person modes value.
bool wasSet(int what) const
Returns whether the given parameter was set.
static bool parseDepartPosLat(const std::string &val, const std::string &element, const std::string &id, double &pos, DepartPosLatDefinition &dpd, std::string &error)
Validates a given departPosLat value.
static double interpretEdgePos(double pos, double maximumValue, SumoXMLAttr attr, const std::string &id, bool silent=false)
Interprets negative edge positions and fits them onto a given edge.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int arrivalEdge
(optional) The final edge within the route of the vehicle
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static double parseWalkPos(SumoXMLAttr attr, const bool hardFail, const std::string &id, double maxPos, const std::string &val, SumoRNG *rng=0)
parse departPos or arrivalPos for a walk
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it