SUMO - Simulation of Urban MObility
MSAbstractLaneChangeModel.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // Interface for lane-change models
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
14 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
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 
36 #include <microsim/MSNet.h>
37 #include <microsim/MSEdge.h>
38 #include <microsim/MSLane.h>
39 #include <microsim/MSGlobals.h>
40 #include "MSLCM_DK2008.h"
41 #include "MSLCM_LC2013.h"
42 #include "MSLCM_SL2015.h"
43 
44 /* -------------------------------------------------------------------------
45  * static members
46  * ----------------------------------------------------------------------- */
50 
51 /* -------------------------------------------------------------------------
52  * MSAbstractLaneChangeModel-methods
53  * ----------------------------------------------------------------------- */
54 
55 void
57  myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
58  myLCOutput = oc.isSet("lanechange-output");
59 }
60 
61 
64  if (MSGlobals::gLateralResolution > 0 && lcm != LCM_SL2015 && lcm != LCM_DEFAULT) {
65  throw ProcessError("Lane change model '" + toString(lcm) + "' is not compatible with sublane simulation");
66  }
67  switch (lcm) {
68  case LCM_DK2008:
69  return new MSLCM_DK2008(v);
70  case LCM_LC2013:
71  return new MSLCM_LC2013(v);
72  case LCM_SL2015:
73  return new MSLCM_SL2015(v);
74  case LCM_DEFAULT:
76  return new MSLCM_LC2013(v);
77  } else {
78  return new MSLCM_SL2015(v);
79  }
80  default:
81  throw ProcessError("Lane change model '" + toString(lcm) + "' not implemented");
82  }
83 }
84 
85 
87  myVehicle(v),
88  myOwnState(0),
89  mySpeedLat(0),
93  myAlreadyChanged(false),
94  myShadowLane(0),
95  myCarFollowModel(v.getCarFollowModel()),
96  myModel(model),
98  myAmOpposite(false) {
99 }
100 
101 
103 }
104 
105 void
107  myOwnState = state;
108  // reset lateral influence after step is completed
109  if (myVehicle.hasInfluencer()) {
111  }
112 }
113 
114 bool
116  if (neighLeader == 0) {
117  return false;
118  }
119  // Congested situation are relevant only on highways (maxSpeed > 70km/h)
120  // and congested on German Highways means that the vehicles have speeds
121  // below 60km/h. Overtaking on the right is allowed then.
122  if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
123 
124  return false;
125  }
126  if (myVehicle.congested() && neighLeader->congested()) {
127  return true;
128  }
129  return false;
130 }
131 
132 
133 
134 bool
135 MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
136  if (leader.first == 0) {
137  return false;
138  }
139  // let's check it on highways only
140  if (leader.first->getSpeed() < (80.0 / 3.6)) {
141  return false;
142  }
143  return leader.second < myCarFollowModel.interactionGap(&myVehicle, leader.first->getSpeed());
144 }
145 
146 
147 bool
149  if (&source->getEdge() != &target->getEdge()) {
151  }
154  myLaneChangeDirection = direction;
155  mySpeedLat = (target->getCenterOnEdge() - source->getCenterOnEdge()) * (double)DELTA_T / (double)MSGlobals::gLaneChangeDuration;
158  return true;
159  } else {
160  primaryLaneChanged(source, target, direction);
161  return false;
162  }
163 }
164 
165 
166 void
168  initLastLaneChangeOffset(direction);
170  source->leftByLaneChange(&myVehicle);
172  target->enteredByLaneChange(&myVehicle);
173  if (myLCOutput) {
174  OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
175  of.openTag("change");
178  of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
179  of.writeAttr(SUMO_ATTR_FROM, source->getID());
180  of.writeAttr(SUMO_ATTR_TO, target->getID());
181  of.writeAttr(SUMO_ATTR_DIR, direction);
184  of.writeAttr("leaderGap", myLastLeaderGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderGap));
185  of.writeAttr("leaderSecureGap", myLastLeaderSecureGap == NO_NEIGHBOR ? "None" : toString(myLastLeaderSecureGap));
186  of.writeAttr("followerGap", myLastFollowerGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerGap));
187  of.writeAttr("followerSecureGap", myLastFollowerSecureGap == NO_NEIGHBOR ? "None" : toString(myLastFollowerSecureGap));
189  const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
190  of.writeAttr("latGap", latGap == NO_NEIGHBOR ? "None" : toString(latGap));
191  }
192  of.closeTag();
193  }
194  changed();
195 }
196 
197 
198 bool
200  const bool pastBefore = pastMidpoint();
202  return !pastBefore && pastMidpoint();
203 }
204 
205 
206 void
208  UNUSED_PARAMETER(reason);
214  if (myAmOpposite) {
216  }
217 }
218 
219 
220 MSLane*
221 MSAbstractLaneChangeModel::getShadowLane(const MSLane* lane, double posLat) const {
223  // initialize shadow lane
224  const double overlap = myVehicle.getLateralOverlap(posLat);
225  if (debugVehicle()) {
226  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << posLat << " overlap=" << overlap << "\n";
227  }
228  if (overlap > NUMERICAL_EPS ||
229  // "reserve" target lane even when there is no overlap yet
231  const int shadowDirection = posLat < 0 ? -1 : 1;
232  return lane->getParallelLane(shadowDirection);
233  } else {
234  return 0;
235  }
236  } else {
237  return 0;
238  }
239 }
240 
241 
242 MSLane*
245 }
246 
247 
248 void
250  if (myShadowLane != 0) {
251  if (debugVehicle()) {
252  std::cout << SIMTIME << " cleanupShadowLane\n";
253  }
255  myShadowLane = 0;
256  }
257  for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
258  if (debugVehicle()) {
259  std::cout << SIMTIME << " cleanupShadowLane2\n";
260  }
261  (*it)->resetPartialOccupation(&myVehicle);
262  }
263  myShadowFurtherLanes.clear();
265 }
266 
267 
268 bool
270  int ret = myVehicle.influenceChangeDecision(state);
271  return ret != state;
272 }
273 
274 
275 void
277  if (dir > 0) {
279  } else if (dir < 0) {
281  }
282 }
283 
284 void
286  if (myShadowLane != 0) {
287  if (debugVehicle()) {
288  std::cout << SIMTIME << " updateShadowLane\n";
289  }
291  }
293  std::vector<MSLane*> passed;
294  if (myShadowLane != 0) {
296  const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
297  const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
298  assert(further.size() == furtherPosLat.size());
299  passed.push_back(myShadowLane);
300  for (int i = 0; i < (int)further.size(); ++i) {
301  MSLane* shadowFurther = getShadowLane(further[i], furtherPosLat[i]);
302  if (debugVehicle()) {
303  std::cout << SIMTIME << " further=" << further[i]->getID() << " shadowFurther=" << Named::getIDSecure(shadowFurther) << "\n";
304  }
305  if (shadowFurther != 0 && MSLinkContHelper::getConnectingLink(*shadowFurther, *passed.back()) != 0) {
306  passed.push_back(shadowFurther);
307  }
308  }
309  std::reverse(passed.begin(), passed.end());
310  } else {
312  WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
313  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
315  }
316  }
317  if (debugVehicle()) std::cout << SIMTIME << " updateShadowLane veh=" << myVehicle.getID()
318  << " newShadowLane=" << Named::getIDSecure(myShadowLane)
319  << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed)
320  << "\n";
322  if (debugVehicle()) std::cout
323  << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
324 }
325 
326 
327 int
329  if (isChangingLanes()) {
330  if (pastMidpoint()) {
331  return -myLaneChangeDirection;
332  } else {
333  return myLaneChangeDirection;
334  }
335  } else if (myShadowLane == 0) {
336  return 0;
337  } else {
338  assert(&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge());
340  }
341 }
342 
343 
344 double
347  return myLaneChangeDirection * angleOffset;
348 }
349 
350 
351 SUMOTime
354 }
355 
356 
357 void
359  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
360  myApproachedByShadow.push_back(link);
361 }
362 
363 void
365  for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
366  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
367  (*it)->removeApproaching(&myVehicle);
368  }
369  myApproachedByShadow.clear();
370 }
371 
372 
373 void
376  myAlreadyChanged = true;
377 }
378 
379 void
381  if (follower.first != 0) {
382  myLastFollowerGap = follower.second + follower.first->getVehicleType().getMinGap();
383  myLastFollowerSecureGap = secGap;
384  }
385 }
386 
387 void
389  if (leader.first != 0) {
390  myLastLeaderGap = leader.second + myVehicle.getVehicleType().getMinGap();
391  myLastLeaderSecureGap = secGap;
392  }
393 }
394 
395 void
397  int rightmost;
398  int leftmost;
399  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
400  for (int i = rightmost; i <= leftmost; ++i) {
401  CLeaderDist vehDist = vehicles[i];
402  if (vehDist.first != 0) {
403  const MSVehicle* leader = &myVehicle;
404  const MSVehicle* follower = vehDist.first;
405  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
406  if (netGap < myLastFollowerGap) {
407  myLastFollowerGap = netGap;
408  myLastFollowerSecureGap = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
409  }
410  }
411  }
412 }
413 
414 void
416  int rightmost;
417  int leftmost;
418  vehicles.getSubLanes(&myVehicle, 0, rightmost, leftmost);
419  for (int i = rightmost; i <= leftmost; ++i) {
420  CLeaderDist vehDist = vehicles[i];
421  if (vehDist.first != 0) {
422  const MSVehicle* leader = vehDist.first;
423  const MSVehicle* follower = &myVehicle;
424  const double netGap = vehDist.second + follower->getVehicleType().getMinGap();
425  if (netGap < myLastLeaderGap) {
426  myLastLeaderGap = netGap;
427  myLastLeaderSecureGap = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
428  }
429  }
430  }
431 }
double getMinGap() const
Get the free space in front of vehicles of this class.
static double gLateralResolution
Definition: MSGlobals.h:92
A lane change model developed by J. Erdmann.
Definition: MSLCM_SL2015.h:44
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:261
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:476
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:136
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:582
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
const std::vector< double > & getFurtherLanesPosLat() const
Definition: MSVehicle.h:698
double getCenterOnEdge() const
Definition: MSLane.h:943
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:796
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
bool hasInfluencer() const
Definition: MSVehicle.h:1451
void setLeaderGaps(CLeaderDist, double secGap)
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
virtual double interactionGap(const MSVehicle *const veh, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
Definition: MSCFModel.cpp:185
double myLastLeaderGap
the actual minimum longitudinal distances to vehicles on the target lane
double getSecureGap(const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.h:305
bool congested() const
Definition: MSVehicle.h:635
double myLaneChangeCompletion
progress of the lane change maneuver 0:started, 1:complete
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
int getShadowDirection() const
return the direction in which the current shadow lane lies
Notification
Definition of a vehicle state.
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:60
Wants go to the right.
static bool myLCOutput
whether to record lane-changing
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:169
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:59
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2263
MSLane * myShadowLane
A lane that is partially occupied by the front of the vehicle but that is not the primary lane...
virtual bool predInteraction(const std::pair< MSVehicle *, double > &leader)
virtual double setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:228
Wants go to the left.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:40
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:2989
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
#define SIMTIME
Definition: SUMOTime.h:70
Right blinker lights are switched on.
Definition: MSVehicle.h:1078
std::vector< double > myShadowFurtherLanesPosLat
void setFollowerGaps(CLeaderDist follower, double secGap)
const LaneChangeModel myModel
the type of this model
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
const std::string & getID() const
Returns the id.
Definition: Named.h:66
LaneChangeModel
void leaveLane(const MSMoveReminder::Notification reason, const MSLane *approachedLane=0)
Update of members if vehicle leaves a new lane in the lane change step or at arrival.
Definition: MSVehicle.cpp:3094
The vehicle changes lanes (micro only)
A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013...
Definition: MSLCM_LC2013.h:55
Left blinker lights are switched on.
Definition: MSVehicle.h:1080
#define max(a, b)
Definition: polyfonts.c:65
bool cancelRequest(int state)
whether the influencer cancels the given request
std::vector< MSLane * > myNoPartiallyOccupatedByShadow
void setSublaneChange(double latDist)
Sets a new sublane-change request.
Definition: MSVehicle.cpp:275
double getAngleOffset() const
return the angle offset during a continuous change maneuver
bool pastMidpoint() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver ...
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:241
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:212
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2270
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:1867
std::vector< MSLane * > myShadowFurtherLanes
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
double updateFurtherLanes(std::vector< MSLane * > &furtherLanes, std::vector< double > &furtherLanesPosLat, const std::vector< MSLane * > &passedLanes)
update a vector of further lanes and return the new backPos
Definition: MSVehicle.cpp:2561
int myLaneChangeDirection
direction of the lane change maneuver -1 means right, 1 means left
virtual void changed()=0
static void initGlobalOptions(const OptionsCont &oc)
init global model parameters
MSLane * getShadowLane() const
Returns the lane the vehicles shadow is on during continuous/sublane lane change. ...
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:3549
double myLastLeaderSecureGap
the minimum longitudinal distances to vehicles on the target lane that would be necessary for stringe...
int myOwnState
The current state of the vehicle.
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:507
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:42
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:694
trigger: the time of the step
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:4223
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
virtual void setOwnState(const int state)
SUMOTime remainingTime() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver ...
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
A storage for options typed value containers)
Definition: OptionsCont.h:99
double mySpeedLat
the current lateral speed
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
const std::string & getID() const
Returns the name of the vehicle type.
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:407
The abstract direction of a link.
A lane change model developed by D. Krajzewicz between 2004 and 2010.
Definition: MSLCM_DK2008.h:47
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
void changedToOpposite()
called when a vehicle changes between lanes in opposite directions
bool closeTag()
Closes the most recently opened tag.
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1139
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1131
long long int SUMOTime
Definition: TraCIDefs.h:52
double myCommittedSpeed
the speed when committing to a change maneuver
#define NUMERICAL_EPS
Definition: config.h:152
std::vector< MSLink * > myApproachedByShadow
links which are approached by the shadow vehicle
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it&#39;s primary lane ...
Definition: MSVehicle.cpp:3912
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:499
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:4247
double myLastLateralGapLeft
the minimum lateral gaps to other vehicles that were found when last changing to the left and right ...
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:89
static MSAbstractLaneChangeModel * build(LaneChangeModel lcm, MSVehicle &vehicle)
Factory method for instantiating new lane changing models.
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
bool myAlreadyChanged
whether the vehicle has already moved this step
const MSCFModel & myCarFollowModel
The vehicle&#39;s car following model.
bool myAmOpposite
whether the vehicle is driving in the opposite direction
MSAbstractLaneChangeModel(MSVehicle &v, const LaneChangeModel model)
Constructor.
Interface for lane-change models.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
const std::string & getID() const
Returns the name of the vehicle.
virtual bool congested(const MSVehicle *const neighLeader)
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:443
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual ~MSAbstractLaneChangeModel()
Destructor.