SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSBaseVehicle.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // A base class for vehicle implementations
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
12 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
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 <iostream>
34 #include <cassert>
35 #include <utils/common/StdDefs.h>
39 #include "MSVehicleType.h"
40 #include "MSEdge.h"
41 #include "MSLane.h"
42 #include "MSMoveReminder.h"
43 #include "MSBaseVehicle.h"
44 #include "MSNet.h"
45 #include "devices/MSDevice.h"
46 
47 #ifdef CHECK_MEMORY_LEAKS
48 #include <foreign/nvwa/debug_new.h>
49 #endif // CHECK_MEMORY_LEAKS
50 
51 // ===========================================================================
52 // static members
53 // ===========================================================================
55 #ifdef _DEBUG
56 std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
57 #endif
58 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
62 MSBaseVehicle::MSBaseVehicle(SUMOVehicleParameter* pars, const MSRoute* route, const MSVehicleType* type, const SUMOReal speedFactor) :
63  myParameter(pars),
64  myRoute(route),
65  myType(type),
66  myCurrEdge(route->begin()),
67  myChosenSpeedFactor(speedFactor),
68  myMoveReminders(0),
69  myDeparture(NOT_YET_DEPARTED),
70  myArrivalPos(-1),
71  myNumberReroutes(0)
72 #ifdef _DEBUG
73  , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
74 #endif
75 {
76  // init devices
78  //
79  for (std::vector< MSDevice* >::iterator dev = myDevices.begin(); dev != myDevices.end(); ++dev) {
80  myMoveReminders.push_back(std::make_pair(*dev, 0.));
81  }
84 }
85 
87  myRoute->release();
88  delete myParameter;
89  for (std::vector< MSDevice* >::iterator dev = myDevices.begin(); dev != myDevices.end(); ++dev) {
90  delete(*dev);
91  }
92 }
93 
94 
95 const std::string&
97  return myParameter->id;
98 }
99 
100 
103  return *myParameter;
104 }
105 
106 
107 SUMOReal
109  return myType->getMaxSpeed();
110 }
111 
112 
113 const MSEdge*
114 MSBaseVehicle::succEdge(unsigned int nSuccs) const {
115  if (myCurrEdge + nSuccs < myRoute->end()) {
116  return *(myCurrEdge + nSuccs);
117  } else {
118  return 0;
119  }
120 }
121 
122 
123 const MSEdge*
125  return *myCurrEdge;
126 }
127 
128 
129 void
131  // check whether to reroute
132  std::vector<const MSEdge*> edges;
133  if (withTaz && MSEdge::dictionary(myParameter->fromTaz + "-source") && MSEdge::dictionary(myParameter->toTaz + "-sink")) {
134  router.compute(MSEdge::dictionary(myParameter->fromTaz + "-source"), MSEdge::dictionary(myParameter->toTaz + "-sink"), this, t, edges);
135  if (edges.size() >= 2) {
136  edges.erase(edges.begin());
137  edges.pop_back();
138  }
139  } else {
140  router.compute(*myCurrEdge, myRoute->getLastEdge(), this, t, edges);
141  }
142  if (edges.empty()) {
143  WRITE_WARNING("No route for vehicle '" + getID() + "' found.");
144  return;
145  }
146  replaceRouteEdges(edges, withTaz);
147 }
148 
149 
150 bool
151 MSBaseVehicle::replaceRouteEdges(const MSEdgeVector& edges, bool onInit) {
152  // build a new id, first
153  std::string id = getID();
154  if (id[0] != '!') {
155  id = "!" + id;
156  }
157  if (myRoute->getID().find("!var#") != std::string::npos) {
158  id = myRoute->getID().substr(0, myRoute->getID().rfind("!var#") + 5) + toString(getNumberReroutes() + 1);
159  } else {
160  id = id + "!var#1";
161  }
162  const RGBColor& c = myRoute->getColor();
163  MSRoute* newRoute = new MSRoute(id, edges, 0, &c == &RGBColor::DEFAULT_COLOR ? 0 : new RGBColor(c), myRoute->getStops());
164  if (!MSRoute::dictionary(id, newRoute)) {
165  delete newRoute;
166  return false;
167  }
168  if (!replaceRoute(newRoute, onInit)) {
169  newRoute->addReference();
170  newRoute->release();
171  return false;
172  }
173  return true;
174 }
175 
176 
177 SUMOReal
179  return 0;
180 }
181 
182 
183 void
187 }
188 
189 
190 bool
192  return myDeparture != NOT_YET_DEPARTED;
193 }
194 
195 
196 bool
198  return succEdge(1) == 0;
199 }
200 
201 void
203 }
204 
205 
206 bool
207 MSBaseVehicle::hasValidRoute(std::string& msg) const {
208  MSRouteIterator last = myRoute->end() - 1;
209  // check connectivity, first
210  for (MSRouteIterator e = myCurrEdge; e != last; ++e) {
211  if ((*e)->allowedLanes(**(e + 1), myType->getVehicleClass()) == 0) {
212  msg = "No connection between '" + (*e)->getID() + "' and '" + (*(e + 1))->getID() + "'.";
213  return false;
214  }
215  }
216  last = myRoute->end();
217  // check usable lanes, then
218  for (MSRouteIterator e = myCurrEdge; e != last; ++e) {
219  if ((*e)->prohibits(this)) {
220  msg = "Edge '" + (*e)->getID() + "' prohibits.";
221  return false;
222  }
223  }
224  return true;
225 }
226 
227 
228 void
230 #ifdef _DEBUG
231  if (myTraceMoveReminders) {
232  traceMoveReminder("add", rem, 0, true);
233  }
234 #endif
235  myMoveReminders.push_back(std::make_pair(rem, 0.));
236 }
237 
238 
239 void
241  for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
242  if (r->first == rem) {
243 #ifdef _DEBUG
244  if (myTraceMoveReminders) {
245  traceMoveReminder("remove", rem, 0, false);
246  }
247 #endif
248  myMoveReminders.erase(r);
249  return;
250  }
251  }
252 }
253 
254 
255 void
257  for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
258  if (rem->first->notifyEnter(*this, reason)) {
259 #ifdef _DEBUG
260  if (myTraceMoveReminders) {
261  traceMoveReminder("notifyEnter", rem->first, rem->second, true);
262  }
263 #endif
264  ++rem;
265  } else {
266 #ifdef _DEBUG
267  if (myTraceMoveReminders) {
268  traceMoveReminder("notifyEnter", rem->first, rem->second, false);
269  }
270 #endif
271  rem = myMoveReminders.erase(rem);
272  }
273  }
274 }
275 
276 
277 void
279  const SUMOReal lastLaneLength = (myRoute->getLastEdge()->getLanes())[0]->getLength();
280  switch (myParameter->arrivalPosProcedure) {
281  case ARRIVAL_POS_GIVEN:
282  if (fabs(myParameter->arrivalPos) > lastLaneLength) {
283  WRITE_WARNING("Vehicle '" + getID() + "' will not be able to arrive at the given position!");
284  }
285  // Maybe we should warn the user about invalid inputs!
286  myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
287  if (myArrivalPos < 0) {
288  myArrivalPos = MAX2(myArrivalPos + lastLaneLength, static_cast<SUMOReal>(0));
289  }
290  break;
291  case ARRIVAL_POS_RANDOM:
292  myArrivalPos = RandHelper::rand(static_cast<SUMOReal>(0), lastLaneLength);
293  break;
294  default:
295  myArrivalPos = lastLaneLength;
296  break;
297  }
298 }
299 
300 
301 MSDevice*
302 MSBaseVehicle::getDevice(const std::type_info& type) const {
303  for (std::vector<MSDevice*>::const_iterator dev = myDevices.begin(); dev != myDevices.end(); ++dev) {
304  if (typeid(**dev) == type) {
305  return *dev;
306  }
307  }
308  return 0;
309 }
310 
311 
312 void
318  // here starts the vehicle internal part (see loading)
319  // @note: remember to close the vehicle tag when calling this in a subclass!
320 }
321 
322 
323 #ifdef _DEBUG
324 void
325 MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
326  if (oc.isSet("movereminder-output.vehicles")) {
327  const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
328  myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
329  }
330 }
331 
332 
333 void
334 MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, SUMOReal pos, bool keep) const {
335  OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
336  od.openTag("movereminder");
337  od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
338  od.writeAttr("veh", getID());
340  od.writeAttr("type", type);
341  od.writeAttr("pos", toString(pos));
342  od.writeAttr("keep", toString(keep));
343  od.closeTag();
344 }
345 #endif
346 
347 /****************************************************************************/
348