Eclipse SUMO - Simulation of Urban MObility
MSRouteHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
22 // Parser and container for routes during their loading
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include "MSRouteHandler.h"
30 #include <microsim/MSEdge.h>
31 #include <microsim/MSLane.h>
39 
40 #define JUNCTION_TAZ_MISSING_HELP "\nSet option '--junction-taz' or load a TAZ-file"
41 
42 
43 // ===========================================================================
44 // static members
45 // ===========================================================================
47 
48 
49 // ===========================================================================
50 // method definitions
51 // ===========================================================================
52 MSRouteHandler::MSRouteHandler(const std::string& file, bool addVehiclesDirectly) :
53  SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes", true),
54  myActiveRouteRepeat(0),
55  myActiveRoutePeriod(0),
56  myActiveType(ObjectTypeEnum::UNDEFINED),
57  myActiveTransportablePlan(nullptr),
58  myAddVehiclesDirectly(addVehiclesDirectly),
59  myCurrentVTypeDistribution(nullptr),
60  myCurrentRouteDistribution(nullptr),
61  myAmLoadingState(false),
62  myScaleSuffix(OptionsCont::getOptions().getString("scale-suffix")) {
63  myActiveRoute.reserve(100);
64 }
65 
66 
68 
69 
70 void
72  MSTransportable::MSTransportablePlan::iterator i;
73  if (myActiveTransportablePlan != nullptr) {
74  for (i = myActiveTransportablePlan->begin(); i != myActiveTransportablePlan->end(); i++) {
75  delete *i;
76  }
78  }
79  delete myVehicleParameter;
81 }
82 
83 
84 void
86  myVehicleParameter = nullptr;
87  myActiveTransportablePlan = nullptr;
89  myActiveTypeName = "";
90 }
91 
92 
93 void
95  const std::string element = toString(tag);
96  myActiveRoute.clear();
97  bool useTaz = OptionsCont::getOptions().getBool("with-taz");
99  WRITE_WARNING("Taz usage was requested but no taz present in " + element + " '" + myVehicleParameter->id + "'!");
100  useTaz = false;
101  }
102  bool ok = true;
103  // from-attributes
104  if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
106  const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROMJUNCTION);
107  const std::string tazType = useJunction ? "junction" : "taz";
108  const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROMJUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok, true);
109  const MSEdge* fromTaz = MSEdge::dictionary(tazID + "-source");
110  if (fromTaz == nullptr) {
111  throw ProcessError("Source " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
112  + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
113  } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
114  throw ProcessError("Source " + tazType + " '" + tazID + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
115  } else {
116  myActiveRoute.push_back(fromTaz);
117  }
118  } else {
119  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok, "", true),
120  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
121  }
122 
123  // via-attributes
124  if (!attrs.hasAttribute(SUMO_ATTR_VIA) && !attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
125  myInsertStopEdgesAt = (int)myActiveRoute.size();
126  }
127  ConstMSEdgeVector viaEdges;
129  for (std::string junctionID : attrs.getStringVector(SUMO_ATTR_VIAJUNCTIONS)) {
130  const MSEdge* viaSink = MSEdge::dictionary(junctionID + "-sink");
131  if (viaSink == nullptr) {
132  throw ProcessError("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
133  } else {
134  viaEdges.push_back(viaSink);
135  }
136  }
137  } else {
138  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true),
139  viaEdges, "for " + element + " '" + myVehicleParameter->id + "'");
140  }
141  for (const MSEdge* e : viaEdges) {
142  myActiveRoute.push_back(e);
143  myVehicleParameter->via.push_back(e->getID());
144  }
145 
146  // to-attributes
147  if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
149  const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TOJUNCTION);
150  const std::string tazType = useJunction ? "junction" : "taz";
151  const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TOJUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
152  const MSEdge* toTaz = MSEdge::dictionary(tazID + "-sink");
153  if (toTaz == nullptr) {
154  throw ProcessError("Sink " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
155  + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
156  } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
157  throw ProcessError("Sink " + tazType + " '" + tazID + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
158  } else {
159  myActiveRoute.push_back(toTaz);
160  }
161  } else {
162  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
163  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
164  }
166  if (myVehicleParameter->routeid == "") {
168  }
169 }
170 
171 
172 void
174  try {
176  && element != SUMO_TAG_RIDE && element != SUMO_TAG_TRANSPORT) {
177  const std::string mode = myActiveType == ObjectTypeEnum::PERSON ? "ride" : "transport";
178  throw ProcessError("Triggered departure for " + myActiveTypeName + " '" + myVehicleParameter->id + "' requires starting with a " + mode + ".");
179  }
180  SUMORouteHandler::myStartElement(element, attrs);
181  switch (element) {
182  case SUMO_TAG_PERSON:
183  case SUMO_TAG_PERSONFLOW:
184  addPerson(attrs);
185  break;
186  case SUMO_TAG_CONTAINER:
188  addContainer(attrs);
189  break;
190  case SUMO_TAG_FLOW:
191  parseFromViaTo((SumoXMLTag)element, attrs);
192  break;
193  case SUMO_TAG_TRIP:
194  parseFromViaTo((SumoXMLTag)element, attrs);
195  break;
196  default:
197  break;
198  }
199  } catch (ProcessError&) {
201  throw;
202  }
203 }
204 
205 
206 void
208  bool ok = true;
209  myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
210  if (ok) {
212  if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
213  const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
214  StringTokenizer st(vTypes);
215  while (st.hasNext()) {
216  std::string vtypeID = st.next();
218  if (type == nullptr) {
219  throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
220  }
222  }
223  }
224  }
225 }
226 
227 
228 void
230  if (myCurrentVTypeDistribution != nullptr) {
231  if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
233  return;
234  }
237  throw ProcessError("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
238  }
239  if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
241  throw ProcessError("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
242  }
243  myCurrentVTypeDistribution = nullptr;
244  }
245 }
246 
247 
248 void
250  myActiveRoute.clear();
251  myInsertStopEdgesAt = -1;
252  // check whether the id is really necessary
253  std::string rid;
254  if (myCurrentRouteDistribution != nullptr) {
256  rid = "distribution '" + myCurrentRouteDistributionID + "'";
257  } else if (myVehicleParameter != nullptr) {
258  // ok, a vehicle is wrapping the route,
259  // we may use this vehicle's id as default
260  myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
261  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
262  WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "').");
263  }
264  } else {
265  bool ok = true;
266  myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok, false);
267  if (!ok) {
268  return;
269  }
270  rid = "'" + myActiveRouteID + "'";
271  }
272  if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
273  rid = "for vehicle '" + myVehicleParameter->id + "'";
274  }
275  bool ok = true;
276  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
277  MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
278  }
279  myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
281  WRITE_ERROR("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
282  }
285  myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
287  // handle obsolete attribute name
289  if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
290  WRITE_WARNING("Attribute 'period' is deprecated for route. Use 'cycleTime' instead.");
291  }
292  if (myActiveRouteRepeat > 0) {
295  if (myVehicleParameter != nullptr) {
298  if (vtype != nullptr) {
299  vClass = vtype->getVehicleClass();
300  }
301  }
302  if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
303  WRITE_ERROR("Disconnected route " + rid + " when repeating.");
304  }
305  }
306  }
307  myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
308  if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
309  WRITE_ERROR("Invalid cost for route '" + myActiveRouteID + "'.");
310  }
311 }
312 
313 
314 void
316  // Currently unused
317 }
318 
319 
320 void
322  // Currently unused
323 }
324 
325 
326 void
328  // Currently unsued
329 }
330 
331 
332 void
333 MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
334  std::string type = "vehicle";
335  if (mayBeDisconnected) {
337  type = "flow";
338  } else {
339  type = "trip";
340  }
341  }
342 
343  try {
344  const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
345  if (mustReroute) {
346  // implicit route from stops
347  for (const SUMOVehicleParameter::Stop& stop : myActiveRouteStops) {
348  myActiveRoute.push_back(MSEdge::dictionary(stop.edge));
349  }
350  }
351  if (myActiveRoute.size() == 0) {
352  delete myActiveRouteColor;
353  myActiveRouteColor = nullptr;
354  if (myActiveRouteRefID != "" && myCurrentRouteDistribution != nullptr) {
356  if (route != nullptr) {
358  route->addReference();
359  }
360  }
361  myActiveRouteID = "";
362  myActiveRouteRefID = "";
363  return;
364  }
365  if (myVehicleParameter != nullptr) {
366  throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
367  } else {
368  throw ProcessError("Route '" + myActiveRouteID + "' has no edges.");
369  }
370  }
371  if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
372  throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
373  }
374  if (myActiveRouteRepeat > 0) {
375  // duplicate route
376  ConstMSEdgeVector tmpEdges = myActiveRoute;
377  auto tmpStops = myActiveRouteStops;
378  for (int i = 0; i < myActiveRouteRepeat; i++) {
379  myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
380  for (SUMOVehicleParameter::Stop stop : tmpStops) {
381  if (stop.until > 0) {
382  if (myActiveRoutePeriod <= 0) {
383  const std::string description = myVehicleParameter != nullptr
384  ? "for " + type + " '" + myVehicleParameter->id + "'"
385  : "'" + myActiveRouteID + "'";
386  throw ProcessError("Cannot repeat stops with 'until' in route " + description + " because no cycleTime is defined.");
387  }
388  stop.until += myActiveRoutePeriod * (i + 1);
389  }
390  if (stop.arrival > 0) {
391  if (myActiveRoutePeriod <= 0) {
392  const std::string description = myVehicleParameter != nullptr
393  ? "for " + type + " '" + myVehicleParameter->id + "'"
394  : "'" + myActiveRouteID + "'";
395  throw ProcessError("Cannot repeat stops with 'arrival' in route " + description + " because no cycleTime is defined.");
396  }
397  stop.arrival += myActiveRoutePeriod * (i + 1);
398  }
399  myActiveRouteStops.push_back(stop);
400  }
401  }
402  }
407  route->setCosts(myCurrentCosts);
408  route->setReroute(mustReroute);
409  myActiveRoute.clear();
410  if (!MSRoute::dictionary(myActiveRouteID, route)) {
411  delete route;
413  if (myVehicleParameter != nullptr) {
414  if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == nullptr) {
415  throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
416  } else {
417  throw ProcessError("A vehicle with id '" + myVehicleParameter->id + "' already exists.");
418  }
419  } else {
420  throw ProcessError("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
421  }
422  }
423  } else {
424  if (myCurrentRouteDistribution != nullptr) {
426  route->addReference();
427  }
428  }
429  }
430  myActiveRouteID = "";
431  myActiveRouteColor = nullptr;
432  myActiveRouteStops.clear();
433  } catch (ProcessError&) {
435  throw;
436  }
437 }
438 
439 
440 void
442  // check whether the id is really necessary
443  if (myVehicleParameter != nullptr) {
444  // ok, a vehicle is wrapping the route,
445  // we may use this vehicle's id as default
446  myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
447  } else {
448  bool ok = true;
449  myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
450  if (!ok) {
451  return;
452  }
453  }
455  std::vector<double> probs;
456  if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
457  bool ok = true;
458  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
459  while (st.hasNext()) {
460  probs.push_back(StringUtils::toDoubleSecure(st.next(), 1.0));
461  }
462  }
463  if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
464  bool ok = true;
465  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
466  int probIndex = 0;
467  while (st.hasNext()) {
468  std::string routeID = st.next();
469  const MSRoute* route = MSRoute::dictionary(routeID, &myParsingRNG);
470  if (route == nullptr) {
471  throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
472  }
473  const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
474  if (myCurrentRouteDistribution->add(route, prob, false)) {
475  route->addReference();
476  }
477  probIndex++;
478  }
479  if (probs.size() > 0 && probIndex != (int)probs.size()) {
480  WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
481  " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
482  }
483  }
484 }
485 
486 
487 void
489  if (myCurrentRouteDistribution != nullptr) {
490  const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != nullptr;
491  if (MSGlobals::gStateLoaded && haveSameID) {
493  myCurrentRouteDistribution = nullptr;
494  return;
495  }
496  if (haveSameID) {
498  throw ProcessError("Another route (or distribution) with the id '" + myCurrentRouteDistributionID + "' exists.");
499  }
502  throw ProcessError("Route distribution '" + myCurrentRouteDistributionID + "' is empty.");
503  }
505  myCurrentRouteDistribution = nullptr;
506  }
507 }
508 
509 
510 void
512  // get nested route
516  // let's check whether this vehicle had to depart before the simulation starts
518  if (route != nullptr) {
519  route->addReference();
520  route->release();
521  }
522  return;
523  }
524  }
525 
526  // get the vehicle's type
527  MSVehicleType* vtype = nullptr;
528 
529  try {
530  if (myVehicleParameter->vtypeid != "") {
531  vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
532  if (vtype == nullptr) {
533  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
534  }
535  if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
536  WRITE_WARNING("Vehicle type '" + vtype->getID() + "' with vClass=pedestrian should only be used for persons and not for vehicle '" + myVehicleParameter->id + "'.");
537  }
538  } else {
539  // there should be one (at least the default one)
540  vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
541  }
543  // if the route id was given, prefer that one
544  if (route != nullptr && !myAmLoadingState) {
545  WRITE_WARNING("Ignoring child element 'route' for vehicle '" + myVehicleParameter->id + "' because attribute 'route' is set.");
546  }
548  }
549  if (route == nullptr) {
550  // nothing found? -> error
551  if (myVehicleParameter->routeid != "") {
552  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
553  } else {
554  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route.");
555  }
556  }
557  myActiveRouteID = "";
558 
559  } catch (ProcessError&) {
561  throw;
562  }
563  if (route->mustReroute()) {
565  if (myVehicleParameter->stops.size() > 0) {
566  route = addVehicleStopsToImplicitRoute(route, false);
567  }
568  }
572  myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
573  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid departEdge index "
574  + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
575  }
576  }
580  myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
581  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
582  + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
583  }
584  }
585 
586  // try to build the vehicle
587  SUMOVehicle* vehicle = nullptr;
588  if (vehControl.getVehicle(myVehicleParameter->id) == nullptr) {
589  try {
590  vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes);
591  } catch (const ProcessError& e) {
593  WRITE_WARNING(e.what());
594  vehControl.fixVehicleCounts();
595  myVehicleParameter = nullptr;
596  vehicle = nullptr;
597  return;
598  } else {
599  throw e;
600  }
601  }
602  const SUMOTime origDepart = myVehicleParameter->depart;
603  // maybe we do not want this vehicle to be inserted due to scaling
604  int quota = myAmLoadingState ? 1 : vehControl.getQuota();
605  if (quota > 0) {
608  vehControl.addVehicle(myVehicleParameter->id, vehicle);
609  int offset = 0;
610  for (int i = 1; i < quota; i++) {
611  if (vehicle->getParameter().departProcedure == DEPART_GIVEN) {
613  }
615  newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
616  while (vehControl.getVehicle(newPars->id) != nullptr) {
617  offset += 1;
618  newPars->id = myVehicleParameter->id + myScaleSuffix + toString(i + offset);
619  }
621  vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes);
622  vehControl.addVehicle(newPars->id, vehicle);
623  }
624  myVehicleParameter = nullptr;
625  } else {
626  vehControl.deleteVehicle(vehicle, true);
627  myVehicleParameter = nullptr;
628  vehicle = nullptr;
629  }
630  } else {
631  // strange: another vehicle with the same id already exists
633  // and was not loaded while loading a simulation state
634  // -> error
635  std::string veh_id = myVehicleParameter->id;
637  std::string scaleWarning = "";
638  if (vehControl.getScale() > 0 && veh_id.find(myScaleSuffix) != std::string::npos) {
639  scaleWarning = "\n (Possibly duplicate id due to using option --scale. Set option --scale-suffix to prevent this)";
640  }
641  throw ProcessError("Another vehicle with the id '" + veh_id + "' exists." + scaleWarning);
642  } else {
643  // ok, it seems to be loaded previously while loading a simulation state
644  vehicle = nullptr;
645  }
646  }
647  // check whether the vehicle shall be added directly to the network or
648  // shall stay in the internal buffer
649  if (vehicle != nullptr) {
650  if (vehicle->getParameter().departProcedure == DEPART_GIVEN) {
652  }
653  }
654 }
655 
656 
657 MSRoute*
659  // the route was defined without edges and its current edges were
660  // derived from route-stops.
661  // We may need to add additional edges for the vehicle-stops
663  assert(route->getStops().size() > 0);
664  ConstMSEdgeVector edges = route->getEdges();
666  MSEdge* stopEdge = MSEdge::dictionary(stop.edge);
667  if (stop.index == 0) {
668  if (edges.front() != stopEdge ||
669  route->getStops().front().endPos < stop.endPos) {
670  edges.insert(edges.begin(), stopEdge);
671  }
672  } else if (stop.index == STOP_INDEX_END) {
673  if (edges.back() != stopEdge ||
674  route->getStops().back().endPos > stop.endPos) {
675  edges.push_back(stopEdge);
676  }
677  } else {
678  WRITE_WARNING("Could not merge vehicle stops for vehicle '" + myVehicleParameter->id + "' into implicitly defined route '" + route->getID() + "'");
679  }
680  }
681  MSRoute* newRoute = new MSRoute("!" + myVehicleParameter->id, edges,
682  isPermanent, new RGBColor(route->getColor()), route->getStops());
683  if (!MSRoute::dictionary(newRoute->getID(), newRoute)) {
684  delete newRoute;
685  throw ProcessError("Could not adapt implicit route for " + std::string(isPermanent ? "flow" : "vehicle") + " '" + myVehicleParameter->id + "'");
686  }
687  return newRoute;
688 }
689 
690 
691 void
693  try {
694  if (myActiveTransportablePlan->size() == 0) {
695  std::string error = myActiveTypeName + " '" + myVehicleParameter->id + "' has no plan.";
696  error[0] = (char)::toupper((char)error[0]);
697  throw ProcessError(error);
698  }
699  // let's check whether this transportable had to depart before the simulation starts
703  return;
704  }
705  // type existence has been checked on opening
708  && type->getVehicleClass() != SVC_PEDESTRIAN
710  WRITE_WARNINGF("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'.", myVehicleParameter->id, type->getID(), toString(type->getVehicleClass()));
711  }
715  } catch (ProcessError&) {
717  throw;
718  }
719 }
720 
721 
722 void
725 }
726 
727 
728 void
731 }
732 
733 
734 void
737 }
738 
739 
740 void
743 }
744 
745 
746 void
748  try {
749  const std::string fid = myVehicleParameter->id;
750  if (myActiveTransportablePlan->size() == 0) {
751  throw ProcessError(myActiveTypeName + "Flow '" + fid + "' has no plan.");
752  }
753  // let's check whether this transportable (person/container) had to depart before the simulation starts
757  return;
758  }
759  // type existence has been checked on opening
761  // instantiate all persons/containers of this flow
762  int i = 0;
764  std::string baseID = myVehicleParameter->id;
767  throw ProcessError("probabilistic " + myActiveTypeName + "Flow '" + fid + "' must specify end time");
768  } else {
769  for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
771  addFlowTransportable(t, type, baseID, i++);
772  }
773  }
774  }
775  } else {
777  for (; i < myVehicleParameter->repetitionNumber; i++) {
778  addFlowTransportable(depart, type, baseID, i);
781  }
782  }
783  }
785  } catch (ProcessError&) {
787  throw;
788  }
789 }
790 
791 
792 void
793 MSRouteHandler::addFlowTransportable(SUMOTime depart, MSVehicleType* type, const std::string& baseID, int i) {
794  try {
795  MSNet* const net = MSNet::getInstance();
797  //MSTransportableControl& pc = net->getPersonControl();
798  const int quota = MSNet::getInstance()->getVehicleControl().getQuota(-1, tc.getLoadedNumber());
799  if (quota == 0) {
800  tc.addDiscarded();
801  }
802  for (int j = 0; j < quota; j++) {
803  if (i > 0 || j > 0) {
804  // copy parameter and plan because the transportable takes over responsibility
805  SUMOVehicleParameter* copyParam = new SUMOVehicleParameter();
806  *copyParam = *myVehicleParameter;
807  myVehicleParameter = copyParam;
809  for (MSStage* s : *myActiveTransportablePlan) {
810  copyPlan->push_back(s->clone());
811  }
812  myActiveTransportablePlan = copyPlan;
814  const double initialDepartPos = RandHelper::rand(myActiveTransportablePlan->front()->getDestination()->getLength(), &myParsingRNG);
815  myActiveTransportablePlan->front()->setArrivalPos(initialDepartPos);
816  }
817  }
818  myVehicleParameter->id = (baseID
819  + (i >= 0 ? "." + toString(i) : "")
820  + (j > 0 ? "." + toString(j) : ""));
825  if (!tc.add(transportable)) {
826  std::string error = "Another " + myActiveTypeName + " with the id '" + myVehicleParameter->id + "' exists.";
827  delete transportable;
830  throw ProcessError(error);
831  }
832  } else if ((net->hasPersons() && net->getPersonControl().get(myVehicleParameter->id) != nullptr)
833  && (net->hasContainers() && net->getContainerControl().get(myVehicleParameter->id) != nullptr)) {
834  WRITE_WARNINGF("There exists a person and a container with the same id '%'. Starting with SUMO 1.9.0 this will be an error.", myVehicleParameter->id);
835  }
836  }
837  } catch (ProcessError&) {
839  throw;
840  }
841 }
842 
843 
844 void
847  vehType->check();
848  if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
849  const std::string id = vehType->getID();
850  delete vehType;
852  throw ProcessError("Another vehicle type (or distribution) with the id '" + id + "' exists.");
853  }
854  } else {
855  if (myCurrentVTypeDistribution != nullptr) {
857  }
858  }
859 }
860 
861 
862 void
864  myInsertStopEdgesAt = -1;
866  delete myVehicleParameter;
867  myVehicleParameter = nullptr;
868  return;
869  }
870  // let's check whether vehicles had to depart before the simulation starts
873  const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
877  delete myVehicleParameter;
878  myVehicleParameter = nullptr;
879  return;
880  }
881  }
882  }
883  if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == nullptr) {
884  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
885  }
888  closeRoute(true);
889  }
891  if (route == nullptr) {
892  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
893  }
894  if (route->mustReroute()) {
896  if (myVehicleParameter->stops.size() > 0) {
897  route = addVehicleStopsToImplicitRoute(route, true);
898  myVehicleParameter->routeid = route->getID();
899  }
900  }
904  myVehicleParameter->departEdge >= (int)route->getEdges().size()) {
905  throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid departEdge index "
906  + toString(myVehicleParameter->departEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
907  }
908  }
912  myVehicleParameter->arrivalEdge >= (int)route->getEdges().size()) {
913  throw ProcessError("Flow '" + myVehicleParameter->id + "' has invalid arrivalEdge index "
914  + toString(myVehicleParameter->arrivalEdge) + " for route with " + toString(route->getEdges().size()) + " edges.");
915  }
916  }
917  myActiveRouteID = "";
918 
919  // check whether the vehicle shall be added directly to the network or
920  // shall stay in the internal buffer
922  if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
924  } else {
925  throw ProcessError("Another flow with the id '" + myVehicleParameter->id + "' exists.");
926  }
927  }
928  myVehicleParameter = nullptr;
929 }
930 
931 
932 void
935  closeRoute(true);
936  closeVehicle();
937 }
938 
939 void
942 }
943 
944 void
947 }
948 
949 void
951  try {
952  const std::string mode = modeTag == SUMO_TAG_RIDE ? "ride" : "transport";
953  std::string agent = "person";
954  std::string stop = "bus stop";
956  agent = "container";
957  stop = "container stop";
958  }
959 
960  if (!((myActiveType == ObjectTypeEnum::PERSON && modeTag == SUMO_TAG_RIDE) ||
962  throw ProcessError("Found " + mode + " inside " + agent + " element");
963  }
964  const std::string aid = myVehicleParameter->id;
965  bool ok = true;
966  const MSEdge* from = nullptr;
967  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, aid.c_str(), ok);
968  StringTokenizer st(desc);
969  MSStoppingPlace* s = retrieveStoppingPlace(attrs, "in " + agent + " '" + aid + "'");
970  MSEdge* to = nullptr;
971  if (s != nullptr) {
972  to = &s->getLane().getEdge();
973  }
974  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, aid.c_str(), ok,
975  s == nullptr ? std::numeric_limits<double>::infinity() : s->getEndLanePosition());
976 
977  SUMOVehicle* startVeh = nullptr;
979  if (st.size() != 1) {
980  throw ProcessError("Triggered departure for " + agent + " '" + aid + "' requires a unique lines value.");
981  }
982  // agent starts
984  const std::string vehID = st.front();
985  startVeh = vehControl.getVehicle(vehID);
986  if (startVeh == nullptr) {
987  throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
988  }
989  if (startVeh->getParameter().departProcedure == DEPART_TRIGGERED) {
990  throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for " + agent + " '" + aid + "'.");
991  }
992  myVehicleParameter->depart = startVeh->getParameter().depart;
993  }
994 
995  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
996  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, aid.c_str(), ok);
997  from = MSEdge::dictionary(fromID);
998  if (from == nullptr) {
999  throw ProcessError("The from edge '" + fromID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1000  }
1001  if (!myActiveTransportablePlan->empty() && myActiveTransportablePlan->back()->getDestination() != from) {
1002  const bool stopWithAccess = (myActiveTransportablePlan->back()->getDestinationStop() != nullptr
1003  && &myActiveTransportablePlan->back()->getDestinationStop()->getLane().getEdge() == from);
1004  const bool transferAtJunction = (from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getFromJunction()
1005  || from->getFromJunction() == myActiveTransportablePlan->back()->getDestination()->getToJunction());
1006  if (!(stopWithAccess || transferAtJunction)) {
1007  throw ProcessError("Disconnected plan for " + agent + " '" + aid +
1008  "' (edge '" + fromID + "' != edge '" + myActiveTransportablePlan->back()->getDestination()->getID() + "').");
1009  }
1010  }
1011  if (startVeh != nullptr && startVeh->getRoute().getEdges().front() != from) {
1012  throw ProcessError("Disconnected plan for triggered " + agent + " '" + aid +
1013  "' (edge '" + fromID + "' != edge '" + startVeh->getRoute().getEdges().front()->getID() + "').");
1014  }
1015  } else if (startVeh != nullptr) {
1016  from = startVeh->getRoute().getEdges().front();
1017  }
1018  if (myActiveTransportablePlan->empty()) {
1019  if (from == nullptr) {
1020  throw ProcessError("The start edge for " + agent + " '" + aid + "' is not known.");
1021  } else {
1023  from, nullptr, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
1024  }
1025  }
1026  if (to == nullptr) {
1027  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, aid.c_str(), ok);
1028  to = MSEdge::dictionary(toID);
1029  if (to == nullptr) {
1030  throw ProcessError("The to edge '" + toID + "' within a " + mode + " of " + agent + " '" + aid + "' is not known.");
1031  }
1032  }
1033  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, aid.c_str(), ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1034  const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, nullptr, ok, "");
1035  const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, nullptr, ok, -1);
1036  arrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, to->getLength(), SUMO_ATTR_ARRIVALPOS, agent + " '" + aid + "' takes a " + mode + " to edge '" + to->getID() + "'");
1037  myActiveTransportablePlan->push_back(new MSStageDriving(from, to, s, arrivalPos, st.getVector(), group, intendedVeh, intendedDepart));
1038  } catch (ProcessError&) {
1040  throw;
1041  }
1042 }
1043 
1045 MSRouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, SUMOVehicleParameter::Stop* stopParam) {
1046  // dummy stop parameter to hold the attributes
1048  if (stopParam != nullptr) {
1049  stop = *stopParam;
1050  } else {
1051  bool ok = true;
1052  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1053  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
1054  stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1055  stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1056  stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1057  stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1058  }
1059  MSStoppingPlace* toStop = nullptr;
1060  if (stop.busstop != "") {
1062  if (toStop == nullptr) {
1063  WRITE_ERROR("The busStop '" + stop.busstop + "' is not known " + errorSuffix + ".");
1064  }
1065  } else if (stop.containerstop != "") {
1067  if (toStop == nullptr) {
1068  WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known " + errorSuffix + ".");
1069  }
1070  } else if (stop.parkingarea != "") {
1072  if (toStop == nullptr) {
1073  WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known " + errorSuffix + ".");
1074  }
1075  } else if (stop.chargingStation != "") {
1076  // ok, we have a charging station
1078  if (toStop == nullptr) {
1079  WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known " + errorSuffix + ".");
1080  }
1081  } else if (stop.overheadWireSegment != "") {
1082  // ok, we have an overhead wire segment
1084  if (toStop == nullptr) {
1085  WRITE_ERROR("The overhead wire segment '" + stop.overheadWireSegment + "' is not known " + errorSuffix + ".");
1086  }
1087  }
1088  return toStop;
1089 }
1090 
1091 void
1093  try {
1094  std::string errorSuffix;
1096  errorSuffix = " in person '" + myVehicleParameter->id + "'.";
1097  } else if (myActiveType == ObjectTypeEnum::CONTAINER) {
1098  errorSuffix = " in container '" + myVehicleParameter->id + "'.";
1099  } else if (myVehicleParameter != nullptr) {
1100  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
1101  } else {
1102  errorSuffix = " in route '" + myActiveRouteID + "'.";
1103  }
1105  bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
1106  if (!ok) {
1107  return;
1108  }
1109  const MSEdge* edge = nullptr;
1110  MSStoppingPlace* toStop = retrieveStoppingPlace(attrs, errorSuffix, &stop);
1111  // if one of the previous stops is defined
1112  if (toStop != nullptr) {
1113  const MSLane& l = toStop->getLane();
1114  stop.lane = l.getID();
1115  stop.endPos = toStop->getEndLanePosition();
1116  stop.startPos = toStop->getBeginLanePosition();
1117  edge = &l.getEdge();
1118  } else {
1119  // no, the lane and the position should be given directly
1120  // get the lane
1121  stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
1122  stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1123  if (ok && stop.edge != "") { // edge is given directly
1124  edge = MSEdge::dictionary(stop.edge);
1125  if (edge == nullptr || (edge->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1126  WRITE_ERROR("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
1127  return;
1128  }
1129  } else if (ok && stop.lane != "") { // lane is given directly
1130  MSLane* stopLane = MSLane::dictionary(stop.lane);
1131  if (stopLane == nullptr) {
1132  // check for opposite-direction stop
1133  stopLane = MSBaseVehicle::interpretOppositeStop(stop);
1134  if (stopLane != nullptr) {
1135  edge = MSEdge::dictionary(stop.edge);
1136  }
1137  } else {
1138  edge = &stopLane->getEdge();
1139  }
1140  if (stopLane == nullptr || (stopLane->isInternal() && !MSGlobals::gUsingInternalLanes)) {
1141  WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
1142  return;
1143  }
1144  } else {
1145  if (myActiveTransportablePlan && !myActiveTransportablePlan->empty()) { // use end of movement before
1146  toStop = myActiveTransportablePlan->back()->getDestinationStop();
1147  if (toStop != nullptr) { // use end of movement before definied as a stopping place
1148  edge = &toStop->getLane().getEdge();
1149  stop.lane = toStop->getLane().getID();
1150  stop.endPos = toStop->getEndLanePosition();
1151  stop.startPos = toStop->getBeginLanePosition();
1152  } else { // use end of movement before definied as lane/edge
1153  edge = myActiveTransportablePlan->back()->getDestination();
1154  stop.lane = edge->getLanes()[0]->getID();
1155  stop.endPos = myActiveTransportablePlan->back()->getArrivalPos();
1156  stop.startPos = MAX2(0., stop.endPos - MIN_STOP_LENGTH);
1157  }
1158  } else {
1159  WRITE_ERROR("A stop must be placed on a busStop, a chargingStation, an overheadWireSegment, a containerStop, a parkingArea, an edge or a lane" + errorSuffix);
1160  return;
1161  }
1162  }
1163  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
1164  if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
1165  WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix);
1166  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, nullptr, ok, stop.endPos);
1167  }
1168  stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, MAX2(0., stop.endPos - MIN_STOP_LENGTH));
1169  if (!myAmLoadingState) {
1170  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS));
1171  // @note stop startPos=endPos is interpreted as a collision in MSBaseVehicle::addStops so we cannot use minLength=0
1172  if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength(), NUMERICAL_EPS, friendlyPos) != StopPos::STOPPOS_VALID)) {
1173  WRITE_ERROR("Invalid start or end position for stop on "
1174  + (stop.lane != ""
1175  ? ("lane '" + stop.lane)
1176  : ("edge '" + stop.edge)) + "'" + errorSuffix);
1177  return;
1178  }
1179  }
1180  }
1181  stop.edge = edge->getID();
1183  if (myActiveTransportablePlan->empty()) {
1184  double departPos = toStop == nullptr || myVehicleParameter->wasSet(VEHPARS_DEPARTPOS_SET)
1186  : (toStop->getBeginLanePosition() + toStop->getEndLanePosition()) / 2;
1188  edge, toStop, -1, myVehicleParameter->depart, departPos, "start", true));
1189  } else if (myActiveTransportablePlan->back()->getDestination() != edge) {
1190  throw ProcessError("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id + "' (" + edge->getID() + "!=" + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1191  }
1192  // transporting veh stops somewhere
1193  else if (myActiveTransportablePlan->back()->getStageType() == MSStageType::WAITING
1195  const double start = SUMOVehicleParameter::interpretEdgePos(stop.startPos, edge->getLength(), SUMO_ATTR_STARTPOS, "stopping at " + edge->getID());
1196  const double end = SUMOVehicleParameter::interpretEdgePos(stop.endPos, edge->getLength(), SUMO_ATTR_ENDPOS, "stopping at " + edge->getID());
1197  const double prevAr = myActiveTransportablePlan->back()->getArrivalPos();
1198  if (start > prevAr + NUMERICAL_EPS || end < prevAr - NUMERICAL_EPS) {
1199  WRITE_WARNING("Disconnected plan for " + myActiveTypeName + " '" + myVehicleParameter->id
1200  + "' (stop range " + toString(start) + "-" + toString(end) + " does not cover previous arrival position " + toString(prevAr) + + ").");
1201  }
1202  }
1203  std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1204  double pos = (stop.startPos + stop.endPos) / 2.;
1205  if (!myActiveTransportablePlan->empty()) {
1206  pos = myActiveTransportablePlan->back()->getArrivalPos();
1207  }
1208  myActiveTransportablePlan->push_back(new MSStageWaiting(edge, toStop, stop.duration, stop.until, pos, actType, false));
1209 
1210  } else if (myVehicleParameter != nullptr) {
1211  myVehicleParameter->stops.push_back(stop);
1212  } else {
1213  myActiveRouteStops.push_back(stop);
1214  }
1215  if (myInsertStopEdgesAt >= 0) {
1216  //std::cout << " myInsertStopEdgesAt=" << myInsertStopEdgesAt << " edge=" << edge->getID() << " myRoute=" << toString(myActiveRoute) << "\n";
1217  if (edge->isInternal()) {
1218  if (myInsertStopEdgesAt > 0 && *(myActiveRoute.begin() + (myInsertStopEdgesAt - 1)) != edge->getNormalBefore()) {
1221  }
1224  } else {
1225  myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
1227  }
1228  }
1229  } catch (ProcessError&) {
1231  throw;
1232  }
1233 }
1234 
1235 
1236 void
1237 MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1238  const MSEdge* fromEdge, const MSEdge*& toEdge,
1239  double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
1240  const MSStage* const lastStage, bool& ok) {
1241  try {
1242  const std::string description = "person '" + personID + "' walking from " + fromEdge->getID();
1243 
1244  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1245  WRITE_WARNING("The attribute departPos is no longer supported for walks, please use the person attribute, the arrivalPos of the previous step or explicit stops.");
1246  }
1247  departPos = 0.;
1248  if (lastStage != nullptr) {
1249  if (lastStage->getDestinationStop() != nullptr) {
1250  departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge);
1251  } else if (lastStage->getDestination() == fromEdge) {
1252  departPos = lastStage->getArrivalPos();
1253  } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
1254  departPos = fromEdge->getLength();
1255  }
1256  }
1257 
1258  bs = retrieveStoppingPlace(attrs, description);
1259  if (bs != nullptr) {
1260  arrivalPos = bs->getAccessPos(toEdge != nullptr ? toEdge : &bs->getLane().getEdge());
1261  if (arrivalPos < 0) {
1262  throw ProcessError("Bus stop '" + bs->getID() + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1263  }
1264  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1265  const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1266  const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, description, length,
1267  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1268  if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1269  arrivalPos = arrPos;
1270  } else {
1271  WRITE_WARNING("Ignoring arrivalPos for " + description + " because it is outside the given stop '" + toString(SUMO_ATTR_BUS_STOP) + "'.");
1272  arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1273  }
1274  }
1275  } else {
1276  if (toEdge == nullptr) {
1277  throw ProcessError("No destination edge for " + description + ".");
1278  }
1279  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1281  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1282  } else {
1283  arrivalPos = toEdge->getLength() / 2.;
1284  }
1285  }
1286  } catch (ProcessError&) {
1288  throw;
1289  }
1290 }
1291 
1292 
1293 void
1295  try {
1296  myActiveRoute.clear();
1297  bool ok = true;
1298  const char* const id = myVehicleParameter->id.c_str();
1299  const MSEdge* from = nullptr;
1300  const MSEdge* to = nullptr;
1302  myInsertStopEdgesAt = -1;
1304  from = myActiveRoute.front();
1305  } else if (myActiveTransportablePlan->empty()) {
1306  throw ProcessError("Start edge not defined for person '" + myVehicleParameter->id + "'.");
1307  } else {
1308  from = myActiveTransportablePlan->back()->getDestination();
1309  }
1311  to = myActiveRoute.back();
1312  } // else, to may also be derived from stopping place
1313 
1314  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1315  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1316  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1317  }
1318 
1319  double departPos = 0;
1320  double arrivalPos = 0;
1321  MSStoppingPlace* stoppingPlace = nullptr;
1322  parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, stoppingPlace, nullptr, ok);
1323 
1324  const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1325  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, OptionsCont::getOptions().getString("persontrip.default.group"));
1326  SVCPermissions modeSet = 0;
1327  std::string errorMsg;
1328  // try to parse person modes
1329  if (!SUMOVehicleParameter::parsePersonModes(modes, "person", id, modeSet, errorMsg)) {
1330  throw InvalidArgument(errorMsg);
1331  }
1333  const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1334  for (StringTokenizer st(types); st.hasNext();) {
1335  const std::string vtypeid = st.next();
1336  if (vehControl.getVType(vtypeid) == nullptr) {
1337  throw InvalidArgument("The vehicle type '" + vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1338  }
1339  modeSet |= SVC_PASSENGER;
1340  }
1341  const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1342  if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1343  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1344  }
1345  const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1346  const double departPosLat = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, 0);
1347  if (ok) {
1348  if (myActiveTransportablePlan->empty()) {
1349  double initialDepartPos = myVehicleParameter->departPos;
1351  initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1352  }
1353  myActiveTransportablePlan->push_back(new MSStageWaiting(from, nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1354  }
1356  MSStoppingPlace* fromStop = myActiveTransportablePlan->empty() ? nullptr : myActiveTransportablePlan->back()->getDestinationStop();
1357  myActiveTransportablePlan->push_back(new MSStageTrip(from, fromStop, to == nullptr ? &stoppingPlace->getLane().getEdge() : to,
1358  stoppingPlace, duration, modeSet, types, speed, walkFactor, group,
1359  departPosLat, attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS), arrivalPos));
1360  }
1361  myActiveRoute.clear();
1362  } catch (ProcessError&) {
1364  throw;
1365  }
1366 }
1367 
1368 
1369 void
1372  try {
1373  myActiveRoute.clear();
1374  bool ok = true;
1375  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1376  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1377  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1378  }
1379  double speed = -1; // default to vType speed
1380  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1381  speed = attrs.get<double>(SUMO_ATTR_SPEED, nullptr, ok);
1382  if (speed <= 0) {
1383  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1384  }
1385  }
1386  double departPos = 0;
1387  double arrivalPos = 0;
1388  MSStoppingPlace* bs = nullptr;
1389  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1390  const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1391  const MSRoute* route = MSRoute::dictionary(routeID, &myParsingRNG);
1392  if (route == nullptr) {
1393  throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1394  }
1395  myActiveRoute = route->getEdges();
1396  } else {
1398  }
1399  if (myActiveTransportablePlan->empty()) {
1400  double initialDepartPos = myVehicleParameter->departPos;
1402  initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1403  }
1404  myActiveTransportablePlan->push_back(new MSStageWaiting(myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1405  }
1406  parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActiveTransportablePlan->back(), ok);
1407  if (myActiveRoute.empty()) {
1408  throw ProcessError("No edges to walk for person '" + myVehicleParameter->id + "'.");
1409  }
1410  if (myActiveTransportablePlan->back()->getDestination() != myActiveRoute.front() &&
1411  myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1412  myActiveTransportablePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1413  if (myActiveTransportablePlan->back()->getDestinationStop() == nullptr || myActiveTransportablePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1414  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActiveTransportablePlan->back()->getDestination()->getID() + ").");
1415  }
1416  }
1417  const double departPosLat = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS_LAT, nullptr, ok, 0);
1418  const int departLane = attrs.getOpt<int>(SUMO_ATTR_DEPARTLANE, nullptr, ok, -1);
1419  myActiveTransportablePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat, departLane));
1420  myActiveRoute.clear();
1421  } catch (ProcessError&) {
1423  throw;
1424  }
1425  } else { // parse walks from->to as person trips
1426  addPersonTrip(attrs);
1427  }
1428 }
1429 
1430 
1431 void
1434  myActiveTypeName = "person";
1437 }
1438 
1439 
1440 void
1443  myActiveTypeName = "container";
1446 }
1447 
1448 void
1450  try {
1451  if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
1452  const std::string error = "The type '" + myVehicleParameter->vtypeid + "' for " + myActiveTypeName + " '" + myVehicleParameter->id + "' is not known.";
1453  throw ProcessError(error);
1454  }
1455  } catch (ProcessError&) {
1457  throw;
1458  }
1459 }
1460 
1461 void
1463  try {
1464  myActiveRoute.clear();
1465  const std::string cid = myVehicleParameter->id;
1466  bool ok = true;
1467  const MSEdge* from = nullptr;
1468  const MSEdge* to = nullptr;
1469  MSStoppingPlace* cs = nullptr;
1470 
1471  double speed;
1473  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) { // speed is explicitly set
1474  speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1);
1475  if (!ok) {
1476  throw ProcessError("Could not read tranship speed for container '" + cid + "'.");
1477  }
1478  } else if (vtype != nullptr && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) { // speed is set by vtype
1479  speed = vtype->getMaxSpeed();
1480  } else { // default speed value
1482  }
1483  if (speed <= 0) {
1484  throw ProcessError("Non-positive tranship speed for container '" + cid + "'.");
1485  }
1486  // values from preceding stage:
1487  const MSEdge* preEdge = nullptr;
1488  double prePos = 0;
1489  if (!myActiveTransportablePlan->empty()) {
1490  preEdge = myActiveTransportablePlan->back()->getDestination();
1491  prePos = myActiveTransportablePlan->back()->getArrivalPos();
1492  }
1493  // set depart position as given attribute value, arrival position of preceding stage or default (=0)
1494  double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, cid.c_str(), ok, prePos);
1495 
1496  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
1497  MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, cid.c_str(), ok), myActiveRoute, myActiveRouteID);
1498  } else {
1499  // set 'from':
1500  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
1501  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, cid.c_str(), ok);
1502  from = MSEdge::dictionary(fromID);
1503  if (from == nullptr) {
1504  throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + cid + "' is not known.");
1505  }
1506  if (preEdge != nullptr && preEdge != from) {
1507  throw ProcessError("Disconnected plan for container '" + cid + "' (" + from->getID() + "!=" + preEdge->getID() + ").");
1508  }
1509  } else if (preEdge == nullptr) {
1510  throw ProcessError("The start edge for container '" + cid + "' is not known.");
1511  } else {
1512  from = preEdge;
1513  }
1514  // set 'to':
1516  std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1518  if (cs == nullptr) {
1519  throw ProcessError("Unknown container stop '" + csID + "' for container '" + cid + "'.");
1520  }
1521  to = &cs->getLane().getEdge();
1522  } else if (attrs.hasAttribute(SUMO_ATTR_TO)) {
1523  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, cid.c_str(), ok);
1524  to = MSEdge::dictionary(toID);
1525  if (to == nullptr) {
1526  throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + cid + "' is not known.");
1527  }
1528  } else {
1529  throw ProcessError("Inconsistent tranship for container '" + cid + "', only one option is allowed: 'edges', 'to', 'containerStop'");
1530  }
1531  myActiveRoute.push_back(from);
1532  myActiveRoute.push_back(to);
1533  }
1534  if (myActiveRoute.empty()) {
1535  throw ProcessError("No edges to tranship container '" + cid + "'.");
1536  }
1537  if (preEdge == nullptr) { // additional 'stop' to start the container plan
1539  myActiveRoute.front(), nullptr, -1, myVehicleParameter->depart, departPos, "start", true));
1540  }
1541  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, cid.c_str(), ok,
1542  cs == nullptr ? myActiveRoute.back()->getLength() : cs->getEndLanePosition());
1543  myActiveTransportablePlan->push_back(new MSStageTranship(myActiveRoute, cs, speed, departPos, arrivalPos));
1544  myActiveRoute.clear();
1545  } catch (ProcessError&) {
1547  throw;
1548  }
1549 }
1550 
1551 /****************************************************************************/
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
#define JUNCTION_TAZ_MISSING_HELP
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:281
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:32
const int VTYPEPARS_MAXSPEED_SET
const int VTYPEPARS_VEHICLECLASS_SET
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_PEDESTRIAN
pedestrian
const double DEFAULT_VEH_PROB
const std::string DEFAULT_VTYPE_ID
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const double DEFAULT_CONTAINER_TRANSHIP_SPEED
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const int VEHPARS_ROUTE_SET
const int VEHPARS_TO_TAZ_SET
@ RANDOM
The position is chosen randomly.
const int VEHPARS_DEPARTPOS_SET
const int VEHPARS_FROM_TAZ_SET
const int VEHPARS_FORCE_REROUTE
const double MIN_STOP_LENGTH
@ DEPART_GIVEN
The time is given.
@ DEPART_TRIGGERED
The departure is person triggered.
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_TRANSPORT
@ SUMO_TAG_CONTAINER
@ SUMO_TAG_RIDE
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
@ SUMO_TAG_PERSON
@ SUMO_TAG_PERSONFLOW
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_ATTR_STARTPOS
@ SUMO_ATTR_LINES
@ SUMO_ATTR_LANE
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_REFID
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_FROMJUNCTION
@ SUMO_ATTR_DEPARTPOS_LAT
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_ACTTYPE
@ SUMO_ATTR_PROBS
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_CHARGING_STATION
@ SUMO_ATTR_ROUTES
@ SUMO_ATTR_MODES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_OVERHEAD_WIRE_SEGMENT
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_GROUP
@ SUMO_ATTR_COST
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_VIAJUNCTIONS
@ SUMO_ATTR_PROB
@ SUMO_ATTR_FRIENDLY_POS
@ SUMO_ATTR_WALKFACTOR
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_REPEAT
@ SUMO_ATTR_INTENDED
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_CYCLETIME
@ SUMO_ATTR_TOJUNCTION
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
A road/street connecting two junctions.
Definition: MSEdge.h:77
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:942
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition: MSEdge.cpp:804
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:641
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:262
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:885
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: MSEdge.cpp:794
const MSJunction * getToJunction() const
Definition: MSEdge.h:401
static bool gCheckRoutes
Definition: MSGlobals.h:82
static bool gStateLoaded
Information whether a state has been loaded.
Definition: MSGlobals.h:91
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:72
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:82
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1991
bool isInternal() const
Definition: MSLane.cpp:2122
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:674
The simulated network and simulation perfomer.
Definition: MSNet.h:88
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1068
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:376
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1250
bool hasContainers() const
Returns whether containers are simulated.
Definition: MSNet.h:409
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:429
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:393
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1059
void addRideOrTransport(const SUMOSAXAttributes &attrs, const SumoXMLTag modeTag)
Processing of a transport.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
void deleteActivePlanAndVehicleParameter()
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
bool myAmLoadingState
whether a state file is being loaded
void resetActivePlanAndVehicleParameter()
reset MSTransportablePlans after transportable tag closes
SUMOTime myActiveRoutePeriod
void closeContainerFlow()
Ends the processing of a containerFlow.
void closeTransportable()
ends the processing of a transportable (as person or container)
void closeVType()
Ends the processing of a vehicle type.
void openTrip(const SUMOSAXAttributes &attrs)
opens a trip for reading
MSStoppingPlace * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, SUMOVehicleParameter::Stop *stopParam=nullptr)
Parse destination stop.
void closeVehicleTypeDistribution()
closes (ends) the building of a distribution
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
RandomDistributor< const MSRoute * > * myCurrentRouteDistribution
The currently parsed distribution of routes (probability->route)
void closeRouteDistribution()
closes (ends) the building of a distribution
static SumoRNG myParsingRNG
A random number generator used to choose from vtype/route distributions and computing the speed facto...
void parseFromViaTo(SumoXMLTag tag, const SUMOSAXAttributes &attrs)
Called for parsing from and to and the corresponding taz attributes.
void closeFlow()
Ends the processing of a flow.
MSTransportable::MSTransportablePlan * myActiveTransportablePlan
The plan of the current transportable (person or container)
void closeContainer()
Ends the processing of a container.
std::string myCurrentRouteDistributionID
The id of the currently parsed route distribution.
void closePersonFlow()
Ends the processing of a personFlow.
void openRouteFlow(const SUMOSAXAttributes &attrs)
opens a route flow for reading
RandomDistributor< MSVehicleType * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
void closePerson()
Ends the processing of a person.
void closeTrip()
Ends the processing of a trip.
void openRouteDistribution(const SUMOSAXAttributes &attrs)
opens a route distribution for reading
ConstMSEdgeVector myActiveRoute
The current route.
int myActiveRouteRepeat
number of repetitions of the active route
ObjectTypeEnum myActiveType
The type of the current object.
void addPersonTrip(const SUMOSAXAttributes &attrs)
add a routing request for a walking or intermodal person
void addTranship(const SUMOSAXAttributes &attrs)
Processing of a tranship.
virtual void closeVehicle()
Ends the processing of a vehicle (note: is virtual because is reimplemented in MSStateHandler)
MSRoute * addVehicleStopsToImplicitRoute(const MSRoute *route, bool isPermanent)
adapt implicit route (edges derived from stops) to additional vehicle-stops
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs)
opens a type distribution for reading
void openFlow(const SUMOSAXAttributes &attrs)
opens a flow for reading
MSRouteHandler(const std::string &file, bool addVehiclesDirectly)
standard constructor
std::string myScaleSuffix
prefix when copying vehicles with –scale
ObjectTypeEnum
enum for object type
virtual ~MSRouteHandler()
standard destructor
bool myAddVehiclesDirectly
Information whether vehicles shall be directly added to the network or kept within the buffer.
void addWalk(const SUMOSAXAttributes &attrs)
add a fully specified walk
void openRoute(const SUMOSAXAttributes &attrs)
opens a route for reading
void addTransport(const SUMOSAXAttributes &attrs)
Processing of a transport.
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const MSEdge *fromEdge, const MSEdge *&toEdge, double &departPos, double &arrivalPos, MSStoppingPlace *&bs, const MSStage *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
void 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 checkTransportableType()
Check if vtype of given transportable exists.
std::string myActiveTypeName
The name of the current object type.
void addRide(const SUMOSAXAttributes &attrs)
Processing of a ride.
void addPerson(const SUMOSAXAttributes &attrs)
Processing of a person.
void closeTransportableFlow()
ends the flow of a transportable
void closeRoute(const bool mayBeDisconnected=false)
closes (ends) the building of a route.
void addContainer(const SUMOSAXAttributes &attrs)
Processing of a container.
void addReference() const
increments the reference counter for the route
Definition: MSRoute.cpp:94
void setReroute(bool reroute=true)
Definition: MSRoute.h:200
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:389
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:113
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:185
void release() const
deletes the route if there are no further references to it
Definition: MSRoute.cpp:100
const RGBColor & getColor() const
Returns the color.
Definition: MSRoute.cpp:380
void setPeriod(SUMOTime period)
sets the period
Definition: MSRoute.h:177
bool mustReroute() const
Definition: MSRoute.h:196
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:120
const MSEdge * getDestination() const
returns the destination edge
Definition: MSStage.cpp:70
virtual double getArrivalPos() const
Definition: MSStage.h:89
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition: MSStage.h:80
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
double getAccessPos(const MSEdge *edge) const
the position on the given edge which is connected to this stop, -1 on failure
int getLoadedNumber() const
Returns the number of build transportables.
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, SumoRNG *rng) const
Builds a new person.
bool add(MSTransportable *transportable)
Adds a single transportable, returns false if an id clash occurred.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
std::vector< MSStage * > MSTransportablePlan
the structure holding the plan of a transportable
The class responsible for building and deletion of vehicles.
double getScale() const
sets the demand scaling factor
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
int getQuota(double frac=-1, int loaded=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true)
Builds a vehicle, increases the number of built vehicles.
The car-following model and parameter.
Definition: MSVehicleType.h:62
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 maximum speed [m/s].
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:90
bool wasSet(int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:79
const SUMOVTypeParameter & getParameter() const
void check()
Checks whether vehicle type parameters may be problematic (Currently, only the value for the action s...
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:119
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.
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.
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, bool report=true) const
Tries to read given attribute assuming it is an int.
const std::vector< std::string > getStringVector(int attr) const
Tries to read given attribute assuming it is a string vector.
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(int what) const
Returns whether the given parameter was set.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at (used only in NETEDIT)
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
std::string overheadWireSegment
(Optional) overhead line segment if one is assigned to the stop
int 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)
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.
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 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