Eclipse SUMO - Simulation of Urban MObility
MELoop.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-2019 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 /****************************************************************************/
14 // The main mesocopic simulation loop
15 /****************************************************************************/
16 
17 
18 // ===========================================================================
19 // included modules
20 // ===========================================================================
21 #include <config.h>
22 
23 #include <queue>
24 #include <vector>
25 #include <map>
26 #include <cmath>
27 
28 #include <microsim/MSNet.h>
29 #include <microsim/MSEdge.h>
30 #include <microsim/MSGlobals.h>
31 #include <microsim/MSLane.h>
32 #include <microsim/MSVehicle.h>
35 #include <utils/common/ToString.h>
37 #include <utils/common/SUMOTime.h>
39 #include "MELoop.h"
40 #include "MESegment.h"
41 #include "MEVehicle.h"
42 
43 
44 // ===========================================================================
45 // method definitions
46 // ===========================================================================
47 MELoop::MELoop(const SUMOTime recheckInterval) : myFullRecheckInterval(recheckInterval), myLinkRecheckInterval(TIME2STEPS(1)) {
48 }
49 
51  for (std::vector<MESegment*>::const_iterator j = myEdges2FirstSegments.begin(); j != myEdges2FirstSegments.end(); ++j) {
52  for (MESegment* s = *j; s != nullptr;) {
53  MESegment* n = s->getNextSegment();
54  delete s;
55  s = n;
56  }
57  }
58 }
59 
60 
61 void
63  while (!myLeaderCars.empty()) {
64  const SUMOTime time = myLeaderCars.begin()->first;
65  assert(time > tMax - DELTA_T);
66  if (time > tMax) {
67  return;
68  }
69  std::vector<MEVehicle*> vehs = myLeaderCars[time];
70  myLeaderCars.erase(time);
71  for (std::vector<MEVehicle*>::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
72  checkCar(*i);
73  assert(myLeaderCars.empty() || myLeaderCars.begin()->first >= time);
74  }
75  }
76 }
77 
78 
79 bool
80 MELoop::changeSegment(MEVehicle* veh, SUMOTime leaveTime, MESegment* const toSegment, const bool ignoreLink) {
81  MESegment* const onSegment = veh->getSegment();
82  if (MESegment::isInvalid(toSegment)) {
83  if (onSegment != nullptr) {
84  onSegment->send(veh, toSegment, leaveTime, toSegment == nullptr ? MSMoveReminder::NOTIFICATION_ARRIVED : MSMoveReminder::NOTIFICATION_VAPORIZED);
85  } else {
86  WRITE_WARNING("Vehicle '" + veh->getID() + "' teleports beyond arrival edge '" + veh->getEdge()->getID() + "', time " + time2string(leaveTime) + ".");
87  }
88  veh->setSegment(toSegment); // signal arrival
90  return true;
91  }
92  if (toSegment->hasSpaceFor(veh, leaveTime) && (ignoreLink || veh->mayProceed())) {
93  if (onSegment != nullptr) {
94  onSegment->send(veh, toSegment, leaveTime, onSegment->getNextSegment() == nullptr ? MSMoveReminder::NOTIFICATION_JUNCTION : MSMoveReminder::NOTIFICATION_SEGMENT);
95  toSegment->receive(veh, leaveTime, false, ignoreLink);
96  } else {
97  WRITE_WARNING("Vehicle '" + veh->getID() + "' ends teleporting on edge '" + toSegment->getEdge().getID()
98  + "':" + toString(toSegment->getIndex()) + ", time " + time2string(leaveTime) + ".");
99  // this is not quite correct but suffices for interrogation by
100  // subsequent methods (veh->getSpeed() needs segment != 0)
102  toSegment->receive(veh, leaveTime, false, true);
103  }
104  return true;
105  }
106  return false;
107 }
108 
109 
110 void
112  const SUMOTime leaveTime = veh->getEventTime();
113  MESegment* const onSegment = veh->getSegment();
114  MESegment* const toSegment = nextSegment(onSegment, veh);
115  const bool teleporting = (onSegment == nullptr); // is the vehicle currently teleporting?
116  if (changeSegment(veh, leaveTime, toSegment, teleporting)) {
117  return;
118  }
120  teleportVehicle(veh, toSegment);
121  return;
122  }
123  if (veh->getBlockTime() == SUMOTime_MAX) {
124  veh->setBlockTime(leaveTime);
125  }
126  if (leaveTime < toSegment->getEntryBlockTime()) {
127  // receiving segment has recently received another vehicle
128  veh->setEventTime(toSegment->getEntryBlockTime());
129  } else if (toSegment->hasSpaceFor(veh, leaveTime) && !veh->mayProceed()) {
130  // either the junction is blocked or the traffic light is red
131  veh->setEventTime(leaveTime + MAX2(SUMOTime(1), myLinkRecheckInterval));
132  } else {
133  SUMOTime newEventTime = MAX3(toSegment->getEventTime() + 1, leaveTime + 1, leaveTime + myFullRecheckInterval);
134  if (MSGlobals::gTimeToGridlock > 0) {
135  // if teleporting is enabled, make sure we look at the vehicle when the the gridlock-time is up
136  newEventTime = MIN2(newEventTime, veh->getBlockTime() + MSGlobals::gTimeToGridlock + 1);
137  }
138  veh->setEventTime(newEventTime);
139  }
140  addLeaderCar(veh, onSegment->getLink(veh));
141 }
142 
143 
144 void
145 MELoop::teleportVehicle(MEVehicle* veh, MESegment* const toSegment) {
146  const SUMOTime leaveTime = veh->getEventTime();
147  MESegment* const onSegment = veh->getSegment();
148  const bool teleporting = (onSegment == nullptr); // is the vehicle already teleporting?
149  // try to find a place on the current edge
150  MESegment* teleSegment = toSegment->getNextSegment();
151  while (teleSegment != nullptr && !teleSegment->hasSpaceFor(veh, leaveTime)) {
152  // @caution the time to get to the next segment here is ignored XXX
153  teleSegment = teleSegment->getNextSegment();
154  }
155  if (teleSegment != nullptr) {
156  if (!teleporting) {
157  // we managed to teleport in a single jump
158  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long, from edge '" + onSegment->getEdge().getID()
159  + "':" + toString(onSegment->getIndex())
160  + " to edge '" + teleSegment->getEdge().getID()
161  + "':" + toString(teleSegment->getIndex())
162  + ", time " + time2string(leaveTime) + ".");
164  }
165  changeSegment(veh, leaveTime, teleSegment, true);
166  teleSegment->setEntryBlockTime(leaveTime); // teleports should not block normal flow
167  } else {
168  // teleport across the current edge and try insertion later
169  if (!teleporting) {
170  // announce start of multi-step teleport, arrival will be announced in changeSegment()
171  WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long, from edge '" + onSegment->getEdge().getID()
172  + "':" + toString(onSegment->getIndex()) + ", time " + time2string(leaveTime) + ".");
174  // remove from current segment
175  onSegment->send(veh, nullptr, leaveTime, MSMoveReminder::NOTIFICATION_TELEPORT);
176  // mark veh as teleporting
177  veh->setSegment(nullptr, 0);
178  }
179  // @caution microsim uses current travel time teleport duration
180  const SUMOTime teleArrival = leaveTime + TIME2STEPS(veh->getEdge()->getLength() / MAX2(veh->getEdge()->getSpeedLimit(), NUMERICAL_EPS));
181  const bool atDest = veh->moveRoutePointer();
182  if (atDest) {
183  // teleporting to end of route
184  changeSegment(veh, teleArrival, nullptr, true);
185  } else {
186  veh->setEventTime(teleArrival);
187  addLeaderCar(veh, nullptr);
188  // teleporting vehicles must react to rerouters
189  getSegmentForEdge(*veh->getEdge())->addReminders(veh);
191  }
192  }
193 }
194 
195 
196 void
198  myLeaderCars[veh->getEventTime()].push_back(veh);
199  setApproaching(veh, link);
200 }
201 
202 
203 void
205  if (link != nullptr) {
206  link->setApproaching(veh, veh->getEventTime() + (link->getState() == LINKSTATE_ALLWAY_STOP ?
207  (SUMOTime)RandHelper::rand((int)2) : 0), // tie braker
208  veh->getSpeed(), veh->getSpeed(), true,
209  veh->getEventTime(), veh->getSpeed(), veh->getWaitingTime(),
210  // @note: dist is not used by meso (getZipperSpeed is never called)
211  veh->getSegment()->getLength());
212  }
213 }
214 
215 
216 void
218  std::vector<MEVehicle*>& cands = myLeaderCars[v->getEventTime()];
219  cands.erase(find(cands.begin(), cands.end(), v));
220 }
221 
222 void
224  v->getSegment()->send(v, nullptr, MSNet::getInstance()->getCurrentTimeStep(), MSMoveReminder::NOTIFICATION_VAPORIZED);
225  // try removeLeaderCar
226  std::vector<MEVehicle*>& cands = myLeaderCars[v->getEventTime()];
227  auto it = find(cands.begin(), cands.end(), v);
228  if (it != cands.end()) {
229  cands.erase(it);
230  }
231 }
232 
233 MESegment*
235  if (s != nullptr) { // vehicle is not teleporting
236  MESegment* next = s->getNextSegment();
237  if (next != nullptr) {
238  // ok, the street continues
239  return next;
240  }
241  }
242  // we have to check the next edge in the vehicle's route
243  const MSEdge* nextEdge = v->succEdge(1);
244  if (nextEdge == nullptr) {
245  // end of route
246  return nullptr;
247  }
248  return myEdges2FirstSegments[nextEdge->getNumericalID()];
249 }
250 
251 
252 int
253 MELoop::numSegmentsFor(const double length, const double sLength) {
254  int no = (int)floor(length / sLength + 0.5);
255  if (no == 0) { // assure there is at least one segment
256  return 1;
257  } else {
258  return no;
259  }
260 }
261 
262 
263 void
265  const double length = e.getLength();
266  int no = numSegmentsFor(length, oc.getFloat("meso-edgelength"));
267  const double slength = length / (double)no;
268  MESegment* newSegment = nullptr;
269  MESegment* nextSegment = nullptr;
270  bool multiQueue = oc.getBool("meso-multi-queue");
271  bool junctionControl = oc.getBool("meso-junction-control") || isEnteringRoundabout(e);
272  for (int s = no - 1; s >= 0; s--) {
273  std::string id = e.getID() + ":" + toString(s);
274  newSegment =
275  new MESegment(id, e, nextSegment, slength,
276  e.getLanes()[0]->getSpeedLimit(), s,
277  string2time(oc.getString("meso-tauff")), string2time(oc.getString("meso-taufj")),
278  string2time(oc.getString("meso-taujf")), string2time(oc.getString("meso-taujj")),
279  oc.getFloat("meso-jam-threshold"), multiQueue, junctionControl);
280  multiQueue = false;
281  junctionControl = false;
282  nextSegment = newSegment;
283  }
284  while (e.getNumericalID() >= static_cast<int>(myEdges2FirstSegments.size())) {
285  myEdges2FirstSegments.push_back(0);
286  }
287  myEdges2FirstSegments[e.getNumericalID()] = newSegment;
288 }
289 
290 
291 MESegment*
292 MELoop::getSegmentForEdge(const MSEdge& e, double pos) {
293  if (e.getNumericalID() >= (int)myEdges2FirstSegments.size()) {
294  return nullptr;
295  }
297  if (pos > 0) {
298  double cpos = 0;
299  while (s->getNextSegment() != nullptr && cpos + s->getLength() < pos) {
300  cpos += s->getLength();
301  s = s->getNextSegment();
302  }
303  }
304  return s;
305 }
306 
307 
308 bool
310  for (const MSEdge* succ : e.getSuccessors()) {
311  if (succ->isRoundabout()) {
312  return true;
313  }
314  }
315  return false;
316 }
317 
318 /****************************************************************************/
MELoop::myFullRecheckInterval
const SUMOTime myFullRecheckInterval
the interval at which to recheck at full segments (<=0 means asap)
Definition: MELoop.h:151
MEVehicle
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:44
ToString.h
MSEdge::getSuccessors
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:959
MELoop::MELoop
MELoop(const SUMOTime recheckInterval)
SUMO constructor.
Definition: MELoop.cpp:47
MIN2
T MIN2(T a, T b)
Definition: StdDefs.h:73
MSEdge::getNumericalID
int getNumericalID() const
Returns the numerical id of the edge.
Definition: MSEdge.h:265
MSEdge::getSpeedLimit
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is retured; should pro...
Definition: MSEdge.cpp:877
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:275
SUMOTime.h
MSNet.h
MESegment
A single mesoscopic segment (cell)
Definition: MESegment.h:49
MSVehicleControl::registerTeleportJam
void registerTeleportJam()
register one non-collision-related teleport
Definition: MSVehicleControl.h:440
DELTA_T
SUMOTime DELTA_T
Definition: SUMOTime.cpp:36
NUMERICAL_EPS
#define NUMERICAL_EPS
Definition: config.h:148
OptionsCont.h
MELoop::changeSegment
bool changeSegment(MEVehicle *veh, SUMOTime leaveTime, MESegment *const toSegment, const bool ignoreLink=false)
change to the next segment this handles combinations of the following cases: (ending / continuing rou...
Definition: MELoop.cpp:80
MESegment::getEdge
const MSEdge & getEdge() const
Returns the edge this segment belongs to.
Definition: MESegment.h:265
OptionsCont::getString
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
Definition: OptionsCont.cpp:201
FileHelpers.h
MESegment::hasSpaceFor
bool hasSpaceFor(const MEVehicle *veh, SUMOTime entryTime, bool init=false) const
Returns whether the given vehicle would still fit into the segment.
Definition: MESegment.cpp:251
SUMOTime
long long int SUMOTime
Definition: SUMOTime.h:34
OptionsCont::getBool
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Definition: OptionsCont.cpp:222
MSEdge.h
MAX3
T MAX3(T a, T b, T c)
Definition: StdDefs.h:93
MSVehicleControl::scheduleVehicleRemoval
void scheduleVehicleRemoval(SUMOVehicle *veh, bool checkDuplicate=false)
Removes a vehicle after it has ended.
Definition: MSVehicleControl.cpp:117
MEVehicle::setEventTime
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:217
MSEdge::getLength
double getLength() const
return the length of the edge
Definition: MSEdge.h:589
MEVehicle::moveRoutePointer
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:138
MESegment::getEntryBlockTime
SUMOTime getEntryBlockTime() const
return the next time at which a vehicle my enter this segment
Definition: MESegment.h:364
MSVehicle.h
MSMoveReminder::NOTIFICATION_VAPORIZED
@ NOTIFICATION_VAPORIZED
The vehicle got vaporized.
Definition: MSMoveReminder.h:109
MESegment.h
MSBaseVehicle::getEdge
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
Definition: MSBaseVehicle.cpp:181
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:79
MEVehicle::getBlockTime
SUMOTime getBlockTime() const
Returns the time at which the vehicle was blocked.
Definition: MEVehicle.h:288
MEVehicle::getEventTime
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:229
MELoop::myEdges2FirstSegments
std::vector< MESegment * > myEdges2FirstSegments
mapping from internal edge ids to their initial segments
Definition: MELoop.h:148
MELoop::addLeaderCar
void addLeaderCar(MEVehicle *veh, MSLink *link)
Adds the given car to the leading vehicles.
Definition: MELoop.cpp:197
RandHelper::rand
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:53
MESegment::receive
void receive(MEVehicle *veh, SUMOTime time, bool isDepart=false, bool afterTeleport=false)
Adds the vehicle to the segment, adapting its parameters.
Definition: MESegment.cpp:491
TIME2STEPS
#define TIME2STEPS(x)
Definition: SUMOTime.h:58
MELoop::nextSegment
MESegment * nextSegment(MESegment *s, MEVehicle *v)
Retrieve next segment.
Definition: MELoop.cpp:234
MEVehicle::mayProceed
bool mayProceed() const
Returns whether the vehicle is allowed to pass the next junction.
Definition: MEVehicle.cpp:362
MEVehicle::setBlockTime
void setBlockTime(const SUMOTime t)
Sets the time at which the vehicle was blocked.
Definition: MEVehicle.h:279
MELoop::getSegmentForEdge
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:292
MESegment::getLink
MSLink * getLink(const MEVehicle *veh, bool tlsPenalty=false) const
Returns the link the given car will use when passing the next junction.
Definition: MESegment.cpp:376
MELoop::vaporizeCar
void vaporizeCar(MEVehicle *v)
remove the given car and clean up the relevant data structures
Definition: MELoop.cpp:223
time2string
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:67
MELoop::myLinkRecheckInterval
const SUMOTime myLinkRecheckInterval
the interval at which to recheck at blocked junctions (<=0 means asap)
Definition: MELoop.h:154
MSGlobals.h
OptionsCont
A storage for options typed value containers)
Definition: OptionsCont.h:89
MESegment::getNextSegment
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:151
MSEdge
A road/street connecting two junctions.
Definition: MSEdge.h:78
MELoop::myLeaderCars
std::map< SUMOTime, std::vector< MEVehicle * > > myLeaderCars
leader cars in the segments sorted by exit time
Definition: MELoop.h:145
MESegment::getEventTime
SUMOTime getEventTime() const
Returns the (planned) time at which the next vehicle leaves this segment.
Definition: MESegment.cpp:633
string2time
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:44
MELoop::isEnteringRoundabout
static bool isEnteringRoundabout(const MSEdge &e)
whether the given edge is entering a roundabout
Definition: MELoop.cpp:309
MELoop::setApproaching
static void setApproaching(MEVehicle *veh, MSLink *link)
registers vehicle with the given link
Definition: MELoop.cpp:204
MSMoveReminder::NOTIFICATION_SEGMENT
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
Definition: MSMoveReminder.h:97
MELoop::teleportVehicle
void teleportVehicle(MEVehicle *veh, MESegment *const toSegment)
teleports a vehicle or continues a teleport
Definition: MELoop.cpp:145
OptionsCont::getFloat
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
Definition: OptionsCont.cpp:208
MEVehicle::getWaitingTime
SUMOTime getWaitingTime() const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:294
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:47
MESegment::isInvalid
static bool isInvalid(const MESegment *segment)
whether the given segment is 0 or encodes vaporization
Definition: MESegment.h:341
MEVehicle::getSegment
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:247
MSNet::getInstance
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:167
MSGlobals::gTimeToGridlock
static SUMOTime gTimeToGridlock
Definition: MSGlobals.h:59
MESegment::getLength
double getLength() const
Returns the length of the segment in meters.
Definition: MESegment.h:159
MSMoveReminder::NOTIFICATION_ARRIVED
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
Definition: MSMoveReminder.h:107
MEVehicle::getSpeed
double getSpeed() const
Returns the vehicle's estimated speed assuming no delays.
Definition: MEVehicle.cpp:106
MSBaseVehicle::succEdge
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
Definition: MSBaseVehicle.cpp:171
MESegment::setEntryBlockTime
void setEntryBlockTime(SUMOTime entryBlockTime)
set the next time at which a vehicle my enter this segment
Definition: MESegment.h:369
MEVehicle::setSegment
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:238
MELoop::~MELoop
~MELoop()
Definition: MELoop.cpp:50
MELoop::buildSegmentsFor
void buildSegmentsFor(const MSEdge &e, const OptionsCont &oc)
Build the segments for a given edge.
Definition: MELoop.cpp:264
MESegment::send
void send(MEVehicle *veh, MESegment *next, SUMOTime time, const MSMoveReminder::Notification reason)
Removes the vehicle from the segment, adapting its parameters.
Definition: MESegment.cpp:456
MESegment::addReminders
void addReminders(MEVehicle *veh) const
add this lanes MoveReminders to the given vehicle
Definition: MESegment.cpp:484
MSBaseVehicle::getID
const std::string & getID() const
Returns the name of the vehicle.
Definition: MSBaseVehicle.cpp:138
MEVehicle.h
MSEdge::getLanes
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:167
LINKSTATE_ALLWAY_STOP
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
Definition: SUMOXMLDefinitions.h:1163
config.h
RandHelper.h
MELoop.h
SUMOTime_MAX
#define SUMOTime_MAX
Definition: SUMOTime.h:35
MSLane.h
MELoop::numSegmentsFor
static int numSegmentsFor(const double length, const double slength)
Compute number of segments per edge (best value stay close to the configured segment length)
Definition: MELoop.cpp:253
MESegment::getIndex
int getIndex() const
Returns the running index of the segment in the edge (0 is the most upstream).
Definition: MESegment.h:143
MELoop::simulate
void simulate(SUMOTime tMax)
Perform simulation up to the given time.
Definition: MELoop.cpp:62
MSVehicleControl.h
MSBaseVehicle::activateReminders
virtual void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
Definition: MSBaseVehicle.cpp:490
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:76
MSMoveReminder::NOTIFICATION_JUNCTION
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
Definition: MSMoveReminder.h:95
MSNet::getVehicleControl
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:336
MSMoveReminder::NOTIFICATION_TELEPORT
@ NOTIFICATION_TELEPORT
The vehicle is being teleported.
Definition: MSMoveReminder.h:103
MELoop::checkCar
void checkCar(MEVehicle *veh)
Check whether the vehicle may move.
Definition: MELoop.cpp:111
MELoop::removeLeaderCar
void removeLeaderCar(MEVehicle *v)
Removes the given car from the leading vehicles.
Definition: MELoop.cpp:217