SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RORouteHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Parser and container for routes during their loading
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
35 #include <map>
36 #include <vector>
37 #include <iostream>
47 #include "RONet.h"
48 #include "RORouteHandler.h"
49 
50 #ifdef CHECK_MEMORY_LEAKS
51 #include <foreign/nvwa/debug_new.h>
52 #endif // CHECK_MEMORY_LEAKS
53 
54 
55 // ===========================================================================
56 // method definitions
57 // ===========================================================================
58 RORouteHandler::RORouteHandler(RONet& net, const std::string& file,
59  const bool tryRepair) :
60  SUMORouteHandler(file),
61  myNet(net),
62  myActivePlan(0),
63  myTryRepair(tryRepair),
64  myCurrentVTypeDistribution(0),
65  myCurrentAlternatives(0) {
66  myActiveRoute.reserve(100);
67 }
68 
69 
71 }
72 
73 
74 void
76  const SUMOSAXAttributes& attrs) {
77  SUMORouteHandler::myStartElement(element, attrs);
78  switch (element) {
79  case SUMO_TAG_PERSON:
80  myActivePlan = new OutputDevice_String(false, 1);
81  break;
82  case SUMO_TAG_RIDE: {
84  (*myActivePlan) << attrs;
85  myActivePlan->closeTag(true);
86  break;
87  }
88  case SUMO_TAG_WALK: {
90  (*myActivePlan) << attrs;
91  myActivePlan->closeTag(true);
92  break;
93  }
94  case SUMO_TAG_FLOW:
97  bool ok = true;
99  myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'");
101  myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'");
102  closeRoute();
103  }
104  break;
105  case SUMO_TAG_TRIP: {
106  bool ok = true;
109  myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'");
111  myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'");
112  } else {
113  const ROEdge* fromTaz = myNet.getEdge(myVehicleParameter->fromTaz + "-source");
114  if (fromTaz == 0) {
115  WRITE_ERROR("Source district '" + myVehicleParameter->fromTaz + "' not known for '" + myVehicleParameter->id + "'!");
116  } else if (fromTaz->getNoFollowing() == 0) {
117  WRITE_ERROR("Source district '" + myVehicleParameter->fromTaz + "' has no outgoing edges for '" + myVehicleParameter->id + "'!");
118  } else {
119  myActiveRoute.push_back(fromTaz->getFollower(0));
120  }
121  }
122  closeRoute();
123  closeVehicle();
124  }
125  break;
126  default:
127  break;
128  }
129  // parse embedded vtype information
130  if (myCurrentVType != 0 && element != SUMO_TAG_VTYPE) {
132  return;
133  }
134 }
135 
136 
137 void
139  bool ok = true;
141  if (ok) {
143  if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
144  const std::string vTypes = attrs.getStringReporting(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok);
145  StringTokenizer st(vTypes);
146  while (st.hasNext()) {
148  myCurrentVTypeDistribution->add(1., type);
149  }
150  }
151  }
152 }
153 
154 
155 void
157  if (myCurrentVTypeDistribution != 0) {
160  WRITE_ERROR("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty.");
163  WRITE_ERROR("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists.");
164  }
166  }
167 }
168 
169 
170 void
172  // check whether the id is really necessary
173  std::string rid;
174  if (myCurrentAlternatives != 0) {
176  rid = "distribution '" + myCurrentAlternatives->getID() + "'";
177  } else if (myVehicleParameter != 0) {
178  // ok, a vehicle is wrapping the route,
179  // we may use this vehicle's id as default
180  myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this
181  if (attrs.hasAttribute(SUMO_ATTR_ID)) {
182  WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "').");
183  }
184  } else {
185  bool ok = true;
186  myActiveRouteID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok, false);
187  if (!ok) {
188  return;
189  }
190  rid = "'" + myActiveRouteID + "'";
191  }
192  if (myVehicleParameter != 0) { // have to do this here for nested route distributions
193  rid = "for vehicle '" + myVehicleParameter->id + "'";
194  }
195  bool ok = true;
196  if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
198  }
201  WRITE_ERROR("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + ".");
202  }
205 }
206 
207 
208 void
211  switch (element) {
212  case SUMO_TAG_VTYPE: {
214  if (myCurrentVTypeDistribution != 0) {
216  }
217  }
218  myCurrentVType = 0;
219  }
220  break;
221  default:
222  break;
223  }
224 }
225 
226 
227 void
229  if (myActiveRoute.size() == 0) {
230  if (myActiveRouteRefID != "" && myCurrentAlternatives != 0) {
232  myActiveRouteID = "";
233  myActiveRouteRefID = "";
234  return;
235  }
236  if (myVehicleParameter != 0) {
237  throw ProcessError("Vehicle's '" + myVehicleParameter->id + "' route has no edges.");
238  } else {
239  throw ProcessError("Route '" + myActiveRouteID + "' has no edges.");
240  }
241  }
244  myActiveRoute.clear();
245  if (myCurrentAlternatives == 0) {
246  if (myNet.getRouteDef(myActiveRouteID) != 0) {
247  delete route;
248  if (myVehicleParameter != 0) {
249  throw ProcessError("Another route for vehicle '" + myVehicleParameter->id + "' exists.");
250  } else {
251  throw ProcessError("Another route (or distribution) with the id '" + myActiveRouteID + "' exists.");
252  }
253  } else {
258  }
259  } else {
261  }
262  myActiveRouteID = "";
263  myActiveRouteStops.clear();
264 }
265 
266 
267 void
269  // check whether the id is really necessary
270  bool ok = true;
271  std::string id;
272  if (myVehicleParameter != 0) {
273  // ok, a vehicle is wrapping the route,
274  // we may use this vehicle's id as default
275  id = "!" + myVehicleParameter->id; // !!! document this
276  } else {
277  id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
278  if (!ok) {
279  return;
280  }
281  }
282  // try to get the index of the last element
283  int index = attrs.getIntReporting(SUMO_ATTR_LAST, id.c_str(), ok);
284  if (ok && index < 0) {
285  WRITE_ERROR("Negative index of a route alternative (id='" + id + "').");
286  return;
287  }
288  // build the alternative cont
289  myCurrentAlternatives = new RORouteDef(id, index, false);
290  if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) {
291  ok = true;
292  StringTokenizer st(attrs.getStringReporting(SUMO_ATTR_ROUTES, id.c_str(), ok));
293  while (st.hasNext()) {
294  const std::string routeID = st.next();
295  const RORouteDef* route = myNet.getRouteDef(routeID);
296  if (route == 0) {
297  throw ProcessError("Unknown route '" + routeID + "' in distribution '" + id + "'.");
298  }
300  }
301  }
302 }
303 
304 
305 void
307  if (myCurrentAlternatives != 0) {
309  WRITE_ERROR("Route distribution '" + myCurrentAlternatives->getID() + "' is empty.");
310  delete myCurrentAlternatives;
311  } else if (!myNet.addRouteDef(myCurrentAlternatives)) {
312  WRITE_ERROR("Another route (or distribution) with the id '" + myCurrentAlternatives->getID() + "' exists.");
313  delete myCurrentAlternatives;
314  }
316  }
317 }
318 
319 
320 void
322  // get the vehicle id
323  if (myVehicleParameter->depart < string2time(OptionsCont::getOptions().getString("begin"))) {
324  return;
325  }
326  // get vehicle type
328  // get the route
330  if (route == 0) {
331  route = myNet.getRouteDef("!" + myVehicleParameter->id);
332  }
333  if (route == 0) {
334  WRITE_ERROR("The route of the vehicle '" + myVehicleParameter->id + "' is not known.");
335  return;
336  }
337  // build the vehicle
338  if (!MsgHandler::getErrorInstance()->wasInformed()) {
339  ROVehicle* veh = new ROVehicle(*myVehicleParameter, route, type);
341  }
342 }
343 
344 
345 void
348  delete myVehicleParameter;
349  myVehicleParameter = 0;
350  delete myActivePlan;
351  myActivePlan = 0;
352 }
353 
354 
355 void
357  /* // @todo: consider myScale?
358  // let's check whether vehicles had to depart before the simulation starts
359  myVehicleParameter->repetitionsDone = 0;
360  SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart;
361  while (myVehicleParameter->repetitionsDone * myVehicleParameter->repetitionOffset < offsetToBegin) {
362  myVehicleParameter->repetitionsDone++;
363  if (myVehicleParameter->repetitionsDone == myVehicleParameter->repetitionNumber) {
364  return;
365  }
366  }
367  if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid) == 0) {
368  throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
369  }
370  if (MSRoute::dictionary("!" + myVehicleParameter->id) == 0) {
371  // if not, try via the (hopefully) given route-id
372  if (MSRoute::dictionary(myVehicleParameter->routeid) == 0) {
373  if (myVehicleParameter->routeid != "") {
374  throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known.");
375  } else {
376  throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route.");
377  }
378  }
379  } else {
380  myVehicleParameter->routeid = "!" + myVehicleParameter->id;
381  }
382  myActiveRouteID = "";
383 
384  // check whether the vehicle shall be added directly to the network or
385  // shall stay in the internal buffer
386  if (myAddVehiclesDirectly || checkLastDepart()) {
387  MSNet::getInstance()->getInsertionControl().add(myVehicleParameter);
388  registerLastDepart();
389  }
390  myVehicleParameter = 0;*/
391 }
392 
393 
394 void
396  /*bool ok = true;
397  std::string errorSuffix;
398  if (myActiveRouteID != "") {
399  errorSuffix = " in route '" + myActiveRouteID + "'.";
400  } else if (myActivePlan) {
401  errorSuffix = " in person '" + myVehicleParameter->id + "'.";
402  } else {
403  errorSuffix = " in vehicle '" + myVehicleParameter->id + "'.";
404  }
405  SUMOVehicleParameter::Stop stop;
406  // try to parse the assigned bus stop
407  stop.busstop = attrs.getOptStringReporting(SUMO_ATTR_BUS_STOP, 0, ok, "");
408  if (stop.busstop != "") {
409  // ok, we have obviously a bus stop
410  MSBusStop* bs = MSNet::getInstance()->getBusStop(stop.busstop);
411  if (bs != 0) {
412  const MSLane& l = bs->getLane();
413  stop.lane = l.getID();
414  stop.endPos = bs->getEndLanePosition();
415  stop.startPos = bs->getBeginLanePosition();
416  } else {
417  WRITE_ERROR("The bus stop '" + stop.busstop + "' is not known" + errorSuffix);
418  return;
419  }
420  } else {
421  // no, the lane and the position should be given
422  // get the lane
423  stop.lane = attrs.getOptStringReporting(SUMO_ATTR_LANE, 0, ok, "");
424  if (ok && stop.lane != "") {
425  if (MSLane::dictionary(stop.lane) == 0) {
426  WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix);
427  return;
428  }
429  } else {
430  WRITE_ERROR("A stop must be placed on a bus stop or a lane" + errorSuffix);
431  return;
432  }
433  if (myActivePlan &&
434  !myActivePlan->empty() &&
435  &myActivePlan->back()->getDestination() != &MSLane::dictionary(stop.lane)->getEdge()) {
436  throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + MSLane::dictionary(stop.lane)->getEdge().getID() + "!=" + myActivePlan->back()->getDestination().getID() + ").");
437  }
438  stop.endPos = attrs.getOptSUMORealReporting(SUMO_ATTR_ENDPOS, 0, ok, MSLane::dictionary(stop.lane)->getLength());
439  if (attrs.hasAttribute(SUMO_ATTR_POSITION)) {
440  WRITE_WARNING("eprecated attribute 'pos' in description of stop" + errorSuffix);
441  stop.endPos = attrs.getOptSUMORealReporting(SUMO_ATTR_POSITION, 0, ok, stop.endPos);
442  }
443  stop.startPos = attrs.getOptSUMORealReporting(SUMO_ATTR_STARTPOS, 0, ok, stop.endPos - 2 * POSITION_EPS);
444  const bool friendlyPos = attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS, 0, ok, false);
445  if (!ok || !checkStopPos(stop.startPos, stop.endPos, MSLane::dictionary(stop.lane)->getLength(), POSITION_EPS, friendlyPos)) {
446  WRITE_ERROR("Invalid start or end position for stop" + errorSuffix);
447  return;
448  }
449  }
450 
451  // get the standing duration
452  if (!attrs.hasAttribute(SUMO_ATTR_DURATION) && !attrs.hasAttribute(SUMO_ATTR_UNTIL)) {
453  stop.triggered = attrs.getOptBoolReporting(SUMO_ATTR_TRIGGERED, 0, ok, true);
454  stop.duration = -1;
455  stop.until = -1;
456  } else {
457  stop.duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, 0, ok, -1);
458  stop.until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, 0, ok, -1);
459  if (!ok || (stop.duration < 0 && stop.until < 0)) {
460  WRITE_ERROR("Invalid duration or end time is given for a stop" + errorSuffix);
461  return;
462  }
463  stop.triggered = attrs.getOptBoolReporting(SUMO_ATTR_TRIGGERED, 0, ok, false);
464  }
465  stop.parking = attrs.getOptBoolReporting(SUMO_ATTR_PARKING, 0, ok, stop.triggered);
466  if (!ok) {
467  WRITE_ERROR("Invalid bool for 'triggered' or 'parking' for stop" + errorSuffix);
468  return;
469  }
470  const std::string idx = attrs.getOptStringReporting(SUMO_ATTR_INDEX, 0, ok, "end");
471  if (idx == "end") {
472  stop.index = STOP_INDEX_END;
473  } else if (idx == "fit") {
474  stop.index = STOP_INDEX_FIT;
475  } else {
476  stop.index = attrs.getIntReporting(SUMO_ATTR_INDEX, 0, ok);
477  if (!ok || stop.index < 0) {
478  WRITE_ERROR("Invalid 'index' for stop" + errorSuffix);
479  return;
480  }
481  }
482  if (myActiveRouteID != "") {
483  myActiveRouteStops.push_back(stop);
484  } else if (myActivePlan) {
485  myActivePlan->push_back(new MSPerson::MSPersonStage_Waiting(MSLane::dictionary(stop.lane)->getEdge(), stop.duration, stop.until));
486  } else {
487  myVehicleParameter->stops.push_back(stop);
488  }*/
489 }
490 
491 
492 void
493 RORouteHandler::parseEdges(const std::string& desc, std::vector<const ROEdge*>& into,
494  const std::string& rid) {
495  StringTokenizer st(desc);
496  while (st.hasNext()) {
497  const std::string id = st.next();
498  const ROEdge* edge = myNet.getEdge(id);
499  // check whether the edge exists
500  if (edge == 0) {
501  throw ProcessError("The edge '" + id + "' within the route " + rid + " is not known."
502  + "\n The route can not be build.");
503  }
504  into.push_back(edge);
505  }
506 }
507 
508 
509 /****************************************************************************/