Eclipse SUMO - Simulation of Urban MObility
RORouteHandler.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 /****************************************************************************/
21 // Parser and container for routes during their loading
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <string>
26 #include <map>
27 #include <vector>
28 #include <iostream>
40 #include <utils/xml/XMLSubSys.h>
42 #include "RONet.h"
43 #include "ROEdge.h"
44 #include "ROLane.h"
45 #include "RORouteDef.h"
46 #include "RORouteHandler.h"
47 
48 #define JUNCTION_TAZ_MISSING_HELP "\nSet option '--junction-taz' or load a TAZ-file"
49 
50 // ===========================================================================
51 // method definitions
52 // ===========================================================================
53 RORouteHandler::RORouteHandler(RONet& net, const std::string& file,
54  const bool tryRepair,
55  const bool emptyDestinationsAllowed,
56  const bool ignoreErrors,
57  const bool checkSchema) :
58  SUMORouteHandler(file, checkSchema ? "routes" : "", true),
59  myNet(net),
60  myActiveRouteRepeat(0),
61  myActiveRoutePeriod(0),
62  myActivePlan(nullptr),
63  myActiveContainerPlan(nullptr),
64  myActiveContainerPlanSize(0),
65  myTryRepair(tryRepair),
66  myEmptyDestinationsAllowed(emptyDestinationsAllowed),
67  myErrorOutput(ignoreErrors ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
68  myBegin(string2time(OptionsCont::getOptions().getString("begin"))),
69  myKeepVTypeDist(OptionsCont::getOptions().getBool("keep-vtype-distributions")),
70  myMapMatchingDistance(OptionsCont::getOptions().getFloat("mapmatch.distance")),
71  myMapMatchJunctions(OptionsCont::getOptions().getBool("mapmatch.junctions")),
72  myUnsortedInput(OptionsCont::getOptions().exists("unsorted-input") && OptionsCont::getOptions().getBool("unsorted-input")),
73  myCurrentVTypeDistribution(nullptr),
74  myCurrentAlternatives(nullptr),
75  myLaneTree(nullptr) {
76  myActiveRoute.reserve(100);
77 }
78 
79 
81  delete myLaneTree;
82 }
83 
84 
85 void
87  const std::string element = toString(tag);
88  myActiveRoute.clear();
89  bool useTaz = OptionsCont::getOptions().getBool("with-taz");
91  WRITE_WARNING("Taz usage was requested but no taz present in " + element + " '" + myVehicleParameter->id + "'!");
92  useTaz = false;
93  }
94  // from-attributes
95  const std::string rid = "for " + element + " '" + myVehicleParameter->id + "'";
96  if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_FROM)) &&
98  const bool useJunction = attrs.hasAttribute(SUMO_ATTR_FROMJUNCTION);
99  const std::string tazType = useJunction ? "junction" : "taz";
100  const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_FROMJUNCTION : SUMO_ATTR_FROM_TAZ, myVehicleParameter->id.c_str(), ok, true);
101  const ROEdge* fromTaz = myNet.getEdge(tazID + "-source");
102  if (fromTaz == nullptr) {
103  myErrorOutput->inform("Source " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
104  + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
105  ok = false;
106  } else if (fromTaz->getNumSuccessors() == 0 && tag != SUMO_TAG_PERSON) {
107  myErrorOutput->inform("Source " + tazType + " '" + tazID + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
108  ok = false;
109  } else {
110  myActiveRoute.push_back(fromTaz);
111  }
112  } else if (attrs.hasAttribute(SUMO_ATTR_FROMXY)) {
113  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMXY, myVehicleParameter->id.c_str(), ok, true), false, myActiveRoute, rid, true, ok);
114  } else if (attrs.hasAttribute(SUMO_ATTR_FROMLONLAT)) {
115  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_FROMLONLAT, myVehicleParameter->id.c_str(), ok, true), true, myActiveRoute, rid, true, ok);
116  } else {
117  parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok, "", true), myActiveRoute, rid, ok);
118  }
120  myInsertStopEdgesAt = (int)myActiveRoute.size();
121  }
122 
123  // via-attributes
124  ConstROEdgeVector viaEdges;
125  if (attrs.hasAttribute(SUMO_ATTR_VIAXY)) {
126  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIAXY, myVehicleParameter->id.c_str(), ok, true), false, viaEdges, rid, false, ok);
127  } else if (attrs.hasAttribute(SUMO_ATTR_VIALONLAT)) {
128  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_VIALONLAT, myVehicleParameter->id.c_str(), ok, true), true, viaEdges, rid, false, ok);
129  } else if (attrs.hasAttribute(SUMO_ATTR_VIAJUNCTIONS)) {
130  for (std::string junctionID : attrs.getStringVector(SUMO_ATTR_VIAJUNCTIONS)) {
131  const ROEdge* viaSink = myNet.getEdge(junctionID + "-sink");
132  if (viaSink == nullptr) {
133  myErrorOutput->inform("Junction-taz '" + junctionID + "' not found." + JUNCTION_TAZ_MISSING_HELP);
134  ok = false;
135  } else {
136  viaEdges.push_back(viaSink);
137  }
138  }
139  } else {
140  parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true), viaEdges, rid, ok);
141  }
142  for (const ROEdge* e : viaEdges) {
143  myActiveRoute.push_back(e);
144  myVehicleParameter->via.push_back(e->getID());
145  }
146 
147  // to-attributes
148  if ((useTaz || !attrs.hasAttribute(SUMO_ATTR_TO)) &&
150  const bool useJunction = attrs.hasAttribute(SUMO_ATTR_TOJUNCTION);
151  const std::string tazType = useJunction ? "junction" : "taz";
152  const std::string tazID = attrs.get<std::string>(useJunction ? SUMO_ATTR_TOJUNCTION : SUMO_ATTR_TO_TAZ, myVehicleParameter->id.c_str(), ok, true);
153  const ROEdge* toTaz = myNet.getEdge(tazID + "-sink");
154  if (toTaz == nullptr) {
155  myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' not known for " + element + " '" + myVehicleParameter->id + "'!"
156  + (useJunction ? JUNCTION_TAZ_MISSING_HELP : ""));
157  ok = false;
158  } else if (toTaz->getNumPredecessors() == 0 && tag != SUMO_TAG_PERSON) {
159  myErrorOutput->inform("Sink " + tazType + " '" + tazID + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
160  ok = false;
161  } else {
162  myActiveRoute.push_back(toTaz);
163  }
164  } else if (attrs.hasAttribute(SUMO_ATTR_TOXY)) {
165  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOXY, myVehicleParameter->id.c_str(), ok, true), false, myActiveRoute, rid, false, ok);
166  } else if (attrs.hasAttribute(SUMO_ATTR_TOLONLAT)) {
167  parseGeoEdges(attrs.get<PositionVector>(SUMO_ATTR_TOLONLAT, myVehicleParameter->id.c_str(), ok, true), true, myActiveRoute, rid, false, ok);
168  } else {
169  parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true), myActiveRoute, rid, ok);
170  }
172  if (myVehicleParameter->routeid == "") {
174  }
175 }
176 
177 
178 void
180  const SUMOSAXAttributes& attrs) {
181  if (myActivePlan != nullptr && myActivePlan->empty() && myVehicleParameter->departProcedure == DEPART_TRIGGERED && element != SUMO_TAG_RIDE) {
182  throw ProcessError("Triggered departure for person '" + myVehicleParameter->id + "' requires starting with a ride.");
184  throw ProcessError("Triggered departure for container '" + myVehicleParameter->id + "' requires starting with a transport.");
185  }
186  SUMORouteHandler::myStartElement(element, attrs);
187  bool ok = true;
188  switch (element) {
189  case SUMO_TAG_PERSON:
190  case SUMO_TAG_PERSONFLOW: {
191  myActivePlan = new std::vector<ROPerson::PlanItem*>();
192  break;
193  }
194  case SUMO_TAG_RIDE:
195  break; // handled in addRide, called from SUMORouteHandler::myStartElement
196  case SUMO_TAG_CONTAINER:
201  (*myActiveContainerPlan) << attrs;
202  break;
203  case SUMO_TAG_TRANSPORT:
204  case SUMO_TAG_TRANSHIP:
205  if (myActiveContainerPlan == nullptr) {
206  throw ProcessError("Found " + toString((SumoXMLTag)element) + " outside container element");
207  }
208  // copy container elements
210  (*myActiveContainerPlan) << attrs;
213  break;
214  case SUMO_TAG_FLOW:
216  parseFromViaTo((SumoXMLTag)element, attrs, ok);
217  break;
218  case SUMO_TAG_TRIP:
220  parseFromViaTo((SumoXMLTag)element, attrs, ok);
221  break;
222  default:
223  break;
224  }
225 }
226 
227 
228 void
230  bool ok = true;
231  myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
232  if (ok) {
234  if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
235  const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
236  StringTokenizer st(vTypes);
237  while (st.hasNext()) {
238  const std::string typeID = st.next();
239  SUMOVTypeParameter* const type = myNet.getVehicleTypeSecure(typeID);
240  if (type == nullptr) {
241  myErrorOutput->inform("Unknown vehicle type '" + typeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
242  } else {
243  myCurrentVTypeDistribution->add(type, 1.);
244  }
245  }
246  }
247  }
248 }
249 
250 
251 void
253  if (myCurrentVTypeDistribution != nullptr) {
256  myErrorOutput->inform("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
259  myErrorOutput->inform("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
260  }
261  myCurrentVTypeDistribution = nullptr;
262  }
263 }
264 
265 
266 void
268  myActiveRoute.clear();
269  myInsertStopEdgesAt = -1;
270  // check whether the id is really necessary
271  std::string rid;
272  if (myCurrentAlternatives != nullptr) {
274  rid = "distribution '" + myCurrentAlternatives->getID() + "'";
275  } else if (myVehicleParameter != nullptr) {
276  // ok, a vehicle is wrapping the route,
277  // we may use this vehicle's id as default
278  myVehicleParameter->routeid = myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
279  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
280  WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "').");
281  }
282  } else {
283  bool ok = true;
284  myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
285  if (!ok) {
286  return;
287  }
288  rid = "'" + myActiveRouteID + "'";
289  }
290  if (myVehicleParameter != nullptr) { // have to do this here for nested route distributions
291  rid = "for vehicle '" + myVehicleParameter->id + "'";
292  }
293  bool ok = true;
294  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
295  parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid, ok);
296  }
297  myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
298  if (myActiveRouteRefID != "" && myNet.getRouteDef(myActiveRouteRefID) == nullptr) {
299  myErrorOutput->inform("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
300  }
301  if (myCurrentAlternatives != nullptr && !attrs.hasAttribute(SUMO_ATTR_PROB)) {
302  WRITE_WARNINGF("No probability for route %, using default.", rid);
303  }
305  if (ok && myActiveRouteProbability < 0) {
306  myErrorOutput->inform("Invalid probability for route '" + myActiveRouteID + "'.");
307  }
309  ok = true;
310  myActiveRouteRepeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, myActiveRouteID.c_str(), ok, 0);
312  if (myActiveRouteRepeat > 0) {
314  if (myVehicleParameter != nullptr) {
316  if (type != nullptr) {
317  vClass = type->vehicleClass;
318  }
319  }
320  if (myActiveRoute.size() > 0 && !myActiveRoute.back()->isConnectedTo(*myActiveRoute.front(), vClass)) {
321  myErrorOutput->inform("Disconnected route " + rid + " when repeating.");
322  }
323  }
324  myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
325  if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
326  myErrorOutput->inform("Invalid cost for route '" + myActiveRouteID + "'.");
327  }
328 }
329 
330 
331 void
333  // currently unused
334 }
335 
336 
337 void
339  // currently unused
340 }
341 
342 
343 void
345  // currently unused
346 }
347 
348 
349 void
350 RORouteHandler::closeRoute(const bool mayBeDisconnected) {
351  const bool mustReroute = myActiveRoute.size() == 0 && myActiveRouteStops.size() != 0;
352  if (mustReroute) {
353  // implicit route from stops
354  for (const SUMOVehicleParameter::Stop& stop : myActiveRouteStops) {
355  ROEdge* edge = myNet.getEdge(stop.edge);
356  myActiveRoute.push_back(edge);
357  }
358  }
359  if (myActiveRoute.size() == 0) {
360  if (myActiveRouteRefID != "" && myCurrentAlternatives != nullptr) {
362  myActiveRouteID = "";
363  myActiveRouteRefID = "";
364  return;
365  }
366  if (myVehicleParameter != nullptr) {
367  myErrorOutput->inform("The route for vehicle '" + myVehicleParameter->id + "' has no edges.");
368  } else {
369  myErrorOutput->inform("Route '" + myActiveRouteID + "' has no edges.");
370  }
371  myActiveRouteID = "";
372  myActiveRouteStops.clear();
373  return;
374  }
375  if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
376  myErrorOutput->inform("The routing information for vehicle '" + myVehicleParameter->id + "' is insufficient.");
377  myActiveRouteID = "";
378  myActiveRouteStops.clear();
379  return;
380  }
381  if (!mayBeDisconnected && OptionsCont::getOptions().exists("no-internal-links") && !OptionsCont::getOptions().getBool("no-internal-links")) {
382  // fix internal edges which did not get parsed
383  const ROEdge* last = nullptr;
384  ConstROEdgeVector fullRoute;
385  for (const ROEdge* roe : myActiveRoute) {
386  if (last != nullptr) {
387  for (const ROEdge* intern : last->getSuccessors()) {
388  if (intern->isInternal() && intern->getSuccessors().size() == 1 && intern->getSuccessors().front() == roe) {
389  fullRoute.push_back(intern);
390  }
391  }
392  }
393  fullRoute.push_back(roe);
394  last = roe;
395  }
396  myActiveRoute = fullRoute;
397  }
398  if (myActiveRouteRepeat > 0) {
399  // duplicate route
400  ConstROEdgeVector tmpEdges = myActiveRoute;
401  auto tmpStops = myActiveRouteStops;
402  for (int i = 0; i < myActiveRouteRepeat; i++) {
403  myActiveRoute.insert(myActiveRoute.begin(), tmpEdges.begin(), tmpEdges.end());
404  for (SUMOVehicleParameter::Stop stop : tmpStops) {
405  if (stop.until > 0) {
406  if (myActiveRoutePeriod <= 0) {
407  const std::string description = myVehicleParameter != nullptr
408  ? "for vehicle '" + myVehicleParameter->id + "'"
409  : "'" + myActiveRouteID + "'";
410  throw ProcessError("Cannot repeat stops with 'until' in route " + description + " because no cycleTime is defined.");
411  }
412  stop.until += myActiveRoutePeriod * (i + 1);
413  stop.arrival += myActiveRoutePeriod * (i + 1);
414  }
415  myActiveRouteStops.push_back(stop);
416  }
417  }
418  }
421  myActiveRoute.clear();
422  if (myCurrentAlternatives == nullptr) {
423  if (myNet.getRouteDef(myActiveRouteID) != nullptr) {
424  delete route;
425  if (myVehicleParameter != nullptr) {
426  myErrorOutput->inform("Another route for vehicle '" + myVehicleParameter->id + "' exists.");
427  } else {
428  myErrorOutput->inform("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
429  }
430  myActiveRouteID = "";
431  myActiveRouteStops.clear();
432  return;
433  } else {
434  myCurrentAlternatives = new RORouteDef(myActiveRouteID, 0, mayBeDisconnected || myTryRepair, mayBeDisconnected);
437  myCurrentAlternatives = nullptr;
438  }
439  } else {
441  }
442  myActiveRouteID = "";
443  myActiveRouteStops.clear();
444 }
445 
446 
447 void
449  // check whether the id is really necessary
450  bool ok = true;
451  std::string id;
452  if (myVehicleParameter != nullptr) {
453  // ok, a vehicle is wrapping the route,
454  // we may use this vehicle's id as default
455  myVehicleParameter->routeid = id = "!" + myVehicleParameter->id; // !!! document this
456  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
457  WRITE_WARNING("Ids of internal route distributions are ignored (vehicle '" + myVehicleParameter->id + "').");
458  }
459  } else {
460  id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
461  if (!ok) {
462  return;
463  }
464  }
465  // try to get the index of the last element
466  int index = attrs.getOpt<int>(SUMO_ATTR_LAST, id.c_str(), ok, 0);
467  if (ok && index < 0) {
468  myErrorOutput->inform("Negative index of a route alternative (id='" + id + "').");
469  return;
470  }
471  // build the alternative cont
472  myCurrentAlternatives = new RORouteDef(id, index, myTryRepair, false);
473  if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
474  ok = true;
475  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, id.c_str(), ok));
476  while (st.hasNext()) {
477  const std::string routeID = st.next();
478  const RORouteDef* route = myNet.getRouteDef(routeID);
479  if (route == nullptr) {
480  myErrorOutput->inform("Unknown route '" + routeID + "' in distribution '" + id + "'.");
481  } else {
483  }
484  }
485  }
486 }
487 
488 
489 void
491  if (myCurrentAlternatives != nullptr) {
493  myErrorOutput->inform("Route distribution '" + myCurrentAlternatives->getID() + "' is empty.");
494  delete myCurrentAlternatives;
495  } else if (!myNet.addRouteDef(myCurrentAlternatives)) {
496  myErrorOutput->inform("Another route (or distribution) with the id '" + myCurrentAlternatives->getID() + "' exists.");
497  delete myCurrentAlternatives;
498  }
499  myCurrentAlternatives = nullptr;
500  }
501 }
502 
503 
504 void
506  checkLastDepart();
507  // get the vehicle id
509  return;
510  }
511  // get vehicle type
513  if (type == nullptr) {
514  myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
516  } else {
517  if (!myKeepVTypeDist) {
518  // fix the type id in case we used a distribution
519  myVehicleParameter->vtypeid = type->id;
520  }
521  }
522  if (type->vehicleClass == SVC_PEDESTRIAN) {
523  WRITE_WARNING("Vehicle type '" + type->id + "' with vClass=pedestrian should only be used for persons and not for vehicle '" + myVehicleParameter->id + "'.");
524  }
525  // get the route
527  if (route == nullptr) {
528  myErrorOutput->inform("The route of the vehicle '" + myVehicleParameter->id + "' is not known.");
529  return;
530  }
531  if (route->getID()[0] != '!') {
532  route = route->copy("!" + myVehicleParameter->id, myVehicleParameter->depart);
533  }
534  // build the vehicle
535  if (!MsgHandler::getErrorInstance()->wasInformed()) {
536  ROVehicle* veh = new ROVehicle(*myVehicleParameter, route, type, &myNet, myErrorOutput);
537  if (myNet.addVehicle(myVehicleParameter->id, veh)) {
539  }
540  }
541 }
542 
543 
544 void
547  if (myCurrentVTypeDistribution != nullptr) {
549  }
550  }
551  if (OptionsCont::getOptions().isSet("restriction-params")) {
552  const std::vector<std::string> paramKeys = OptionsCont::getOptions().getStringVector("restriction-params");
554  }
555  myCurrentVType = nullptr;
556 }
557 
558 
559 void
562  if (type == nullptr) {
563  myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for person '" + myVehicleParameter->id + "' is not known.");
565  }
566  if (myActivePlan == nullptr || myActivePlan->empty()) {
567  WRITE_WARNING("Discarding person '" + myVehicleParameter->id + "' because it's plan is empty");
568  } else {
569  ROPerson* person = new ROPerson(*myVehicleParameter, type);
570  for (ROPerson::PlanItem* item : *myActivePlan) {
571  person->getPlan().push_back(item);
572  }
573  if (myNet.addPerson(person)) {
574  checkLastDepart();
576  }
577  }
578  delete myVehicleParameter;
579  myVehicleParameter = nullptr;
580  delete myActivePlan;
581  myActivePlan = nullptr;
582 }
583 
584 
585 void
588  if (type == nullptr) {
589  myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for personFlow '" + myVehicleParameter->id + "' is not known.");
591  }
592  if (myActivePlan == nullptr || myActivePlan->empty()) {
593  WRITE_WARNING("Discarding personFlow '" + myVehicleParameter->id + "' because it's plan is empty");
594  } else {
595  checkLastDepart();
596  // instantiate all persons of this flow
597  int i = 0;
598  std::string baseID = myVehicleParameter->id;
601  throw ProcessError("probabilistic personFlow '" + myVehicleParameter->id + "' must specify end time");
602  } else {
603  for (SUMOTime t = myVehicleParameter->depart; t < myVehicleParameter->repetitionEnd; t += TIME2STEPS(1)) {
605  addFlowPerson(type, t, baseID, i++);
606  }
607  }
608  }
609  } else {
611  for (; i < myVehicleParameter->repetitionNumber; i++) {
612  addFlowPerson(type, depart, baseID, i);
614  }
615  }
616  }
617  delete myVehicleParameter;
618  myVehicleParameter = nullptr;
619  delete myActivePlan;
620  myActivePlan = nullptr;
621 }
622 
623 
624 void
625 RORouteHandler::addFlowPerson(SUMOVTypeParameter* type, SUMOTime depart, const std::string& baseID, int i) {
627  pars.id = baseID + "." + toString(i);
628  pars.depart = depart;
629  ROPerson* person = new ROPerson(pars, type);
630  for (ROPerson::PlanItem* item : *myActivePlan) {
631  person->getPlan().push_back(item->clone());
632  }
633  if (myNet.addPerson(person)) {
634  if (i == 0) {
636  }
637  }
638 }
639 
640 void
643  if (myActiveContainerPlanSize > 0) {
645  checkLastDepart();
647  } else {
648  WRITE_WARNING("Discarding container '" + myVehicleParameter->id + "' because it's plan is empty");
649  }
650  delete myVehicleParameter;
651  myVehicleParameter = nullptr;
652  delete myActiveContainerPlan;
653  myActiveContainerPlan = nullptr;
655 }
656 
659  if (myActiveContainerPlanSize > 0) {
661  checkLastDepart();
663  } else {
664  WRITE_WARNING("Discarding containerFlow '" + myVehicleParameter->id + "' because it's plan is empty");
665  }
666  delete myVehicleParameter;
667  myVehicleParameter = nullptr;
668  delete myActiveContainerPlan;
669  myActiveContainerPlan = nullptr;
671 }
672 
673 
674 void
676  checkLastDepart();
677  // @todo: consider myScale?
679  delete myVehicleParameter;
680  myVehicleParameter = nullptr;
681  return;
682  }
683  // let's check whether vehicles had to depart before the simulation starts
685  const SUMOTime offsetToBegin = myBegin - myVehicleParameter->depart;
689  delete myVehicleParameter;
690  myVehicleParameter = nullptr;
691  return;
692  }
693  }
695  myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
696  }
697  if (myVehicleParameter->routeid[0] == '!' && myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
698  closeRoute(true);
699  }
700  if (myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
701  myErrorOutput->inform("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
702  delete myVehicleParameter;
703  myVehicleParameter = nullptr;
704  return;
705  }
706  myActiveRouteID = "";
707  if (!MsgHandler::getErrorInstance()->wasInformed()) {
708  if (myNet.addFlow(myVehicleParameter, OptionsCont::getOptions().getBool("randomize-flows"))) {
710  } else {
711  myErrorOutput->inform("Another flow with the id '" + myVehicleParameter->id + "' exists.");
712  }
713  } else {
714  delete myVehicleParameter;
715  }
716  myVehicleParameter = nullptr;
717  myInsertStopEdgesAt = -1;
718 }
719 
720 
721 void
723  closeRoute(true);
724  closeVehicle();
725 }
726 
728 RORouteHandler::retrieveStoppingPlace(const SUMOSAXAttributes& attrs, const std::string& errorSuffix, std::string& id, const SUMOVehicleParameter::Stop* stopParam) {
729  // dummy stop parameter to hold the attributes
731  if (stopParam != nullptr) {
732  stop = *stopParam;
733  } else {
734  bool ok = true;
735  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
736  stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop); // alias
737  stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
738  stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
739  stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
740  stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
741  }
742  const SUMOVehicleParameter::Stop* toStop = nullptr;
743  if (stop.busstop != "") {
745  id = stop.busstop;
746  if (toStop == nullptr) {
747  WRITE_ERROR("The busStop '" + stop.busstop + "' is not known" + errorSuffix);
748  }
749  } else if (stop.containerstop != "") {
751  id = stop.containerstop;
752  if (toStop == nullptr) {
753  WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known" + errorSuffix);
754  }
755  } else if (stop.parkingarea != "") {
757  id = stop.parkingarea;
758  if (toStop == nullptr) {
759  WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known" + errorSuffix);
760  }
761  } else if (stop.chargingStation != "") {
762  // ok, we have a charging station
764  id = stop.chargingStation;
765  if (toStop == nullptr) {
766  WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known" + errorSuffix);
767  }
768  } else if (stop.overheadWireSegment != "") {
769  // ok, we have an overhead wire segment
771  id = stop.overheadWireSegment;
772  if (toStop == nullptr) {
773  WRITE_ERROR("The overhead wire segment '" + stop.overheadWireSegment + "' is not known" + errorSuffix);
774  }
775  }
776  return toStop;
777 }
778 
779 void
781  if (myActiveContainerPlan != nullptr) {
783  (*myActiveContainerPlan) << attrs;
786  return;
787  }
788  std::string errorSuffix;
789  if (myActivePlan != nullptr) {
790  errorSuffix = " in person '" + myVehicleParameter->id + "'.";
791  } else if (myActiveContainerPlan != nullptr) {
792  errorSuffix = " in container '" + myVehicleParameter->id + "'.";
793  } else if (myVehicleParameter != nullptr) {
794  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
795  } else {
796  errorSuffix = " in route '" + myActiveRouteID + "'.";
797  }
799  bool ok = parseStop(stop, attrs, errorSuffix, myErrorOutput);
800  if (!ok) {
801  return;
802  }
803  // try to parse the assigned bus stop
804  const ROEdge* edge = nullptr;
805  std::string stoppingPlaceID;
806  const SUMOVehicleParameter::Stop* stoppingPlace = retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID, &stop);
807  bool hasPos = false;
808  if (stoppingPlace != nullptr) {
809  stop.lane = stoppingPlace->lane;
810  stop.endPos = stoppingPlace->endPos;
811  stop.startPos = stoppingPlace->startPos;
813  } else {
814  // no, the lane and the position should be given
815  stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
816  stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
817  if (ok && stop.edge != "") {
818  edge = myNet.getEdge(stop.edge);
819  if (edge == nullptr) {
820  myErrorOutput->inform("The edge '" + stop.edge + "' for a stop is not known" + errorSuffix);
821  return;
822  }
823  } else if (ok && stop.lane != "") {
825  if (edge == nullptr) {
826  myErrorOutput->inform("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
827  return;
828  }
829  } else if (ok && ((attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y))
830  || (attrs.hasAttribute(SUMO_ATTR_LON) && attrs.hasAttribute(SUMO_ATTR_LAT)))) {
831  Position pos;
832  bool geo = false;
833  if (attrs.hasAttribute(SUMO_ATTR_X) && attrs.hasAttribute(SUMO_ATTR_Y)) {
834  pos = Position(attrs.get<double>(SUMO_ATTR_X, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_Y, myVehicleParameter->id.c_str(), ok));
835  } else {
836  pos = Position(attrs.get<double>(SUMO_ATTR_LON, myVehicleParameter->id.c_str(), ok), attrs.get<double>(SUMO_ATTR_LAT, myVehicleParameter->id.c_str(), ok));
837  geo = true;
838  }
839  PositionVector positions;
840  positions.push_back(pos);
841  ConstROEdgeVector geoEdges;
842  parseGeoEdges(positions, geo, geoEdges, myVehicleParameter->id, true, ok);
843  if (ok) {
844  edge = geoEdges.front();
845  hasPos = true;
846  if (geo) {
848  }
849  stop.parametersSet |= STOP_END_SET;
850  stop.endPos = edge->getLanes()[0]->getShape().nearest_offset_to_point2D(pos, false);
851  } else {
852  return;
853  }
854  } else if (!ok || (stop.lane == "" && stop.edge == "")) {
855  myErrorOutput->inform("A stop must be placed on a bus stop, a container stop, a parking area, an edge or a lane" + errorSuffix);
856  return;
857  }
858  if (!hasPos) {
859  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
860  }
861  stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, stop.endPos - 2 * POSITION_EPS);
862  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, !attrs.hasAttribute(SUMO_ATTR_STARTPOS) && !attrs.hasAttribute(SUMO_ATTR_ENDPOS));
863  const double endPosOffset = edge->isInternal() ? edge->getNormalBefore()->getLength() : 0;
864  if (!ok || (checkStopPos(stop.startPos, stop.endPos, edge->getLength() + endPosOffset, POSITION_EPS, friendlyPos) != SUMORouteHandler::StopPos::STOPPOS_VALID)) {
865  myErrorOutput->inform("Invalid start or end position for stop" + errorSuffix);
866  return;
867  }
868  }
869  stop.edge = edge->getID();
870  if (myActivePlan != nullptr) {
871  ROPerson::addStop(*myActivePlan, stop, edge);
872  } else if (myVehicleParameter != nullptr) {
873  myVehicleParameter->stops.push_back(stop);
874  } else {
875  myActiveRouteStops.push_back(stop);
876  }
877  if (myInsertStopEdgesAt >= 0) {
878  myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
880  }
881 }
882 
883 
884 void
886 }
887 
888 
889 void
891 }
892 
893 
894 void
896  bool ok = true;
897  std::vector<ROPerson::PlanItem*>& plan = *myActivePlan;
898  const std::string pid = myVehicleParameter->id;
899 
900  ROEdge* from = nullptr;
901  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
902  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, pid.c_str(), ok);
903  from = myNet.getEdge(fromID);
904  if (from == nullptr) {
905  throw ProcessError("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known.");
906  }
907  } else if (plan.empty()) {
908  throw ProcessError("The start edge for person '" + pid + "' is not known.");
909  }
910  ROEdge* to = nullptr;
911  std::string stoppingPlaceID;
912  const SUMOVehicleParameter::Stop* stop = retrieveStoppingPlace(attrs, " for ride of person '" + myVehicleParameter->id + "'", stoppingPlaceID);
913  if (stop != nullptr) {
915  } else {
916  const std::string toID = attrs.getOpt<std::string>(SUMO_ATTR_TO, pid.c_str(), ok, "");
917  if (toID != "") {
918  to = myNet.getEdge(toID);
919  if (to == nullptr) {
920  throw ProcessError("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known.");
921  }
922  } else {
923  throw ProcessError("The to edge is missing within a ride of '" + myVehicleParameter->id + "'.");
924  }
925  }
926  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
927  stop == nullptr ? std::numeric_limits<double>::infinity() : stop->endPos);
928  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
929  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, pid.c_str(), ok, "");
930 
931  if (plan.empty() && myVehicleParameter->departProcedure == DEPART_TRIGGERED) {
932  StringTokenizer st(desc);
933  if (st.size() != 1) {
934  throw ProcessError("Triggered departure for person '" + pid + "' requires a unique lines value.");
935  }
936  const std::string vehID = st.front();
937  if (!myNet.knowsVehicle(vehID)) {
938  throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
939  }
940  SUMOTime vehDepart = myNet.getDeparture(vehID);
941  if (vehDepart == -1) {
942  throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for person '" + pid + "'.");
943  }
944  myVehicleParameter->depart = vehDepart + 1; // write person after vehicle
945  }
946  ROPerson::addRide(plan, from, to, desc, arrivalPos, stoppingPlaceID, group);
947 }
948 
949 
950 void
953  bool ok = true;
954  const std::string pid = myVehicleParameter->id;
955  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
956  StringTokenizer st(desc);
957  if (st.size() != 1) {
958  throw ProcessError("Triggered departure for container '" + pid + "' requires a unique lines value.");
959  }
960  const std::string vehID = st.front();
961  if (!myNet.knowsVehicle(vehID)) {
962  throw ProcessError("Unknown vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
963  }
964  SUMOTime vehDepart = myNet.getDeparture(vehID);
965  if (vehDepart == -1) {
966  throw ProcessError("Cannot use triggered vehicle '" + vehID + "' in triggered departure for container '" + pid + "'.");
967  }
968  myVehicleParameter->depart = vehDepart + 1; // write container after vehicle
969  }
970 }
971 
972 
973 void
975 }
976 
977 
978 void
979 RORouteHandler::parseEdges(const std::string& desc, ConstROEdgeVector& into,
980  const std::string& rid, bool& ok) {
981  for (StringTokenizer st(desc); st.hasNext();) {
982  const std::string id = st.next();
983  const ROEdge* edge = myNet.getEdge(id);
984  if (edge == nullptr) {
985  myErrorOutput->inform("The edge '" + id + "' within the route " + rid + " is not known.");
986  ok = false;
987  } else {
988  into.push_back(edge);
989  }
990  }
991 }
992 
993 void
995  ConstROEdgeVector& into, const std::string& rid, bool isFrom, bool& ok) {
996  if (geo && !GeoConvHelper::getFinal().usingGeoProjection()) {
997  WRITE_ERROR("Cannot convert geo-positions because the network has no geo-reference");
998  return;
999  }
1002  if (type != nullptr) {
1003  vClass = type->vehicleClass;
1004  }
1005  for (Position pos : positions) {
1006  Position orig = pos;
1007  if (geo) {
1009  }
1010  double dist = MIN2(10.0, myMapMatchingDistance);
1011  const ROEdge* best = getClosestEdge(pos, dist, vClass);
1012  while (best == nullptr && dist < myMapMatchingDistance) {
1013  dist = MIN2(dist * 2, myMapMatchingDistance);
1014  best = getClosestEdge(pos, dist, vClass);
1015  }
1016  if (best == nullptr) {
1017  myErrorOutput->inform("No edge found near position " + toString(orig, geo ? gPrecisionGeo : gPrecision) + " within the route " + rid + ".");
1018  ok = false;
1019  } else {
1020  if (myMapMatchJunctions) {
1021  best = getJunctionTaz(pos, best, vClass, isFrom);
1022  if (best != nullptr) {
1023  into.push_back(best);
1024  }
1025  } else {
1026  into.push_back(best);
1027  }
1028  }
1029  }
1030 }
1031 
1032 
1033 const ROEdge*
1034 RORouteHandler::getClosestEdge(const Position& pos, double distance, SUMOVehicleClass vClass) {
1035  NamedRTree* t = getLaneTree();
1036  Boundary b;
1037  b.add(pos);
1038  b.grow(distance);
1039  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1040  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1041  std::set<const Named*> lanes;
1042  Named::StoringVisitor sv(lanes);
1043  t->Search(cmin, cmax, sv);
1044  // use closest
1045  double minDist = std::numeric_limits<double>::max();
1046  const ROLane* best = nullptr;
1047  for (const Named* o : lanes) {
1048  const ROLane* cand = static_cast<const ROLane*>(o);
1049  if (!cand->allowsVehicleClass(vClass)) {
1050  continue;
1051  }
1052  double dist = cand->getShape().distance2D(pos);
1053  if (dist < minDist) {
1054  minDist = dist;
1055  best = cand;
1056  }
1057  }
1058  if (best == nullptr) {
1059  return nullptr;
1060  } else {
1061  const ROEdge* bestEdge = &best->getEdge();
1062  while (bestEdge->isInternal()) {
1063  bestEdge = bestEdge->getSuccessors().front();
1064  }
1065  return bestEdge;
1066  }
1067 }
1068 
1069 
1070 const ROEdge*
1071 RORouteHandler::getJunctionTaz(const Position& pos, const ROEdge* closestEdge, SUMOVehicleClass vClass, bool isFrom) {
1072  if (closestEdge == nullptr) {
1073  return nullptr;
1074  } else {
1075  const RONode* fromJunction = closestEdge->getFromJunction();
1076  const RONode* toJunction = closestEdge->getToJunction();
1077  const bool fromCloser = (fromJunction->getPosition().distanceSquaredTo2D(pos) <
1078  toJunction->getPosition().distanceSquaredTo2D(pos));
1079  const ROEdge* fromSource = myNet.getEdge(fromJunction->getID() + "-source");
1080  const ROEdge* fromSink = myNet.getEdge(fromJunction->getID() + "-sink");
1081  const ROEdge* toSource = myNet.getEdge(toJunction->getID() + "-source");
1082  const ROEdge* toSink = myNet.getEdge(toJunction->getID() + "-sink");
1083  if (fromSource == nullptr || fromSink == nullptr) {
1084  myErrorOutput->inform("Junction-taz '" + fromJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
1085  return nullptr;
1086  }
1087  if (toSource == nullptr || toSink == nullptr) {
1088  myErrorOutput->inform("Junction-taz '" + toJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
1089  return nullptr;
1090  }
1091  const bool fromPossible = isFrom ? fromSource->getSuccessors(vClass).size() > 0 : fromSink->getPredecessors().size() > 0;
1092  const bool toPossible = isFrom ? toSource->getSuccessors(vClass).size() > 0 : toSink->getPredecessors().size() > 0;
1093  //std::cout << "getJunctionTaz pos=" << pos << " isFrom=" << isFrom << " closest=" << closestEdge->getID() << " fromPossible=" << fromPossible << " toPossible=" << toPossible << "\n";
1094  if (fromCloser && fromPossible) {
1095  // return closest if possible
1096  return isFrom ? fromSource : fromSink;
1097  } else if (!fromCloser && toPossible) {
1098  // return closest if possible
1099  return isFrom ? toSource : toSink;
1100  } else {
1101  // return possible
1102  if (fromPossible) {
1103  return isFrom ? fromSource : fromSink;
1104  } else {
1105  return isFrom ? toSource : toSink;
1106  }
1107  }
1108  }
1109 }
1110 
1111 
1112 void
1113 RORouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
1114  const ROEdge* /*fromEdge*/, const ROEdge*& toEdge,
1115  double& departPos, double& arrivalPos, std::string& busStopID,
1116  const ROPerson::PlanItem* const lastStage, bool& ok) {
1117  const std::string description = "walk or personTrip of '" + personID + "'.";
1118  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1119  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.");
1120  }
1121  departPos = myVehicleParameter->departPos;
1122  if (lastStage != nullptr) {
1123  departPos = lastStage->getDestinationPos();
1124  }
1125 
1126  busStopID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1127 
1128  const SUMOVehicleParameter::Stop* bs = retrieveStoppingPlace(attrs, description, busStopID);
1129  if (bs != nullptr) {
1131  arrivalPos = (bs->startPos + bs->endPos) / 2;
1132  }
1133  if (toEdge != nullptr) {
1134  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1136  myHardFail, description, toEdge->getLength(),
1137  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok));
1138  }
1139  } else {
1140  throw ProcessError("No destination edge for " + description + ".");
1141  }
1142 }
1143 
1144 
1145 void
1147  bool ok = true;
1148  const char* const id = myVehicleParameter->id.c_str();
1149  assert(!attrs.hasAttribute(SUMO_ATTR_EDGES));
1150  const ROEdge* from = nullptr;
1151  const ROEdge* to = nullptr;
1152  parseFromViaTo(SUMO_TAG_PERSON, attrs, ok);
1153  myInsertStopEdgesAt = -1;
1156  if (ok) {
1157  from = myActiveRoute.front();
1158  }
1159  } else if (myActivePlan->empty()) {
1160  throw ProcessError("Start edge not defined for person '" + myVehicleParameter->id + "'.");
1161  } else {
1162  from = myActivePlan->back()->getDestination();
1163  }
1166  to = myActiveRoute.back();
1167  } // else, to may also be derived from stopping place
1168 
1169  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1170  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1171  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1172  }
1173 
1174  double departPos = 0;
1175  double arrivalPos = std::numeric_limits<double>::infinity();
1176  std::string busStopID;
1177  const ROPerson::PlanItem* const lastStage = myActivePlan->empty() ? nullptr : myActivePlan->back();
1178  parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, busStopID, lastStage, ok);
1179 
1180  const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1181  const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, id, ok, "");
1182  SVCPermissions modeSet = 0;
1183  for (StringTokenizer st(modes); st.hasNext();) {
1184  const std::string mode = st.next();
1185  if (mode == "car") {
1186  modeSet |= SVC_PASSENGER;
1187  } else if (mode == "taxi") {
1188  modeSet |= SVC_TAXI;
1189  } else if (mode == "bicycle") {
1190  modeSet |= SVC_BICYCLE;
1191  } else if (mode == "public") {
1192  modeSet |= SVC_BUS;
1193  } else {
1194  throw InvalidArgument("Unknown person mode '" + mode + "'.");
1195  }
1196  }
1197  const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1198  double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1199  if (ok) {
1200  const std::string originStopID = myActivePlan->empty() ? "" : myActivePlan->back()->getStopDest();
1201  ROPerson::addTrip(*myActivePlan, myVehicleParameter->id, from, to, modeSet, types,
1202  departPos, originStopID, arrivalPos, busStopID, walkFactor, group);
1203  }
1204 }
1205 
1206 
1207 void
1209  // parse walks from->to as person trips
1211  // XXX allow --repair?
1212  bool ok = true;
1213  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1214  const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1215  RORouteDef* routeDef = myNet.getRouteDef(routeID);
1216  const RORoute* route = routeDef != nullptr ? routeDef->getFirstRoute() : nullptr;
1217  if (route == nullptr) {
1218  throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1219  }
1220  myActiveRoute = route->getEdgeVector();
1221  } else {
1222  myActiveRoute.clear();
1223  parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myVehicleParameter->id.c_str(), ok), myActiveRoute, " walk for person '" + myVehicleParameter->id + "'", ok);
1224  }
1225  const char* const objId = myVehicleParameter->id.c_str();
1226  const double duration = attrs.getOpt<double>(SUMO_ATTR_DURATION, objId, ok, -1);
1227  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1228  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1229  }
1230  const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, objId, ok, -1.);
1231  if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1232  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1233  }
1234  double departPos = 0.;
1235  double arrivalPos = std::numeric_limits<double>::infinity();
1236  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
1237  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.");
1238  }
1239  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1240  arrivalPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, myHardFail, objId, myActiveRoute.back()->getLength(), attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, objId, ok));
1241  }
1242  std::string stoppingPlaceID;
1243  const std::string errorSuffix = " for walk of person '" + myVehicleParameter->id + "'";
1244  retrieveStoppingPlace(attrs, errorSuffix, stoppingPlaceID);
1245  if (ok) {
1246  ROPerson::addWalk(*myActivePlan, myActiveRoute, duration, speed, departPos, arrivalPos, stoppingPlaceID);
1247  }
1248  } else {
1249  addPersonTrip(attrs);
1250  }
1251 }
1252 
1253 
1254 NamedRTree*
1256  if (myLaneTree == nullptr) {
1257  myLaneTree = new NamedRTree();
1258  for (const auto& edgeItem : myNet.getEdgeMap()) {
1259  for (ROLane* lane : edgeItem.second->getLanes()) {
1260  Boundary b = lane->getShape().getBoxBoundary();
1261  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
1262  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
1263  myLaneTree->Insert(cmin, cmax, lane);
1264  }
1265  }
1266  }
1267  return myLaneTree;
1268 }
1269 
1270 bool
1272  if (!myUnsortedInput) {
1274  }
1275  return true;
1276 }
1277 
1278 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:281
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
std::vector< const ROEdge * > ConstROEdgeVector
Definition: ROEdge.h:54
#define JUNCTION_TAZ_MISSING_HELP
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
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TAXI
vehicle is a taxi
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
const double DEFAULT_VEH_PROB
const std::string DEFAULT_PEDTYPE_ID
const std::string DEFAULT_VTYPE_ID
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const int VEHPARS_TO_TAZ_SET
const int VEHPARS_FROM_TAZ_SET
const int STOP_END_SET
@ 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_TRANSHIP
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_STOP
stop for vehicles
@ 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_LAST
@ SUMO_ATTR_LANE
@ SUMO_ATTR_LON
@ SUMO_ATTR_REFID
@ SUMO_ATTR_VIALONLAT
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_VIA
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_VIAXY
@ SUMO_ATTR_Y
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_FROMJUNCTION
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_X
@ SUMO_ATTR_ARRIVALPOS
@ 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_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ 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_CYCLETIME
@ SUMO_ATTR_TOJUNCTION
int gPrecision
the precision for floating point outputs
Definition: StdDefs.cpp:25
int gPrecisionGeo
Definition: StdDefs.cpp:26
T MIN2(T a, T b)
Definition: StdDefs.h:74
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
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:77
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:129
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:117
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:299
PositionVector getShape(const bool closeShape) const
get position vector (shape) based on this boundary
Definition: Boundary.cpp:387
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:135
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:123
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 MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:117
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition: Named.h:90
Base class for objects which have an id.
Definition: Named.h:54
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
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
Definition: NamedRTree.h:112
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)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
An output device that encapsulates an ofstream.
std::string getString() const
Returns the current content as a string.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:257
A list of positions.
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
A basic edge for routing applications.
Definition: ROEdge.h:70
const ROEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: ROEdge.cpp:267
bool isInternal() const
return whether this edge is an internal edge
Definition: ROEdge.h:145
const RONode * getFromJunction() const
Definition: ROEdge.h:508
const std::vector< ROLane * > & getLanes() const
Returns this edge's lanes.
Definition: ROEdge.h:520
const ROEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: ROEdge.cpp:364
double getLength() const
Returns the length of the edge.
Definition: ROEdge.h:210
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition: ROEdge.h:361
const RONode * getToJunction() const
Definition: ROEdge.h:512
A single lane the router may use.
Definition: ROLane.h:48
ROEdge & getEdge() const
Returns the lane's edge.
Definition: ROLane.h:93
const PositionVector & getShape() const
Definition: ROLane.h:115
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: ROLane.h:111
The router's network representation.
Definition: RONet.h:62
SUMOVTypeParameter * getVehicleTypeSecure(const std::string &id)
Retrieves the named vehicle type.
Definition: RONet.cpp:343
const SUMOVehicleParameter::Stop * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Retrieves a stopping place from the network.
Definition: RONet.h:216
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition: RONet.h:157
bool addRouteDef(RORouteDef *def)
Definition: RONet.cpp:265
bool knowsVehicle(const std::string &id) const
returns whether a vehicle with the given id was already loaded
Definition: RONet.cpp:444
virtual bool addVehicle(const std::string &id, ROVehicle *veh)
Definition: RONet.cpp:422
SUMOTime getDeparture(const std::string &vehID) const
returns departure time for the given vehicle id
Definition: RONet.cpp:449
void addContainer(const SUMOTime depart, const std::string desc)
Definition: RONet.cpp:490
bool addPerson(ROPerson *person)
Definition: RONet.cpp:478
virtual bool addVehicleType(SUMOVTypeParameter *type)
Adds a read vehicle type definition to the network.
Definition: RONet.cpp:398
RORouteDef * getRouteDef(const std::string &name) const
Returns the named route definition.
Definition: RONet.h:305
bool addVTypeDistribution(const std::string &id, RandomDistributor< SUMOVTypeParameter * > *vehTypeDistribution)
Adds a vehicle type distribution.
Definition: RONet.cpp:411
bool addFlow(SUMOVehicleParameter *flow, const bool randomize)
Definition: RONet.cpp:460
const NamedObjectCont< ROEdge * > & getEdgeMap() const
Definition: RONet.h:409
Base class for nodes used by the router.
Definition: RONode.h:43
const Position & getPosition() const
Returns the position of the node.
Definition: RONode.h:64
Every person has a plan comprising of multiple planItems.
Definition: ROPerson.h:82
virtual double getDestinationPos() const =0
A person as used by router.
Definition: ROPerson.h:49
static void addTrip(std::vector< PlanItem * > &plan, const std::string &id, const ROEdge *const from, const ROEdge *const to, const SVCPermissions modeSet, const std::string &vTypes, const double departPos, const std::string &stopOrigin, const double arrivalPos, const std::string &busStop, double walkFactor, const std::string &group)
Definition: ROPerson.cpp:61
static void addStop(std::vector< PlanItem * > &plan, const SUMOVehicleParameter::Stop &stopPar, const ROEdge *const stopEdge)
Definition: ROPerson.cpp:133
static void addRide(std::vector< PlanItem * > &plan, const ROEdge *const from, const ROEdge *const to, const std::string &lines, double arrivalPos, const std::string &destStop, const std::string &group)
Definition: ROPerson.cpp:116
std::vector< PlanItem * > & getPlan()
Definition: ROPerson.h:419
static void addWalk(std::vector< PlanItem * > &plan, const ConstROEdgeVector &edges, const double duration, const double speed, const double departPos, const double arrivalPos, const std::string &busStop)
Definition: ROPerson.cpp:124
Base class for a vehicle's route definition.
Definition: RORouteDef.h:53
void addLoadedAlternative(RORoute *alternative)
Adds a single alternative loaded from the file An alternative may also be generated during DUA.
Definition: RORouteDef.cpp:69
double getOverallProb() const
Returns the sum of the probablities of the contained routes.
Definition: RORouteDef.cpp:413
void addAlternativeDef(const RORouteDef *alternative)
Adds an alternative loaded from the file.
Definition: RORouteDef.cpp:75
RORouteDef * copy(const std::string &id, const SUMOTime stopOffset) const
Returns a deep copy of the route definition.
Definition: RORouteDef.cpp:399
void closeTrip()
Ends the processing of a trip.
void closeRouteDistribution()
closes (ends) the building of a distribution
const SUMOVehicleParameter::Stop * retrieveStoppingPlace(const SUMOSAXAttributes &attrs, const std::string &errorSuffix, std::string &id, const SUMOVehicleParameter::Stop *stopParam=nullptr)
retrieve stopping place element
NamedRTree * myLaneTree
RTree for finding lanes.
void addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
const double myMapMatchingDistance
maximum distance when map-matching
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
virtual ~RORouteHandler()
standard destructor
RORouteHandler(RONet &net, const std::string &file, const bool tryRepair, const bool emptyDestinationsAllowed, const bool ignoreErrors, const bool checkSchema)
standard constructor
void addTranship(const SUMOSAXAttributes &attrs)
Processing of a tranship.
void parseEdges(const std::string &desc, ConstROEdgeVector &into, const std::string &rid, bool &ok)
Parse edges from strings.
void closeVType()
Ends the processing of a vehicle type.
void addRide(const SUMOSAXAttributes &attrs)
Processing of a ride.
void addWalk(const SUMOSAXAttributes &attrs)
add a fully specified walk
RONet & myNet
The current route.
NamedRTree * getLaneTree()
initialize lane-RTree
bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
ConstROEdgeVector myActiveRoute
The current route.
const ROEdge * getJunctionTaz(const Position &pos, const ROEdge *closestEdge, SUMOVehicleClass vClass, bool isFrom)
find closest junction taz given the closest edge
std::vector< ROPerson::PlanItem * > * myActivePlan
The plan of the current person.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
const bool myTryRepair
Information whether routes shall be repaired.
OutputDevice_String * myActiveContainerPlan
The plan of the current container.
SUMOTime myActiveRoutePeriod
const SUMOTime myBegin
The begin time.
RandomDistributor< SUMOVTypeParameter * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
void closePersonFlow()
Ends the processing of a personFlow.
void closePerson()
Ends the processing of a person.
void openRouteDistribution(const SUMOSAXAttributes &attrs)
opens a route distribution for reading
int myActiveContainerPlanSize
The number of stages in myActiveContainerPlan.
const bool myKeepVTypeDist
whether to keep the the vtype distribution in output
void openRouteFlow(const SUMOSAXAttributes &attrs)
opens a route flow for reading
const bool myUnsortedInput
whether input is read all at once (no sorting check is necessary)
void openTrip(const SUMOSAXAttributes &attrs)
opens a trip for reading
void closeVehicle()
Ends the processing of a vehicle.
void addContainer(const SUMOSAXAttributes &attrs)
Processing of a container.
const bool myMapMatchJunctions
void addTransport(const SUMOSAXAttributes &attrs)
Processing of a transport.
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const ROEdge *fromEdge, const ROEdge *&toEdge, double &departPos, double &arrivalPos, std::string &busStopID, const ROPerson::PlanItem *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
MsgHandler *const myErrorOutput
Depending on the "ignore-errors" option different outputs are used.
void closeRoute(const bool mayBeDisconnected=false)
closes (ends) the building of a route.
void closeFlow()
Ends the processing of a flow.
int myActiveRouteRepeat
number of repetitions of the active route
void closeContainer()
Ends the processing of a container.
void closeVehicleTypeDistribution()
closes (ends) the building of a distribution
void addFlowPerson(SUMOVTypeParameter *type, SUMOTime depart, const std::string &baseID, int i)
Processing of a person from a personFlow.
void addPerson(const SUMOSAXAttributes &attrs)
Processing of a person.
void parseGeoEdges(const PositionVector &positions, bool geo, ConstROEdgeVector &into, const std::string &rid, bool isFrom, bool &ok)
Parse edges from coordinates.
RORouteDef * myCurrentAlternatives
The currently parsed route alternatives.
void openFlow(const SUMOSAXAttributes &attrs)
opens a flow for reading
void closeContainerFlow()
Ends the processing of a containerFlow.
void addPersonTrip(const SUMOSAXAttributes &attrs)
add a routing request for a walking or intermodal person
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs)
opens a type distribution for reading
const ROEdge * getClosestEdge(const Position &pos, double distance, SUMOVehicleClass vClass)
find closest edge within distance for the given position or nullptr
void openRoute(const SUMOSAXAttributes &attrs)
opens a route for reading
void parseFromViaTo(SumoXMLTag tag, const SUMOSAXAttributes &attrs, bool &ok)
Called for parsing from and to and the corresponding taz attributes.
A complete router's route.
Definition: RORoute.h:52
const ConstROEdgeVector & getEdgeVector() const
Returns the list of edges this route consists of.
Definition: RORoute.h:152
A vehicle as used by router.
Definition: ROVehicle.h:50
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.
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.
Structure representing possible vehicle parameter.
double defaultProbability
The probability when being added to a distribution without an explicit probability.
void cacheParamRestrictions(const std::vector< std::string > &restrictionKeys)
SUMOVehicleClass vehicleClass
The vehicle's class.
std::string id
The vehicle type's id.
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at (used only in NETEDIT)
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
std::string overheadWireSegment
(Optional) overhead line segment if one is assigned to the stop
int parametersSet
Information for the output which parameter were set.
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
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
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 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.
bool wasSet(int what) const
Returns whether the given parameter was set.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
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
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
std::string front()
returns the first substring without moving the iterator
int size() const
returns the number of existing substrings
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined