SUMO - Simulation of Urban MObility
MSAbstractLaneChangeModel.h
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 /****************************************************************************/
22 // Interface for lane-change models
23 /****************************************************************************/
24 #ifndef MSAbstractLaneChangeModel_h
25 #define MSAbstractLaneChangeModel_h
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #include <microsim/MSVehicle.h>
37 
38 class MSLane;
39 
40 // ===========================================================================
41 // used enumeration
42 // ===========================================================================
43 
44 // ===========================================================================
45 // class definitions
46 // ===========================================================================
52 public:
53 
57  class MSLCMessager {
58  public:
64  MSLCMessager(MSVehicle* leader, MSVehicle* neighLead, MSVehicle* neighFollow)
65  : myLeader(leader), myNeighLeader(neighLead),
66  myNeighFollower(neighFollow) { }
67 
68 
71 
72 
78  void* informLeader(void* info, MSVehicle* sender) {
79  assert(myLeader != 0);
80  return myLeader->getLaneChangeModel().inform(info, sender);
81  }
82 
83 
89  void* informNeighLeader(void* info, MSVehicle* sender) {
90  assert(myNeighLeader != 0);
91  return myNeighLeader->getLaneChangeModel().inform(info, sender);
92  }
93 
94 
100  void* informNeighFollower(void* info, MSVehicle* sender) {
101  assert(myNeighFollower != 0);
102  return myNeighFollower->getLaneChangeModel().inform(info, sender);
103  }
104 
105 
106  private:
113 
114  };
115 
116  struct StateAndDist {
117  // @brief LaneChangeAction flags
118  int state;
119  // @brief Lateral distance to be completed in the next step
120  double latDist;
121  // @brief Full lateral distance required for the completion of the envisioned maneuver
122  double maneuverDist;
123  // @brief direction that was checked
124  int dir;
125 
126  StateAndDist(int _state, double _latDist, double _targetDist, int _dir) :
127  state(_state),
128  latDist(_latDist),
129  maneuverDist(_targetDist),
130  dir(_dir) {}
131 
132  bool sameDirection(const StateAndDist& other) const {
133  return latDist * other.latDist > 0;
134  }
135  };
136 
138  void static initGlobalOptions(const OptionsCont& oc);
139 
145 
147  static bool haveLCOutput() {
148  return myLCOutput;
149  }
150 
152  static bool outputLCStarted() {
153  return myLCStartedOutput;
154  }
155 
157  static bool outputLCEnded() {
158  return myLCEndedOutput;
159  }
160 
166 
168  virtual ~MSAbstractLaneChangeModel();
169 
170  inline int getOwnState() const {
171  return myOwnState;
172  }
173 
174  inline int getPrevState() const {
176  return myPreviousState2;
177  }
178 
179  virtual void setOwnState(const int state);
180 
182  void setManeuverDist(const double dist);
184  double getManeuverDist() const;
185 
187  virtual void updateSafeLatDist(const double travelledLatDist);
188 
189  const std::pair<int, int>& getSavedState(const int dir) const {
190  return mySavedStates.find(dir)->second;
191  }
192 
193  void saveState(const int dir, const int stateWithoutTraCI, const int state) {
194  mySavedStates[dir] = std::make_pair(stateWithoutTraCI, state);
195  }
196 
197  void setFollowerGaps(CLeaderDist follower, double secGap);
198  void setLeaderGaps(CLeaderDist, double secGap);
199  void setOrigLeaderGaps(CLeaderDist, double secGap);
200  void setFollowerGaps(const MSLeaderDistanceInfo& vehicles);
201  void setLeaderGaps(const MSLeaderDistanceInfo& vehicles);
202  void setOrigLeaderGaps(const MSLeaderDistanceInfo& vehicles);
203 
204  virtual void prepareStep() {
216  myCommittedSpeed = 0;
217  }
218 
223  virtual int wantsChange(
224  int laneOffset,
225  MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
226  const std::pair<MSVehicle*, double>& leader,
227  const std::pair<MSVehicle*, double>& neighLead,
228  const std::pair<MSVehicle*, double>& neighFollow,
229  const MSLane& neighLane,
230  const std::vector<MSVehicle::LaneQ>& preb,
231  MSVehicle** lastBlocked,
232  MSVehicle** firstBlocked) {
233  UNUSED_PARAMETER(laneOffset);
234  UNUSED_PARAMETER(&msgPass);
235  UNUSED_PARAMETER(blocked);
236  UNUSED_PARAMETER(&leader);
237  UNUSED_PARAMETER(&neighLead);
238  UNUSED_PARAMETER(&neighFollow);
239  UNUSED_PARAMETER(&neighLane);
240  UNUSED_PARAMETER(&preb);
241  UNUSED_PARAMETER(lastBlocked);
242  UNUSED_PARAMETER(firstBlocked);
243  throw ProcessError("Method not implemented by model " + toString(myModel));
244  };
245 
246  virtual int wantsChangeSublane(
247  int laneOffset,
248  LaneChangeAction alternatives,
249  const MSLeaderDistanceInfo& leaders,
250  const MSLeaderDistanceInfo& followers,
251  const MSLeaderDistanceInfo& blockers,
252  const MSLeaderDistanceInfo& neighLeaders,
253  const MSLeaderDistanceInfo& neighFollowers,
254  const MSLeaderDistanceInfo& neighBlockers,
255  const MSLane& neighLane,
256  const std::vector<MSVehicle::LaneQ>& preb,
257  MSVehicle** lastBlocked,
258  MSVehicle** firstBlocked,
259  double& latDist, double& targetDistLat, int& blocked) {
260  UNUSED_PARAMETER(laneOffset);
261  UNUSED_PARAMETER(alternatives);
262  UNUSED_PARAMETER(&leaders);
263  UNUSED_PARAMETER(&followers);
264  UNUSED_PARAMETER(&blockers);
265  UNUSED_PARAMETER(&neighLeaders);
266  UNUSED_PARAMETER(&neighFollowers);
267  UNUSED_PARAMETER(&neighBlockers);
268  UNUSED_PARAMETER(&neighLane);
269  UNUSED_PARAMETER(&preb);
270  UNUSED_PARAMETER(lastBlocked);
271  UNUSED_PARAMETER(firstBlocked);
272  UNUSED_PARAMETER(latDist);
273  UNUSED_PARAMETER(targetDistLat);
274  UNUSED_PARAMETER(blocked);
275  throw ProcessError("Method not implemented by model " + toString(myModel));
276  }
277 
279  virtual void updateExpectedSublaneSpeeds(const MSLeaderDistanceInfo& ahead, int sublaneOffset, int laneIndex) {
280  UNUSED_PARAMETER(&ahead);
281  UNUSED_PARAMETER(sublaneOffset);
282  UNUSED_PARAMETER(laneIndex);
283  throw ProcessError("Method not implemented by model " + toString(myModel));
284  }
285 
288  UNUSED_PARAMETER(sd1);
289  UNUSED_PARAMETER(sd2);
290  throw ProcessError("Method not implemented by model " + toString(myModel));
291  }
292 
293  virtual void* inform(void* info, MSVehicle* sender) = 0;
294 
308  virtual double patchSpeed(const double min, const double wanted, const double max,
309  const MSCFModel& cfModel) = 0;
310 
311  /* @brief called once when the primary lane of the vehicle changes (updates
312  * the custom variables of each child implementation */
313  virtual void changed() = 0;
314 
315 
317  virtual bool debugVehicle() const {
318  return false;
319  }
320 
322  void changedToOpposite();
323 
324  void unchanged() {
325  if (myLastLaneChangeOffset > 0) {
327  } else if (myLastLaneChangeOffset < 0) {
329  }
330  }
331 
336  return myShadowLane;
337  }
338 
340  MSLane* getShadowLane(const MSLane* lane) const;
341 
343  MSLane* getShadowLane(const MSLane* lane, double posLat) const;
344 
346  void setShadowLane(MSLane* lane) {
347  myShadowLane = lane;
348  }
349 
350  const std::vector<MSLane*>& getShadowFurtherLanes() const {
351  return myShadowFurtherLanes;
352  }
353 
354  const std::vector<double>& getShadowFurtherLanesPosLat() const {
356  }
357 
362  return myTargetLane;
363  }
364 
365  const std::vector<MSLane*>& getFurtherTargetLanes() const {
366  return myFurtherTargetLanes;
367  }
368 
370  return myLastLaneChangeOffset;
371  }
372 
373 
375  inline bool pastMidpoint() const {
376  return myLaneChangeCompletion >= 0.5;
377  }
378 
380  SUMOTime remainingTime() const;
381 
383  inline bool isChangingLanes() const {
384  return myLaneChangeCompletion < (1 - NUMERICAL_EPS);
385  }
386 
388  inline int getLaneChangeDirection() const {
389  return myLaneChangeDirection;
390  }
391 
393  int getShadowDirection() const;
394 
396  double getAngleOffset() const;
397 
399  inline bool alreadyChanged() const {
400  return myAlreadyChanged;
401  }
402 
404  void resetChanged() {
405  myAlreadyChanged = false;
406  }
407 
409  bool startLaneChangeManeuver(MSLane* source, MSLane* target, int direction);
410 
411  /* @brief continue the lane change maneuver and return whether the midpoint
412  * was passed in this step
413  */
414  bool updateCompletion();
415 
416  /* @brief update lane change shadow after the vehicle moved to a new lane */
417  void updateShadowLane();
418 
419  /* @brief update lane change reservations after the vehicle moved to a new lane
420  * @note The shadow lane should always be updated before updating the target lane. */
421  void updateTargetLane();
422 
423  /* @brief Determines the lane which the vehicle intends to enter during its current action step.
424  * targetDir is set to the offset of the returned lane with respect to the vehicle'a current lane. */
425  MSLane* determineTargetLane(int& targetDir) const;
426 
427  /* @brief finish the lane change maneuver
428  */
430 
431  /* @brief clean up all references to the shadow vehicle
432  */
433  void cleanupShadowLane();
434 
435  /* @brief clean up all references to the vehicle on its target lanes
436  */
437  void cleanupTargetLane();
438 
440  virtual void saveBlockerLength(double length) {
441  UNUSED_PARAMETER(length);
442  }
443 
445  myPartiallyOccupatedByShadow.push_back(lane);
446  }
447 
449  myNoPartiallyOccupatedByShadow.push_back(lane);
450  }
451 
453  void primaryLaneChanged(MSLane* source, MSLane* target, int direction);
454 
456  void laneChangeOutput(const std::string& tag, MSLane* source, MSLane* target, int direction);
457 
459  virtual bool sublaneChangeCompleted(const double latDist) const {
460  UNUSED_PARAMETER(latDist);
461  throw ProcessError("Method not implemented by model " + toString(myModel));
462  }
463 
465  void setShadowApproachingInformation(MSLink* link) const;
467 
468  bool isOpposite() const {
469  return myAmOpposite;
470  }
471 
472  double getCommittedSpeed() const {
473  return myCommittedSpeed;
474  }
475 
477  double getSpeedLat() const {
478  return mySpeedLat;
479  }
480 
481  void setSpeedLat(double speedLat) {
482  mySpeedLat = speedLat;
483  }
484 
487  virtual double computeSpeedLat(double latDist, double& maneuverDist) {
488  UNUSED_PARAMETER(latDist);
489  UNUSED_PARAMETER(maneuverDist);
490  throw ProcessError("Method not implemented by model " + toString(myModel));
491  }
492 
494  virtual std::string getParameter(const std::string& key) const {
495  throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
496  }
497 
499  virtual void setParameter(const std::string& key, const std::string& value) {
500  UNUSED_PARAMETER(value);
501  throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
502  }
503 
504 
507  void checkTraCICommands();
508 
509  static const double NO_NEIGHBOR;
510 
511 protected:
512  virtual bool congested(const MSVehicle* const neighLeader);
513 
514  virtual bool predInteraction(const std::pair<MSVehicle*, double>& leader);
515 
517  bool cancelRequest(int state);
518 
519 
520 protected:
523 
530 
531  std::map<int, std::pair<int, int> > mySavedStates;
532 
534  double mySpeedLat;
535 
538 
541 
544 
548 
551 
554  /* @brief Lanes that are partially (laterally) occupied by the back of the
555  * vehicle (analogue to MSVehicle::myFurtherLanes) */
556  std::vector<MSLane*> myShadowFurtherLanes;
557  std::vector<double> myShadowFurtherLanesPosLat;
558 
559 
568 
569  /* @brief Further upstream lanes that are affected by the vehicle's maneuver (analogue to MSVehicle::myFurtherLanes)
570  * @note If myTargetLane==nullptr, we may assume myFurtherTargetLanes.size()==0, otherwise we have
571  * myFurtherTargetLanes.size() == myVehicle.getFurtherLanes.size()
572  * Here it may occur that an element myFurtherTargetLanes[i]==nullptr if myFurtherLanes[i] has
573  * no parallel lane in the change direction.
574  * */
575  std::vector<MSLane*> myFurtherTargetLanes;
576 
579 
582 
584  std::vector<MSLane*> myPartiallyOccupatedByShadow;
585 
586  /* @brief list of lanes where there is no shadow vehicle partial occupator
587  * (when changing to a lane that has no predecessor) */
588  std::vector<MSLane*> myNoPartiallyOccupatedByShadow;
589 
593 
603 
604  /* @brief to be called by derived classes in their changed() method.
605  * If dir=0 is given, the current value remains unchanged */
606  void initLastLaneChangeOffset(int dir);
607 
610 
612  static bool myLCOutput;
613  static bool myLCStartedOutput;
614  static bool myLCEndedOutput;
615 
616 
617 private:
618  /* @brief information how long ago the vehicle has performed a lane-change,
619  * sign indicates direction of the last change
620  */
622 
624  mutable std::vector<MSLink*> myApproachedByShadow;
625 
628 
629 
630 private:
633 };
634 
635 
636 #endif
637 
638 /****************************************************************************/
639 
virtual bool sublaneChangeCompleted(const double latDist) const
whether the current change completes the manoeuvre
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
std::vector< MSLane * > myPartiallyOccupatedByShadow
list of lanes where the shadow vehicle is partial occupator
const std::vector< double > & getShadowFurtherLanesPosLat() const
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:135
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
int myPreviousState
lane changing state from the previous simulation step
virtual void * inform(void *info, MSVehicle *sender)=0
void setLeaderGaps(CLeaderDist, double secGap)
MSVehicle * myNeighLeader
The leader on the lane the vehicle want to change to.
double myLastLeaderGap
the actual minimum longitudinal distances to vehicles on the target lane
int getShadowDirection() const
return the direction in which the current shadow lane lies
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model) ...
double myLaneChangeCompletion
progress of the lane change maneuver 0:started, 1:complete
The car-following model abstraction.
Definition: MSCFModel.h:59
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
Notification
Definition of a vehicle state.
static bool myLCOutput
whether to record lane-changing
double myLastOrigLeaderGap
acutal and secure distance to closest leader vehicle on the original when performing lane change ...
MSLCMessager(MSVehicle *leader, MSVehicle *neighLead, MSVehicle *neighFollow)
Constructor.
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
double getAngleOffset() const
return the angle offset during a continuous change maneuver
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key ...
virtual StateAndDist decideDirection(StateAndDist sd1, StateAndDist sd2) const
decide in which direction to move in case both directions are desirable
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
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)
bool sameDirection(const StateAndDist &other) const
MSLane * myTargetLane
The target lane for the vehicle&#39;s current maneuver.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
SUMOTime remainingTime() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver ...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:3674
void saveState(const int dir, const int stateWithoutTraCI, const int state)
std::vector< double > myShadowFurtherLanesPosLat
virtual double computeSpeedLat(double latDist, double &maneuverDist)
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
virtual double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel)=0
Called to adapt the speed in order to allow a lane change. It uses information on LC-related desired ...
MSVehicle * myNeighFollower
The follower on the lane the vehicle want to change to.
void setFollowerGaps(CLeaderDist follower, double secGap)
const LaneChangeModel myModel
the type of this model
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
A class responsible for exchanging messages between cars involved in lane-change interaction.
LaneChangeModel
The vehicle changes lanes (micro only)
The action has not been determined.
bool cancelRequest(int state)
whether the influencer cancels the given request
std::vector< MSLane * > myNoPartiallyOccupatedByShadow
double myManeuverDist
The complete lateral distance the vehicle wants to travel to finish its maneuver Only used by sublane...
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
void setShadowPartialOccupator(MSLane *lane)
void setShadowLane(MSLane *lane)
set the shadow lane
virtual void setParameter(const std::string &key, const std::string &value)
try to set the given parameter for this laneChangeModel. Throw exception for unsupported key ...
virtual int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
std::vector< MSLane * > myShadowFurtherLanes
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
int myLaneChangeDirection
direction of the lane change maneuver -1 means right, 1 means left
bool pastMidpoint() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver ...
virtual void changed()=0
static void initGlobalOptions(const OptionsCont &oc)
init global model parameters
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
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.
MSLane * determineTargetLane(int &targetDir) const
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
void setOrigLeaderGaps(CLeaderDist, double secGap)
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
virtual void updateExpectedSublaneSpeeds(const MSLeaderDistanceInfo &ahead, int sublaneOffset, int laneIndex)
update expected speeds for each sublane of the current edge
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
MSAbstractLaneChangeModel & operator=(const MSAbstractLaneChangeModel &s)
Invalidated assignment operator.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:41
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
virtual void setOwnState(const int state)
void setNoShadowPartialOccupator(MSLane *lane)
StateAndDist(int _state, double _latDist, double _targetDist, int _dir)
void * informLeader(void *info, MSVehicle *sender)
Informs the leader on the same lane.
void resetChanged()
reset the flag whether a vehicle already moved to false
A storage for options typed value containers)
Definition: OptionsCont.h:98
std::vector< MSLane * > myFurtherTargetLanes
double mySpeedLat
the current lateral speed
static bool haveLCOutput()
whether lanechange-output is active
virtual int wantsChangeSublane(int laneOffset, LaneChangeAction alternatives, const MSLeaderDistanceInfo &leaders, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &blockers, const MSLeaderDistanceInfo &neighLeaders, const MSLeaderDistanceInfo &neighFollowers, const MSLeaderDistanceInfo &neighBlockers, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked, double &latDist, double &targetDistLat, int &blocked)
virtual void saveBlockerLength(double length)
reserve space at the end of the lane to avoid dead locks
MSLane * getTargetLane() const
Returns the lane the vehicle has committed to enter during a sublane lane change. ...
const std::vector< MSLane * > & getShadowFurtherLanes() const
void changedToOpposite()
called when a vehicle changes between lanes in opposite directions
static bool outputLCStarted()
whether start of maneuvers shall be recorede
long long int SUMOTime
Definition: TraCIDefs.h:51
double myCommittedSpeed
the speed when committing to a change maneuver
#define NUMERICAL_EPS
Definition: config.h:151
std::vector< MSLink * > myApproachedByShadow
links which are approached by the shadow vehicle
MSLane * getShadowLane() const
Returns the lane the vehicle&#39;s shadow is on during continuous/sublane lane change.
void setManeuverDist(const double dist)
Updates the remaining distance for the current maneuver while it is continued within non-action steps...
virtual void updateSafeLatDist(const double travelledLatDist)
Updates the value of safe lateral distances (in SL2015) during maneuver continuation in non-action st...
static bool outputLCEnded()
whether start of maneuvers shall be recorede
int myPreviousState2
lane changing state from step before the previous simulation step
double myLastLateralGapLeft
the minimum lateral gaps to other vehicles that were found when last changing to the left and right ...
void laneChangeOutput(const std::string &tag, MSLane *source, MSLane *target, int direction)
called once the vehicle ends a lane change manoeuvre (non-instant)
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:77
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.
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
Interface for lane-change models.
const std::vector< MSLane * > & getFurtherTargetLanes() const
MSVehicle * myLeader
The leader on the informed vehicle&#39;s lane.
std::map< int, std::pair< int, int > > mySavedStates
virtual bool congested(const MSVehicle *const neighLeader)
const std::pair< int, int > & getSavedState(const int dir) const
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual ~MSAbstractLaneChangeModel()
Destructor.