SUMO - Simulation of Urban MObility
MSRouteHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-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 <microsim/MSRoute.h>
31 #include <microsim/MSEdge.h>
32 #include <microsim/MSJunction.h>
33 #include <microsim/MSVehicleType.h>
34 #include <microsim/MSVehicle.h>
37 #include <microsim/MSLane.h>
38 #include "MSRouteHandler.h"
39 #include "MSTransportableControl.h"
49 #include "MSNet.h"
50 
51 #include "MSParkingArea.h"
52 #include "MSStoppingPlace.h"
53 #include <microsim/MSGlobals.h>
56 
57 
58 // ===========================================================================
59 // static members
60 // ===========================================================================
61 std::mt19937 MSRouteHandler::myParsingRNG;
62 
63 
64 // ===========================================================================
65 // method definitions
66 // ===========================================================================
67 MSRouteHandler::MSRouteHandler(const std::string& file,
68  bool addVehiclesDirectly) :
69  SUMORouteHandler(file, addVehiclesDirectly ? "" : "routes"),
70  myActivePlan(0),
71  myActiveContainerPlan(0),
72  myAddVehiclesDirectly(addVehiclesDirectly),
73  myCurrentVTypeDistribution(0),
74  myCurrentRouteDistribution(0),
75  myAmLoadingState(false) {
76  myActiveRoute.reserve(100);
77 }
78 
79 
81 }
82 
83 void
85  MSTransportable::MSTransportablePlan::iterator i;
86  if (myActivePlan != 0) {
87  for (i = myActivePlan->begin(); i != myActivePlan->end(); i++) {
88  delete *i;
89  }
90  delete myActivePlan;
91  myActivePlan = NULL;
92  }
93  if (myActiveContainerPlan != 0) {
94  for (i = myActiveContainerPlan->begin(); i != myActiveContainerPlan->end(); i++) {
95  delete *i;
96  }
97  delete myActiveContainerPlan;
98  myActivePlan = NULL;
99  }
100 }
101 
102 
103 void
104 MSRouteHandler::parseFromViaTo(std::string element,
105  const SUMOSAXAttributes& attrs) {
106  myActiveRoute.clear();
107  bool useTaz = OptionsCont::getOptions().getBool("with-taz");
109  WRITE_WARNING("Taz usage was requested but no taz present in " + element + " '" + myVehicleParameter->id + "'!");
110  useTaz = false;
111  }
112  bool ok = true;
114  const MSEdge* fromTaz = MSEdge::dictionary(myVehicleParameter->fromTaz + "-source");
115  if (fromTaz == 0) {
116  throw ProcessError("Source taz '" + myVehicleParameter->fromTaz + "' not known for " + element + " '" + myVehicleParameter->id + "'!");
117  } else if (fromTaz->getNumSuccessors() == 0) {
118  throw ProcessError("Source taz '" + myVehicleParameter->fromTaz + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
119  } else {
120  myActiveRoute.push_back(fromTaz);
121  }
122  } else {
123  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok, "", true),
124  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
125  }
126  if (!attrs.hasAttribute(SUMO_ATTR_VIA) && !attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
127  myInsertStopEdgesAt = (int)myActiveRoute.size();
128  }
129  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true),
130  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
131  myVehicleParameter->via = StringTokenizer(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true)).getVector();
133  const MSEdge* toTaz = MSEdge::dictionary(myVehicleParameter->toTaz + "-sink");
134  if (toTaz == 0) {
135  throw ProcessError("Sink taz '" + myVehicleParameter->toTaz + "' not known for " + element + " '" + myVehicleParameter->id + "'!");
136  } else if (toTaz->getNumPredecessors() == 0) {
137  throw ProcessError("Sink taz '" + myVehicleParameter->toTaz + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
138  } else {
139  myActiveRoute.push_back(toTaz);
140  }
141  } else {
142  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
143  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
144  }
146  if (myVehicleParameter->routeid == "") {
148  }
149 }
150 
151 
152 void
154  const SUMOSAXAttributes& attrs) {
155  SUMORouteHandler::myStartElement(element, attrs);
156  try {
157  switch (element) {
158  case SUMO_TAG_PERSON:
159  if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
160  const std::string error = "The type '" + myVehicleParameter->vtypeid + "' for person '" + myVehicleParameter->id + "' is not known.";
161  delete myVehicleParameter;
162  myVehicleParameter = 0;
163  throw ProcessError(error);
164  }
166  break;
167  case SUMO_TAG_CONTAINER:
169  break;
170  case SUMO_TAG_RIDE: {
171  const std::string pid = myVehicleParameter->id;
172  bool ok = true;
173  MSEdge* from = 0;
174  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
175  StringTokenizer st(desc);
176  std::string bsID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, 0, ok, "");
177  MSStoppingPlace* bs = 0;
178  MSEdge* to = 0;
179  if (bsID != "") {
181  if (bs == 0) {
182  throw ProcessError("Unknown bus stop '" + bsID + "' for person '" + myVehicleParameter->id + "'.");
183  }
184  to = &bs->getLane().getEdge();
185  }
186  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
187  bs == 0 ? -NUMERICAL_EPS : bs->getEndLanePosition());
188  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
189  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, pid.c_str(), ok);
190  from = MSEdge::dictionary(fromID);
191  if (from == 0) {
192  throw ProcessError("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known.");
193  }
194  if (!myActivePlan->empty() && myActivePlan->back()->getDestination() != from) {
195  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + fromID + "!=" + myActivePlan->back()->getDestination()->getID() + ").");
196  }
197  if (myActivePlan->empty()) {
199  from, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
200  }
201  } else if (myActivePlan->empty()) {
202  throw ProcessError("The start edge for person '" + pid + "' is not known.");
203  }
204  if (to == 0) {
205  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, pid.c_str(), ok);
206  to = MSEdge::dictionary(toID);
207  if (to == 0) {
208  throw ProcessError("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known.");
209  }
210  }
211  const std::string intendedVeh = attrs.getOpt<std::string>(SUMO_ATTR_INTENDED, 0, ok, "");
212  const SUMOTime intendedDepart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DEPART, 0, ok, -1);
213  myActivePlan->push_back(new MSPerson::MSPersonStage_Driving(to, bs, arrivalPos, st.getVector(), intendedVeh, intendedDepart));
214  break;
215  }
216  case SUMO_TAG_TRANSPORT:
217  try {
218  const std::string containerId = myVehicleParameter->id;
219  bool ok = true;
220  MSEdge* from = 0;
221  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, containerId.c_str(), ok);
222  StringTokenizer st(desc);
223  std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, 0, ok, "");
224  MSStoppingPlace* cs = 0;
225  if (csID != "") {
227  if (cs == 0) {
228  throw ProcessError("Unknown container stop '" + csID + "' for container '" + myVehicleParameter->id + "'.");
229  }
230  }
231  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
232  cs == 0 ? -NUMERICAL_EPS : cs->getEndLanePosition());
233  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
234  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, containerId.c_str(), ok);
235  from = MSEdge::dictionary(fromID);
236  if (from == 0) {
237  throw ProcessError("The from edge '" + fromID + "' within a transport of container '" + containerId + "' is not known.");
238  }
239  if (!myActiveContainerPlan->empty() && myActiveContainerPlan->back()->getDestination() != from) {
240  throw ProcessError("Disconnected plan for container '" + myVehicleParameter->id + "' (" + fromID + "!=" + myActiveContainerPlan->back()->getDestination()->getID() + ").");
241  }
242  if (myActiveContainerPlan->empty()) {
244  from, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
245  }
246  } else if (myActiveContainerPlan->empty()) {
247  throw ProcessError("The start edge within a transport of container '" + containerId + "' is not known.");
248  }
249  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, containerId.c_str(), ok);
250  MSEdge* to = MSEdge::dictionary(toID);
251  if (to == 0) {
252  throw ProcessError("The to edge '" + toID + "' within a transport of container '" + containerId + "' is not known.");
253  }
254  myActiveContainerPlan->push_back(new MSContainer::MSContainerStage_Driving(to, cs, arrivalPos, st.getVector()));
255 
256  } catch (ProcessError&) {
258  throw;
259  }
260  break;
261  case SUMO_TAG_TRANSHIP: {
262  myActiveRoute.clear();
263  bool ok = true;
264  double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, myVehicleParameter->id.c_str(), ok, 0);
265  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok, -NUMERICAL_EPS);
266  double speed = DEFAULT_CONTAINER_TRANSHIP_SPEED;
268  // need to check for explicitly set speed since we might have // DEFAULT_VEHTYPE
269  if (vtype != 0 && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) {
270  speed = vtype->getMaxSpeed();
271  }
272  speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, 0, ok, speed);
273  if (speed <= 0) {
274  throw ProcessError("Non-positive tranship speed for container '" + myVehicleParameter->id + "'.");
275  }
276  std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, 0, ok, "");
277  MSStoppingPlace* cs = 0;
278  if (csID != "") {
280  if (cs == 0) {
281  throw ProcessError("Unknown container stop '" + csID + "' for container '" + myVehicleParameter->id + "'.");
282  }
283  arrivalPos = cs->getEndLanePosition();
284  }
285  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
287  } else {
288  if (attrs.hasAttribute(SUMO_ATTR_FROM) && attrs.hasAttribute(SUMO_ATTR_TO)) {
289  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok);
290  MSEdge* from = MSEdge::dictionary(fromID);
291  if (from == 0) {
292  throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + myVehicleParameter->id + "' is not known.");
293  }
294  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok);
295  MSEdge* to = MSEdge::dictionary(toID);
296  if (to == 0) {
297  throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + myVehicleParameter->id + "' is not known.");
298  }
299  //the route of the container's tranship stage consists only of the 'from' and the 'to' edge
300  myActiveRoute.push_back(from);
301  myActiveRoute.push_back(to);
302  if (myActiveRoute.empty()) {
303  const std::string error = "No connection found between '" + from->getID() + "' and '" + to->getID() + "' for container '" + myVehicleParameter->id + "'.";
305  myActiveRoute.push_back(from);
306  } else {
307  WRITE_ERROR(error);
308  }
309  }
310  }
311  }
312  if (myActiveRoute.empty()) {
313  throw ProcessError("No edges to tranship container '" + myVehicleParameter->id + "'.");
314  }
315  if (!myActiveContainerPlan->empty() && myActiveContainerPlan->back()->getDestination() != myActiveRoute.front()) {
316  throw ProcessError("Disconnected plan for container '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + "!=" + myActiveContainerPlan->back()->getDestination()->getID() + ").");
317  }
318  if (myActiveContainerPlan->empty()) {
320  myActiveRoute.front(), -1, myVehicleParameter->depart, departPos, "start", true));
321  }
322  myActiveContainerPlan->push_back(new MSContainer::MSContainerStage_Tranship(myActiveRoute, cs, speed, departPos, arrivalPos));
323  myActiveRoute.clear();
324  break;
325  }
326  case SUMO_TAG_FLOW:
327  parseFromViaTo("flow", attrs);
328  break;
329  case SUMO_TAG_TRIP:
330  parseFromViaTo("trip", attrs);
331  break;
332  default:
333  break;
334  }
335  } catch (ProcessError&) {
336  delete myVehicleParameter;
337  myVehicleParameter = 0;
338  throw;
339  }
340 }
341 
342 
343 void
345  bool ok = true;
346  myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
347  if (ok) {
349  if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
350  const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
351  StringTokenizer st(vTypes);
352  while (st.hasNext()) {
353  std::string vtypeID = st.next();
355  if (type == 0) {
356  throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
357  }
359  }
360  }
361  }
362 }
363 
364 
365 void
367  if (myCurrentVTypeDistribution != 0) {
368  if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
370  return;
371  }
374  throw ProcessError("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
375  }
376  if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
378  throw ProcessError("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
379  }
381  }
382 }
383 
384 
385 void
387  myActiveRoute.clear();
388  myInsertStopEdgesAt = -1;
389  // check whether the id is really necessary
390  std::string rid;
391  if (myCurrentRouteDistribution != 0) {
393  rid = "distribution '" + myCurrentRouteDistributionID + "'";
394  } else if (myVehicleParameter != 0) {
395  // ok, a vehicle is wrapping the route,
396  // we may use this vehicle's id as default
397  myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
398  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
399  WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "').");
400  }
401  } else {
402  bool ok = true;
403  myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok, false);
404  if (!ok) {
405  return;
406  }
407  rid = "'" + myActiveRouteID + "'";
408  }
409  if (myVehicleParameter != 0) { // have to do this here for nested route distributions
410  rid = "for vehicle '" + myVehicleParameter->id + "'";
411  }
412  bool ok = true;
413  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
414  MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
415  }
416  myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
418  WRITE_ERROR("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
419  }
422  myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
423  if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
424  WRITE_ERROR("Invalid cost for route '" + myActiveRouteID + "'.");
425  }
426 }
427 
428 
429 void
432  switch (element) {
433  case SUMO_TAG_VTYPE: {
435  delete myCurrentVType;
436  myCurrentVType = 0;
437  if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
438  const std::string id = vehType->getID();
439  delete vehType;
441  throw ProcessError("Another vehicle type (or distribution) with the id '" + id + "' exists.");
442  }
443  } else {
444  if (myCurrentVTypeDistribution != 0) {
446  }
447  }
448  }
449  break;
450  case SUMO_TAG_TRIP:
452  closeRoute(true);
453  closeVehicle();
454  delete myVehicleParameter;
455  myVehicleParameter = 0;
456  myInsertStopEdgesAt = -1;
457  break;
458  default:
459  break;
460  }
461 }
462 
463 
464 void
465 MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
466  std::string type = "vehicle";
467  if (mayBeDisconnected) {
469  type = "flow";
470  } else {
471  type = "trip";
472  }
473  }
474 
475  try {
476  if (myActiveRoute.size() == 0) {
477  delete myActiveRouteColor;
478  myActiveRouteColor = 0;
481  if (route != 0) {
483  route->addReference();
484  }
485  }
486  myActiveRouteID = "";
487  myActiveRouteRefID = "";
488  return;
489  }
490  if (myVehicleParameter != 0) {
491  throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
492  } else {
493  throw ProcessError("Route '" + myActiveRouteID + "' has no edges.");
494  }
495  }
496  if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
497  throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
498  }
502  route->setCosts(myCurrentCosts);
503  myActiveRoute.clear();
504  if (!MSRoute::dictionary(myActiveRouteID, route)) {
505  delete route;
507  if (myVehicleParameter != 0) {
508  if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == 0) {
509  throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
510  } else {
511  throw ProcessError("A vehicle with id '" + myVehicleParameter->id + "' already exists.");
512  }
513  } else {
514  throw ProcessError("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
515  }
516  }
517  } else {
518  if (myCurrentRouteDistribution != 0) {
520  route->addReference();
521  }
522  }
523  }
524  myActiveRouteID = "";
525  myActiveRouteColor = 0;
526  myActiveRouteStops.clear();
527  } catch (ProcessError&) {
528  delete myVehicleParameter;
529  throw;
530  }
531 }
532 
533 
534 void
536  // check whether the id is really necessary
537  bool ok = true;
538  if (myVehicleParameter != 0) {
539  // ok, a vehicle is wrapping the route,
540  // we may use this vehicle's id as default
541  myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
542  } else {
543  myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
544  if (!ok) {
545  return;
546  }
547  }
549  std::vector<double> probs;
550  if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
551  bool ok = true;
552  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
553  while (st.hasNext()) {
554  probs.push_back(TplConvert::_2doubleSec(st.next().c_str(), 1.0));
555  }
556  }
557  if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
558  bool ok = true;
559  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
560  int probIndex = 0;
561  while (st.hasNext()) {
562  std::string routeID = st.next();
563  const MSRoute* route = MSRoute::dictionary(routeID, &myParsingRNG);
564  if (route == 0) {
565  throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
566  }
567  const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
568  if (myCurrentRouteDistribution->add(route, prob, false)) {
569  route->addReference();
570  }
571  probIndex++;
572  }
573  if (probs.size() > 0 && probIndex != (int)probs.size()) {
574  WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
575  " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
576  }
577  }
578 }
579 
580 
581 void
583  if (myCurrentRouteDistribution != 0) {
584  const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != 0;
585  if (MSGlobals::gStateLoaded && haveSameID) {
587  return;
588  }
589  if (haveSameID) {
591  throw ProcessError("Another route (or distribution) with the id '" + myCurrentRouteDistributionID + "' exists.");
592  }
595  throw ProcessError("Route distribution '" + myCurrentRouteDistributionID + "' is empty.");
596  }
599  }
600 }
601 
602 
603 void
605  // get nested route
609  // let's check whether this vehicle had to depart before the simulation starts
611  if (route != 0) {
612  route->addReference();
613  route->release();
614  }
615  return;
616  }
617  }
618 
619  // get the vehicle's type
620  MSVehicleType* vtype = 0;
621 
622  try {
623  if (myVehicleParameter->vtypeid != "") {
624  vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
625  if (vtype == 0) {
626  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
627  }
628  if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
629  WRITE_WARNING("Vehicle type '" + vtype->getID() + "' with vClass=pedestrian should only be used for persons and not for vehicle '" + myVehicleParameter->id + "'.");
630  }
631  } else {
632  // there should be one (at least the default one)
633  vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
634  }
636  // if the route id was given, prefer that one
637  if (route != 0 && !myAmLoadingState) {
638  WRITE_WARNING("Ignoring child element 'route' for vehicle '" + myVehicleParameter->id + "' because attribute 'route' is set.");
639  }
641  }
642  if (route == 0) {
643  // nothing found? -> error
644  if (myVehicleParameter->routeid != "") {
645  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
646  } else {
647  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route.");
648  }
649  }
650  myActiveRouteID = "";
651 
652  } catch (ProcessError&) {
653  delete myVehicleParameter;
654  throw;
655  }
656 
657  // try to build the vehicle
658  SUMOVehicle* vehicle = 0;
659  if (vehControl.getVehicle(myVehicleParameter->id) == 0) {
660  try {
661  vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes);
662  } catch (const ProcessError& e) {
664  WRITE_WARNING(e.what());
665  vehControl.deleteVehicle(0, true);
666  myVehicleParameter = 0;
667  vehicle = 0;
668  return;
669  } else {
670  throw e;
671  }
672  }
673  const SUMOTime origDepart = myVehicleParameter->depart;
674  // maybe we do not want this vehicle to be inserted due to scaling
675  int quota = myAmLoadingState ? 1 : vehControl.getQuota();
676  if (quota > 0) {
679  vehControl.addVehicle(myVehicleParameter->id, vehicle);
680  for (int i = 1; i < quota; i++) {
683  newPars->id = myVehicleParameter->id + "." + toString(i);
685  vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes);
686  vehControl.addVehicle(newPars->id, vehicle);
687  }
688  myVehicleParameter = 0;
689  } else {
690  vehControl.deleteVehicle(vehicle, true);
691  myVehicleParameter = 0;
692  vehicle = 0;
693  }
694  } else {
695  // strange: another vehicle with the same id already exists
697  // and was not loaded while loading a simulation state
698  // -> error
699  std::string veh_id = myVehicleParameter->id;
700  delete myVehicleParameter;
701  myVehicleParameter = 0;
702  throw ProcessError("Another vehicle with the id '" + veh_id + "' exists.");
703  } else {
704  // ok, it seems to be loaded previously while loading a simulation state
705  vehicle = 0;
706  }
707  }
708  // check whether the vehicle shall be added directly to the network or
709  // shall stay in the internal buffer
710  if (vehicle != 0) {
711  if (vehicle->getParameter().departProcedure == DEPART_GIVEN) {
713  }
714  }
715 }
716 
717 
718 void
720  if (myActivePlan->size() == 0) {
721  const std::string error = "Person '" + myVehicleParameter->id + "' has no plan.";
722  delete myVehicleParameter;
723  myVehicleParameter = 0;
725  throw ProcessError(error);
726  }
727  // let's check whether this person had to depart before the simulation starts
730  delete myVehicleParameter;
731  myVehicleParameter = 0;
733  return;
734  }
735  // type existence has been checked on opening
738  // @todo: consider myScale?
739  if (MSNet::getInstance()->getPersonControl().add(person)) {
741  } else {
742  ProcessError error("Another person with the id '" + myVehicleParameter->id + "' exists.");
743  delete person;
744  throw error;
745  }
746  myVehicleParameter = 0;
747  myActivePlan = 0;
748 }
749 
750 void
752  if (myActiveContainerPlan->size() == 0) {
753  throw ProcessError("Container '" + myVehicleParameter->id + "' has no plan.");
754  }
756  if (type == 0) {
757  throw ProcessError("The type '" + myVehicleParameter->vtypeid + "' for container '" + myVehicleParameter->id + "' is not known.");
758  }
760  // @todo: consider myScale?
762  if (MSNet::getInstance()->getContainerControl().add(container)) {
764  } else {
765  ProcessError error("Another container with the id '" + myVehicleParameter->id + "' exists.");
766  delete container;
767  throw error;
768  }
769  } else {
770  // warning already given
771  delete container;
772  }
773  myVehicleParameter = 0;
775 }
776 
777 
778 void
780  myInsertStopEdgesAt = -1;
782  delete myVehicleParameter;
783  myVehicleParameter = 0;
784  return;
785  }
786  // let's check whether vehicles had to depart before the simulation starts
789  const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
793  delete myVehicleParameter;
794  myVehicleParameter = 0;
795  return;
796  }
797  }
798  }
799  if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == 0) {
800  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
801  }
804  closeRoute(true);
805  }
807  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
808  }
809  myActiveRouteID = "";
810 
811  // check whether the vehicle shall be added directly to the network or
812  // shall stay in the internal buffer
814  if (MSNet::getInstance()->getInsertionControl().addFlow(myVehicleParameter)) {
816  } else {
817  throw ProcessError("Another flow with the id '" + myVehicleParameter->id + "' exists.");
818  }
819  }
820  myVehicleParameter = 0;
821 }
822 
823 
824 void
826  std::string errorSuffix;
827  if (myActivePlan != 0) {
828  errorSuffix = " in person '" + myVehicleParameter->id + "'.";
829  } else if (myVehicleParameter != 0) {
830  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
831  } else if (myActiveContainerPlan != 0) {
832  errorSuffix = " in container '" + myVehicleParameter->id + "'.";
833  } else {
834  errorSuffix = " in route '" + myActiveRouteID + "'.";
835  }
837  bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
838  if (!ok) {
839  return;
840  }
841  const MSEdge* edge = 0;
842  // try to parse the assigned bus stop
843  if (stop.busstop != "") {
844  // ok, we have a bus stop
846  if (bs == 0) {
847  WRITE_ERROR("The busStop '" + stop.busstop + "' is not known" + errorSuffix);
848  return;
849  }
850  const MSLane& l = bs->getLane();
851  stop.lane = l.getID();
852  stop.endPos = bs->getEndLanePosition();
853  stop.startPos = bs->getBeginLanePosition();
854  edge = &l.getEdge();
855  } //try to parse the assigned container stop
856  else if (stop.containerstop != "") {
857  // ok, we have obviously a container stop
859  if (cs == 0) {
860  WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known" + errorSuffix);
861  return;
862  }
863  const MSLane& l = cs->getLane();
864  stop.lane = l.getID();
865  stop.endPos = cs->getEndLanePosition();
866  stop.startPos = cs->getBeginLanePosition();
867  edge = &l.getEdge();
868  } //try to parse the assigned parking area
869  else if (stop.parkingarea != "") {
870  // ok, we have obviously a parking area
872  if (pa == 0) {
873  WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known" + errorSuffix);
874  return;
875  }
876  const MSLane& l = pa->getLane();
877  stop.lane = l.getID();
878  stop.endPos = pa->getEndLanePosition();
879  stop.startPos = pa->getBeginLanePosition();
880  edge = &l.getEdge();
881  } else if (stop.chargingStation != "") {
882  // ok, we have a charging station
884  if (cs != 0) {
885  const MSLane& l = cs->getLane();
886  stop.lane = l.getID();
887  stop.endPos = cs->getEndLanePosition();
888  stop.startPos = cs->getBeginLanePosition();
889  } else {
890  WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known" + errorSuffix);
891  return;
892  }
893  } else {
894  // no, the lane and the position should be given
895  // get the lane
896  stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, 0, ok, "");
897  if (ok && stop.lane != "") {
898  if (MSLane::dictionary(stop.lane) == 0) {
899  WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
900  return;
901  }
902  } else {
903  if (myActivePlan && !myActivePlan->empty()) {
904  const MSStoppingPlace* bs = myActivePlan->back()->getDestinationStop();
905  if (bs != 0) {
906  edge = &bs->getLane().getEdge();
907  stop.lane = bs->getLane().getID();
908  stop.endPos = bs->getEndLanePosition();
909  stop.startPos = bs->getBeginLanePosition();
910  } else {
911  edge = myActivePlan->back()->getDestination();
912  stop.lane = edge->getLanes()[0]->getID();
913  stop.endPos = myActivePlan->back()->getArrivalPos();
914  stop.startPos = stop.endPos - POSITION_EPS;
915  }
916  } else {
917  WRITE_ERROR("A stop must be placed on a busStop, a chargingStation, a containerStop a parkingArea or a lane" + errorSuffix);
918  return;
919  }
920  }
921  edge = &MSLane::dictionary(stop.lane)->getEdge();
922  if (myActivePlan &&
923  !myActivePlan->empty() &&
924  myActivePlan->back()->getDestination() != edge) {
925  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + edge->getID() + "!=" + myActivePlan->back()->getDestination()->getID() + ").");
926  }
927  if (myActivePlan && myActivePlan->empty()) {
929  edge, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
930  }
931  if (myActiveContainerPlan &&
932  !myActiveContainerPlan->empty() &&
933  myActiveContainerPlan->back()->getDestination() != &MSLane::dictionary(stop.lane)->getEdge()) {
934  throw ProcessError("Disconnected plan for container '" + myVehicleParameter->id + "' (" + MSLane::dictionary(stop.lane)->getEdge().getID() + "!=" + myActiveContainerPlan->back()->getDestination()->getID() + ").");
935  }
938  &MSLane::dictionary(stop.lane)->getEdge(), -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
939  }
940  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, 0, ok, MSLane::dictionary(stop.lane)->getLength());
941  if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
942  WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix);
943  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, 0, ok, stop.endPos);
944  }
945  stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, 0, ok, MAX2(0., stop.endPos - 2 * POSITION_EPS));
946  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, 0, ok, false);
947  if (!ok || !checkStopPos(stop.startPos, stop.endPos, MSLane::dictionary(stop.lane)->getLength(), POSITION_EPS, friendlyPos)) {
948  WRITE_ERROR("Invalid start or end position for stop on lane '" + stop.lane + "'" + errorSuffix);
949  return;
950  }
951  }
952  if (myActivePlan != 0) {
953  std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, 0, ok, "waiting");
954  double pos = (stop.startPos + stop.endPos) / 2.;
955  if (!myActivePlan->empty()) {
956  pos = myActivePlan->back()->getArrivalPos();
957  }
959  &MSLane::dictionary(stop.lane)->getEdge(), stop.duration, stop.until, pos, actType, false));
960  } else if (myActiveContainerPlan != 0) {
961  std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, 0, ok, "waiting");
963  &MSLane::dictionary(stop.lane)->getEdge(), stop.duration, stop.until, stop.startPos, actType, false));
964  } else if (myVehicleParameter != 0) {
965  myVehicleParameter->stops.push_back(stop);
966  } else {
967  myActiveRouteStops.push_back(stop);
968  }
969  if (myInsertStopEdgesAt >= 0) {
970  myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
972  }
973 }
974 
975 
976 void
977 MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
978  const MSEdge* fromEdge, const MSEdge*& toEdge,
979  double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
980  const MSTransportable::Stage* const lastStage, bool& ok) {
981  const std::string description = "person '" + personID + "' walking from " + fromEdge->getID();
982 
983  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
984  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.");
985  }
986  departPos = 0.;
987  if (lastStage->getDestinationStop() != nullptr) {
988  departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge);
989  } else if (lastStage->getDestination() == fromEdge) {
990  departPos = lastStage->getArrivalPos();
991  } else if (lastStage->getDestination()->getToJunction() == fromEdge->getToJunction()) {
992  departPos = fromEdge->getLength();
993  }
994 
995  std::string bsID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, 0, ok, "");
996  if (bsID != "") {
998  if (bs == nullptr) {
999  throw ProcessError("Unknown bus stop '" + bsID + "' for " + description + ".");
1000  }
1001  if (toEdge != nullptr) {
1002  arrivalPos = bs->getAccessPos(toEdge);
1003  if (arrivalPos < 0) {
1004  throw ProcessError("Bus stop '" + bsID + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1005  }
1006  }
1007  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1008  const double length = toEdge != nullptr ? toEdge->getLength() : bs->getLane().getLength();
1009  const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, description, length,
1010  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1011  if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1012  arrivalPos = arrPos;
1013  } else {
1014  WRITE_WARNING("Ignoring arrivalPos for " + description + " because it is outside the given stop '" + toString(SUMO_ATTR_BUS_STOP) + "'.");
1015  arrivalPos = bs->getAccessPos(&bs->getLane().getEdge());
1016  }
1017  }
1018  } else {
1019  if (toEdge == nullptr) {
1020  throw ProcessError("No destination edge for " + description + ".");
1021  }
1022  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1023  arrivalPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, description, toEdge->getLength(),
1024  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1025  } else {
1026  arrivalPos = toEdge->getLength() / 2.;
1027  }
1028  }
1029 }
1030 
1031 
1032 void
1034  myActiveRoute.clear();
1035  bool ok = true;
1037  const char* const id = myVehicleParameter->id.c_str();
1038  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, id, ok, -1);
1039  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1040  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1041  }
1042  const MSVehicleType* pedType = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
1043  const std::string fromID = attrs.getOpt<std::string>(SUMO_ATTR_FROM, id, ok, "");
1044  const MSEdge* from = fromID != "" || myActivePlan->empty() ? MSEdge::dictionary(fromID) : myActivePlan->back()->getDestination();
1045  if (from == 0) {
1046  throw ProcessError("The from edge '" + fromID + "' within a walk of person '" + myVehicleParameter->id + "' is not known.");
1047  }
1048  const std::string toID = attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "");
1049  const MSEdge* to = MSEdge::dictionary(toID);
1050  if (toID != "" && to == 0) {
1051  throw ProcessError("The to edge '" + toID + "' within a walk of person '" + myVehicleParameter->id + "' is not known.");
1052  }
1053  double departPos = 0;
1054  double arrivalPos = 0;
1055  MSStoppingPlace* bs = nullptr;
1056  if (myActivePlan->empty()) {
1057  double initialDepartPos = myVehicleParameter->departPos;
1059  initialDepartPos = RandHelper::rand(from->getLength(), &myParsingRNG);
1060  }
1061  myActivePlan->push_back(new MSTransportable::Stage_Waiting(from, -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1062  }
1063  parseWalkPositions(attrs, myVehicleParameter->id, from, to, departPos, arrivalPos, bs, myActivePlan->back(), ok);
1064 
1065  const std::string modes = attrs.getOpt<std::string>(SUMO_ATTR_MODES, id, ok, "");
1066  SVCPermissions modeSet = 0;
1067  for (StringTokenizer st(modes); st.hasNext();) {
1068  const std::string mode = st.next();
1069  if (mode == "car") {
1070  modeSet |= SVC_PASSENGER;
1071  } else if (mode == "bicycle") {
1072  modeSet |= SVC_BICYCLE;
1073  } else if (mode == "public") {
1074  modeSet |= SVC_BUS;
1075  } else {
1076  throw InvalidArgument("Unknown person mode '" + mode + "'.");
1077  }
1078  }
1079  const std::string types = attrs.getOpt<std::string>(SUMO_ATTR_VTYPES, id, ok, "");
1080  std::vector<SUMOVehicleParameter*> pars;
1081  for (StringTokenizer st(types); st.hasNext();) {
1082  pars.push_back(new SUMOVehicleParameter());
1083  pars.back()->vtypeid = st.next();
1084  pars.back()->parametersSet |= VEHPARS_VTYPE_SET;
1085  pars.back()->departProcedure = DEPART_TRIGGERED;
1086  MSVehicleType* type = vehControl.getVType(pars.back()->vtypeid);
1087  if (type == 0) {
1088  throw InvalidArgument("The vehicle type '" + pars.back()->vtypeid + "' in a trip for person '" + myVehicleParameter->id + "' is not known.");
1089  }
1090  pars.back()->id = myVehicleParameter->id + "_" + toString(pars.size() - 1);
1091  modeSet |= SVC_PASSENGER;
1092  }
1093  if (pars.empty()) {
1094  if ((modeSet & SVC_PASSENGER) != 0) {
1095  pars.push_back(new SUMOVehicleParameter());
1096  pars.back()->id = myVehicleParameter->id + "_0";
1097  pars.back()->departProcedure = DEPART_TRIGGERED;
1098  } else if ((modeSet & SVC_BICYCLE) != 0) {
1099  pars.push_back(new SUMOVehicleParameter());
1100  pars.back()->vtypeid = DEFAULT_BIKETYPE_ID;
1101  pars.back()->id = myVehicleParameter->id + "_b0";
1102  pars.back()->departProcedure = DEPART_TRIGGERED;
1103  } else {
1104  // allow shortcut via busStop even when not intending to ride
1105  pars.push_back(nullptr);
1106  }
1107  }
1108 
1109  const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1110  if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1111  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1112  }
1113  const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1114  const double departPosLat = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS_LAT, 0, ok, 0);
1115  if (ok) {
1116  const std::string error = "No connection found between '" + from->getID() + "' and '" + (bs != nullptr ? bs->getID() : to->getID()) + "' for person '" + myVehicleParameter->id + "'.";
1117  for (SUMOVehicleParameter* vehPar : pars) {
1118  SUMOVehicle* vehicle = nullptr;
1119  if (vehPar != nullptr) {
1120  MSVehicleType* type = MSNet::getInstance()->getVehicleControl().getVType(vehPar->vtypeid);
1121  if (type->getVehicleClass() != SVC_IGNORING && (from->getPermissions() & type->getVehicleClass()) == 0) {
1122  WRITE_WARNING("Ignoring vehicle type '" + type->getID() + "' when routing person '" + myVehicleParameter->id + "' because it is not allowed on the start edge.");
1123  } else {
1124  const MSRoute* const routeDummy = new MSRoute(vehPar->id, ConstMSEdgeVector({ from }), false, 0, std::vector<SUMOVehicleParameter::Stop>());
1125  vehicle = vehControl.buildVehicle(vehPar, routeDummy, type, !MSGlobals::gCheckRoutes);
1126  }
1127  }
1128  bool carUsed = false;
1129  std::vector<MSNet::MSIntermodalRouter::TripItem> result;
1130  if (MSNet::getInstance()->getIntermodalRouter().compute(from, to, departPos, arrivalPos, bs == nullptr ? "" : bs->getID(),
1131  pedType->getMaxSpeed() * walkFactor, vehicle, modeSet, myVehicleParameter->depart, result)) {
1132  for (std::vector<MSNet::MSIntermodalRouter::TripItem>::iterator it = result.begin(); it != result.end(); ++it) {
1133  if (!it->edges.empty()) {
1134  bs = MSNet::getInstance()->getStoppingPlace(it->destStop, SUMO_TAG_BUS_STOP);
1135  double localArrivalPos = bs != nullptr ? bs->getAccessPos(it->edges.back()) : it->edges.back()->getLength() / 2.;
1136  if (it + 1 == result.end() && attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1137  localArrivalPos = arrivalPos;
1138  }
1139  if (it->line == "") {
1140  const double depPos = myActivePlan->back()->getDestinationStop() != nullptr ? myActivePlan->back()->getDestinationStop()->getAccessPos(it->edges.front()) : departPos;
1141  myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, it->edges, bs, duration, speed, depPos, localArrivalPos, departPosLat));
1142  } else if (vehicle != nullptr && it->line == vehicle->getID()) {
1143  if (bs == nullptr && it + 1 != result.end()) {
1144  // we have no defined endpoint and are in the middle of the trip, drive as far as possible
1145  localArrivalPos = it->edges.back()->getLength();
1146  }
1147  myActivePlan->push_back(new MSPerson::MSPersonStage_Driving(it->edges.back(), bs, localArrivalPos, std::vector<std::string>({ it->line })));
1148  vehicle->replaceRouteEdges(it->edges, "person:" + myVehicleParameter->id, true);
1149  vehicle->setArrivalPos(localArrivalPos);
1150  vehControl.addVehicle(vehPar->id, vehicle);
1151  carUsed = true;
1152  } else {
1154  it->edges.back(), bs, localArrivalPos, std::vector<std::string>({ it->line }), it->intended, TIME2STEPS(it->depart)));
1155  }
1156  }
1157  }
1158  } else {
1160  throw ProcessError(error);
1161  } else {
1162  myActiveRoute.push_back(from);
1163  myActiveRoute.push_back(to); // pedestrian will teleport
1164  myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat));
1165  }
1166  }
1167  if (vehicle != 0 && !carUsed) {
1168  vehControl.deleteVehicle(vehicle, true);
1169  }
1170  }
1171  }
1172  myActiveRoute.clear();
1173 }
1174 
1175 
1176 void
1178  try {
1179  myActiveRoute.clear();
1180  bool ok = true;
1181  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, 0, ok, -1);
1182  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1183  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1184  }
1185  double speed = -1; // default to vType speed
1186  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1187  speed = attrs.get<double>(SUMO_ATTR_SPEED, 0, ok);
1188  if (speed <= 0) {
1189  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1190  }
1191  }
1192  double departPos = 0;
1193  double arrivalPos = 0;
1194  MSStoppingPlace* bs = 0;
1195  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1196  const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1197  const MSRoute* route = MSRoute::dictionary(routeID, &myParsingRNG);
1198  if (route == 0) {
1199  throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1200  }
1201  myActiveRoute = route->getEdges();
1202  } else {
1204  }
1205  if (myActivePlan->empty()) {
1206  double initialDepartPos = myVehicleParameter->departPos;
1208  initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1209  }
1210  myActivePlan->push_back(new MSTransportable::Stage_Waiting(myActiveRoute.front(), -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1211  }
1212  parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActivePlan->back(), ok);
1213  if (myActiveRoute.empty()) {
1214  throw ProcessError("No edges to walk for person '" + myVehicleParameter->id + "'.");
1215  }
1216  if (myActivePlan->back()->getDestination() != myActiveRoute.front() &&
1217  myActivePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getFromJunction() &&
1218  myActivePlan->back()->getDestination()->getToJunction() != myActiveRoute.front()->getToJunction()) {
1219  if (myActivePlan->back()->getDestinationStop() == 0 || myActivePlan->back()->getDestinationStop()->getAccessPos(myActiveRoute.front()) < 0.) {
1220  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActivePlan->back()->getDestination()->getID() + ").");
1221  }
1222  }
1223  const double departPosLat = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS_LAT, 0, ok, 0);
1224  myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat));
1225  myActiveRoute.clear();
1226  } catch (ProcessError&) {
1228  throw;
1229  }
1230 }
1231 
1232 
1233 /****************************************************************************/
The departure is person triggered.
void addStop(const SUMOSAXAttributes &attrs)
Processing of a stop.
const int VTYPEPARS_MAXSPEED_SET
const int VEHPARS_TO_TAZ_SET
MSRouteHandler(const std::string &file, bool addVehiclesDirectly)
standard constructor
double getAccessPos(const MSEdge *edge) const
the position on the given edge which is connected to this stop, -1 on failure
int getNumPredecessors() const
Returns the number of edges this edge is connected to.
Definition: MSEdge.h:329
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.
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:617
ConstMSEdgeVector myActiveRoute
The current route.
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
long long int SUMOTime
Definition: SUMOTime.h:36
const int VEHPARS_FORCE_REROUTE
double getBeginLanePosition() const
Returns the begin position of this stop.
void parseFromViaTo(std::string element, const SUMOSAXAttributes &attrs)
Called for parsing from and to and the corresponding taz attributes.
description of a vehicle type
RandomDistributor< const MSRoute * > * myCurrentRouteDistribution
The currently parsed distribution of routes (probability->route)
The time is given.
is a pedestrian
std::string next()
static double _2doubleSec(const E *const data, double def)
converts a 0-terminated char-type array into the double value described by it
Definition: TplConvert.h:365
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.
std::string vtypeid
The vehicle&#39;s type id.
virtual void closeVehicle()
Ends the processing of a vehicle.
void release() const
deletes the route if there are no further references to it
Definition: MSRoute.cpp:98
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:841
a flow definition (used by router)
A lane area vehicles can halt at.
Represents a generic random distribution.
bool myAddVehiclesDirectly
Information whether vehicles shall be directly added to the network or kept within the buffer...
SUMOTime duration
The stopping duration.
SUMOVehicleParameter * myVehicleParameter
Parameter of the current vehicle, trip, person, container or flow.
const MSEdge * getDestination() const
returns the destination edge
vehicle is a bicycle
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
double repetitionProbability
The probability for emitting a vehicle per second.
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:61
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
static bool gStateLoaded
Information whether a state has been loaded.
Definition: MSGlobals.h:88
int parametersSet
Information for the router which parameter were set, TraCI may modify this (whe changing color) ...
SUMOVTypeParameter * myCurrentVType
The currently parsed vehicle type.
void closePerson()
Ends the processing of a person.
int repetitionsDone
The number of times the vehicle was already inserted.
int getQuota(double frac=-1) const
Returns the number of instances of the current vehicle that shall be emitted considering that "frac" ...
void openRoute(const SUMOSAXAttributes &attrs)
double myActiveRouteProbability
The probability of the current route.
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:162
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:160
T MAX2(T a, T b)
Definition: StdDefs.h:76
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:507
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn&#39;t already in the dictionary...
Definition: MSEdge.cpp:742
const std::string DEFAULT_BIKETYPE_ID
SUMOTime until
The time at which the vehicle may continue its journey.
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:72
void registerLastDepart()
save last depart (only to be used if vehicle is not discarded)
const double DEFAULT_VEH_PROB
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void addWalk(const SUMOSAXAttributes &attrs)
add a fully specified walk
const std::string & getID() const
Returns the id.
Definition: Named.h:69
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
std::string myActiveRouteID
The id of the current route.
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:167
int myInsertStopEdgesAt
where stop edges can be inserted into the current route (-1 means no insertion)
double getLength() const
return the length of the edge
Definition: MSEdge.h:563
const MSJunction * getToJunction() const
Definition: MSEdge.h:346
const std::string DEFAULT_VTYPE_ID
The position is chosen randomly.
void parseWalkPositions(const SUMOSAXAttributes &attrs, const std::string &personID, const MSEdge *fromEdge, const MSEdge *&toEdge, double &departPos, double &arrivalPos, MSStoppingPlace *&bs, const MSTransportable::Stage *const lastStage, bool &ok)
@ brief parse depart- and arrival positions of a walk
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
virtual MSTransportable * buildContainer(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan) const
Builds a new container.
static MSVehicleType * build(SUMOVTypeParameter &from)
Builds the microsim vehicle type described by the given parameter.
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
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
The car-following model and parameter.
Definition: MSVehicleType.h:66
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
std::string toTaz
The vehicle&#39;s destination zone (district)
bool wasSet(int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:83
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int getNumSuccessors() const
Returns the number of edges that may be reached from this edge.
Definition: MSEdge.h:307
void addPersonTrip(const SUMOSAXAttributes &attrs)
add a routing request for a walking or intermodal person
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:756
double getDefaultProbability() const
Get the default probability of this vehicle type.
std::string busstop
(Optional) bus stop if one is assigned to the stop
A road/street connecting two junctions.
Definition: MSEdge.h:75
std::vector< MSTransportable::Stage * > MSTransportablePlan
the structure holding the plan of a transportable
double getEndLanePosition() const
Returns the end position of this stop.
RandomDistributor< MSVehicleType * > * myCurrentVTypeDistribution
The currently parsed distribution of vehicle types (probability->vehicle type)
the edges of a route
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
void closeRouteDistribution()
std::string routeid
The vehicle&#39;s route id.
const std::vector< double > & getProbs() const
Returns the probabilities assigned to the members of the distribution.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
static bool gCheckRoutes
Definition: MSGlobals.h:79
double startPos
The stopping position start.
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
Encapsulated SAX-Attributes.
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:748
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
std::string chargingStation
(Optional) charging station if one is assigned to the stop
void deleteActivePlans()
delete already created MSTransportablePlans if error occurs before handing over responsibility to a M...
void closeContainer()
Ends the processing of a container.
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:309
void closeVehicleTypeDistribution()
const double DEFAULT_CONTAINER_TRANSHIP_SPEED
SUMOTime depart
The vehicle&#39;s departure time.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
double getArrivalPos() const
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:42
double getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
const int VEHPARS_ROUTE_SET
#define POSITION_EPS
Definition: config.h:172
std::string fromTaz
The vehicle&#39;s origin zone (district)
double endPos
The stopping position end.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
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)
const int VEHPARS_FROM_TAZ_SET
MSTransportable::MSTransportablePlan * myActivePlan
The plan of the current person.
std::string lane
The lane to stop at.
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, std::mt19937 *rng=0)
Returns the named vehicle type or a sample from the named distribution.
Parser for routes during their loading.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
std::string myCurrentRouteDistributionID
The id of the currently parsed route distribution.
std::vector< std::string > getVector()
void openRouteDistribution(const SUMOSAXAttributes &attrs)
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:248
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
virtual void myEndElement(int element)
Called when a closing tag occurs.
vehicle is a bus
double departPos
(optional) The position the vehicle shall depart from
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:1708
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.
Structure representing possible vehicle parameter.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
bool myAmLoadingState
whether a state file is being loaded
static std::mt19937 myParsingRNG
A random number generator used to choose from vtype/route distributions and computing the speed facto...
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:362
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle&#39;s parameter (including departure definition)
std::string myCurrentVTypeDistributionID
The id of the currently parsed vehicle type distribution.
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.
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 std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:94
void addReference() const
increments the reference counter for the route
Definition: MSRoute.cpp:92
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
bool wasSet(int what) const
Returns whether the given parameter was set.
const int VEHPARS_VTYPE_SET
const RGBColor * myActiveRouteColor
The currently parsed route&#39;s color.
double myCurrentCosts
The currently parsed route costs.
virtual MSTransportable * buildPerson(const SUMOVehicleParameter *pars, MSVehicleType *vtype, MSTransportable::MSTransportablePlan *plan, std::mt19937 *rng) const
Builds a new person.
#define NUMERICAL_EPS
Definition: config.h:148
virtual ~MSRouteHandler()
standard destructor
a single trip definition (used by router)
void openVehicleTypeDistribution(const SUMOSAXAttributes &attrs)
The class responsible for building and deletion of vehicles.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true)
Builds a vehicle, increases the number of built vehicles.
const MSLane & getLane() const
Returns the lane this stop is located at.
SUMOTime computeRandomDepartOffset() const
compute (optional) random offset to the departure time
bool add(T val, double prob, bool checkDuplicates=true)
Adds a value with an assigned probability to the distribution.
void add(SUMOVehicle *veh)
Adds a single vehicle for departure.
bool checkLastDepart()
Checks whether the route file is sorted by departure time if needed.
std::string myActiveRouteRefID
The id of the route the current route references to.
Representation of a lane in the micro simulation.
Definition: MSLane.h:71
A color information.
static void parseEdgesList(const std::string &desc, ConstMSEdgeVector &into, const std::string &rid)
Parses the given string assuming it contains a list of edge ids divided by spaces.
Definition: MSEdge.cpp:799
vehicles ignoring classes
void closeRoute(const bool mayBeDisconnected=false)
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
void closeFlow()
Ends the processing of a flow.
MSTransportable::MSTransportablePlan * myActiveContainerPlan
The plan of the current container.
std::string id
The vehicle&#39;s id.
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:111