Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSLaneChanger.h
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2002-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// Performs lane changing of vehicles
22/****************************************************************************/
23#pragma once
24#include <config.h>
25
26#include "MSLane.h"
27#include "MSEdge.h"
28#include "MSVehicle.h"
29#include <vector>
31
32
33// ===========================================================================
34// class declarations
35// ===========================================================================
36
37
38// ===========================================================================
39// class definitions
40// ===========================================================================
46public:
48 MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging);
49
51 virtual ~MSLaneChanger();
52
54 void laneChange(SUMOTime t);
55
56public:
61 struct ChangeElem {
62
63 ChangeElem(MSLane* _lane);
64
66 void registerHop(MSVehicle* vehicle);
67
80
81 double dens;
82
86
89 std::vector<int> siblings;
90
93 // the vehicles in front of the current vehicle (only on the current edge, continously updated during change() )
95
96 // the vehicles in front of the current vehicle (including those on the next edge, contiously update during change() ))
98
100 std::vector<MSVehicle*> outsideBounds;
101
104
107
111
112 };
113
114public:
117 typedef std::vector< ChangeElem > Changer;
118
120 typedef Changer::iterator ChangerIt;
121
123 typedef Changer::const_iterator ConstChangerIt;
124
127 return myChanger;
128 }
129
131 std::pair<double, SUMOTime> getLastBlocked(int index) const;
132
133protected:
135 virtual void initChanger();
136
139 bool vehInChanger() const {
140 // If there is at least one valid vehicle under the veh's in myChanger
141 // return true.
142 for (ConstChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
143 if (veh(ce) != 0) {
144 return true;
145 }
146 }
147 return false;
148 }
149
153 // If ce has a valid vehicle, return it. Otherwise return 0.
154 if (!ce->lane->myVehicles.empty()) {
155 return ce->lane->myVehicles.back();
156 } else {
157 return 0;
158 }
159 }
160
161
163 virtual bool change();
164
165
167 bool changeOpposite(MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, MSVehicle* lastStopped);
168
169 std::pair<MSVehicle* const, double> getOncomingVehicle(const MSLane* opposite, std::pair<MSVehicle*,
170 double> neighOncoming, double searchDist, double& vMax, const MSVehicle* overtaken = nullptr,
172
173 std::pair<MSVehicle* const, double> getOncomingOppositeVehicle(const MSVehicle* vehicle,
174 std::pair<MSVehicle*, double> overtaken, double searchDist);
175
177 void registerUnchanged(MSVehicle* vehicle);
178
181 void checkTraCICommands(MSVehicle* vehicle);
182
186 bool applyTraCICommands(MSVehicle* vehicle);
187
189 virtual void updateChanger(bool vehHasChanged);
190
194 void updateLanes(SUMOTime t);
195
199
200 /* @brief check whether lane changing in the given direction is desirable
201 * and possible */
203 int laneOffset,
204 const std::pair<MSVehicle* const, double>& leader,
205 const std::vector<MSVehicle::LaneQ>& preb) const;
206
207 /* @brief check whether lane changing in the given direction is desirable
208 * and possible */
209 int checkChange(
210 int laneOffset,
211 const MSLane* targetLane,
212 const std::pair<MSVehicle* const, double>& leader,
213 const std::pair<MSVehicle* const, double>& follower,
214 const std::pair<MSVehicle* const, double>& neighLead,
215 const std::pair<MSVehicle* const, double>& neighFollow,
216 const std::vector<MSVehicle::LaneQ>& preb) const;
217
218 /* @brief call lanechange model to check the merits of an opposite-direction
219 * change and update state accordingly */
220 virtual bool checkChangeOpposite(
221 MSVehicle* vehicle,
222 int laneOffset,
223 MSLane* targetLane,
224 const std::pair<MSVehicle* const, double>& leader,
225 const std::pair<MSVehicle* const, double>& neighLead,
226 const std::pair<MSVehicle* const, double>& neighFollow,
227 const std::vector<MSVehicle::LaneQ>& preb);
228
229
230 /* @brief start the lane change maneuver (and finish it instantly if gLaneChangeDuration == 0)
231 * @return False when aborting the change due to being remote controlled*/
232 bool startChange(MSVehicle* vehicle, ChangerIt& from, int direction);
233
235 bool continueChange(MSVehicle* vehicle, ChangerIt& from);
236
237 std::pair<MSVehicle* const, double> getRealFollower(const ChangerIt& target) const;
238
239 std::pair<MSVehicle* const, double> getRealLeader(const ChangerIt& target) const;
240
242 bool mayChange(int direction) const;
243
245 static MSVehicle* getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2);
246
254 static void computeOvertakingTime(const MSVehicle* vehicle, double vMax, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake);
255
265 static std::pair<MSVehicle*, double> getColumnleader(double& maxSpace, MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, double maxLookAhead = std::numeric_limits<double>::max());
266
268 static const MSLane* getLaneAfter(const MSLane* lane, const std::vector<MSLane*>& conts, bool allowMinor, bool& contsEnd);
269
271 static bool hasOppositeStop(MSVehicle* vehicle);
272
274 bool checkOppositeStop(MSVehicle* vehicle, const MSLane* oncomingLane, const MSLane* opposite, std::pair<MSVehicle*, double> leader);
275
279 bool avoidDeadlock(MSVehicle* vehicle,
280 std::pair<MSVehicle*, double> neighLead,
281 std::pair<MSVehicle*, double> overtaken,
282 std::pair<MSVehicle*, double> leader);
283
287 bool resolveDeadlock(MSVehicle* vehicle,
288 std::pair<MSVehicle* const, double> leader,
289 std::pair<MSVehicle*, double> neighLead,
290 std::pair<MSVehicle*, double> overtaken);
291
293 bool yieldToDeadlockOncoming(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist);
294
296 bool yieldToOppositeWaiting(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist, SUMOTime deltaWait = 0);
297
299 double computeSafeOppositeLength(MSVehicle* vehicle, double oppositeLength, const MSLane* source, double usableDist,
300 std::pair<MSVehicle*, double> oncoming, double vMax, double oncomingSpeed,
301 std::pair<MSVehicle*, double> neighLead,
302 std::pair<MSVehicle*, double> overtaken,
303 std::pair<MSVehicle*, double> neighFollow,
304 double surplusGap, const MSLane* opposite,
305 bool canOvertake);
306
307 // @brief compute distance that can safely be driven on the opposite side
308 static double computeSurplusGap(const MSVehicle* vehicle, const MSLane* opposite, std::pair<MSVehicle*, double> oncoming, double timeToOvertake,
309 double spaceToOvertake, double& oncomingSpeed, bool oncomingOpposite = false);
310
311 // @brief find hilltop within searchDistance
312 static bool foundHilltop(MSVehicle* vehicle, bool foundHill, double searchDist, const std::vector<MSLane*>& bestLanes, int view, double pos, double lastMax, double hilltopThreshold);
313
315 static std::vector<MSVehicle::LaneQ> getBestLanesOpposite(MSVehicle* vehicle, const MSLane* stopLane, double oppositeLength);
316
318 static double getMaxOvertakingSpeed(const MSVehicle* vehicle, double maxSpaceToOvertake);
319
320protected:
323
328
329 /* @brief Whether vehicles may start to change lanes on this edge
330 * (finishing a change in progress is always permitted) */
332
335
336private:
339
342
345};
long long int SUMOTime
Definition GUI.h:36
Performs lane changing of vehicles.
virtual ~MSLaneChanger()
Destructor.
bool applyTraCICommands(MSVehicle *vehicle)
Execute TraCI LC-commands.
bool continueChange(MSVehicle *vehicle, ChangerIt &from)
continue a lane change maneuver and return whether the vehicle has completely moved onto the new lane...
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
MSLaneChanger(const MSLaneChanger &)
Copy constructor.
bool checkOppositeStop(MSVehicle *vehicle, const MSLane *oncomingLane, const MSLane *opposite, std::pair< MSVehicle *, double > leader)
decide whether to change (back or forth) for an opposite stop
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, MSVehicle *lastStopped)
MSLaneChanger()
Default constructor.
static bool hasOppositeStop(MSVehicle *vehicle)
whether vehicle has an opposite-direction stop within relevant range
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
virtual void initChanger()
Initialize the changer before looping over all vehicles.
std::pair< double, SUMOTime > getLastBlocked(int index) const
retrieve properties of a blocked vehicle that wants to chane to the lane with the given index
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one.
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
virtual bool change()
static const MSLane * getLaneAfter(const MSLane *lane, const std::vector< MSLane * > &conts, bool allowMinor, bool &contsEnd)
return the next lane in conts beyond lane or nullptr
std::pair< MSVehicle *const, double > getOncomingOppositeVehicle(const MSVehicle *vehicle, std::pair< MSVehicle *, double > overtaken, double searchDist)
std::vector< ChangeElem > Changer
The list of changers; For each lane, a ChangeElem is being build.
MSVehicle * veh(ConstChangerIt ce) const
std::pair< MSVehicle *const, double > getOncomingVehicle(const MSLane *opposite, std::pair< MSVehicle *, double > neighOncoming, double searchDist, double &vMax, const MSVehicle *overtaken=nullptr, MSLane::MinorLinkMode mLinkMode=MSLane::MinorLinkMode::FOLLOW_NEVER)
bool startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
const bool myAllowsChanging
double computeSafeOppositeLength(MSVehicle *vehicle, double oppositeLength, const MSLane *source, double usableDist, std::pair< MSVehicle *, double > oncoming, double vMax, double oncomingSpeed, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > neighFollow, double surplusGap, const MSLane *opposite, bool canOvertake)
determine for how long the vehicle can drive safely on the opposite side
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
static bool foundHilltop(MSVehicle *vehicle, bool foundHill, double searchDist, const std::vector< MSLane * > &bestLanes, int view, double pos, double lastMax, double hilltopThreshold)
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
static double computeSurplusGap(const MSVehicle *vehicle, const MSLane *opposite, std::pair< MSVehicle *, double > oncoming, double timeToOvertake, double spaceToOvertake, double &oncomingSpeed, bool oncomingOpposite=false)
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
Changer::const_iterator ConstChangerIt
the iterator moving over the ChangeElems
bool yieldToOppositeWaiting(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist, SUMOTime deltaWait=0)
check whether to yield for oncoming vehicles that have waited longer for opposite overtaking
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
void registerUnchanged(MSVehicle *vehicle)
void updateLanes(SUMOTime t)
bool avoidDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > leader)
avoid opposite-diretion deadlock when vehicles are stopped on both sides of the road The method may c...
static std::pair< MSVehicle *, double > getColumnleader(double &maxSpace, MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
return leader vehicle that is to be overtaken
static double getMaxOvertakingSpeed(const MSVehicle *vehicle, double maxSpaceToOvertake)
compute maximum maneuver speed
ChangerIt myCandi
bool resolveDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *const, double > leader, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken)
keep stopping to resolve opposite-diretion deadlock while there is oncoming traffic The method may ca...
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
bool yieldToDeadlockOncoming(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist)
check whether to keep stopping for oncoming vehicles in the deadlock zone
Changer & getChanger()
return changer (only to be used by MSLaneChangerSublane from another instance)
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
int checkChange(int laneOffset, const MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &follower, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb) const
virtual bool checkChangeOpposite(MSVehicle *vehicle, int laneOffset, MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb)
MSLaneChanger & operator=(const MSLaneChanger &)
Assignment operator.
static void computeOvertakingTime(const MSVehicle *vehicle, double vMax, const MSVehicle *leader, double gap, double &timeToOvertake, double &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
static std::vector< MSVehicle::LaneQ > getBestLanesOpposite(MSVehicle *vehicle, const MSLane *stopLane, double oppositeLength)
add LaneQ for opposite lanes
virtual void updateChanger(bool vehHasChanged)
Representation of a lane in the micro simulation.
Definition MSLane.h:84
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
Definition MSLane.h:978
@ FOLLOW_NEVER
Definition MSLane.h:979
saves leader/follower vehicles and their distances relative to an ego vehicle
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
std::vector< int > siblings
std::vector< MSVehicle * > outsideBounds
vehicles that cannot be stored in ahead because they are outside the lane bounds
bool mayChangeRight
whether changing is possible to either direction
MSVehicle * lead
the leader vehicle for the current change candidate
MSVehicle * lastStopped
the next vehicle downstream of the ego vehicle that is stopped (and thus an obstacle)
double lastBlockedBackPos
the back position of the last blocked vehicle that wants to change to this lane
MSLeaderDistanceInfo aheadNext
double zipperDist
visibility distance to the closest zipper link that may be encountered when driving on this lane
SUMOTime lastBlockedWaitingTime
the waiting time of the last blocked vehicle that wants to change to this lane
MSLane * lane
the lane corresponding to this ChangeElem (the current change candidate is on this lane)
MSVehicle * lastBlocked
the next vehicle downstream of the ego vehicle that is blocked from changing to this lane
MSVehicle * firstBlocked
the farthest downstream vehicle on this edge that is blocked from changing to this lane
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.
MSVehicle * hoppedVeh
last vehicle that changed into this lane