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 }
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
double getSpeedLimit() const
Returns the lane&#39;s maximum allowed speed.
Definition: MSLane.h:476
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:687
double getCenterOnEdge() const
Definition: MSLane.h:932
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
bool hasInfluencer() const
Definition: MSVehicle.h:1425
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:178
bool congested() const
Definition: MSVehicle.h:624
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:158
double myLateralspeed
The lateral offset during a continuous LaneChangeManeuver.
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:2081
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:223
Wants go to the left.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
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
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: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
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
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:236
void enteredByLaneChange(MSVehicle *v)
Definition: MSLane.cpp:2088
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
std::vector< MSLane * > myShadowFurtherLanes
#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:2347
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:3323
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.
const std::vector< MSLane * > & getFurtherLanes() const
Definition: MSVehicle.h:683
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)
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 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: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: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:3681
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:488
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.
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:442
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual ~MSAbstractLaneChangeModel()
Destructor.