1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSLCM_LC2013.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Friedemann Wesner
14 /// @author  Sascha Krieg
15 /// @author  Michael Behrisch
16 /// @date    Fri, 08.10.2013
17 /// @version $Id$
18 ///
19 // A lane change model developed by D. Krajzewicz, J. Erdmann et al. between 2004 and 2013
20 /****************************************************************************/
21 #ifndef MSLCM_LC2013_h
22 #define MSLCM_LC2013_h
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #include <config.h>
29 
30 #include "MSAbstractLaneChangeModel.h"
31 #include <vector>
32 
33 // INVALID_SPEED should be used when the construction of upper bound for the speed
34 // leads to no restrictions, e.g. during LC-messaging to followers or leaders.
35 // Currently either std::numeric_limits<...>.max() or -1 is used for this purpose in many places.
36 // TODO: implement this everywhere and remove workarounds for ballistic update in cases of possible '-1'-returns. Refs. #2577
37 #define INVALID_SPEED 299792458 + 1 // nothing can go faster than the speed of light!
38 
39 
40 // ===========================================================================
41 // class definitions
42 // ===========================================================================
43 /**
44  * @class MSLCM_LC2013
45  * @brief A lane change model developed by D. Krajzewicz, J. Erdmann
46  * et al. between 2004 and 2013
47  */
48 class MSLCM_LC2013 : public MSAbstractLaneChangeModel {
49 public:
50 
51     MSLCM_LC2013(MSVehicle& v);
52 
53     virtual ~MSLCM_LC2013();
54 
55     /// @brief Returns the model's id
getModelID()56     LaneChangeModel getModelID() const {
57         return LCM_LC2013;
58     }
59 
60     /// @brief init cached parameters derived directly from model parameters
61     void initDerivedParameters();
62 
63     bool debugVehicle() const;
64 
65     /** @brief Called to examine whether the vehicle wants to change
66      * using the given laneOffset.
67      * This method gets the information about the surrounding vehicles
68      * and whether another lane may be more preferable
69      *
70      * TODO: better documentation, refs #2
71      *
72      * */
73     int wantsChange(
74         int laneOffset,
75         MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
76         const std::pair<MSVehicle*, double>& leader,
77         const std::pair<MSVehicle*, double>& neighLead,
78         const std::pair<MSVehicle*, double>& neighFollow,
79         const MSLane& neighLane,
80         const std::vector<MSVehicle::LaneQ>& preb,
81         MSVehicle** lastBlocked,
82         MSVehicle** firstBlocked);
83 
84     void* inform(void* info, MSVehicle* sender);
85 
86     /** @brief Called to adapt the speed in order to allow a lane change.
87      *         It uses information on LC-related desired speed-changes from
88      *         the call to wantsChange() at the end of the previous simulation step
89      *
90      * @param min The minimum resulting speed
91      * @param wanted The aspired speed of the car following model
92      * @param max The maximum resulting speed
93      * @param cfModel The model used
94      * @return the new speed of the vehicle as proposed by the lane changer
95      */
96     double patchSpeed(const double min, const double wanted, const double max,
97                       const MSCFModel& cfModel);
98     /** helper function which contains the actual logic */
99     double _patchSpeed(const double min, const double wanted, const double max,
100                        const MSCFModel& cfModel);
101 
102     void changed();
103 
104     double getSafetyFactor() const;
105 
106     double getOppositeSafetyFactor() const;
107 
108     void prepareStep();
109 
110     /// @brief try to retrieve the given parameter from this device. Throw exception for unsupported key
111     std::string getParameter(const std::string& key) const;
112 
113     /// @brief try to set the given parameter for this laneChangeModel. Throw exception for unsupported key
114     void setParameter(const std::string& key, const std::string& value);
115 
116     /// @brief decides the next lateral speed (for continuous lane changing)
117     double computeSpeedLat(double latDist, double& maneuverDist);
118 
119     /// @brief Returns a deceleration value which is used for the estimation of the duration of a lane change.
120     /// @note  Effective only for continuous lane-changing when using attributes myMaxSpeedLatFactor and myMaxSpeedLatStanding. See #3771
121     double getAssumedDecelForLaneChangeDuration() const;
122 
123 protected:
124 
125     /// @brief helper function for doing the actual work
126     int _wantsChange(
127         int laneOffset,
128         MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
129         const std::pair<MSVehicle*, double>& leader,
130         const std::pair<MSVehicle*, double>& neighLead,
131         const std::pair<MSVehicle*, double>& neighFollow,
132         const MSLane& neighLane,
133         const std::vector<MSVehicle::LaneQ>& preb,
134         MSVehicle** lastBlocked,
135         MSVehicle** firstBlocked);
136 
137     /* @brief decide whether we will overtake or follow a blocking leader
138      * and inform it accordingly
139      * If we decide to follow, myVSafes will be extended
140      * returns the planned speed if following or -1 if overtaking */
141     double informLeader(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
142                         int blocked, int dir,
143                         const std::pair<MSVehicle*, double>& neighLead,
144                         double remainingSeconds);
145 
146     /// @brief decide whether we will try cut in before the follower or allow to be overtaken
147     void informFollower(MSAbstractLaneChangeModel::MSLCMessager& msgPass,
148                         int blocked, int dir,
149                         const std::pair<MSVehicle*, double>& neighFollow,
150                         double remainingSeconds,
151                         double plannedSpeed);
152 
153 
154     /* @brief compute the distance to cover until a safe gap to the vehicle v in front is reached
155      *        assuming constant velocities
156          * @param[in] follower the vehicle which overtakes
157          * @param[in] leader the vehicle to be overtaken
158          * @param[in] gap initial distance between front of follower and back of leader
159          * @param[in] leaderSpeed an assumed speed for the leader (default uses the current speed)
160          * @param[in] followerSpeed an assumed speed for the follower (default uses the current speed)
161          * @return the distance that the relative positions would have to change.
162          */
163     static double overtakeDistance(const MSVehicle* follower, const MSVehicle* leader, const double gap, double followerSpeed = INVALID_SPEED, double leaderSpeed = INVALID_SPEED);
164 
165     /// @brief compute useful slowdowns for blocked vehicles
166     int slowDownForBlocked(MSVehicle** blocked, int state);
167 
168 
169     // XXX: consider relocation of the roundabout functions (perhaps to MSVehicle or the abstract LC Model...) (Leo)
170     /// @brief computes the distance and number of edges in the next upcoming
171     ///        roundabout along the lane continuations given in curr and neigh
172     /// @param[in] veh The considered ego Vehicle
173     /// @param[in] curr continuation info along veh's current lane
174     /// @param[in] neigh continuation info along a neighboring lane (in MSLCM_2013::_wantsChange() the considered lane for a lanechange)
175     /// @param[out] roundaboutDistanceAhead Accumulated length of lanes in the next oncoming roundabout in curr
176     /// @param[out] roundaboutDistanceAheadNeigh Accumulated length of lanes in the next oncoming roundabout in neigh
177     /// @param[out] roundaboutEdgesAhead  Number of lanes in the next oncoming roundabout in curr
178     /// @param[out] roundaboutEdgesAheadNeigh Number of lanes in the next oncoming roundabout in neigh
179     static void
180     getRoundaboutAheadInfo(const MSLCM_LC2013* lcm, const MSVehicle::LaneQ& curr, const MSVehicle::LaneQ& neigh,
181                            double& roundaboutDistanceAhead, double& roundaboutDistanceAheadNeigh, int& roundaboutEdgesAhead, int& roundaboutEdgesAheadNeigh);
182 
183     /// @brief Computes the artificial bonus distance for roundabout lanes
184     ///        this additional distance reduces the sense of urgency within
185     ///        roundabouts and thereby promotes the use of the inner roundabout
186     ///        lane in multi-lane roundabouts.
187     /// @param[in] roundaboutDistAhead Distance on roundabout
188     /// @param[in] roundaboutEdgesAhead number of edges on roundabout
189     double
190     roundaboutDistBonus(double roundaboutDistAhead, int roundaboutEdgesAhead) const;
191 
192     /// @brief compute the distance on the next upcoming roundabout along a given sequence of lanes.
193     /// @param[in] position position of the vehicle on the initial lane
194     /// @param[in] initialLane starting lane for the computation (may be internal)
195     /// @param[in] continuationLanes sequence of lanes along which the roundabout distance is to be computed (only containing non-internal lanes)
196     /// @return distance along next upcoming roundabout on the given sequence of lanes continuationLanes
197     static double
198     distanceAlongNextRoundabout(double position, const MSLane* initialLane, const std::vector<MSLane*>& continuationLanes);
199 
200     /// @brief save space for vehicles which need to counter-lane-change
201     void saveBlockerLength(MSVehicle* blocker, int lcaCounter);
202 
203     /// @brief react to pedestrians on the given lane
204     void adaptSpeedToPedestrians(const MSLane* lane, double& v);
205 
206     /// @brief reserve space at the end of the lane to avoid dead locks
saveBlockerLength(double length)207     inline void saveBlockerLength(double length) {
208         myLeadingBlockerLength = MAX2(length, myLeadingBlockerLength);
209     };
210 
amBlockingLeader()211     inline bool amBlockingLeader() {
212         return (myOwnState & LCA_AMBLOCKINGLEADER) != 0;
213     }
amBlockingFollower()214     inline bool amBlockingFollower() {
215         return (myOwnState & LCA_AMBLOCKINGFOLLOWER) != 0;
216     }
amBlockingFollowerNB()217     inline bool amBlockingFollowerNB() {
218         return (myOwnState & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0;
219     }
amBlockingFollowerPlusNB()220     inline bool amBlockingFollowerPlusNB() {
221         return (myOwnState & (LCA_AMBLOCKINGFOLLOWER | LCA_AMBLOCKINGFOLLOWER_DONTBRAKE)) != 0;
222     }
currentDistDisallows(double dist,int laneOffset,double lookForwardDist)223     inline bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist) {
224         return dist / (abs(laneOffset)) < lookForwardDist;
225     }
currentDistAllows(double dist,int laneOffset,double lookForwardDist)226     inline bool currentDistAllows(double dist, int laneOffset, double lookForwardDist) {
227         return dist / abs(laneOffset) > lookForwardDist;
228     }
229 
230     /** @brief Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration
231      *         and stores it into myLCAccelerationAdvices.
232      *  @note  This construction was introduced to deal with action step lengths,
233      *         where operation on the speed in the next sim step had to be replaced by acceleration
234      *         throughout the next action step.
235      */
236     void addLCSpeedAdvice(const double vSafe);
237 
238 protected:
239 
240     /// @brief information regarding save velocity (unused) and state flags of the ego vehicle
241     typedef std::pair<double, int> Info;
242 
243     /// @brief a value for tracking the probability that a change to the offset with the same sign is beneficial
244     double mySpeedGainProbability;
245     /* @brief a value for tracking the probability of following the/"Rechtsfahrgebot"
246      * A larger negative value indicates higher probability for moving to the
247      * right (as in mySpeedGainProbability) */
248     double myKeepRightProbability;
249 
250     double myLeadingBlockerLength;
251     double myLeftSpace;
252 
253     /*@brief the speed to use when computing the look-ahead distance for
254      * determining urgency of strategic lane changes */
255     double myLookAheadSpeed;
256 
257     /// @brief vector of LC-related acceleration recommendations
258     ///        Filled in wantsChange() and applied in patchSpeed()
259     std::vector<double> myLCAccelerationAdvices;
260 
261     bool myDontBrake; // XXX: myDontBrake is initialized as false and seems not to be changed anywhere... What's its purpose???
262 
263     /// @name user configurable model parameters (can be changed via TraCI)
264     //@{
265     double myStrategicParam;
266     double myCooperativeParam; // in [0,1]
267     double mySpeedGainParam;
268     double myKeepRightParam;
269     double myOppositeParam;
270 
271     // @brief the factor by which the lookahead distance to the left differs from the lookahead to the right
272     double myLookaheadLeft;
273     // @brief the factor by which the speedGain-threshold for the leftdiffers from the threshold for the right
274     double mySpeedGainRight;
275 
276     // @brief willingness to undercut longitudinal safe gaps
277     double myAssertive;
278 
279     const double myExperimentalParam1; // for feature testing
280     //@}
281 
282     /// @name derived parameters
283     //@{
284     // @brief willingness to encroach on other vehicles laterally (pushing them around)
285     double myChangeProbThresholdRight;
286     double myChangeProbThresholdLeft;
287     //@}
288 };
289 
290 
291 #endif
292 
293 /****************************************************************************/
294 
295