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-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
20 // Parser and container for routes during their loading
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <string>
34 #include <map>
35 #include <vector>
36 #include <microsim/MSRoute.h>
37 #include <microsim/MSEdge.h>
38 #include <microsim/MSJunction.h>
39 #include <microsim/MSVehicleType.h>
40 #include <microsim/MSVehicle.h>
43 #include <microsim/MSLane.h>
44 #include "MSRouteHandler.h"
45 #include "MSTransportableControl.h"
53 #include "MSNet.h"
54 
55 #include "MSParkingArea.h"
56 #include "MSStoppingPlace.h"
57 #include <microsim/MSGlobals.h>
60 
61 
62 // ===========================================================================
63 // static members
64 // ===========================================================================
65 std::mt19937 MSRouteHandler::myParsingRNG;
66 
67 
68 // ===========================================================================
69 // method definitions
70 // ===========================================================================
71 MSRouteHandler::MSRouteHandler(const std::string& file,
72  bool addVehiclesDirectly) :
73  SUMORouteHandler(file),
74  myActivePlan(0),
75  myActiveContainerPlan(0),
76  myAddVehiclesDirectly(addVehiclesDirectly),
77  myCurrentVTypeDistribution(0),
78  myCurrentRouteDistribution(0),
79  myAmLoadingState(false) {
80  myActiveRoute.reserve(100);
81  // check for valid value has been performed in MSFrame
83 }
84 
85 
87 }
88 
89 void
91  MSTransportable::MSTransportablePlan::iterator i;
92  if (myActivePlan != 0) {
93  for (i = myActivePlan->begin(); i != myActivePlan->end(); i++) {
94  delete *i;
95  }
96  delete myActivePlan;
97  myActivePlan = NULL;
98  }
99  if (myActiveContainerPlan != 0) {
100  for (i = myActiveContainerPlan->begin(); i != myActiveContainerPlan->end(); i++) {
101  delete *i;
102  }
103  delete myActiveContainerPlan;
104  myActivePlan = NULL;
105  }
106 }
107 
108 
109 void
110 MSRouteHandler::parseFromViaTo(std::string element,
111  const SUMOSAXAttributes& attrs) {
112  myActiveRoute.clear();
113  bool useTaz = OptionsCont::getOptions().getBool("with-taz");
115  WRITE_WARNING("Taz usage was requested but no taz present in " + element + " '" + myVehicleParameter->id + "'!");
116  useTaz = false;
117  }
118  bool ok = true;
120  const MSEdge* fromTaz = MSEdge::dictionary(myVehicleParameter->fromTaz + "-source");
121  if (fromTaz == 0) {
122  throw ProcessError("Source taz '" + myVehicleParameter->fromTaz + "' not known for " + element + " '" + myVehicleParameter->id + "'!");
123  } else if (fromTaz->getNumSuccessors() == 0) {
124  throw ProcessError("Source taz '" + myVehicleParameter->fromTaz + "' has no outgoing edges for " + element + " '" + myVehicleParameter->id + "'!");
125  } else {
126  myActiveRoute.push_back(fromTaz);
127  }
128  } else {
129  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok, "", true),
130  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
131  }
132  if (!attrs.hasAttribute(SUMO_ATTR_VIA) && !attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
133  myInsertStopEdgesAt = (int)myActiveRoute.size();
134  }
135  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true),
136  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
137  myVehicleParameter->via = StringTokenizer(attrs.getOpt<std::string>(SUMO_ATTR_VIA, myVehicleParameter->id.c_str(), ok, "", true)).getVector();
139  const MSEdge* toTaz = MSEdge::dictionary(myVehicleParameter->toTaz + "-sink");
140  if (toTaz == 0) {
141  throw ProcessError("Sink taz '" + myVehicleParameter->toTaz + "' not known for " + element + " '" + myVehicleParameter->id + "'!");
142  } else if (toTaz->getNumPredecessors() == 0) {
143  throw ProcessError("Sink taz '" + myVehicleParameter->toTaz + "' has no incoming edges for " + element + " '" + myVehicleParameter->id + "'!");
144  } else {
145  myActiveRoute.push_back(toTaz);
146  }
147  } else {
148  MSEdge::parseEdgesList(attrs.getOpt<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok, "", true),
149  myActiveRoute, "for " + element + " '" + myVehicleParameter->id + "'");
150  }
152  if (myVehicleParameter->routeid == "") {
154  }
155 }
156 
157 
158 void
160  const SUMOSAXAttributes& attrs) {
161  SUMORouteHandler::myStartElement(element, attrs);
162  try {
163  switch (element) {
164  case SUMO_TAG_PERSON:
165  if (!MSNet::getInstance()->getVehicleControl().hasVType(myVehicleParameter->vtypeid)) {
166  const std::string error = "The type '" + myVehicleParameter->vtypeid + "' for person '" + myVehicleParameter->id + "' is not known.";
167  delete myVehicleParameter;
168  myVehicleParameter = 0;
169  throw ProcessError(error);
170  }
172  break;
173  case SUMO_TAG_CONTAINER:
175  break;
176  case SUMO_TAG_RIDE: {
177  const std::string pid = myVehicleParameter->id;
178  bool ok = true;
179  MSEdge* from = 0;
180  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, pid.c_str(), ok);
181  StringTokenizer st(desc);
182  std::string bsID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, 0, ok, "");
183  MSStoppingPlace* bs = 0;
184  MSEdge* to = 0;
185  if (bsID != "") {
187  if (bs == 0) {
188  throw ProcessError("Unknown bus stop '" + bsID + "' for person '" + myVehicleParameter->id + "'.");
189  }
190  to = &bs->getLane().getEdge();
191  }
192  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
193  bs == 0 ? -NUMERICAL_EPS : bs->getEndLanePosition());
194  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
195  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, pid.c_str(), ok);
196  from = MSEdge::dictionary(fromID);
197  if (from == 0) {
198  throw ProcessError("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known.");
199  }
200  if (!myActivePlan->empty() && &myActivePlan->back()->getDestination() != from) {
201  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + fromID + "!=" + myActivePlan->back()->getDestination().getID() + ").");
202  }
203  if (myActivePlan->empty()) {
205  *from, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
206  }
207  } else if (myActivePlan->empty()) {
208  throw ProcessError("The start edge for person '" + pid + "' is not known.");
209  }
210  if (to == 0) {
211  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, pid.c_str(), ok);
212  to = MSEdge::dictionary(toID);
213  if (to == 0) {
214  throw ProcessError("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known.");
215  }
216  }
217  myActivePlan->push_back(new MSPerson::MSPersonStage_Driving(*to, bs, arrivalPos, st.getVector()));
218  break;
219  }
220  case SUMO_TAG_TRANSPORT:
221  try {
222  const std::string containerId = myVehicleParameter->id;
223  bool ok = true;
224  MSEdge* from = 0;
225  const std::string desc = attrs.get<std::string>(SUMO_ATTR_LINES, containerId.c_str(), ok);
226  StringTokenizer st(desc);
227  std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, 0, ok, "");
228  MSStoppingPlace* cs = 0;
229  if (csID != "") {
231  if (cs == 0) {
232  throw ProcessError("Unknown container stop '" + csID + "' for container '" + myVehicleParameter->id + "'.");
233  }
234  }
235  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok,
236  cs == 0 ? -NUMERICAL_EPS : cs->getEndLanePosition());
237  if (attrs.hasAttribute(SUMO_ATTR_FROM)) {
238  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, containerId.c_str(), ok);
239  from = MSEdge::dictionary(fromID);
240  if (from == 0) {
241  throw ProcessError("The from edge '" + fromID + "' within a transport of container '" + containerId + "' is not known.");
242  }
243  if (!myActiveContainerPlan->empty() && &myActiveContainerPlan->back()->getDestination() != from) {
244  throw ProcessError("Disconnected plan for container '" + myVehicleParameter->id + "' (" + fromID + "!=" + myActiveContainerPlan->back()->getDestination().getID() + ").");
245  }
246  if (myActiveContainerPlan->empty()) {
248  *from, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
249  }
250  } else if (myActiveContainerPlan->empty()) {
251  throw ProcessError("The start edge within a transport of container '" + containerId + "' is not known.");
252  }
253  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, containerId.c_str(), ok);
254  MSEdge* to = MSEdge::dictionary(toID);
255  if (to == 0) {
256  throw ProcessError("The to edge '" + toID + "' within a transport of container '" + containerId + "' is not known.");
257  }
258  myActiveContainerPlan->push_back(new MSContainer::MSContainerStage_Driving(*to, cs, arrivalPos, st.getVector()));
259 
260  } catch (ProcessError&) {
262  throw;
263  }
264  break;
265  case SUMO_TAG_TRANSHIP: {
266  myActiveRoute.clear();
267  bool ok = true;
268  double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, myVehicleParameter->id.c_str(), ok, 0);
269  double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, myVehicleParameter->id.c_str(), ok, -NUMERICAL_EPS);
270  double speed = DEFAULT_CONTAINER_TRANSHIP_SPEED;
272  // need to check for explicitly set speed since we might have // DEFAULT_VEHTYPE
273  if (vtype != 0 && vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) {
274  speed = vtype->getMaxSpeed();
275  }
276  speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, 0, ok, speed);
277  if (speed <= 0) {
278  throw ProcessError("Non-positive tranship speed for container '" + myVehicleParameter->id + "'.");
279  }
280  std::string csID = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, 0, ok, "");
281  MSStoppingPlace* cs = 0;
282  if (csID != "") {
284  if (cs == 0) {
285  throw ProcessError("Unknown container stop '" + csID + "' for container '" + myVehicleParameter->id + "'.");
286  }
287  arrivalPos = cs->getEndLanePosition();
288  }
289  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
291  } else {
292  if (attrs.hasAttribute(SUMO_ATTR_FROM) && attrs.hasAttribute(SUMO_ATTR_TO)) {
293  const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok);
294  MSEdge* from = MSEdge::dictionary(fromID);
295  if (from == 0) {
296  throw ProcessError("The from edge '" + fromID + "' within a tranship of container '" + myVehicleParameter->id + "' is not known.");
297  }
298  const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok);
299  MSEdge* to = MSEdge::dictionary(toID);
300  if (to == 0) {
301  throw ProcessError("The to edge '" + toID + "' within a tranship of container '" + myVehicleParameter->id + "' is not known.");
302  }
303  //the route of the container's tranship stage consists only of the 'from' and the 'to' edge
304  myActiveRoute.push_back(from);
305  myActiveRoute.push_back(to);
306  if (myActiveRoute.empty()) {
307  const std::string error = "No connection found between '" + from->getID() + "' and '" + to->getID() + "' for container '" + myVehicleParameter->id + "'.";
309  myActiveRoute.push_back(from);
310  } else {
311  WRITE_ERROR(error);
312  }
313  }
314  }
315  }
316  if (myActiveRoute.empty()) {
317  throw ProcessError("No edges to tranship container '" + myVehicleParameter->id + "'.");
318  }
319  if (!myActiveContainerPlan->empty() && &myActiveContainerPlan->back()->getDestination() != myActiveRoute.front()) {
320  throw ProcessError("Disconnected plan for container '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + "!=" + myActiveContainerPlan->back()->getDestination().getID() + ").");
321  }
322  if (myActiveContainerPlan->empty()) {
324  *myActiveRoute.front(), -1, myVehicleParameter->depart, departPos, "start", true));
325  }
326  myActiveContainerPlan->push_back(new MSContainer::MSContainerStage_Tranship(myActiveRoute, cs, speed, departPos, arrivalPos));
327  myActiveRoute.clear();
328  break;
329  }
330  case SUMO_TAG_FLOW:
331  parseFromViaTo("flow", attrs);
332  break;
333  case SUMO_TAG_TRIP:
334  parseFromViaTo("trip", attrs);
335  break;
336  default:
337  break;
338  }
339  } catch (ProcessError&) {
340  delete myVehicleParameter;
341  myVehicleParameter = 0;
342  throw;
343  }
344 }
345 
346 
347 void
349  bool ok = true;
350  myCurrentVTypeDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
351  if (ok) {
353  if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
354  const std::string vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
355  StringTokenizer st(vTypes);
356  while (st.hasNext()) {
357  std::string vtypeID = st.next();
359  if (type == 0) {
360  throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'.");
361  }
363  }
364  }
365  }
366 }
367 
368 
369 void
371  if (myCurrentVTypeDistribution != 0) {
372  if (MSGlobals::gStateLoaded && MSNet::getInstance()->getVehicleControl().hasVTypeDistribution(myCurrentVTypeDistributionID)) {
374  return;
375  }
378  throw ProcessError("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
379  }
380  if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) {
382  throw ProcessError("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
383  }
385  }
386 }
387 
388 
389 void
391  myActiveRoute.clear();
392  myInsertStopEdgesAt = -1;
393  // check whether the id is really necessary
394  std::string rid;
395  if (myCurrentRouteDistribution != 0) {
397  rid = "distribution '" + myCurrentRouteDistributionID + "'";
398  } else if (myVehicleParameter != 0) {
399  // ok, a vehicle is wrapping the route,
400  // we may use this vehicle's id as default
401  myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
402  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
403  WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "').");
404  }
405  } else {
406  bool ok = true;
407  myActiveRouteID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok, false);
408  if (!ok) {
409  return;
410  }
411  rid = "'" + myActiveRouteID + "'";
412  }
413  if (myVehicleParameter != 0) { // have to do this here for nested route distributions
414  rid = "for vehicle '" + myVehicleParameter->id + "'";
415  }
416  bool ok = true;
417  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
418  MSEdge::parseEdgesList(attrs.get<std::string>(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid);
419  }
420  myActiveRouteRefID = attrs.getOpt<std::string>(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, "");
422  WRITE_ERROR("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
423  }
426  myCurrentCosts = attrs.getOpt<double>(SUMO_ATTR_COST, myActiveRouteID.c_str(), ok, -1);
427  if (ok && myCurrentCosts != -1 && myCurrentCosts < 0) {
428  WRITE_ERROR("Invalid cost for route '" + myActiveRouteID + "'.");
429  }
430 }
431 
432 
433 void
436  switch (element) {
437  case SUMO_TAG_VTYPE: {
439  delete myCurrentVType;
440  myCurrentVType = 0;
441  if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) {
442  const std::string id = vehType->getID();
443  delete vehType;
445  throw ProcessError("Another vehicle type (or distribution) with the id '" + id + "' exists.");
446  }
447  } else {
448  if (myCurrentVTypeDistribution != 0) {
450  }
451  }
452  }
453  break;
454  case SUMO_TAG_TRIP:
456  closeRoute(true);
457  closeVehicle();
458  delete myVehicleParameter;
459  myVehicleParameter = 0;
460  myInsertStopEdgesAt = -1;
461  break;
462  default:
463  break;
464  }
465 }
466 
467 
468 void
469 MSRouteHandler::closeRoute(const bool mayBeDisconnected) {
470  std::string type = "vehicle";
471  if (mayBeDisconnected) {
473  type = "flow";
474  } else {
475  type = "trip";
476  }
477  }
478 
479  try {
480  if (myActiveRoute.size() == 0) {
481  delete myActiveRouteColor;
482  myActiveRouteColor = 0;
485  if (route != 0) {
487  route->addReference();
488  }
489  }
490  myActiveRouteID = "";
491  myActiveRouteRefID = "";
492  return;
493  }
494  if (myVehicleParameter != 0) {
495  throw ProcessError("The route for " + type + " '" + myVehicleParameter->id + "' has no edges.");
496  } else {
497  throw ProcessError("Route '" + myActiveRouteID + "' has no edges.");
498  }
499  }
500  if (myActiveRoute.size() == 1 && myActiveRoute.front()->isTazConnector()) {
501  throw ProcessError("The routing information for " + type + " '" + myVehicleParameter->id + "' is insufficient.");
502  }
506  route->setCosts(myCurrentCosts);
507  myActiveRoute.clear();
508  if (!MSRoute::dictionary(myActiveRouteID, route)) {
509  delete route;
511  if (myVehicleParameter != 0) {
512  if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == 0) {
513  throw ProcessError("Another route for " + type + " '" + myVehicleParameter->id + "' exists.");
514  } else {
515  throw ProcessError("A vehicle with id '" + myVehicleParameter->id + "' already exists.");
516  }
517  } else {
518  throw ProcessError("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
519  }
520  }
521  } else {
522  if (myCurrentRouteDistribution != 0) {
524  route->addReference();
525  }
526  }
527  }
528  myActiveRouteID = "";
529  myActiveRouteColor = 0;
530  myActiveRouteStops.clear();
531  } catch (ProcessError&) {
532  delete myVehicleParameter;
533  throw;
534  }
535 }
536 
537 
538 void
540  // check whether the id is really necessary
541  bool ok = true;
542  if (myVehicleParameter != 0) {
543  // ok, a vehicle is wrapping the route,
544  // we may use this vehicle's id as default
545  myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this
546  } else {
547  myCurrentRouteDistributionID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
548  if (!ok) {
549  return;
550  }
551  }
553  std::vector<double> probs;
554  if (attrs.hasAttribute(SUMO_ATTR_PROBS)) {
555  bool ok = true;
556  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_PROBS, myCurrentRouteDistributionID.c_str(), ok));
557  while (st.hasNext()) {
558  probs.push_back(TplConvert::_2doubleSec(st.next().c_str(), 1.0));
559  }
560  }
561  if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
562  bool ok = true;
563  StringTokenizer st(attrs.get<std::string>(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok));
564  int probIndex = 0;
565  while (st.hasNext()) {
566  std::string routeID = st.next();
567  const MSRoute* route = MSRoute::dictionary(routeID, &myParsingRNG);
568  if (route == 0) {
569  throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'.");
570  }
571  const double prob = ((int)probs.size() > probIndex ? probs[probIndex] : 1.0);
572  if (myCurrentRouteDistribution->add(route, prob, false)) {
573  route->addReference();
574  }
575  probIndex++;
576  }
577  if (probs.size() > 0 && probIndex != (int)probs.size()) {
578  WRITE_WARNING("Got " + toString(probs.size()) + " probabilities for " + toString(probIndex) +
579  " routes in routeDistribution '" + myCurrentRouteDistributionID + "'");
580  }
581  }
582 }
583 
584 
585 void
587  if (myCurrentRouteDistribution != 0) {
588  const bool haveSameID = MSRoute::dictionary(myCurrentRouteDistributionID, &myParsingRNG) != 0;
589  if (MSGlobals::gStateLoaded && haveSameID) {
591  return;
592  }
593  if (haveSameID) {
595  throw ProcessError("Another route (or distribution) with the id '" + myCurrentRouteDistributionID + "' exists.");
596  }
599  throw ProcessError("Route distribution '" + myCurrentRouteDistributionID + "' is empty.");
600  }
603  }
604 }
605 
606 
607 void
609  // get nested route
613  // let's check whether this vehicle had to depart before the simulation starts
615  if (route != 0) {
616  route->addReference();
617  route->release();
618  }
619  return;
620  }
621  }
622 
623  // get the vehicle's type
624  MSVehicleType* vtype = 0;
625 
626  try {
627  if (myVehicleParameter->vtypeid != "") {
628  vtype = vehControl.getVType(myVehicleParameter->vtypeid, &myParsingRNG);
629  if (vtype == 0) {
630  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
631  }
632  if (vtype->getVehicleClass() == SVC_PEDESTRIAN) {
633  WRITE_WARNING("Vehicle type '" + vtype->getID() + "' with vClass=pedestrian should only be used for persons and not for vehicle '" + myVehicleParameter->id + "'.");
634  }
635  } else {
636  // there should be one (at least the default one)
637  vtype = vehControl.getVType(DEFAULT_VTYPE_ID, &myParsingRNG);
638  }
640  // if the route id was given, prefer that one
641  if (route != 0 && !myAmLoadingState) {
642  WRITE_WARNING("Ignoring child element 'route' for vehicle '" + myVehicleParameter->id + "' because attribute 'route' is set.");
643  }
645  }
646  if (route == 0) {
647  // nothing found? -> error
648  if (myVehicleParameter->routeid != "") {
649  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
650  } else {
651  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route.");
652  }
653  }
654  myActiveRouteID = "";
655 
656  } catch (ProcessError&) {
657  delete myVehicleParameter;
658  throw;
659  }
660 
661  // try to build the vehicle
662  SUMOVehicle* vehicle = 0;
663  if (vehControl.getVehicle(myVehicleParameter->id) == 0) {
664  try {
665  vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype, !MSGlobals::gCheckRoutes);
666  } catch (const ProcessError& e) {
668  WRITE_WARNING(e.what());
669  vehControl.deleteVehicle(0, true);
670  myVehicleParameter = 0;
671  vehicle = 0;
672  return;
673  } else {
674  throw e;
675  }
676  }
677  // maybe we do not want this vehicle to be inserted due to scaling
678  int quota = myAmLoadingState ? 1 : vehControl.getQuota();
679  if (quota > 0) {
680  vehControl.addVehicle(myVehicleParameter->id, vehicle);
681  for (int i = 1; i < quota; i++) {
684  newPars->id = myVehicleParameter->id + "." + toString(i);
685  vehicle = vehControl.buildVehicle(newPars, route, vtype, !MSGlobals::gCheckRoutes);
686  vehControl.addVehicle(newPars->id, vehicle);
687  }
689  myVehicleParameter = 0;
690  } else {
691  vehControl.deleteVehicle(vehicle, true);
692  myVehicleParameter = 0;
693  vehicle = 0;
694  }
695  } else {
696  // strange: another vehicle with the same id already exists
698  // and was not loaded while loading a simulation state
699  // -> error
700  std::string veh_id = myVehicleParameter->id;
701  delete myVehicleParameter;
702  myVehicleParameter = 0;
703  throw ProcessError("Another vehicle with the id '" + veh_id + "' exists.");
704  } else {
705  // ok, it seems to be loaded previously while loading a simulation state
706  vehicle = 0;
707  }
708  }
709  // check whether the vehicle shall be added directly to the network or
710  // shall stay in the internal buffer
711  if (vehicle != 0) {
712  if (vehicle->getParameter().departProcedure == DEPART_GIVEN) {
714  }
715  }
716 }
717 
718 
719 void
721  if (myActivePlan->size() == 0) {
722  const std::string error = "Person '" + myVehicleParameter->id + "' has no plan.";
723  delete myVehicleParameter;
724  myVehicleParameter = 0;
726  throw ProcessError(error);
727  }
728  // let's check whether this person had to depart before the simulation starts
731  delete myVehicleParameter;
732  myVehicleParameter = 0;
734  return;
735  }
736  // type existence has been checked on opening
739  // @todo: consider myScale?
740  if (MSNet::getInstance()->getPersonControl().add(person)) {
742  } else {
743  ProcessError error("Another person with the id '" + myVehicleParameter->id + "' exists.");
744  delete person;
745  throw error;
746  }
747  myVehicleParameter = 0;
748  myActivePlan = 0;
749 }
750 
751 void
753  if (myActiveContainerPlan->size() == 0) {
754  throw ProcessError("Container '" + myVehicleParameter->id + "' has no plan.");
755  }
757  if (type == 0) {
758  throw ProcessError("The type '" + myVehicleParameter->vtypeid + "' for container '" + myVehicleParameter->id + "' is not known.");
759  }
761  // @todo: consider myScale?
763  if (MSNet::getInstance()->getContainerControl().add(container)) {
765  } else {
766  ProcessError error("Another container with the id '" + myVehicleParameter->id + "' exists.");
767  delete container;
768  throw error;
769  }
770  } else {
771  // warning already given
772  delete container;
773  }
774  myVehicleParameter = 0;
776 }
777 
778 
779 void
781  myInsertStopEdgesAt = -1;
783  delete myVehicleParameter;
784  myVehicleParameter = 0;
785  return;
786  }
787  // let's check whether vehicles had to depart before the simulation starts
790  const SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
794  delete myVehicleParameter;
795  myVehicleParameter = 0;
796  return;
797  }
798  }
799  }
800  if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid, &myParsingRNG) == 0) {
801  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
802  }
805  closeRoute(true);
806  }
808  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for flow '" + myVehicleParameter->id + "' is not known.");
809  }
810  myActiveRouteID = "";
811 
812  // check whether the vehicle shall be added directly to the network or
813  // shall stay in the internal buffer
815  if (MSNet::getInstance()->getInsertionControl().add(myVehicleParameter)) {
817  } else {
818  throw ProcessError("Another flow with the id '" + myVehicleParameter->id + "' exists.");
819  }
820  }
821  myVehicleParameter = 0;
822 }
823 
824 
825 void
827  std::string errorSuffix;
828  if (myActivePlan != 0) {
829  errorSuffix = " in person '" + myVehicleParameter->id + "'.";
830  } else if (myVehicleParameter != 0) {
831  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
832  } else if (myActiveContainerPlan != 0) {
833  errorSuffix = " in container '" + myVehicleParameter->id + "'.";
834  } else {
835  errorSuffix = " in route '" + myActiveRouteID + "'.";
836  }
838  bool ok = parseStop(stop, attrs, errorSuffix, MsgHandler::getErrorInstance());
839  if (!ok) {
840  return;
841  }
842  const MSEdge* edge = 0;
843  // try to parse the assigned bus stop
844  if (stop.busstop != "") {
845  // ok, we have a bus stop
847  if (bs == 0) {
848  WRITE_ERROR("The busStop '" + stop.busstop + "' is not known" + errorSuffix);
849  return;
850  }
851  const MSLane& l = bs->getLane();
852  stop.lane = l.getID();
853  stop.endPos = bs->getEndLanePosition();
854  stop.startPos = bs->getBeginLanePosition();
855  edge = &l.getEdge();
856  } //try to parse the assigned container stop
857  else if (stop.containerstop != "") {
858  // ok, we have obviously a container stop
860  if (cs == 0) {
861  WRITE_ERROR("The containerStop '" + stop.containerstop + "' is not known" + errorSuffix);
862  return;
863  }
864  const MSLane& l = cs->getLane();
865  stop.lane = l.getID();
866  stop.endPos = cs->getEndLanePosition();
867  stop.startPos = cs->getBeginLanePosition();
868  edge = &l.getEdge();
869  } //try to parse the assigned parking area
870  else if (stop.parkingarea != "") {
871  // ok, we have obviously a parking area
873  if (pa == 0) {
874  WRITE_ERROR("The parkingArea '" + stop.parkingarea + "' is not known" + errorSuffix);
875  return;
876  }
877  const MSLane& l = pa->getLane();
878  stop.lane = l.getID();
879  stop.endPos = pa->getEndLanePosition();
880  stop.startPos = pa->getBeginLanePosition();
881  edge = &l.getEdge();
882  } else if (stop.chargingStation != "") {
883  // ok, we have a charging station
885  if (cs != 0) {
886  const MSLane& l = cs->getLane();
887  stop.lane = l.getID();
888  stop.endPos = cs->getEndLanePosition();
889  stop.startPos = cs->getBeginLanePosition();
890  } else {
891  WRITE_ERROR("The chargingStation '" + stop.chargingStation + "' is not known" + errorSuffix);
892  return;
893  }
894  } else {
895  // no, the lane and the position should be given
896  // get the lane
897  stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, 0, ok, "");
898  if (ok && stop.lane != "") {
899  if (MSLane::dictionary(stop.lane) == 0) {
900  WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
901  return;
902  }
903  } else {
904  if (myActivePlan && !myActivePlan->empty()) {
905  const MSStoppingPlace* bs = myActivePlan->back()->getDestinationStop();
906  if (bs != 0) {
907  edge = &bs->getLane().getEdge();
908  stop.lane = bs->getLane().getID();
909  stop.endPos = bs->getEndLanePosition();
910  stop.startPos = bs->getBeginLanePosition();
911  } else {
912  edge = &myActivePlan->back()->getDestination();
913  stop.lane = edge->getLanes()[0]->getID();
914  stop.endPos = myActivePlan->back()->getArrivalPos();
915  stop.startPos = stop.endPos - POSITION_EPS;
916  }
917  } else {
918  WRITE_ERROR("A stop must be placed on a busStop, a chargingStation, a containerStop a parkingArea or a lane" + errorSuffix);
919  return;
920  }
921  }
922  edge = &MSLane::dictionary(stop.lane)->getEdge();
923  if (myActivePlan &&
924  !myActivePlan->empty() &&
925  &myActivePlan->back()->getDestination() != edge) {
926  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + edge->getID() + "!=" + myActivePlan->back()->getDestination().getID() + ").");
927  }
928  if (myActivePlan && myActivePlan->empty()) {
930  *edge, -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
931  }
932  if (myActiveContainerPlan &&
933  !myActiveContainerPlan->empty() &&
934  &myActiveContainerPlan->back()->getDestination() != &MSLane::dictionary(stop.lane)->getEdge()) {
935  throw ProcessError("Disconnected plan for container '" + myVehicleParameter->id + "' (" + MSLane::dictionary(stop.lane)->getEdge().getID() + "!=" + myActiveContainerPlan->back()->getDestination().getID() + ").");
936  }
939  MSLane::dictionary(stop.lane)->getEdge(), -1, myVehicleParameter->depart, myVehicleParameter->departPos, "start", true));
940  }
941  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, 0, ok, MSLane::dictionary(stop.lane)->getLength());
942  if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
943  WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix);
944  stop.endPos = attrs.getOpt<double>(SUMO_ATTR_POSITION, 0, ok, stop.endPos);
945  }
946  stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, 0, ok, MAX2(0., stop.endPos - 2 * POSITION_EPS));
947  const bool friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, 0, ok, false);
948  if (!ok || !checkStopPos(stop.startPos, stop.endPos, MSLane::dictionary(stop.lane)->getLength(), POSITION_EPS, friendlyPos)) {
949  WRITE_ERROR("Invalid start or end position for stop on lane '" + stop.lane + "'" + errorSuffix);
950  return;
951  }
952  }
953  if (myActivePlan != 0) {
954  std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, 0, ok, "waiting");
955  double pos = (stop.startPos + stop.endPos) / 2.;
956  if (!myActivePlan->empty()) {
957  pos = myActivePlan->back()->getArrivalPos();
958  }
960  MSLane::dictionary(stop.lane)->getEdge(), stop.duration, stop.until, pos, actType, false));
961  } else if (myActiveContainerPlan != 0) {
962  std::string actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, 0, ok, "waiting");
964  MSLane::dictionary(stop.lane)->getEdge(), stop.duration, stop.until, stop.startPos, actType, false));
965  } else if (myVehicleParameter != 0) {
966  myVehicleParameter->stops.push_back(stop);
967  } else {
968  myActiveRouteStops.push_back(stop);
969  }
970  if (myInsertStopEdgesAt >= 0) {
971  myActiveRoute.insert(myActiveRoute.begin() + myInsertStopEdgesAt, edge);
973  }
974 }
975 
976 
977 void
978 MSRouteHandler::parseWalkPositions(const SUMOSAXAttributes& attrs, const std::string& personID,
979  const MSEdge* fromEdge, const MSEdge*& toEdge,
980  double& departPos, double& arrivalPos, MSStoppingPlace*& bs,
981  const MSTransportable::Stage* const lastStage, bool& ok) {
982  const std::string description = "person '" + personID + "' walking from " + fromEdge->getID();
983 
984  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
985  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.");
986  }
987  departPos = 0.;
988  if (lastStage->getDestinationStop() != nullptr) {
989  departPos = lastStage->getDestinationStop()->getAccessPos(fromEdge);
990  } else if (&lastStage->getDestination() == fromEdge) {
991  departPos = lastStage->getArrivalPos();
992  } else if (lastStage->getDestination().getToJunction() == fromEdge->getToJunction()) {
993  departPos = fromEdge->getLength();
994  }
995 
996  std::string bsID = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, 0, ok, "");
997  if (bsID != "") {
999  if (bs == 0) {
1000  throw ProcessError("Unknown bus stop '" + bsID + "' for " + description + ".");
1001  }
1002  if (toEdge == 0) {
1003  toEdge = &bs->getLane().getEdge();
1004  }
1005  arrivalPos = bs->getAccessPos(toEdge);
1006  if (arrivalPos < 0) {
1007  throw ProcessError("Bus stop '" + bsID + "' is not connected to arrival edge '" + toEdge->getID() + "' for " + description + ".");
1008  }
1009  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
1010  const double arrPos = SUMOVehicleParserHelper::parseWalkPos(SUMO_ATTR_ARRIVALPOS, description, toEdge->getLength(),
1011  attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, description.c_str(), ok), &myParsingRNG);
1012  if (arrPos >= bs->getBeginLanePosition() && arrPos < bs->getEndLanePosition()) {
1013  arrivalPos = arrPos;
1014  } else {
1015  WRITE_WARNING("Ignoring arrivalPos for " + description + " because it is outside the given stop '" + toString(SUMO_ATTR_BUS_STOP) + "'.");
1016  }
1017  }
1018  } else {
1019  if (toEdge == 0) {
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 = 0.;
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 = 0;
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_BUS) != 0) {
1099  pars.push_back(0);
1100  }
1101  }
1102 
1103  const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, id, ok, -1.);
1104  if (attrs.hasAttribute(SUMO_ATTR_SPEED) && speed <= 0) {
1105  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1106  }
1107  const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, id, ok, OptionsCont::getOptions().getFloat("persontrip.walkfactor"));
1108  const double departPosLat = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS_LAT, 0, ok, 0);
1109  if (ok) {
1110  const std::string error = "No connection found between '" + from->getID() + "' and '" + to->getID() + "' for person '" + myVehicleParameter->id + "'.";
1111  if (modeSet == 0) {
1112  MSNet::getInstance()->getPedestrianRouter().compute(from, to, departPos, arrivalPos, speed > 0 ? speed : pedType->getMaxSpeed(), 0, 0, myActiveRoute);
1113  if (myActiveRoute.empty()) {
1114  if (!MSGlobals::gCheckRoutes) {
1115  myActiveRoute.push_back(from);
1116  myActiveRoute.push_back(to); // pedestrian will teleport
1117  } else {
1118  throw ProcessError(error);
1119  }
1120  }
1121  myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat));
1122  } else {
1123  for (SUMOVehicleParameter* vehPar : pars) {
1124  SUMOVehicle* vehicle = 0;
1125  if (vehPar != 0) {
1126  MSVehicleType* type = MSNet::getInstance()->getVehicleControl().getVType(vehPar->vtypeid);
1127  if (type->getVehicleClass() != SVC_IGNORING && (from->getPermissions() & type->getVehicleClass()) == 0) {
1128  WRITE_WARNING("Ignoring vehicle type '" + type->getID() + "' when routing person '" + myVehicleParameter->id + "' because it is not allowed on the start edge.");
1129  } else {
1130  const MSRoute* const routeDummy = new MSRoute(vehPar->id, ConstMSEdgeVector({ from }), false, 0, std::vector<SUMOVehicleParameter::Stop>());
1131  vehicle = vehControl.buildVehicle(vehPar, routeDummy, type, !MSGlobals::gCheckRoutes);
1132  }
1133  }
1134  bool carUsed = false;
1135  std::vector<MSNet::MSIntermodalRouter::TripItem> result;
1136  if (MSNet::getInstance()->getIntermodalRouter().compute(from, to, departPos, arrivalPos,
1137  pedType->getMaxSpeed() * walkFactor, vehicle, modeSet, myVehicleParameter->depart, result)) {
1138  for (std::vector<MSNet::MSIntermodalRouter::TripItem>::iterator it = result.begin(); it != result.end(); ++it) {
1139  if (!it->edges.empty()) {
1140  bs = MSNet::getInstance()->getStoppingPlace(it->destStop, SUMO_TAG_BUS_STOP);
1141  if (it->line == "") {
1142  const double depPos = myActivePlan->back()->getDestinationStop() != 0 ? myActivePlan->back()->getDestinationStop()->getAccessPos(it->edges.front()) : departPos;
1143  myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, it->edges, bs, duration, speed, depPos, bs != 0 ? bs->getAccessPos(it->edges.back()) : arrivalPos, departPosLat));
1144  } else if (vehicle != 0 && it->line == vehicle->getID()) {
1145  double vehicleArrivalPos = bs != 0 ? bs->getAccessPos(it->edges.back()) : it->edges.back()->getLength();
1146  if (it + 1 == result.end()) {
1147  vehicleArrivalPos = arrivalPos;
1148  }
1149  myActivePlan->push_back(new MSPerson::MSPersonStage_Driving(*it->edges.back(), bs, vehicleArrivalPos, std::vector<std::string>({ it->line })));
1150  vehicle->replaceRouteEdges(it->edges, true);
1151  vehicle->setArrivalPos(vehicleArrivalPos);
1152  vehControl.addVehicle(vehPar->id, vehicle);
1153  carUsed = true;
1154  } else {
1155  myActivePlan->push_back(new MSPerson::MSPersonStage_Driving(*it->edges.back(), bs, bs != 0 ? bs->getAccessPos(it->edges.back()) : arrivalPos, std::vector<std::string>({ it->line })));
1156  }
1157  }
1158  }
1159  } else {
1161  throw ProcessError(error);
1162  }
1163  }
1164  if (vehicle != 0 && !carUsed) {
1165  vehControl.deleteVehicle(vehicle, true);
1166  }
1167  }
1168  }
1169  }
1170  myActiveRoute.clear();
1171 }
1172 
1173 
1174 void
1176  try {
1177  myActiveRoute.clear();
1178  bool ok = true;
1179  const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, 0, ok, -1);
1180  if (attrs.hasAttribute(SUMO_ATTR_DURATION) && duration <= 0) {
1181  throw ProcessError("Non-positive walking duration for '" + myVehicleParameter->id + "'.");
1182  }
1183  double speed = -1; // default to vType speed
1184  if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1185  speed = attrs.get<double>(SUMO_ATTR_SPEED, 0, ok);
1186  if (speed <= 0) {
1187  throw ProcessError("Non-positive walking speed for '" + myVehicleParameter->id + "'.");
1188  }
1189  }
1190  double departPos = 0;
1191  double arrivalPos = 0;
1192  MSStoppingPlace* bs = 0;
1193  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
1194  const std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, myVehicleParameter->id.c_str(), ok);
1195  const MSRoute* route = MSRoute::dictionary(routeID, &myParsingRNG);
1196  if (route == 0) {
1197  throw ProcessError("The route '" + routeID + "' for walk of person '" + myVehicleParameter->id + "' is not known.");
1198  }
1199  myActiveRoute = route->getEdges();
1200  } else {
1202  }
1203  if (myActivePlan->empty()) {
1204  double initialDepartPos = myVehicleParameter->departPos;
1206  initialDepartPos = RandHelper::rand(myActiveRoute.front()->getLength(), &myParsingRNG);
1207  }
1208  myActivePlan->push_back(new MSTransportable::Stage_Waiting(*myActiveRoute.front(), -1, myVehicleParameter->depart, initialDepartPos, "start", true));
1209  }
1210  parseWalkPositions(attrs, myVehicleParameter->id, myActiveRoute.front(), myActiveRoute.back(), departPos, arrivalPos, bs, myActivePlan->back(), ok);
1211  if (myActiveRoute.empty()) {
1212  throw ProcessError("No edges to walk for person '" + myVehicleParameter->id + "'.");
1213  }
1214  if (&myActivePlan->back()->getDestination() != myActiveRoute.front() &&
1215  myActivePlan->back()->getDestination().getToJunction() != myActiveRoute.front()->getFromJunction() &&
1216  myActivePlan->back()->getDestination().getToJunction() != myActiveRoute.front()->getToJunction()) {
1217  if (myActivePlan->back()->getDestinationStop() == 0 || !myActivePlan->back()->getDestinationStop()->hasAccess(myActiveRoute.front())) {
1218  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + " not connected to " + myActivePlan->back()->getDestination().getID() + ").");
1219  }
1220  }
1221  const double departPosLat = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS_LAT, 0, ok, 0);
1222  myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myVehicleParameter->id, myActiveRoute, bs, duration, speed, departPos, arrivalPos, departPosLat));
1223  myActiveRoute.clear();
1224  } catch (ProcessError&) {
1226  throw;
1227  }
1228 }
1229 
1230 
1231 /****************************************************************************/
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:335
static StringBijection< SumoXMLTag > CarFollowModels
car following models
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:75
virtual void myEndElement(int element)
Called when a closing tag occurs.
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:607
ConstMSEdgeVector myActiveRoute
The current route.
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
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:371
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:104
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:863
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.
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:64
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:94
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:167
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:167
T MAX2(T a, T b)
Definition: StdDefs.h:73
MSPedestrianRouterDijkstra & getPedestrianRouter(const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:928
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:744
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:78
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:65
std::string myActiveRouteID
The id of the current route.
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:173
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:569
const MSJunction * getToJunction() const
Definition: MSEdge.h:352
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:199
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
The car-following model and parameter.
Definition: MSVehicleType.h:72
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:64
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:89
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:312
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:776
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:80
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:55
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:66
static bool gCheckRoutes
Definition: MSGlobals.h:85
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:768
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:306
void closeVehicleTypeDistribution()
T get(const std::string &str) const
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:46
double getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
const int VEHPARS_ROUTE_SET
#define POSITION_EPS
Definition: config.h:175
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)
SumoXMLTag myDefaultCFModel
the default car following model
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:205
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:1639
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;.
double compute(const E *from, const E *to, double departPos, double arrivalPos, double speed, SUMOTime msTime, const N *onlyNode, std::vector< const E *> &into, bool allEdges=false)
Builds the route between the given edges using the minimum effort at the given time The definition of...
const MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
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:359
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.
void addReference() const
increments the reference counter for the route
Definition: MSRoute.cpp:98
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
const MSEdge & getDestination() const
returns the destination edge
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.
long long int SUMOTime
Definition: TraCIDefs.h:51
#define NUMERICAL_EPS
Definition: config.h:151
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.
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:77
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:801
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:117