SUMO - Simulation of Urban MObility
MSLaneChangerSublane.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // Performs sub-lane changing of vehicles
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2002-2017 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #ifdef _MSC_VER
25 #include <windows_config.h>
26 #else
27 #include <config.h>
28 #endif
29 
30 #include "MSLaneChangerSublane.h"
31 #include "MSNet.h"
32 #include "MSVehicle.h"
33 #include "MSVehicleType.h"
34 #include "MSVehicleTransfer.h"
35 #include "MSGlobals.h"
36 #include <cassert>
37 #include <iterator>
38 #include <cstdlib>
39 #include <cmath>
42 #include <utils/geom/GeomHelper.h>
43 
44 
45 // ===========================================================================
46 // member method definitions
47 // ===========================================================================
48 MSLaneChangerSublane::MSLaneChangerSublane(const std::vector<MSLane*>* lanes, bool allowChanging) :
49  MSLaneChanger(lanes, allowChanging) {
50 }
51 
52 
54 
55 void
58  // Prepare myChanger with a safe state.
59  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
60  ce->ahead = ce->lane->getPartialBeyond();
61  //std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
62  }
63 }
64 
65 
66 
67 void
69  MSLaneChanger::updateChanger(vehHasChanged);
70  if (!vehHasChanged) {
71  MSVehicle* lead = myCandi->lead;
72  //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
73  myCandi->ahead.addLeader(lead, false, 0);
74  MSLane* shadowLane = lead->getLaneChangeModel().getShadowLane();
75  if (shadowLane != 0) {
76  const double latOffset = lead->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
77  //std::cout << SIMTIME << " updateChanger shadowLane=" << shadowLane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
78  (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(lead, false, latOffset);
79  }
80  }
81  //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(myCandi->lead) << " ahead=" << myCandi->ahead.toString() << " vehHasChanged=" << vehHasChanged << "\n";
82  //for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
83  // std::cout << " lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
84  //}
85 }
86 
87 
88 bool
90  // variant of change() for the sublane case
92  MSVehicle* vehicle = veh(myCandi);
93 #ifdef DEBUG_VEHICLE_GUI_SELECTION
94  if (gDebugSelectedVehicle == vehicle->getID()) {
95  int bla = 0;
96  }
97 #endif
98  assert(vehicle->getLane() == (*myCandi).lane);
99  assert(!vehicle->getLaneChangeModel().isChangingLanes());
100  if ( vehicle->isStoppedOnLane()) {
101  registerUnchanged(vehicle);
102  return false;
103  }
104 #ifndef NO_TRACI
105  if (vehicle->isRemoteControlled()) {
106  registerUnchanged(vehicle);
107  return false;
108  }
109 #endif
110  vehicle->updateBestLanes(); // needed?
111  for (int i = 0; i < (int) myChanger.size(); ++i) {
112  vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
113  }
114 
115  // update expected speeds
116  int sublaneIndex = 0;
117  for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
118  vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ce->ahead, sublaneIndex, ce->lane->getIndex());
119  sublaneIndex += ce->ahead.numSublanes();
120  }
121 
123  | (mayChange(1) ? LCA_LEFT : LCA_NONE));
124 
125  StateAndDist right = checkChangeHelper(vehicle, -1, alternatives);
126  StateAndDist left = checkChangeHelper(vehicle, 1, alternatives);
127  StateAndDist current = checkChangeHelper(vehicle, 0, alternatives);
128 
129  StateAndDist decision = vehicle->getLaneChangeModel().decideDirection(current,
130  vehicle->getLaneChangeModel().decideDirection(right, left));
131  if ((decision.state & LCA_WANTS_LANECHANGE) != 0 && (decision.state & LCA_BLOCKED) == 0) {
132  // change if the vehicle wants to and is allowed to change
133  if (vehicle->getLaneChangeModel().debugVehicle()) {
134  std::cout << SIMTIME << " decision=" << toString((LaneChangeAction)decision.state) << " latDist=" << decision.latDist << "\n";
135  }
136  vehicle->getLaneChangeModel().setOwnState(decision.state);
137  return startChangeSublane(vehicle, myCandi, decision.latDist);
138  } else {
139  // @note this assumes vehicles can instantly abort any maneuvre in case of emergency
140  vehicle->getLaneChangeModel().setSpeedLat(0);
141  }
142 
143  if ((right.state & (LCA_URGENT)) != 0 && (left.state & (LCA_URGENT)) != 0) {
144  // ... wants to go to the left AND to the right
145  // just let them go to the right lane...
146  left.state = 0;
147  }
148  vehicle->getLaneChangeModel().setOwnState(right.state | left.state | current.state);
149 
150  registerUnchanged(vehicle);
151  return false;
152 }
153 
154 
156 MSLaneChangerSublane::checkChangeHelper(MSVehicle* vehicle, int laneOffset, LaneChangeAction alternatives) {
157  StateAndDist result = StateAndDist(0, 0, 0);
158  if (mayChange(laneOffset)) {
159  const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
160  result.state = checkChangeSublane(laneOffset, alternatives, preb, result.latDist);
161  result.dir = laneOffset;
162  if ((result.state & LCA_WANTS_LANECHANGE) != 0 && (result.state & LCA_URGENT) != 0 && (result.state & LCA_BLOCKED) != 0) {
163  (myCandi + laneOffset)->lastBlocked = vehicle;
164  if ((myCandi + laneOffset)->firstBlocked == 0) {
165  (myCandi + laneOffset)->firstBlocked = vehicle;
166  }
167  }
168  }
169  return result;
170 }
171 
172 
173 bool
175  // 1) update vehicles lateral position according to latDist and target lane
176  vehicle->myState.myPosLat += latDist;
178  vehicle->getLaneChangeModel().setSpeedLat(DIST2SPEED(latDist));
179 
180  // 2) distinguish several cases
181  // a) vehicle moves completely within the same lane
182  // b) vehicle intersects another lane
183  // - vehicle must be moved to the lane where it's midpoint is (either old or new)
184  // - shadow vehicle must be created/moved to the other lane if the vehicle intersects it
185  // 3) updated dens of all lanes that hold the vehicle or its shadow
186  const int direction = vehicle->getLateralPositionOnLane() < 0 ? -1 : 1;
187  ChangerIt to = from;
188  if (mayChange(direction)) {
189  to = from + direction;
190  } else {
192  }
193  const bool changedToNewLane = to != from && fabs(vehicle->getLateralPositionOnLane()) > 0.5 * vehicle->getLane()->getWidth() && mayChange(direction);
194  if (changedToNewLane) {
195  vehicle->myState.myPosLat -= direction * 0.5 * (from->lane->getWidth() + to->lane->getWidth());
196  to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
197  to->dens += vehicle->getVehicleType().getLengthWithGap();
199  vehicle->getLaneChangeModel().setLeaderGaps(getLeaders(to, vehicle));
200  vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
201  }
202  vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
203  to->ahead.addLeader(vehicle, false, 0);
204  } else {
205  registerUnchanged(vehicle);
206  from->ahead.addLeader(vehicle, false, 0);
207  }
208 
209  MSLane* oldShadowLane = vehicle->getLaneChangeModel().getShadowLane();
211  MSLane* shadowLane = vehicle->getLaneChangeModel().getShadowLane();
212  if (shadowLane != 0 && shadowLane != oldShadowLane) {
213  assert(to != from);
214  const double latOffset = vehicle->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
215  (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(vehicle, false, latOffset);
216  }
217 
218 
219  // compute new angle of the vehicle from the x- and y-distances travelled within last time step
220  // (should happen last because primaryLaneChanged() also triggers angle computation)
221  // this part of the angle comes from the orientation of our current lane
222  double laneAngle = vehicle->getLane()->getShape().rotationAtOffset(vehicle->getLane()->interpolateLanePosToGeometryPos(vehicle->getPositionOnLane())) ;
223  // this part of the angle comes from the vehicle's lateral movement
224  double changeAngle = 0;
225  // avoid flicker
226  if (fabs(latDist) > NUMERICAL_EPS) {
227  // angle is between vehicle front and vehicle back (and depending on travelled distance)
228  changeAngle = atan2(latDist, vehicle->getVehicleType().getLength() + SPEED2DIST(vehicle->getSpeed()));
229  }
230  if (vehicle->getLaneChangeModel().debugVehicle()) std::cout << SIMTIME << " startChangeSublane shadowLane"
231  << " latDist=" << latDist
232  << " old=" << Named::getIDSecure(oldShadowLane)
233  << " new=" << Named::getIDSecure(vehicle->getLaneChangeModel().getShadowLane())
234  << " laneA=" << RAD2DEG(laneAngle)
235  << " changeA=" << RAD2DEG(changeAngle)
236  << " oldA=" << RAD2DEG(vehicle->getAngle())
237  << " newA=" << RAD2DEG(laneAngle + changeAngle)
238  << "\n";
239  vehicle->setAngle(laneAngle + changeAngle);
240 
241  return changedToNewLane;
242 }
243 
244 
246 MSLaneChangerSublane::getLeaders(const ChangerIt& target, const MSVehicle* ego) const {
247  //if (ego->getID() == "C" && SIMTIME == 17) {
248  // std::cout << "DEBUG\n";
249  //}
250  // get the leading vehicle on the lane to change to
251  if (gDebugFlag1) {
252  std::cout << SIMTIME << " getLeaders lane=" << target->lane->getID() << " ego=" << ego->getID() << " ahead=" << target->ahead.toString() << "\n";
253  }
254  MSLeaderDistanceInfo result(target->lane, 0, 0);
255  for (int i = 0; i < target->ahead.numSublanes(); ++i) {
256  const MSVehicle* veh = target->ahead[i];
257  if (veh != 0) {
258  const double gap = veh->getBackPositionOnLane(target->lane) - ego->getPositionOnLane() - ego->getVehicleType().getMinGap();
259  if (gDebugFlag1) {
260  std::cout << " ahead lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane() << " gap=" << gap << "\n";
261  }
262  result.addLeader(veh, gap, 0, i);
263  }
264  }
265  // if there are vehicles on the target lane with the same position as ego,
266  // they may not have been added to 'ahead' yet
267  const MSLeaderInfo& aheadSamePos = target->lane->getLastVehicleInformation(0, 0, ego->getPositionOnLane(), false);
268  for (int i = 0; i < aheadSamePos.numSublanes(); ++i) {
269  const MSVehicle* veh = aheadSamePos[i];
270  if (veh != 0 && veh != ego) {
271  const double gap = veh->getBackPositionOnLane(target->lane) - ego->getPositionOnLane() - ego->getVehicleType().getMinGap();
272  if (gDebugFlag1) {
273  std::cout << " further lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane(target->lane) << " gap=" << gap << "\n";
274  }
275  result.addLeader(veh, gap, 0, i);
276  }
277  }
278 
279  if (result.numFreeSublanes() > 0) {
280  MSLane* targetLane = target->lane;
281 
282  double seen = ego->getLane()->getLength() - ego->getPositionOnLane();
283  double speed = ego->getSpeed();
284  double dist = ego->getCarFollowModel().brakeGap(speed) + ego->getVehicleType().getMinGap();
285  if (seen > dist) {
286  return result;
287  }
288  const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane);
289  if (gDebugFlag1) {
290  std::cout << " add consecutive before=" << result.toString() << " dist=" << dist;
291  }
292  target->lane->getLeadersOnConsecutive(dist, seen, speed, ego, bestLaneConts, result);
293  if (gDebugFlag1) {
294  std::cout << " after=" << result.toString() << "\n";
295  }
296  }
297  return result;
298 }
299 
300 
301 int
303  int laneOffset,
304  LaneChangeAction alternatives,
305  const std::vector<MSVehicle::LaneQ>& preb,
306  double& latDist) const {
307 
308  ChangerIt target = myCandi + laneOffset;
309  MSVehicle* vehicle = veh(myCandi);
310  const MSLane& neighLane = *(target->lane);
311  int blocked = 0;
312 
313  //gDebugFlag1 = vehicle->getLaneChangeModel().debugVehicle();
314 
315  MSLeaderDistanceInfo neighLeaders = getLeaders(target, vehicle);
316  MSLeaderDistanceInfo neighFollowers = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
317  MSLeaderDistanceInfo neighBlockers(&neighLane, vehicle, vehicle->getLane()->getRightSideOnEdge() - neighLane.getRightSideOnEdge());
318  MSLeaderDistanceInfo leaders = getLeaders(myCandi, vehicle);
319  MSLeaderDistanceInfo followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
320  MSLeaderDistanceInfo blockers(vehicle->getLane(), vehicle, 0);
321 
322  if (gDebugFlag1) std::cout << SIMTIME
323  << " checkChangeSublane: veh=" << vehicle->getID()
324  << " laneOffset=" << laneOffset
325  << "\n leaders=" << leaders.toString()
326  << "\n neighLeaders=" << neighLeaders.toString()
327  << "\n followers=" << followers.toString()
328  << "\n neighFollowers=" << neighFollowers.toString()
329  << "\n";
330 
331 
332  const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
333  laneOffset, alternatives,
334  leaders, followers, blockers,
335  neighLeaders, neighFollowers, neighBlockers,
336  neighLane, preb,
337  &(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, blocked);
338  int state = blocked | wish;
339 
340  // XXX
341  // do are more carefull (but expensive) check to ensure that a
342  // safety-critical leader is not being overloocked
343 
344  // XXX
345  // ensure that a continuous lane change manoeuvre can be completed
346  // before the next turning movement
347 
348  const int oldstate = state;
349 #ifndef NO_TRACI
350  // let TraCI influence the wish to change lanes and the security to take
351  state = vehicle->influenceChangeDecision(state);
352  //if (vehicle->getID() == "150_2_36000000") {
353  // std::cout << STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) << " veh=" << vehicle->getID() << " oldstate=" << oldstate << " newstate=" << state << "\n";
354  //}
355 #endif
356  vehicle->getLaneChangeModel().saveState(laneOffset, oldstate, state);
357  gDebugFlag1 = false;
358  return state;
359 }
360 
361 /****************************************************************************/
362 
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:33
void setAngle(double angle)
Set a custom vehicle angle in rad.
Definition: MSVehicle.cpp:929
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
Definition: MSVehicle.cpp:4267
double getMinGap() const
Get the free space in front of vehicles of this class.
#define DIST2SPEED(x)
Definition: SUMOTime.h:57
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:136
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:500
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:83
#define SPEED2DIST(x)
Definition: SUMOTime.h:55
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:796
int numSublanes() const
Definition: MSLeaderInfo.h:95
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, int &blocked)
State myState
This Vehicles driving state (pos and speed)
Definition: MSVehicle.h:1535
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
void setLeaderGaps(CLeaderDist, double secGap)
virtual bool debugVehicle() const
whether the current vehicles shall be debugged
virtual std::string toString() const
print a debugging representation
bool isStoppedOnLane() const
Definition: MSVehicle.cpp:1245
virtual void initChanger()
Initialize the changer before looping over all vehicles.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
double myPosLat
the stored lateral position
Definition: MSVehicle.h:146
Wants go to the right.
double interpolateLanePosToGeometryPos(double lanePos) const
Definition: MSLane.h:442
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:484
StateAndDist checkChangeHelper(MSVehicle *vehicle, int laneOffset, LaneChangeAction alternatives)
helper function that calls checkChangeSublane and sets blocker information
MSVehicle * veh(ConstChangerIt ce) const
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
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:375
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
Definition: MSVehicle.cpp:3541
double getAngle() const
Returns the vehicle&#39;s direction in radians.
Definition: MSVehicle.h:605
#define RAD2DEG(x)
Definition: GeomHelper.h:46
Wants go to the left.
virtual void updateChanger(bool vehHasChanged)
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:3144
#define SIMTIME
Definition: SUMOTime.h:70
std::string gDebugSelectedVehicle
Definition: StdDefs.cpp:37
void saveState(const int dir, const int stateWithoutTraCI, const int state)
void setFollowerGaps(CLeaderDist follower, double secGap)
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
Performs lane changing of vehicles.
Definition: MSLaneChanger.h:55
virtual int addLeader(const MSVehicle *veh, double gap, double latOffset=0, int sublane=-1)
int numFreeSublanes() const
Definition: MSLeaderInfo.h:99
MSLaneChangerSublane()
Default constructor.
virtual void updateChanger(bool vehHasChanged)
blocked in all directions
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
The action is urgent (to be defined by lc-model)
virtual void updateExpectedSublaneSpeeds(const MSLeaderInfo &ahead, int sublaneOffset, int laneIndex)
update expected speeds for each sublane of the current edge
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:3502
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
Definition: MSVehicle.cpp:3162
Position myCachedPosition
Definition: MSVehicle.h:1599
MSLeaderDistanceInfo getLeaders(const ChangerIt &target, const MSVehicle *ego) const
get leaders for ego on the given lane
bool startChangeSublane(MSVehicle *vehicle, ChangerIt &from, double latDist)
change by the specified amount and return whether a new lane was entered
virtual StateAndDist decideDirection(StateAndDist sd1, StateAndDist sd2) const
decide in which direction to move in case both directions are desirable
virtual void initChanger()
Initialize the changer before looping over all vehicles.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:2617
MSLane * getShadowLane() const
Returns the lane the vehicles shadow is on during continuous/sublane lane change. ...
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:507
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:3156
~MSLaneChangerSublane()
Destructor.
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
double getLength() const
Get vehicle&#39;s length [m].
LaneChangeAction
The state of a vehicle&#39;s lane-change behavior.
virtual void setOwnState(const int state)
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
static bool haveLCOutput()
whether lanechange-output is active
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:407
MSAbstractLaneChangeModel::StateAndDist StateAndDist
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:426
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
double getRightSideOnEdge() const
Definition: MSLane.h:935
void registerUnchanged(MSVehicle *vehicle)
#define NUMERICAL_EPS
Definition: config.h:152
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
int checkChangeSublane(int laneOffset, LaneChangeAction alternatives, const std::vector< MSVehicle::LaneQ > &preb, double &latDist) const
check whether sub-lane changing in the given direction is desirable and possible
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time tau (i...
Definition: MSCFModel.h:290
ChangerIt myCandi
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:278
const std::string & getID() const
Returns the name of the vehicle.
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:443