Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 : /****************************************************************************/
14 : /// @file MSLCM_LC2013.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Friedemann Wesner
18 : /// @author Sascha Krieg
19 : /// @author Michael Behrisch
20 : /// @date Fri, 08.10.2013
21 : ///
22 : // A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013
23 : /****************************************************************************/
24 : #pragma once
25 : #include <config.h>
26 :
27 : #include "MSAbstractLaneChangeModel.h"
28 : #include <vector>
29 :
30 : // INVALID_SPEED should be used when the construction of upper bound for the speed
31 : // leads to no restrictions, e.g. during LC-messaging to followers or leaders.
32 : // Currently either std::numeric_limits<...>.max() or -1 is used for this purpose in many places.
33 : // TODO: implement this everywhere and remove workarounds for ballistic update in cases of possible '-1'-returns. Refs. #2577
34 : #define INVALID_SPEED 299792458 + 1 // nothing can go faster than the speed of light!
35 :
36 :
37 : // ===========================================================================
38 : // class definitions
39 : // ===========================================================================
40 : /**
41 : * @class MSLCM_LC2013
42 : * @brief A lane change model developed by D. Krajzewicz, J. Erdmann
43 : * et al. between 2004 and 2013
44 : */
45 : class MSLCM_LC2013 : public MSAbstractLaneChangeModel {
46 : public:
47 :
48 : MSLCM_LC2013(MSVehicle& v);
49 :
50 : virtual ~MSLCM_LC2013();
51 :
52 : /// @brief Returns the model's id
53 0 : LaneChangeModel getModelID() const override {
54 0 : return LaneChangeModel::LC2013;
55 : }
56 :
57 : /// @brief init cached parameters derived directly from model parameters
58 : void initDerivedParameters();
59 :
60 : bool debugVehicle() const override;
61 :
62 : /** @brief Called to examine whether the vehicle wants to change
63 : * using the given laneOffset.
64 : * This method gets the information about the surrounding vehicles
65 : * and whether another lane may be more preferable
66 : *
67 : * TODO: better documentation, refs #2
68 : *
69 : * */
70 : int wantsChange(
71 : int laneOffset,
72 : MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
73 : const std::pair<MSVehicle*, double>& leader,
74 : const std::pair<MSVehicle*, double>& follower,
75 : const std::pair<MSVehicle*, double>& neighLead,
76 : const std::pair<MSVehicle*, double>& neighFollow,
77 : const MSLane& neighLane,
78 : const std::vector<MSVehicle::LaneQ>& preb,
79 : MSVehicle** lastBlocked,
80 : MSVehicle** firstBlocked) override;
81 :
82 : void* inform(void* info, MSVehicle* sender) override;
83 :
84 : /** @brief Called to adapt the speed in order to allow a lane change.
85 : * It uses information on LC-related desired speed-changes from
86 : * the call to wantsChange() at the end of the previous simulation step
87 : *
88 : * @param min The minimum resulting speed
89 : * @param wanted The aspired speed of the car following model
90 : * @param max The maximum resulting speed
91 : * @param cfModel The model used
92 : * @return the new speed of the vehicle as proposed by the lane changer
93 : */
94 : double patchSpeed(const double min, const double wanted, const double max,
95 : const MSCFModel& cfModel) override;
96 :
97 : void changed() override;
98 :
99 : void resetState() override;
100 :
101 : double getSafetyFactor() const override;
102 :
103 : double getOppositeSafetyFactor() const override;
104 :
105 : void prepareStep() override;
106 :
107 : /// @brief try to retrieve the given parameter from this device. Throw exception for unsupported key
108 : std::string getParameter(const std::string& key) const override;
109 :
110 : /// @brief try to set the given parameter for this laneChangeModel. Throw exception for unsupported key
111 : void setParameter(const std::string& key, const std::string& value) override;
112 :
113 : /// @brief decides the next lateral speed (for continuous lane changing)
114 : double computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const override;
115 :
116 : /** @brief Save the state of the laneChangeModel
117 : * @param[in] out The OutputDevice to write the information into
118 : */
119 : virtual void saveState(OutputDevice& out) const override;
120 :
121 : /** @brief Loads the state of the laneChangeModel from the given attributes
122 : * @param[in] attrs XML attributes describing the current state
123 : */
124 : virtual void loadState(const SUMOSAXAttributes& attrs) override;
125 :
126 : protected:
127 :
128 : /** helper function which contains the actual logic */
129 : double _patchSpeed(double min, const double wanted, double max,
130 : const MSCFModel& cfModel);
131 :
132 : /// @brief helper function for doing the actual work
133 : int _wantsChange(
134 : int laneOffset,
135 : MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
136 : const std::pair<MSVehicle*, double>& leader,
137 : const std::pair<MSVehicle*, double>& follower,
138 : const std::pair<MSVehicle*, double>& neighLead,
139 : const std::pair<MSVehicle*, double>& neighFollow,
140 : const MSLane& neighLane,
141 : const std::vector<MSVehicle::LaneQ>& preb,
142 : MSVehicle* lastBlocked,
143 : MSVehicle* firstBlocked);
144 :
145 : /* @brief decide whether we will overtake or follow a blocking leader
146 : * and inform it accordingly
147 : * If we decide to follow, myVSafes will be extended
148 : * returns the planned speed if following or -1 if overtaking */
149 : double informLeader(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
150 : int blocked, int dir,
151 : const std::pair<MSVehicle*, double>& neighLead,
152 : double remainingSeconds);
153 :
154 : /// @brief decide whether we will try cut in before the follower or allow to be overtaken
155 : void informFollower(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
156 : int blocked, int dir,
157 : const std::pair<MSVehicle*, double>& neighFollow,
158 : double remainingSeconds,
159 : double plannedSpeed);
160 :
161 :
162 : /* @brief compute the distance to cover until a safe gap to the vehicle v in front is reached
163 : * assuming constant velocities
164 : * @param[in] follower the vehicle which overtakes
165 : * @param[in] leader the vehicle to be overtaken
166 : * @param[in] gap initial distance between front of follower and back of leader
167 : * @param[in] leaderSpeed an assumed speed for the leader (default uses the current speed)
168 : * @param[in] followerSpeed an assumed speed for the follower (default uses the current speed)
169 : * @return the distance that the relative positions would have to change.
170 : */
171 : static double overtakeDistance(const MSVehicle* follower, const MSVehicle* leader, const double gap, double followerSpeed = INVALID_SPEED, double leaderSpeed = INVALID_SPEED);
172 :
173 : /// @brief compute useful slowdowns for blocked vehicles
174 : int slowDownForBlocked(MSVehicle* blocked, int state);
175 :
176 : /// @brief anticipate future follow speed for the given leader
177 : double anticipateFollowSpeed(const std::pair<MSVehicle*, double>& leaderDist, double dist, double vMax, bool acceleratingLeader);
178 :
179 : /// @brief react to pedestrians on the given lane
180 : void adaptSpeedToPedestrians(const MSLane* lane, double& v);
181 :
182 : /// @brief reserve space at the end of the lane to avoid dead locks
183 : bool saveBlockerLength(double length, double foeLeftSpace) override;
184 :
185 : inline bool amBlockingLeader() {
186 : return (myOwnState & LCA_AMBLOCKINGLEADER) != 0;
187 : }
188 : inline bool amBlockingFollower() {
189 : return (myOwnState & LCA_AMBLOCKINGFOLLOWER) != 0;
190 : }
191 : inline bool amBlockingFollowerNB() {
192 : return (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0;
193 : }
194 : inline bool amBlockingFollowerPlusNB() {
195 193028653 : return (myOwnState & (LCA_AMBLOCKINGFOLLOWER | LCA_AMBLOCKINGFOLLOWER_DONTBRAKE)) != 0;
196 : }
197 : inline bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist) {
198 56351793 : return dist / (abs(laneOffset)) < lookForwardDist;
199 : }
200 : inline bool currentDistAllows(double dist, int laneOffset, double lookForwardDist) {
201 246 : return dist / abs(laneOffset) > lookForwardDist;
202 : }
203 :
204 : /// @brief whether there is a lane beyond laneOffset that can be used to overtake the stopped leader on the neighboring lane
205 : bool hasFreeLane(int laneOffset, const std::pair<MSVehicle*, double>& neighLeadStopped) const;
206 :
207 : protected:
208 :
209 : /// @brief information regarding save velocity (unused) and state flags of the ego vehicle
210 : typedef std::pair<double, int> Info;
211 :
212 : /// @brief a value for tracking the probability that a change to that side is beneficial
213 : long long int mySpeedGainProbabilityLeft;
214 : long long int mySpeedGainProbabilityRight;
215 :
216 : /* @brief a value for tracking the probability of following the/"Rechtsfahrgebot"
217 : * A larger negative value indicates higher probability for moving to the
218 : * right (as in mySpeedGainProbability) */
219 : long long int myKeepRightProbability;
220 :
221 : double myLeadingBlockerLength;
222 : double myLeftSpace;
223 :
224 : /*@brief the speed to use when computing the look-ahead distance for
225 : * determining urgency of strategic lane changes */
226 : double myLookAheadSpeed;
227 :
228 : bool myDontBrake; // XXX: myDontBrake is initialized as false and seems not to be changed anywhere... What's its purpose???
229 :
230 : /// @name user configurable model parameters (can be changed via TraCI)
231 : //@{
232 : double myStrategicParam;
233 : double myCooperativeParam; // in [0,1]
234 : double mySpeedGainParam;
235 : double myKeepRightParam;
236 : double myOppositeParam;
237 :
238 : // @brief the factor by which the lookahead distance to the left differs from the lookahead to the right
239 : double myLookaheadLeft;
240 : // @brief the factor by which the speedGain-threshold for the leftdiffers from the threshold for the right
241 : double mySpeedGainRight;
242 :
243 : // @brief lookahead for speedGain in seconds
244 : double mySpeedGainLookahead;
245 : // @brief the minimum time to spent driving without lane change after a speed-gain change
246 : double mySpeedGainRemainTime;
247 : // @brief the threshold value of mySpeedGainProbability for making a speedGain change urgent
248 : double mySpeedGainUrgency;
249 : // @brief bounus factor staying on the inside of multi-lane roundabout
250 : double myRoundaboutBonus;
251 : // @brief factor for cooperative speed adjustment
252 : double myCooperativeSpeed;
253 :
254 : // time for unrestricted driving on the right to accept keepRight change
255 : double myKeepRightAcceptanceTime;
256 :
257 : // @brief speed difference factor for overtaking the leader on the neighbor lane before changing to that lane
258 : double myOvertakeDeltaSpeedFactor;
259 :
260 : // for feature testing
261 : const double myExperimentalParam1;
262 :
263 : //@}
264 :
265 : /// @name derived parameters
266 : //@{
267 : // @brief thresholds for changing to the right/left
268 : long long int myChangeProbThresholdRight;
269 : long long int myChangeProbThresholdLeft;
270 : //@}
271 : };
|