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_JE2013.h"
43 #include "MSLCM_SL2015.h"
44 
45 /* -------------------------------------------------------------------------
46  * static members
47  * ----------------------------------------------------------------------- */
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_JE2013:
73  return new MSLCM_JE2013(v);
74  case LCM_SL2015:
75  return new MSLCM_SL2015(v);
76  case LCM_DEFAULT:
78  return new MSLCM_LC2013(v);
79  } else {
80  return new MSLCM_SL2015(v);
81  }
82  default:
83  throw ProcessError("Lane change model '" + toString(lcm) + "' not implemented");
84  }
85 }
86 
87 
89  myVehicle(v),
90  myOwnState(0),
93  myLateralspeed(0),
94  myAlreadyChanged(false),
95  myShadowLane(0),
96  myCarFollowModel(v.getCarFollowModel()),
97  myModel(model),
99  myAmOpposite(false) {
100 }
101 
102 
104 }
105 
106 
107 bool
109  if (neighLeader == 0) {
110  return false;
111  }
112  // Congested situation are relevant only on highways (maxSpeed > 70km/h)
113  // and congested on German Highways means that the vehicles have speeds
114  // below 60km/h. Overtaking on the right is allowed then.
115  if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
116 
117  return false;
118  }
119  if (myVehicle.congested() && neighLeader->congested()) {
120  return true;
121  }
122  return false;
123 }
124 
125 
126 
127 bool
128 MSAbstractLaneChangeModel::predInteraction(const std::pair<MSVehicle*, SUMOReal>& leader) {
129  if (leader.first == 0) {
130  return false;
131  }
132  // let's check it on highways only
133  if (leader.first->getSpeed() < (80.0 / 3.6)) {
134  return false;
135  }
136  return leader.second < myCarFollowModel.interactionGap(&myVehicle, leader.first->getSpeed());
137 }
138 
139 
140 bool
142  if (&source->getEdge() != &target->getEdge()) {
144  }
147  myLaneChangeDirection = direction;
151  return true;
152  } else {
153  primaryLaneChanged(source, target, direction);
154  return false;
155  }
156 }
157 
158 
159 void
161  initLastLaneChangeOffset(direction);
163  source->leftByLaneChange(&myVehicle);
165  target->enteredByLaneChange(&myVehicle);
166  if (myLCOutput) {
167  OutputDevice& of = OutputDevice::getDeviceByOption("lanechange-output");
168  of.openTag("change");
170  of.writeAttr(SUMO_ATTR_TIME, time2string(MSNet::getInstance()->getCurrentTimeStep()));
171  of.writeAttr(SUMO_ATTR_FROM, source->getID());
172  of.writeAttr(SUMO_ATTR_TO, target->getID());
173  of.writeAttr(SUMO_ATTR_DIR, direction);
176  of.closeTag();
177  }
178  changed();
179 }
180 
181 
182 bool
184  const bool pastBefore = pastMidpoint();
186  return !pastBefore && pastMidpoint();
187 }
188 
189 
190 void
192  UNUSED_PARAMETER(reason);
198 }
199 
200 
201 MSLane*
204  // initialize shadow lane
205  const SUMOReal overlap = myVehicle.getLateralOverlap();
206  if (myVehicle.getID() == "disabled") {
207  std::cout << SIMTIME << " veh=" << myVehicle.getID() << " posLat=" << myVehicle.getLateralPositionOnLane() << " overlap=" << overlap << "\n";
208  }
209  if (overlap > NUMERICAL_EPS ||
210  // "reserve" target lane even when there is no overlap yet
212  const int shadowDirection = myVehicle.getLateralPositionOnLane() < 0 ? -1 : 1;
213  return lane->getParallelLane(shadowDirection);
214  } else {
215  return 0;
216  }
217  } else {
218  return 0;
219  }
220 }
221 
222 
223 void
225  if (myShadowLane != 0) {
226  if (myVehicle.getID() == "disabled") {
227  std::cout << SIMTIME << " cleanupShadowLane\n";
228  }
230  myShadowLane = 0;
231  }
232  for (std::vector<MSLane*>::const_iterator it = myShadowFurtherLanes.begin(); it != myShadowFurtherLanes.end(); ++it) {
233  if (myVehicle.getID() == "disabled") {
234  std::cout << SIMTIME << " cleanupShadowLane2\n";
235  }
236  (*it)->resetPartialOccupation(&myVehicle);
237  }
238  myShadowFurtherLanes.clear();
240 }
241 
242 
243 bool
245  int ret = myVehicle.influenceChangeDecision(state);
246  return ret != state;
247 }
248 
249 
250 void
252  if (dir > 0) {
254  } else if (dir < 0) {
256  }
257 }
258 
259 void
261  if (myShadowLane != 0) {
262  if (gDebugFlag4) {
263  std::cout << SIMTIME << " updateShadowLane\n";
264  }
266  }
268  std::vector<MSLane*> passed;
269  if (myShadowLane != 0) {
271  const std::vector<MSLane*>& further = myVehicle.getFurtherLanes();
272  const std::vector<SUMOReal>& furtherPosLat = myVehicle.getFurtherLanesPosLat();
273  assert(further.size() == furtherPosLat.size());
274  for (int i = (int)further.size() - 1; i >= 0; --i) {
275  if (furtherPosLat[i] == myVehicle.getLateralPositionOnLane()) {
276  MSLane* shadowFurther = getShadowLane(further[i]);
277  if (shadowFurther != 0) {
278  passed.push_back(shadowFurther);
279  }
280  } else {
281  // vehicle end is still on the original lane after lane changing
282  break;
283  }
284  }
285  passed.push_back(myShadowLane);
286  } else {
288  WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
289  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
291  }
292  }
293  if (gDebugFlag4) std::cout << SIMTIME << " updateShadowLane veh=" << myVehicle.getID()
294  << " newShadowLane=" << Named::getIDSecure(myShadowLane)
295  << "\n before:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << " passed=" << toString(passed)
296  << "\n";
298  if (gDebugFlag4) std::cout
299  << "\n after:" << " myShadowFurtherLanes=" << toString(myShadowFurtherLanes) << "\n";
300 }
301 
302 
303 int
305  if (isChangingLanes()) {
306  if (pastMidpoint()) {
307  return -myLaneChangeDirection;
308  } else {
309  return myLaneChangeDirection;
310  }
311  } else if (myShadowLane == 0) {
312  return 0;
313  } else {
314  assert(&myShadowLane->getEdge() == &myVehicle.getLane()->getEdge());
316  }
317 }
318 
319 
320 SUMOReal
323  return myLaneChangeDirection * angleOffset;
324 }
325 
326 
327 SUMOTime
330 }
331 
332 
333 void
335  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " set shadow approaching=" << link->getViaLaneOrLane()->getID() << "\n";
336  myApproachedByShadow.push_back(link);
337 }
338 
339 void
341  for (std::vector<MSLink*>::iterator it = myApproachedByShadow.begin(); it != myApproachedByShadow.end(); ++it) {
342  //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " @=" << &myVehicle << " remove shadow approaching=" << (*it)->getViaLaneOrLane()->getID() << "\n";
343  (*it)->removeApproaching(&myVehicle);
344  }
345  myApproachedByShadow.clear();
346 }
347 
348 
349 void
352  myAlreadyChanged = true;
353 }
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:257
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:567
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:81
long long int SUMOTime
Definition: SUMOTime.h:43
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
std::vector< SUMOReal > myShadowFurtherLanesPosLat
virtual bool predInteraction(const std::pair< MSVehicle *, SUMOReal > &leader)
bool congested() const
Definition: MSVehicle.h:542
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:59
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:159
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
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
SUMOReal getCenterOnEdge() const
Definition: MSLane.h:894
void leftByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:1945
MSLane * myShadowLane
A lane that is partially occupied by the front of the vehicle but that is not the primary lane...
Wants go to the left.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
void enterLaneAtLaneChange(MSLane *enteredLane)
Update when the vehicle enters a new lane in the laneChange step.
Definition: MSVehicle.cpp:2321
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
SUMOReal updateFurtherLanes(std::vector< MSLane * > &furtherLanes, std::vector< SUMOReal > &furtherLanesPosLat, const std::vector< MSLane * > &passedLanes)
update a vector of further lanes and return the new backPos
Definition: MSVehicle.cpp:1911
A lane change model developed by J. Erdmann.
Definition: MSLCM_JE2013.h:47
#define SIMTIME
Definition: SUMOTime.h:70
Right blinker lights are switched on.
Definition: MSVehicle.h:942
SUMOReal getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:375
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
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:49
Left blinker lights are switched on.
Definition: MSVehicle.h:944
bool cancelRequest(int state)
whether the influencer cancels the given request
std::vector< MSLane * > myNoPartiallyOccupatedByShadow
SUMOReal getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it&#39;s primary lane ...
Definition: MSVehicle.cpp:3200
bool pastMidpoint() const
return whether the vehicle passed the midpoint of a continuous lane change maneuver ...
virtual void resetPartialOccupation(MSVehicle *v)
Removes the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:224
virtual SUMOReal interactionGap(const MSVehicle *const veh, SUMOReal vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
Definition: MSCFModel.cpp:74
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:1952
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:1494
std::vector< MSLane * > myShadowFurtherLanes
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
SUMOReal getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:467
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. ...
virtual SUMOReal setPartialOccupation(MSVehicle *v)
Sets the information about a vehicle lapping into this lane.
Definition: MSLane.cpp:211
void fixPosition()
repair errors in vehicle position after changing between internal edges
Definition: MSVehicle.cpp:2854
int myOwnState
The current state of the vehicle.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:498
bool gDebugFlag4
Definition: StdDefs.cpp:94
SUMOReal getAngleOffset() const
return the angle offset during a continuous change maneuver
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void leaveLane(const MSMoveReminder::Notification reason)
Update of members if vehicle leaves a new lane in the lane change step or at arrival.
Definition: MSVehicle.cpp:2413
void setShadowApproachingInformation(MSLink *link) const
set approach information for the shadow vehicle
const std::vector< SUMOReal > & getFurtherLanesPosLat() const
Definition: MSVehicle.h:604
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.
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:600
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
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
static SUMOReal gLateralResolution
Definition: MSGlobals.h:84
SUMOReal myLateralspeed
The lateral offset during a continuous LaneChangeManeuver.
SUMOReal getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:410
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.
#define SUMOReal
Definition: config.h:213
void switchOffSignal(int signal)
Switches the given signal off.
Definition: MSVehicle.h:1003
void switchOnSignal(int signal)
Switches the given signal on.
Definition: MSVehicle.h:995
#define NUMERICAL_EPS
Definition: config.h:160
std::vector< MSLink * > myApproachedByShadow
links which are approached by the shadow vehicle
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:447
SUMOReal myLaneChangeCompletion
progress of the lane change maneuver 0:started, 1:complete
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
Definition: MSVehicle.cpp:3472
static SUMOTime gLaneChangeDuration
Definition: MSGlobals.h:81
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)
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual ~MSAbstractLaneChangeModel()
Destructor.