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-2016 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),
91  myLateralspeed(0),
92  myAlreadyChanged(false),
93  myShadowLane(0),
94  myCarFollowModel(v.getCarFollowModel()),
95  myModel(model),
97  myAmOpposite(false) {
98 }
99 
100 
102 }
103 
104 void
106  myOwnState = state;
107  // reset lateral influence after step is completed
108  if (myVehicle.hasInfluencer()) {
110  }
111 }
112 
113 bool
115  if (neighLeader == 0) {
116  return false;
117  }
118  // Congested situation are relevant only on highways (maxSpeed > 70km/h)
119  // and congested on German Highways means that the vehicles have speeds
120  // below 60km/h. Overtaking on the right is allowed then.
121  if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
122 
123  return false;
124  }
125  if (myVehicle.congested() && neighLeader->congested()) {
126  return true;
127  }
128  return false;
129 }
130 
131 
132 
133 bool
134 MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, double>& leader) {
135  if (leader.first == 0) {
136  return false;
137  }
138  // let's check it on highways only
139  if (leader.first->getSpeed() < (80.0 / 3.6)) {
140  return false;
141  }
142  return leader.second < myCarFollowModel.interactionGap(&myVehicle, leader.first->getSpeed());
143 }
144 
145 
146 bool
148  if (&source->getEdge() != &target->getEdge()) {
150  }
153  myLaneChangeDirection = direction;
154  myLateralspeed = (target->getCenterOnEdge() - source->getCenterOnEdge()) * (double)DELTA_T / (double)MSGlobals::gLaneChangeDuration;
157  return true;
158  } else {
159  primaryLaneChanged(source, target, direction);
160  return false;
161  }
162 }
163 
164 
165 void
167  initLastLaneChangeOffset(direction);
169  source->leftByLaneChange(&myVehicle);
171  target->enteredByLaneChange(&myVehicle);
172  if (myLCOutput) {
173  OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
174  of.openTag("change");
176  of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
177  of.writeAttr(SUMO_ATTR_FROM, source->getID());
178  of.writeAttr(SUMO_ATTR_TO, target->getID());
179  of.writeAttr(SUMO_ATTR_DIR, direction);
183  const double latGap = direction < 0 ? myLastLateralGapRight : myLastLateralGapLeft;
184  of.writeAttr("latGap", latGap == NO_LATERAL_NEIGHBOR ? "None" : toString(latGap));
185  }
186  of.closeTag();
187  }
188  changed();
189 }
190 
191 
192 bool
194  const bool pastBefore = pastMidpoint();
196  return !pastBefore && pastMidpoint();
197 }
198 
199 
200 void
202  UNUSED_PARAMETER(reason);
208  if (myAmOpposite) {
210  }
211 }
212 
213 
214 MSLane*
217  // initialize shadow lane
218  const double overlap = myVehicle.getLateralOverlap();
219  if (myVehicle.getID() == "disabled") {
220  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << myVehicle.getLateralPositionOnLane() << " overlap=" << overlap << "\n";
221  }
222  if (overlap > NUMERICAL_EPS ||
223  // "reserve" target lane even when there is no overlap yet
225  const int shadowDirection = myVehicle.getLateralPositionOnLane() < 0 ? -1 : 1;
226  return lane->getParallelLane(shadowDirection);
227  } else {
228  return 0;
229  }
230  } else {
231  return 0;
232  }
233 }
234 
235 
236 void
238  if (myShadowLane != 0) {
239  if (myVehicle.getID() == "disabled") {
240  std::cout << SIMTIME << " cleanupShadowLane\n";
241  }
243  myShadowLane = 0;
244  }
245  for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
246  if (myVehicle.getID() == "disabled") {
247  std::cout << SIMTIME << " cleanupShadowLane2\n";
248  }
249  (*it)->resetPartialOccupation(&myVehicle);
250  }
251  myShadowFurtherLanes.clear();
253 }
254 
255 
256 bool
258  int ret = myVehicle.influenceChangeDecision(state);
259  return ret != state;
260 }
261 
262 
263 void
265  if (dir > 0) {
267  } else if (dir < 0) {
269  }
270 }
271 
272 void
274  if (myShadowLane != 0) {
275  if (debugVehicle()) {
276  std::cout << SIMTIME << " updateShadowLane\n";
277  }
279  }
281  std::vector<MSLane*> passed;
282  if (myShadowLane != 0) {
284  const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
285  const std::vector<double>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
286  assert(further.size() == furtherPosLat.size());
287  passed.push_back(myShadowLane);
288  for (int i = 0; i < (int)further.size(); ++i) {
289  if (furtherPosLat[i] == myVehicle.getLateralPositionOnLane()) {
290  MSLane* shadowFurther = getShadowLane(further[i]);
291  if (shadowFurther != 0 && MSLinkContHelper::getConnectingLink(*shadowFurther, *passed.back()) != 0) {
292  passed.push_back(shadowFurther);
293  }
294  } else {
295  // vehicle end is still on the original lane after lane changing
296  break;
297  }
298  }
299  std::reverse(passed.begin(), passed.end());
300  } else {
302  WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
303  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
305  }
306  }
307  if (debugVehicle()) std::cout << SIMTIME << " updateShadowLane veh=" << myVehicle.getID()
308  << " newShadowLane=" << Named::getIDSecure(myShadowLane)
309  << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " further=" << toString(myVehicle.getFurtherLanes()) << " passed=" << toString(passed)
310  << "\n";
312  if (debugVehicle()) std::cout
313  << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
314 }
315 
316 
317 int
319  if (isChangingLanes()) {
320  if (pastMidpoint()) {
321  return -myLaneChangeDirection;
322  } else {
323  return myLaneChangeDirection;
324  }
325  } else if (myShadowLane == 0) {
326  return 0;
327  } else {
328  assert(&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge());
330  }
331 }
332 
333 
334 double
337  return myLaneChangeDirection * angleOffset;
338 }
339 
340 
341 SUMOTime
344 }
345 
346 
347 void
349  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
350  myApproachedByShadow.push_back(link);
351 }
352 
353 void
355  for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
356  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
357  (*it)->removeApproaching(&myVehicle);
358  }
359  myApproachedByShadow.clear();
360 }
361 
362 
363 void
366  myAlreadyChanged = true;
367 }
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
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:256
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
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:488
int getShadowDirection() const
return the direction in which the current shadow lane lies
double myLaneChangeCompletion
progress of the lane change maneuver 0:started, 1:complete
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:158
double myLateralspeed
The lateral offset during a continuous LaneChangeManeuver.
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
double getAngleOffset() const
return the angle offset during a continuous change maneuver
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:2081
MSLane * myShadowLane
A lane that is partially occupied by the front of the vehicle but that is not the primary lane...
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:66
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:223
Wants go to the left.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
SUMOTime remainingTime() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver ...
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:2766
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
#define SIMTIME
Definition: SUMOTime.h:70
Right blinker lights are switched on.
Definition: MSVehicle.h:1071
std::vector< double > myShadowFurtherLanesPosLat
const LaneChangeModel myModel
the type of this model
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
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:2872
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
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:507
Left blinker lights are switched on.
Definition: MSVehicle.h:1073
#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:268
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:236
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it&#39;s primary lane ...
Definition: MSVehicle.cpp:3681
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:2347
double getCenterOnEdge() const
Definition: MSLane.h:932
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2088
std::vector< MSLane * > myShadowFurtherLanes
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:683
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:476
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
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:178
int myLaneChangeDirection
direction of the lane change maneuver -1 means right, 1 means left
bool hasInfluencer() const
Definition: MSVehicle.h:1425
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 fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:3323
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
int myOwnState
The current state of the vehicle.
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:407
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
const std::vector< double > & getFurtherLanesPosLat() const
Definition: MSVehicle.h:687
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.
trigger: the time of the step
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:3993
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
virtual void setOwnState(const int state)
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
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:1132
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:1124
long long int SUMOTime
Definition: TraCIDefs.h:52
#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 vehicles shadow is on during continuous/sublane lane change. ...
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:442
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:4017
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.
const std::string & getID() const
Returns the name of the vehicle.
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.
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:1685
virtual bool congested(const MSVehicle *const neighLeader)
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
bool congested() const
Definition: MSVehicle.h:624
virtual ~MSAbstractLaneChangeModel()
Destructor.