View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.following;
2   
3   import org.djunits.value.vdouble.scalar.Acceleration;
4   import org.djunits.value.vdouble.scalar.Length;
5   import org.djunits.value.vdouble.scalar.Speed;
6   import org.opentrafficsim.base.parameters.ParameterException;
7   import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
8   import org.opentrafficsim.base.parameters.ParameterTypeDouble;
9   import org.opentrafficsim.base.parameters.ParameterTypeDuration;
10  import org.opentrafficsim.base.parameters.ParameterTypeLength;
11  import org.opentrafficsim.base.parameters.ParameterTypes;
12  import org.opentrafficsim.base.parameters.Parameters;
13  import org.opentrafficsim.base.parameters.constraint.ConstraintInterface;
14  import org.opentrafficsim.core.gtu.Stateless;
15  import org.opentrafficsim.road.gtu.lane.perception.PerceptionIterable;
16  import org.opentrafficsim.road.gtu.lane.perception.object.PerceivedObject;
17  import org.opentrafficsim.road.gtu.lane.tactical.util.SpeedLimitUtil;
18  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
19  
20  /**
21   * Implementation of the IDM. See <a
22   * href=https://en.wikipedia.org/wiki/Intelligent_driver_model>https://en.wikipedia.org/wiki/Intelligent_driver_model</a>
23   * <p>
24   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
25   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
26   * </p>
27   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
28   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
29   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
30   */
31  // @docs/06-behavior/parameters.md
32  public abstract class AbstractIdm extends AbstractCarFollowingModel
33  {
34  
35      /** Acceleration parameter type. */
36      // @docs/06-behavior/parameters.md
37      protected static final ParameterTypeAcceleration A = ParameterTypes.A;
38  
39      /** Comfortable deceleration parameter type. */
40      protected static final ParameterTypeAcceleration B = ParameterTypes.B;
41  
42      /** Desired headway parameter type. */
43      protected static final ParameterTypeDuration T = ParameterTypes.T;
44  
45      /** Stopping distance parameter type. */
46      protected static final ParameterTypeLength S0 = ParameterTypes.S0;
47  
48      /** Adjustment deceleration parameter type. */
49      protected static final ParameterTypeAcceleration B0 = ParameterTypes.B0;
50  
51      /** Speed limit adherence factor parameter type. */
52      protected static final ParameterTypeDouble FSPEED = ParameterTypes.FSPEED;
53  
54      /** Acceleration flattening. */
55      // @docs/06-behavior/parameters.md
56      public static final ParameterTypeDouble DELTA = new ParameterTypeDouble("delta",
57              "Acceleration flattening exponent towards desired speed", 4.0, ConstraintInterface.POSITIVE);
58  
59      /** Default IDM desired headway model. */
60      public static final IdmDesiredHeadwayModel HEADWAY = IdmDesiredHeadwayModel.SINGLETON;
61  
62      /** Default IDM desired speed model. */
63      public static final IdmDesiredSpeedModel DESIRED_SPEED = IdmDesiredSpeedModel.SINGLETON;
64  
65      /**
66       * Constructor with modular models for desired headway and desired speed.
67       * @param desiredHeadwayModel desired headway model
68       * @param desiredSpeedModel desired speed model
69       */
70      public AbstractIdm(final DesiredHeadwayModel desiredHeadwayModel, final DesiredSpeedModel desiredSpeedModel)
71      {
72          super(desiredHeadwayModel, desiredSpeedModel);
73      }
74  
75      /**
76       * Determination of car-following acceleration, possibly based on multiple leaders. This implementation calculates the IDM
77       * free term, which is returned if there are no leaders. If there are leaders <code>combineInteractionTerm()</code> is
78       * invoked to combine the free term with some implementation specific interaction term. The IDM free term is limited by a
79       * deceleration of <code>B0</code> for cases where the current speed is above the desired speed. This method can be
80       * overridden if the free term needs to be redefined.
81       * @param parameters Parameters.
82       * @param speed Current speed.
83       * @param desiredSpeed Desired speed.
84       * @param desiredHeadway Desired headway.
85       * @param leaders Set of leader headways (guaranteed positive) and speeds, ordered by headway (closest first).
86       * @throws ParameterException If parameter exception occurs.
87       * @return Car-following acceleration.
88       */
89      @Override
90      @SuppressWarnings("checkstyle:designforextension")
91      protected Acceleration followingAcceleration(final Parameters parameters, final Speed speed, final Speed desiredSpeed,
92              final Length desiredHeadway, final PerceptionIterable<? extends PerceivedObject> leaders) throws ParameterException
93      {
94          Acceleration a = parameters.getParameter(A);
95          Acceleration b0 = parameters.getParameter(B0);
96          double delta = parameters.getParameter(DELTA);
97          double aFree = a.si * (1 - Math.pow(speed.si / desiredSpeed.si, delta));
98          // limit deceleration in free term (occurs if speed > desired speed)
99          aFree = aFree > -b0.si ? aFree : -b0.si;
100         // return free term if there are no leaders
101         if (leaders.isEmpty())
102         {
103             return Acceleration.ofSI(aFree);
104         }
105         // return combined acceleration
106         return combineInteractionTerm(Acceleration.ofSI(aFree), parameters, speed, desiredSpeed, desiredHeadway, leaders);
107     }
108 
109     /**
110      * Combines an interaction term with the free term. There should be at least 1 leader for this method.
111      * @param aFree Free term of acceleration.
112      * @param parameters Parameters.
113      * @param speed Current speed.
114      * @param desiredSpeed Desired speed.
115      * @param desiredHeadway Desired headway.
116      * @param leaders Set of leader headways (guaranteed positive) and speeds, ordered by headway (closest first).
117      * @return Combination of terms into a single acceleration.
118      * @throws ParameterException In case of parameter exception.
119      */
120     protected abstract Acceleration combineInteractionTerm(Acceleration aFree, Parameters parameters, Speed speed,
121             Speed desiredSpeed, Length desiredHeadway, PerceptionIterable<? extends PerceivedObject> leaders)
122             throws ParameterException;
123 
124     /**
125      * Determines the dynamic desired headway, which is non-negative.
126      * @param parameters Parameters.
127      * @param speed Current speed.
128      * @param desiredHeadway Desired headway.
129      * @param leaderSpeed Speed of the leading vehicle.
130      * @return Dynamic desired headway.
131      * @throws ParameterException In case of parameter exception.
132      */
133     protected final Length dynamicDesiredHeadway(final Parameters parameters, final Speed speed, final Length desiredHeadway,
134             final Speed leaderSpeed) throws ParameterException
135     {
136         double sStar = desiredHeadway.si + dynamicHeadwayTerm(parameters, speed, leaderSpeed).si;
137         /*
138          * Due to a power of 2 in the IDM, negative values of sStar are not allowed. A negative sStar means that the leader is
139          * faster to such an extent, that the equilibrium headway (s0+vT) is completely compensated by the dynamic part in
140          * sStar. This might occur if a much faster leader changes lane closely in front. The compensation is limited to the
141          * equilibrium headway minus the stopping distance (i.e. sStar > s0), which means the driver wants to follow with
142          * acceleration. Note that usually the free term determines acceleration in such cases.
143          */
144         Length s0 = parameters.getParameter(S0);
145         /*
146          * Limit used to be 0, but the IDM is very sensitive there. With a decelerating leader, an ok acceleration in one time
147          * step, may results in acceleration < -10 in the next.
148          */
149         return Length.ofSI(sStar >= s0.si ? sStar : s0.si);
150     }
151 
152     /**
153      * Determines the dynamic headway term. May be used on individual leaders for multi-anticipative following.
154      * @param parameters Parameters.
155      * @param speed Current speed.
156      * @param leaderSpeed Speed of the leading vehicle.
157      * @return Dynamic headway term.
158      * @throws ParameterException In case of parameter exception.
159      */
160     protected final Length dynamicHeadwayTerm(final Parameters parameters, final Speed speed, final Speed leaderSpeed)
161             throws ParameterException
162     {
163         Acceleration a = parameters.getParameter(A);
164         Acceleration b = parameters.getParameter(B);
165         return Length.ofSI(speed.si * (speed.si - leaderSpeed.si) / (2 * Math.sqrt(a.si * b.si)));
166     }
167 
168     /**
169      * IDM desired headway model.
170      */
171     public static class IdmDesiredHeadwayModel implements DesiredHeadwayModel, Stateless<IdmDesiredHeadwayModel>
172     {
173         /** Singleton instance. */
174         public static final IdmDesiredHeadwayModel SINGLETON = new IdmDesiredHeadwayModel();
175 
176         /**
177          * Constructor.
178          */
179         public IdmDesiredHeadwayModel()
180         {
181             //
182         }
183 
184         @Override
185         public IdmDesiredHeadwayModel get()
186         {
187             return SINGLETON;
188         }
189 
190         @Override
191         public Length desiredHeadway(final Parameters parameters, final Speed speed) throws ParameterException
192         {
193             return Length.ofSI(parameters.getParameter(S0).si + speed.si * parameters.getParameter(T).si);
194         }
195     }
196 
197     /**
198      * IDM desired speed model.
199      */
200     public static class IdmDesiredSpeedModel implements DesiredSpeedModel, Stateless<IdmDesiredSpeedModel>
201     {
202         /** Singleton instance. */
203         public static final IdmDesiredSpeedModel SINGLETON = new IdmDesiredSpeedModel();
204 
205         /**
206          * Constructor.
207          */
208         public IdmDesiredSpeedModel()
209         {
210             //
211         }
212 
213         @Override
214         public IdmDesiredSpeedModel get()
215         {
216             return SINGLETON;
217         }
218 
219         @Override
220         public Speed desiredSpeed(final Parameters parameters, final SpeedLimitInfo speedInfo) throws ParameterException
221         {
222             Speed consideredSpeed = SpeedLimitUtil.getLegalSpeedLimit(speedInfo).times(parameters.getParameter(FSPEED));
223             Speed maxVehicleSpeed = SpeedLimitUtil.getMaximumVehicleSpeed(speedInfo);
224             return consideredSpeed.le(maxVehicleSpeed) ? consideredSpeed : maxVehicleSpeed;
225         }
226     }
227 
228 }