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
133 void postloadInitLC();
134
135protected:
137 virtual void initChanger();
138
141 bool vehInChanger() const {
142 // If there is at least one valid vehicle under the veh's in myChanger
143 // return true.
144 for (ConstChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
145 if (veh(ce) != 0) {
146 return true;
147 }
148 }
149 return false;
150 }
151
155 // If ce has a valid vehicle, return it. Otherwise return 0.
156 if (!ce->lane->myVehicles.empty()) {
157 return ce->lane->myVehicles.back();
158 } else {
159 return 0;
160 }
161 }
162
163
165 virtual bool change();
166
167
169 bool changeOpposite(MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, MSVehicle* lastStopped);
170
171 std::pair<MSVehicle* const, double> getOncomingVehicle(const MSLane* opposite, std::pair<MSVehicle*,
172 double> neighOncoming, double searchDist, double& vMax, const MSVehicle* overtaken = nullptr,
174
175 std::pair<MSVehicle* const, double> getOncomingOppositeVehicle(const MSVehicle* vehicle,
176 std::pair<MSVehicle*, double> overtaken, double searchDist);
177
179 void registerUnchanged(MSVehicle* vehicle);
180
183 void checkTraCICommands(MSVehicle* vehicle);
184
188 bool applyTraCICommands(MSVehicle* vehicle);
189
191 virtual void updateChanger(bool vehHasChanged);
192
196 void updateLanes(SUMOTime t);
197
201
202 /* @brief check whether lane changing in the given direction is desirable
203 * and possible */
205 int laneOffset,
206 const std::pair<MSVehicle* const, double>& leader,
207 const std::vector<MSVehicle::LaneQ>& preb) const;
208
209 /* @brief check whether lane changing in the given direction is desirable
210 * and possible */
211 int checkChange(
212 int laneOffset,
213 const MSLane* targetLane,
214 const std::pair<MSVehicle* const, double>& leader,
215 const std::pair<MSVehicle* const, double>& follower,
216 const std::pair<MSVehicle* const, double>& neighLead,
217 const std::pair<MSVehicle* const, double>& neighFollow,
218 const std::vector<MSVehicle::LaneQ>& preb) const;
219
220 /* @brief call lanechange model to check the merits of an opposite-direction
221 * change and update state accordingly */
222 virtual bool checkChangeOpposite(
223 MSVehicle* vehicle,
224 int laneOffset,
225 MSLane* targetLane,
226 const std::pair<MSVehicle* const, double>& leader,
227 const std::pair<MSVehicle* const, double>& neighLead,
228 const std::pair<MSVehicle* const, double>& neighFollow,
229 const std::vector<MSVehicle::LaneQ>& preb);
230
231
232 /* @brief start the lane change maneuver (and finish it instantly if gLaneChangeDuration == 0)
233 * @return False when aborting the change due to being remote controlled*/
234 bool startChange(MSVehicle* vehicle, ChangerIt& from, int direction);
235
237 bool continueChange(MSVehicle* vehicle, ChangerIt& from);
238
239 std::pair<MSVehicle* const, double> getRealFollower(const ChangerIt& target) const;
240
241 std::pair<MSVehicle* const, double> getRealLeader(const ChangerIt& target) const;
242
244 bool mayChange(int direction) const;
245
247 static MSVehicle* getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2);
248
256 static void computeOvertakingTime(const MSVehicle* vehicle, double vMax, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake);
257
267 static std::pair<MSVehicle*, double> getColumnleader(double& maxSpace, MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, double maxLookAhead = std::numeric_limits<double>::max());
268
270 static const MSLane* getLaneAfter(const MSLane* lane, const std::vector<MSLane*>& conts, bool allowMinor, bool& contsEnd);
271
273 static bool hasOppositeStop(MSVehicle* vehicle);
274
276 bool checkOppositeStop(MSVehicle* vehicle, const MSLane* oncomingLane, const MSLane* opposite, std::pair<MSVehicle*, double> leader);
277
281 bool avoidDeadlock(MSVehicle* vehicle,
282 std::pair<MSVehicle*, double> neighLead,
283 std::pair<MSVehicle*, double> overtaken,
284 std::pair<MSVehicle*, double> leader);
285
289 bool resolveDeadlock(MSVehicle* vehicle,
290 std::pair<MSVehicle* const, double> leader,
291 std::pair<MSVehicle*, double> neighLead,
292 std::pair<MSVehicle*, double> overtaken);
293
295 bool yieldToDeadlockOncoming(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist);
296
298 bool yieldToOppositeWaiting(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist, SUMOTime deltaWait = 0);
299
301 double computeSafeOppositeLength(MSVehicle* vehicle, double oppositeLength, const MSLane* source, double usableDist,
302 std::pair<MSVehicle*, double> oncoming, double vMax, double oncomingSpeed,
303 std::pair<MSVehicle*, double> neighLead,
304 std::pair<MSVehicle*, double> overtaken,
305 std::pair<MSVehicle*, double> neighFollow,
306 double surplusGap, const MSLane* opposite,
307 bool canOvertake);
308
309 // @brief compute distance that can safely be driven on the opposite side
310 static double computeSurplusGap(const MSVehicle* vehicle, const MSLane* opposite, std::pair<MSVehicle*, double> oncoming, double timeToOvertake,
311 double spaceToOvertake, double& oncomingSpeed, bool oncomingOpposite = false);
312
313 // @brief find hilltop within searchDistance
314 static bool foundHilltop(MSVehicle* vehicle, bool foundHill, double searchDist, const std::vector<MSLane*>& bestLanes, int view, double pos, double lastMax, double hilltopThreshold);
315
317 static std::vector<MSVehicle::LaneQ> getBestLanesOpposite(MSVehicle* vehicle, const MSLane* stopLane, double oppositeLength);
318
320 static double getMaxOvertakingSpeed(const MSVehicle* vehicle, double maxSpaceToOvertake);
321
322protected:
325
330
331 /* @brief Whether vehicles may start to change lanes on this edge
332 * (finishing a change in progress is always permitted) */
334
337
338 /* @brief whether neigboring lanes target the same outgoing edge but have different foe links and
339 * therefore require an extra MSLink::opened check before changing */
341
342private:
345
348
351};
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:980
@ FOLLOW_NEVER
Definition MSLane.h:981
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