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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
18 // Parser and container for routes during their loading
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <string>
28 #include <map>
29 #include <vector>
30 #include <iostream>
40 #include <utils/xml/XMLSubSys.h>
42 #include "ROPerson.h"
43 #include "RONet.h"
44 #include "ROEdge.h"
45 #include "ROLane.h"
46 #include "RORouteDef.h"
47 #include "RORouteHandler.h"
48 
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" : ""),
59  myNet(net),
60  myActivePerson(nullptr),
61  myActiveContainerPlan(nullptr),
62  myActiveContainerPlanSize(0),
63  myTryRepair(tryRepair),
64  myEmptyDestinationsAllowed(emptyDestinationsAllowed),
65  myErrorOutput(ignoreErrors ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
66  myBegin(string2time(OptionsCont::getOptions().getString("begin"))),
67  myKeepVTypeDist(OptionsCont::getOptions().getBool("keep-vtype-distributions")),
68  myCurrentVTypeDistribution(nullptr),
69  myCurrentAlternatives(nullptr) {
70  myActiveRoute.reserve(100);
71 }
72 
73 
75 }
76 
77 
78 void
79 RORouteHandler::parseFromViaTo(std::string element,
80  const SUMOSAXAttributes& attrs) {
81  myActiveRoute.clear();
82  bool useTaz = OptionsCont::getOptions().getBool("with-taz");
84  WRITE_WARNING("Taz usage was requested but no taz present in " + element + " '" + myVehicleParameter->id + "'!");
85  useTaz = false;
86  }
87  bool ok = true;
89  const ROEdge* fromTaz = myNet.getEdge(myVehicleParameter->fromTaz + "-source");
90  if (fromTaz == nullptr) {
91  myErrorOutput->inform("Source taz '" + myVehicleParameter->fromTaz + "' not known for " + element + " '" + myVehicleParameter->id + "'!");
92  } else if (fromTaz->getNumSuccessors() == 0) {
93  myErrorOutput->inform("Source taz '" + myVehicleParameter->fromTaz + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
94  } else {
95  myActiveRoute.push_back(fromTaz);
96  }
97  } else {
98  parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok, "", true),
99  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
100  }
101  if (!attrs.hasAttribute(SUMO_ATTR_VIA)) {
102  myInsertStopEdgesAt = (int)myActiveRoute.size();
103  }
104  ConstROEdgeVector viaEdges;
105  parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true),
106  viaEdges, "for " + element + " '" + myVehicleParameter->id + "'");
107  for (ConstROEdgeVector::const_iterator i = viaEdges.begin(); i != viaEdges.end(); ++i) {
108  myActiveRoute.push_back(*i);
109  myVehicleParameter->via.push_back((*i)->getID());
110  }
111 
113  const ROEdge* toTaz = myNet.getEdge(myVehicleParameter->toTaz + "-sink");
114  if (toTaz == nullptr) {
115  myErrorOutput->inform("Sink taz '" + myVehicleParameter->toTaz + "' not known for " + element + " '" + myVehicleParameter->id + "'!");
116  } else if (toTaz->getNumPredecessors() == 0) {
117  myErrorOutput->inform("Sink taz '" + myVehicleParameter->toTaz + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
118  } else {
119  myActiveRoute.push_back(toTaz);
120  }
121  } else {
122  parseEdges(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
123  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
124  }
126  if (myVehicleParameter->routeid == "") {
128  }
129 }
130 
131 
132 void
134  const SUMOSAXAttributes& attrs) {
135  SUMORouteHandler::myStartElement(element, attrs);
136  switch (element) {
137  case SUMO_TAG_PERSON: {
139  if (type == nullptr) {
140  myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for person '" + myVehicleParameter->id + "' is not known.");
142  }
144  break;
145  }
146  case SUMO_TAG_RIDE: {
147  std::vector<ROPerson::PlanItem*>& plan = myActivePerson->getPlan();
148  const std::string pid = myVehicleParameter->id;
149  bool ok = true;
150  ROEdge* from = nullptr;
151  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
152  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, pid.c_str(), ok);
153  from = myNet.getEdge(fromID);
154  if (from == nullptr) {
155  throw ProcessError("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known.");
156  }
157  if (!plan.empty() && plan.back()->getDestination() != from) {
158  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + fromID + "!=" + plan.back()->getDestination()->getID() + ").");
159  }
160  } else if (plan.empty()) {
161  throw ProcessError("The start edge for person '" + pid + "' is not known.");
162  }
163  ROEdge* to = nullptr;
164  const SUMOVehicleParameter::Stop* stop = nullptr;
165  const std::string toID = attrs.getOpt<std::string>(SUMO_ATTR_TO, pid.c_str(), ok, "");
166  const std::string busStopID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, pid.c_str(), ok, "");
167  if (toID != "") {
168  to = myNet.getEdge(toID);
169  if (to == nullptr) {
170  throw ProcessError("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known.");
171  }
172  } else if (busStopID != "") {
173  stop = myNet.getStoppingPlace(busStopID, SUMO_TAG_BUS_STOP);
174  if (stop == nullptr) {
175  throw ProcessError("Unknown bus stop '" + busStopID + "' within a ride of '" + myVehicleParameter->id + "'.");
176  }
178  } else {
179  throw ProcessError("The to edge '' within a ride of '" + myVehicleParameter->id + "' is not known.");
180  }
181  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
182  stop == nullptr ? -NUMERICAL_EPS : stop->endPos);
183  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
184  myActivePerson->addRide(from, to, desc, arrivalPos, busStopID);
185  break;
186  }
187  case SUMO_TAG_CONTAINER:
191  (*myActiveContainerPlan) << attrs;
192  break;
193  case SUMO_TAG_TRANSPORT: {
195  (*myActiveContainerPlan) << attrs;
198  break;
199  }
200  case SUMO_TAG_TRANSHIP: {
201  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
202  // copy walk as it is
203  // XXX allow --repair?
205  (*myActiveContainerPlan) << attrs;
208  } else {
209  //routePerson(attrs, *myActiveContainerPlan);
210  }
211  break;
212  }
213  case SUMO_TAG_FLOW:
215  parseFromViaTo("flow", attrs);
216  break;
217  case SUMO_TAG_TRIP: {
219  parseFromViaTo("trip", attrs);
220  }
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);
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_WARNING("No probability for a route in '" + rid + "', using default.");
303  }
305  if (ok && myActiveRouteProbability < 0) {
306  myErrorOutput->inform("Invalid probability for route '" + myActiveRouteID + "'.");
307  }
309  ok = true;
310  myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
311  if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
312  myErrorOutput->inform("Invalid cost for route '" + myActiveRouteID + "'.");
313  }
314 }
315 
316 
317 void
320  switch (element) {
321  case SUMO_TAG_VTYPE:
323  if (myCurrentVTypeDistribution != nullptr) {
325  }
326  }
327  myCurrentVType = nullptr;
328  break;
329  case SUMO_TAG_TRIP:
330  closeRoute(true);
331  closeVehicle();
332  delete myVehicleParameter;
333  myVehicleParameter = nullptr;
334  myInsertStopEdgesAt = -1;
335  break;
336  default:
337  break;
338  }
339 }
340 
341 
342 void
343 RORouteHandler::closeRoute(const bool mayBeDisconnected) {
344  if (myActiveRoute.size() == 0) {
345  if (myActiveRouteRefID != "" && myCurrentAlternatives != nullptr) {
347  myActiveRouteID = "";
348  myActiveRouteRefID = "";
349  return;
350  }
351  if (myVehicleParameter != nullptr) {
352  myErrorOutput->inform("The route for vehicle '" + myVehicleParameter->id + "' has no edges.");
353  } else {
354  myErrorOutput->inform("Route '" + myActiveRouteID + "' has no edges.");
355  }
356  myActiveRouteID = "";
357  myActiveRouteStops.clear();
358  return;
359  }
360  if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
361  myErrorOutput->inform("The routing information for vehicle '" + myVehicleParameter->id + "' is insufficient.");
362  myActiveRouteID = "";
363  myActiveRouteStops.clear();
364  return;
365  }
366  if (!mayBeDisconnected && OptionsCont::getOptions().exists("no-internal-links") && !OptionsCont::getOptions().getBool("no-internal-links")) {
367  // fix internal edges which did not get parsed
368  const ROEdge* last = nullptr;
369  ConstROEdgeVector fullRoute;
370  for (const ROEdge* roe : myActiveRoute) {
371  if (last != nullptr) {
372  for (const ROEdge* intern : last->getSuccessors()) {
373  if (intern->isInternal() && intern->getSuccessors().size() == 1 && intern->getSuccessors().front() == roe) {
374  fullRoute.push_back(intern);
375  }
376  }
377  }
378  fullRoute.push_back(roe);
379  last = roe;
380  }
381  myActiveRoute = fullRoute;
382  }
385  myActiveRoute.clear();
386  if (myCurrentAlternatives == nullptr) {
387  if (myNet.getRouteDef(myActiveRouteID) != nullptr) {
388  delete route;
389  if (myVehicleParameter != nullptr) {
390  myErrorOutput->inform("Another route for vehicle '" + myVehicleParameter->id + "' exists.");
391  } else {
392  myErrorOutput->inform("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
393  }
394  myActiveRouteID = "";
395  myActiveRouteStops.clear();
396  return;
397  } else {
398  myCurrentAlternatives = new RORouteDef(myActiveRouteID, 0, mayBeDisconnected || myTryRepair, mayBeDisconnected);
401  myCurrentAlternatives = nullptr;
402  }
403  } else {
405  }
406  myActiveRouteID = "";
407  myActiveRouteStops.clear();
408 }
409 
410 
411 void
413  // check whether the id is really necessary
414  bool ok = true;
415  std::string id;
416  if (myVehicleParameter != nullptr) {
417  // ok, a vehicle is wrapping the route,
418  // we may use this vehicle's id as default
419  myVehicleParameter->routeid = id = "!" + myVehicleParameter->id; // !!! document this
420  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
421  WRITE_WARNING("Ids of internal route distributions are ignored (vehicle '" + myVehicleParameter->id + "').");
422  }
423  } else {
424  id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
425  if (!ok) {
426  return;
427  }
428  }
429  // try to get the index of the last element
430  int index = attrs.getOpt<int>(SUMO_ATTR_LAST, id.c_str(), ok, 0);
431  if (ok && index < 0) {
432  myErrorOutput->inform("Negative index of a route alternative (id='" + id + "').");
433  return;
434  }
435  // build the alternative cont
436  myCurrentAlternatives = new RORouteDef(id, index, myTryRepair, false);
437  if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
438  ok = true;
439  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, id.c_str(), ok));
440  while (st.hasNext()) {
441  const std::string routeID = st.next();
442  const RORouteDef* route = myNet.getRouteDef(routeID);
443  if (route == nullptr) {
444  myErrorOutput->inform("Unknown route '" + routeID + "' in distribution '" + id + "'.");
445  } else {
447  }
448  }
449  }
450 }
451 
452 
453 void
455  if (myCurrentAlternatives != nullptr) {
457  myErrorOutput->inform("Route distribution '" + myCurrentAlternatives->getID() + "' is empty.");
458  delete myCurrentAlternatives;
459  } else if (!myNet.addRouteDef(myCurrentAlternatives)) {
460  myErrorOutput->inform("Another route (or distribution) with the id '" + myCurrentAlternatives->getID() + "' exists.");
461  delete myCurrentAlternatives;
462  }
463  myCurrentAlternatives = nullptr;
464  }
465 }
466 
467 
468 void
470  // get the vehicle id
472  return;
473  }
474  // get vehicle type
476  if (type == nullptr) {
477  myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
479  } else {
480  if (!myKeepVTypeDist) {
481  // fix the type id in case we used a distribution
482  myVehicleParameter->vtypeid = type->id;
483  }
484  }
485  if (type->vehicleClass == SVC_PEDESTRIAN) {
486  WRITE_WARNING("Vehicle type '" + type->id + "' with vClass=pedestrian should only be used for persons and not for vehicle '" + myVehicleParameter->id + "'.");
487  }
488  // get the route
490  if (route == nullptr) {
491  myErrorOutput->inform("The route of the vehicle '" + myVehicleParameter->id + "' is not known.");
492  return;
493  }
494  if (route->getID()[0] != '!') {
495  route = route->copy("!" + myVehicleParameter->id, myVehicleParameter->depart);
496  }
497  // build the vehicle
498  if (!MsgHandler::getErrorInstance()->wasInformed()) {
499  ROVehicle* veh = new ROVehicle(*myVehicleParameter, route, type, &myNet, myErrorOutput);
500  if (myNet.addVehicle(myVehicleParameter->id, veh)) {
502  }
503  }
504 }
505 
506 
507 void
509  if (myActivePerson->getPlan().empty()) {
510  WRITE_WARNING("Discarding person '" + myVehicleParameter->id + "' because it's plan is empty");
511  } else {
514  }
515  }
516  delete myVehicleParameter;
517  myVehicleParameter = nullptr;
518  myActivePerson = nullptr;
519 }
520 
521 
522 void
525  if (myActiveContainerPlanSize > 0) {
528  } else {
529  WRITE_WARNING("Discarding container '" + myVehicleParameter->id + "' because it's plan is empty");
530  }
531  delete myVehicleParameter;
532  myVehicleParameter = nullptr;
533  delete myActiveContainerPlan;
534  myActiveContainerPlan = nullptr;
536 }
537 
538 
539 void
541  // @todo: consider myScale?
543  delete myVehicleParameter;
544  myVehicleParameter = nullptr;
545  return;
546  }
547  // let's check whether vehicles had to depart before the simulation starts
549  const SUMOTime offsetToBegin = myBegin - myVehicleParameter->depart;
553  delete myVehicleParameter;
554  myVehicleParameter = nullptr;
555  return;
556  }
557  }
559  myErrorOutput->inform("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
560  }
561  if (myVehicleParameter->routeid[0] == '!' && myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
562  closeRoute(true);
563  }
564  if (myNet.getRouteDef(myVehicleParameter->routeid) == nullptr) {
565  myErrorOutput->inform("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
566  delete myVehicleParameter;
567  myVehicleParameter = nullptr;
568  return;
569  }
570  myActiveRouteID = "";
571  if (!MsgHandler::getErrorInstance()->wasInformed()) {
572  if (myNet.addFlow(myVehicleParameter, OptionsCont::getOptions().getBool("randomize-flows"))) {
574  } else {
575  myErrorOutput->inform("Another flow with the id '" + myVehicleParameter->id + "' exists.");
576  }
577  } else {
578  delete myVehicleParameter;
579  }
580  myVehicleParameter = nullptr;
581  myInsertStopEdgesAt = -1;
582 }
583 
584 
585 void
587  if (myActiveContainerPlan != nullptr) {
589  (*myActiveContainerPlan) << attrs;
592  return;
593  }
594  std::string errorSuffix;
595  if (myVehicleParameter != nullptr) {
596  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
597  } else {
598  errorSuffix = " in route '" + myActiveRouteID + "'.";
599  }
601  bool ok = parseStop(stop, attrs, errorSuffix, myErrorOutput);
602  if (!ok) {
603  return;
604  }
605  // try to parse the assigned bus stop
606  ROEdge* edge = nullptr;
607  if (stop.busstop != "") {
609  if (busstop == nullptr) {
610  myErrorOutput->inform("Unknown bus stop '" + stop.busstop + "'" + errorSuffix);
611  return;
612  }
613  stop.lane = busstop->lane;
614  stop.endPos = busstop->endPos;
615  stop.startPos = busstop->startPos;
616  edge = myNet.getEdge(stop.lane.substr(0, stop.lane.rfind('_')));
617  } // try to parse the assigned container stop
618  else if (stop.containerstop != "") {
620  if (containerstop == nullptr) {
621  myErrorOutput->inform("Unknown container stop '" + stop.containerstop + "'" + errorSuffix);
622  return;
623  }
624  stop.lane = containerstop->lane;
625  stop.endPos = containerstop->endPos;
626  stop.startPos = containerstop->startPos;
627  edge = myNet.getEdge(stop.lane.substr(0, stop.lane.rfind('_')));
628  } // try to parse the assigned parking area
629  else if (stop.parkingarea != "") {
631  if (parkingarea == nullptr) {
632  myErrorOutput->inform("Unknown parking area '" + stop.parkingarea + "'" + errorSuffix);
633  return;
634  }
635  stop.lane = parkingarea->lane;
636  stop.endPos = parkingarea->endPos;
637  stop.startPos = parkingarea->startPos;
638  edge = myNet.getEdge(stop.lane.substr(0, stop.lane.rfind('_')));
639  } else {
640  // no, the lane and the position should be given
641  stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, "");
642  if (!ok || stop.lane == "") {
643  myErrorOutput->inform("A stop must be placed on a bus stop, a container stop, a parking area or a lane" + errorSuffix);
644  return;
645  }
646  edge = myNet.getEdge(stop.lane.substr(0, stop.lane.rfind('_')));
647  if (edge == nullptr) {
648  myErrorOutput->inform("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
649  return;
650  }
651  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, edge->getLength());
652  stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, stop.endPos - 2 * POSITION_EPS);
653  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, false);
654  const double endPosOffset = edge->isInternal() ? edge->getNormalBefore()->getLength() : 0;
655  if (!ok || !checkStopPos(stop.startPos, stop.endPos, edge->getLength() + endPosOffset, POSITION_EPS, friendlyPos)) {
656  myErrorOutput->inform("Invalid start or end position for stop" + errorSuffix);
657  return;
658  }
659  }
660  if (myActivePerson != nullptr) {
661  myActivePerson->addStop(stop, edge);
662  } else if (myVehicleParameter != nullptr) {
663  myVehicleParameter->stops.push_back(stop);
664  } else {
665  myActiveRouteStops.push_back(stop);
666  }
667  if (myInsertStopEdgesAt >= 0) {
668  myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
670  }
671 }
672 
673 
674 void
675 RORouteHandler::parseEdges(const std::string& desc, ConstROEdgeVector& into,
676  const std::string& rid) {
677  if (desc[0] == BinaryFormatter::BF_ROUTE) {
678  std::istringstream in(desc, std::ios::binary);
679  char c;
680  in >> c;
681  FileHelpers::readEdgeVector(in, into, rid);
682  } else {
683  for (StringTokenizer st(desc); st.hasNext();) {
684  const std::string id = st.next();
685  const ROEdge* edge = myNet.getEdge(id);
686  if (edge == nullptr) {
687  myErrorOutput->inform("The edge '" + id + "' within the route " + rid + " is not known.");
688  } else {
689  into.push_back(edge);
690  }
691  }
692  }
693 }
694 
695 
696 void
698  bool ok = true;
699  const char* const id = myVehicleParameter->id.c_str();
700  assert(!attrs.hasAttribute(SUMO_ATTR_EDGES));
701  const std::string fromID = attrs.getOpt<std::string>(SUMO_ATTR_FROM, id, ok, "");
702  std::string toID = attrs.getOpt<std::string>(SUMO_ATTR_TO, id, ok, "");
703  const std::string busStopID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, id, ok, "");
704 
705  const ROEdge* from = fromID != "" || myActivePerson->getPlan().empty() ? myNet.getEdge(fromID) : myActivePerson->getPlan().back()->getDestination();
706  if (from == nullptr) {
707  myErrorOutput->inform("The edge '" + fromID + "' within a walk or personTrip of '" + myVehicleParameter->id + "' is not known."
708  + "\n The route can not be build.");
709  ok = false;
710  }
711  if (toID == "") {
713  if (stop == nullptr) {
714  myErrorOutput->inform("Unknown bus stop '" + busStopID + "' within a walk or personTrip of '" + myVehicleParameter->id + "'.");
715  ok = false;
716  }
717  }
718  const ROEdge* to = myNet.getEdge(toID);
719  if (toID != "" && to == nullptr) {
720  myErrorOutput->inform("The edge '" + toID + "' within a walk or personTrip of '" + myVehicleParameter->id + "' is not known."
721  + "\n The route can not be build.");
722  ok = false;
723  }
724 
725  double departPos = myActivePerson->getParameter().departPos;
726  if (!myActivePerson->getPlan().empty()) {
727  departPos = myActivePerson->getPlan().back()->getDestinationPos();
728  }
729 
730  double arrivalPos = 0.;
731  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
732  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.");
733  }
734  if (to != nullptr && attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
736  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, id, ok));
737  }
738 
739  const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
740  SVCPermissions modeSet = 0;
741  for (StringTokenizer st(modes); st.hasNext();) {
742  const std::string mode = st.next();
743  if (mode == "car") {
744  modeSet |= SVC_PASSENGER;
745  } else if (mode == "bicycle") {
746  modeSet |= SVC_BICYCLE;
747  } else if (mode == "public") {
748  modeSet |= SVC_BUS;
749  } else {
750  throw InvalidArgument("Unknown person mode '" + mode + "'.");
751  }
752  }
753  const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
754  double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
755  if (ok) {
756  myActivePerson->addTrip(from, to, modeSet, types, departPos, arrivalPos, busStopID, walkFactor);
757  }
758 }
759 
760 
761 void
763  // XXX allow --repair?
764  bool ok = true;
765  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
766  const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
767  RORouteDef* routeDef = myNet.getRouteDef(routeID);
768  const RORoute* route = routeDef != nullptr ? routeDef->getFirstRoute() : nullptr;
769  if (route == nullptr) {
770  throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
771  }
772  myActiveRoute = route->getEdgeVector();
773  } else {
774  myActiveRoute.clear();
775  parseEdges(attrs.get<std::string>(SUMO_ATTR_EDGES, myVehicleParameter->id.c_str(), ok), myActiveRoute, " walk for person '" + myVehicleParameter->id + "'");
776  }
777  const char* const objId = myVehicleParameter->id.c_str();
778  const double duration = attrs.getOpt<double>(SUMO_ATTR_DURATION, objId, ok, -1);
779  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
780  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
781  }
782  const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, objId, ok, -1.);
783  if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
784  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
785  }
786  double departPos = 0.;
787  double arrivalPos = 0.;
788  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
789  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.");
790  }
791  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
792  arrivalPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, objId, myActiveRoute.back()->getLength(),
793  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, objId, ok));
794  }
795  const std::string busStop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, objId, ok, "");
796  if (ok) {
797  myActivePerson->addWalk(myActiveRoute, duration, speed, departPos, arrivalPos, busStop);
798  }
799 }
800 
801 
802 /****************************************************************************/
RORouteDef * copy(const std::string &id, const SUMOTime stopOffset) const
Returns a deep copy of the route definition.
Definition: RORouteDef.cpp:384
const int VEHPARS_TO_TAZ_SET
RORouteDef * myCurrentAlternatives
The currently parsed route alternatives.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:76
virtual void myEndElement(int element)
Called when a closing tag occurs.
long long int SUMOTime
Definition: SUMOTime.h:36
description of a vehicle type
void closeVehicleTypeDistribution()
The time is given.
is a pedestrian
std::string next()
std::string containerstop
(Optional) container stop if one is assigned to the stop
int repetitionNumber
The number of times the vehicle shall be repeatedly inserted.
void closePerson()
Ends the processing of a person.
std::string vtypeid
The vehicle&#39;s type id.
int getNumSuccessors() const
Returns the number of edges this edge is connected to.
Definition: ROEdge.cpp:235
void openRouteDistribution(const SUMOSAXAttributes &attrs)
a flow definition (used by router)
Represents a generic random distribution.
SUMOVehicleParameter * myVehicleParameter
Parameter of the current vehicle, trip, person, container or flow.
static void readEdgeVector(std::istream &in, std::vector< const E *> &edges, const std::string &rid)
Reads an edge vector binary.
Definition: FileHelpers.h:267
Structure representing possible vehicle parameter.
const SUMOVehicleParameter & getParameter() const
Returns the definition of the vehicle / person parameter.
Definition: RORoutable.h:74
ConstROEdgeVector myActiveRoute
The current route.
void addAlternativeDef(const RORouteDef *alternative)
Adds an alternative loaded from the file.
Definition: RORouteDef.cpp:75
double defaultProbability
The probability when being added to a distribution without an explicit probability.
vehicle is a bicycle
std::string getString() const
Returns the current content as a string.
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
void addWalk(const SUMOSAXAttributes &attrs)
add a fully specified walk
SUMOVTypeParameter * myCurrentVType
The currently parsed vehicle type.
int repetitionsDone
The number of times the vehicle was already inserted.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
SUMOVehicleClass vehicleClass
The vehicle&#39;s class.
double myActiveRouteProbability
The probability of the current route.
MsgHandler *const myErrorOutput
Depending on the "ignore-errors" option different outputs are used.
virtual void myEndElement(int element)
Called when a closing tag occurs.
double getLength() const
Returns the length of the edge.
Definition: ROEdge.h:199
void registerLastDepart()
save last depart (only to be used if vehicle is not discarded)
const double DEFAULT_VEH_PROB
int myActiveContainerPlanSize
The number of stages in myActiveContainerPlan.
std::vector< const ROEdge * > ConstROEdgeVector
Definition: ROEdge.h:56
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs)
const std::string & getID() const
Returns the id.
Definition: Named.h:78
std::string myActiveRouteID
The id of the current route.
int myInsertStopEdgesAt
where stop edges can be inserted into the current route (-1 means no insertion)
const std::string DEFAULT_VTYPE_ID
const SUMOTime myBegin
The begin time.
double getOverallProb() const
Returns the sum of the probablities of the contained routes.
Definition: RORouteDef.cpp:398
void closeVehicle()
Ends the processing of a vehicle.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
RORouteDef * getRouteDef(const std::string &name) const
Returns the named route definition.
Definition: RONet.h:298
static double parseWalkPos(SumoXMLAttr attr, const std::string &id, double maxPos, const std::string &val, std::mt19937 *rng=0)
parse departPos or arrivalPos for a walk
std::string parkingarea
(Optional) parking area if one is assigned to the stop
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
virtual bool addVehicleType(SUMOVTypeParameter *type)
Adds a read vehicle type definition to the network.
Definition: RONet.cpp:332
RandomDistributor< SUMOVTypeParameter * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
virtual bool addVehicle(const std::string &id, ROVehicle *veh)
Definition: RONet.cpp:355
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
std::string toTaz
The vehicle&#39;s destination zone (district)
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
RONet & myNet
The current route.
int getNumPredecessors() const
Returns the number of edges connected to this edge.
Definition: ROEdge.cpp:244
bool addVTypeDistribution(const std::string &id, RandomDistributor< SUMOVTypeParameter *> *vehTypeDistribution)
Adds a vehicle type distribution.
Definition: RONet.cpp:345
std::string busstop
(Optional) bus stop if one is assigned to the stop
A vehicle as used by router.
Definition: ROVehicle.h:53
bool addRouteDef(RORouteDef *def)
Definition: RONet.cpp:208
ROPerson * myActivePerson
The plan of the current person.
the edges of a route
std::string routeid
The vehicle&#39;s route id.
double startPos
The stopping position start.
Encapsulated SAX-Attributes.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
const SUMOVehicleParameter::Stop * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Retrieves a stopping place from the network.
Definition: RONet.h:212
std::vector< PlanItem * > & getPlan()
Definition: ROPerson.h:349
void addContainer(const SUMOTime depart, const std::string desc)
Definition: RONet.cpp:401
void parseEdges(const std::string &desc, ConstROEdgeVector &into, const std::string &rid)
Parse edges from strings.
void addStop(const SUMOVehicleParameter::Stop &stopPar, const ROEdge *const stopEdge)
Definition: ROPerson.cpp:113
SUMOTime depart
The vehicle&#39;s departure time.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:42
A person as used by router.
Definition: ROPerson.h:51
void addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
#define POSITION_EPS
Definition: config.h:172
std::string fromTaz
The vehicle&#39;s origin zone (district)
double endPos
The stopping position end.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
vehicle is a passenger car (a "normal" car)
A basic edge for routing applications.
Definition: ROEdge.h:72
const int VEHPARS_FROM_TAZ_SET
void addTrip(const ROEdge *const from, const ROEdge *const to, const SVCPermissions modeSet, const std::string &vTypes, const double departPos, const double arrivalPos, const std::string &busStop, double walkFactor)
Definition: ROPerson.cpp:60
std::string lane
The lane to stop at.
Parser for routes during their loading.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
bool isInternal() const
return whether this edge is an internal edge
Definition: ROEdge.h:144
void closeContainer()
Ends the processing of a container.
vehicle is a bus
stop for vehicles
double departPos
(optional) The position the vehicle shall depart from
static bool checkStopPos(double &startPos, double &endPos, const double laneLength, const double minLength, const bool friendlyPos)
check start and end position of a stop
std::vector< SUMOVehicleParameter::Stop > myActiveRouteStops
List of the stops on the parsed route.
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.
The router&#39;s network representation.
Definition: RONet.h:68
void openRoute(const SUMOSAXAttributes &attrs)
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
const std::string DEFAULT_PEDTYPE_ID
void addWalk(const ConstROEdgeVector &edges, const double duration, const double speed, const double departPos, const double arrivalPos, const std::string &busStop)
Definition: ROPerson.cpp:104
Definition of vehicle stop (position and duration)
bool parseStop(SUMOVehicleParameter::Stop &stop, const SUMOSAXAttributes &attrs, std::string errorSuffix, MsgHandler *const errorOutput)
parses attributes common to all stops
const bool myKeepVTypeDist
whether to keep the the vtype distribution in output
const bool myTryRepair
Information whether routes shall be repaired.
const ConstROEdgeVector & getEdgeVector() const
Returns the list of edges this route consists of.
Definition: RORoute.h:155
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:113
A storage for options typed value containers)
Definition: OptionsCont.h:92
OutputDevice_String * myActiveContainerPlan
The plan of the current container.
Base class for a vehicle&#39;s route definition.
Definition: RORouteDef.h:56
std::string id
The vehicle type&#39;s id.
const ROEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: ROEdge.cpp:334
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
void addLoadedAlternative(RORoute *alternative)
Adds a single alternative loaded from the file An alternative may also be generated during DUA...
Definition: RORouteDef.cpp:69
void closeRoute(const bool mayBeDisconnected=false)
bool wasSet(int what) const
Returns whether the given parameter was set.
void addRide(const ROEdge *const from, const ROEdge *const to, const std::string &lines, double arrivalPos, const std::string &destStop)
Definition: ROPerson.cpp:95
const RGBColor * myActiveRouteColor
The currently parsed route&#39;s color.
double myCurrentCosts
The currently parsed route costs.
virtual ~RORouteHandler()
standard destructor
void addPersonTrip(const SUMOSAXAttributes &attrs)
add a routing request for a walking or intermodal person
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
SUMOVTypeParameter * getVehicleTypeSecure(const std::string &id)
Retrieves the named vehicle type.
Definition: RONet.cpp:277
#define NUMERICAL_EPS
Definition: config.h:148
a single trip definition (used by router)
void closeFlow()
Ends the processing of a flow.
const ROEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself ...
Definition: ROEdge.cpp:253
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition: RONet.h:157
bool addFlow(SUMOVehicleParameter *flow, const bool randomize)
Definition: RONet.cpp:375
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
std::string myActiveRouteRefID
The id of the route the current route references to.
A color information.
bool addPerson(ROPerson *person)
Definition: RONet.cpp:389
void parseFromViaTo(std::string element, const SUMOSAXAttributes &attrs)
Called for parsing from and to and the corresponding taz attributes.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
A complete router&#39;s route.
Definition: RORoute.h:55
An output device that encapsulates an ofstream.
void closeRouteDistribution()
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
std::string id
The vehicle&#39;s id.
RORouteHandler(RONet &net, const std::string &file, const bool tryRepair, const bool emptyDestinationsAllowed, const bool ignoreErrors, const bool checkSchema)
standard constructor