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