View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.following;
2   
3   import java.io.Serializable;
4   
5   import org.djunits.unit.AccelerationUnit;
6   import org.djunits.unit.DurationUnit;
7   import org.djunits.unit.LengthUnit;
8   import org.djunits.unit.SpeedUnit;
9   import org.djunits.value.vdouble.scalar.Acceleration;
10  import org.djunits.value.vdouble.scalar.Duration;
11  import org.djunits.value.vdouble.scalar.Length;
12  import org.djunits.value.vdouble.scalar.Speed;
13  import org.opentrafficsim.base.parameters.ParameterException;
14  import org.opentrafficsim.base.parameters.Parameters;
15  import org.opentrafficsim.road.gtu.lane.perception.PerceptionIterable;
16  import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
17  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
18  import org.opentrafficsim.road.network.speed.SpeedLimitTypes;
19  
20  /**
21   * The Intelligent Driver Model by Treiber, Hennecke and Helbing.
22   * <p>
23   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
24   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
25   * <p>
26   * @version $Revision: 1408 $, $LastChangedDate: 2015-09-24 15:17:25 +0200 (Thu, 24 Sep 2015) $, by $Author: pknoppers $,
27   *          initial version 19 nov. 2014 <br>
28   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
29   */
30  public class IDMOld extends AbstractGTUFollowingModelMobil implements Serializable
31  {
32      /** */
33      private static final long serialVersionUID = 20141119L;
34  
35      /** Preferred net longitudinal distance when stopped [m]. */
36      private final Length s0;
37  
38      /** Maximum longitudinal acceleration [m/s^2]. */
39      private Acceleration a;
40  
41      /** Longitudinal deceleration [m/s^2]. (Should be a positive value even though it is a <b>de</b>celeration.) */
42      private final Acceleration b;
43  
44      /** Safe time headway. */
45      private Duration tSafe;
46  
47      /**
48       * Default step size used by IDM (not defined in the paper, but 0.5s is a reasonable trade-off between computational speed
49       * and accuracy).
50       */
51      private static final Duration DEFAULT_STEP_SIZE = new Duration(0.5, DurationUnit.SECOND);
52  
53      /**
54       * Mean speed limit adherence (1.0: mean free speed equals the speed limit; 1.1: mean speed limit equals 110% of the speed
55       * limit, etc.).
56       */
57      private double delta;
58  
59      /**
60       * Construct a new IDM car following model with reasonable values (reasonable for passenger cars).
61       */
62      public IDMOld()
63      {
64          this.a = new Acceleration(1.56, AccelerationUnit.METER_PER_SECOND_2);
65          this.b = new Acceleration(2.09, AccelerationUnit.METER_PER_SECOND_2);
66          this.s0 = new Length(3, LengthUnit.METER);
67          this.tSafe = new Duration(1.2, DurationUnit.SECOND);
68          this.delta = 1.0;
69      }
70  
71      /**
72       * Construct a new IDM car following model.
73       * @param a Acceleration; the maximum acceleration of a stationary vehicle (normal value is 1.56 m/s/s)
74       * @param b Acceleration; the maximum deemed-safe deceleration (this is a positive value). Normal value is 2.09 m/s/s.
75       * @param s0 Length; the minimum stationary headway (normal value is 3 m)
76       * @param tSafe Duration; the minimum time-headway (normal value is 1.2 s)
77       * @param delta double; the speed limit adherence (1.0; mean free speed equals the speed limit; 1.1: mean free speed equals
78       *            110% of the speed limit; etc.)
79       */
80      public IDMOld(final Acceleration a, final Acceleration b, final Length s0, final Duration tSafe, final double delta)
81      {
82          this.a = a;
83          this.b = b;
84          this.s0 = s0;
85          this.tSafe = tSafe;
86          this.delta = delta;
87      }
88  
89      /**
90       * Desired speed (taking into account the urge to drive a little faster or slower than the posted speed limit).
91       * @param speedLimit Speed; the speed limit
92       * @param followerMaximumSpeed Speed; the maximum speed that the follower can drive
93       * @return DoubleScalarRel&lt;SpeedUnit&gt;; the desired speed
94       */
95      private Speed vDes(final Speed speedLimit, final Speed followerMaximumSpeed)
96      {
97          return new Speed(Math.min(this.delta * speedLimit.getSI(), followerMaximumSpeed.getSI()), SpeedUnit.SI);
98      }
99  
100     /** {@inheritDoc} */
101     @Override
102     public final Acceleration computeAcceleration(final Speed followerSpeed, final Speed followerMaximumSpeed,
103             final Speed leaderSpeed, final Length headway, final Speed speedLimit)
104     {
105         return computeAcceleration(followerSpeed, followerMaximumSpeed, leaderSpeed, headway, speedLimit, DEFAULT_STEP_SIZE);
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     public final Acceleration computeAcceleration(final Speed followerSpeed, final Speed followerMaximumSpeed,
111             final Speed leaderSpeed, final Length headway, final Speed speedLimit, final Duration stepSize)
112     {
113         // TODO maxDistance
114         // dV is the approach speed
115         Speed dV = followerSpeed.minus(leaderSpeed);
116         double sStar = this.s0.si + followerSpeed.si * this.tSafe.si
117                 + dV.si * followerSpeed.si / (2.0 * Math.sqrt(this.a.si * this.b.si));
118         if (sStar < 0.0 && headway.si < 0.0)
119         {
120             return new Acceleration(Double.NEGATIVE_INFINITY, AccelerationUnit.SI);
121         }
122         sStar = sStar >= 0.0 ? sStar : 0.0;
123         double s = headway.si > 0.0 ? headway.si : 1E-99;
124         Acceleration aInteraction = new Acceleration(this.a.si * (sStar / s) * (sStar / s), AccelerationUnit.SI);
125         Acceleration aFree =
126                 new Acceleration(this.a.si * (1.0 - Math.pow(followerSpeed.si / vDes(speedLimit, followerMaximumSpeed).si, 4)),
127                         AccelerationUnit.SI);
128         // limit deceleration for free term (= aFree)
129         if (aFree.si < -0.5)
130         {
131             aFree = new Acceleration(-0.5, AccelerationUnit.SI);
132         }
133         Acceleration newAcceleration = aFree.minus(aInteraction);
134         if (newAcceleration.si * stepSize.si + followerSpeed.si < 0)
135         {
136             newAcceleration = new Acceleration(-followerSpeed.si / stepSize.si, AccelerationUnit.SI);
137         }
138         return newAcceleration;
139     }
140 
141     /** {@inheritDoc} */
142     @Override
143     public final Duration getStepSize()
144     {
145         return DEFAULT_STEP_SIZE;
146     }
147 
148     /** {@inheritDoc} */
149     @Override
150     public final Acceleration getMaximumSafeDeceleration()
151     {
152         return this.b;
153     }
154 
155     /** {@inheritDoc} */
156     @Override
157     public final String getName()
158     {
159         return "IDM";
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     public final String getLongName()
165     {
166         return String.format("%s (a=%.1fm/s\u00b2, b=%.1fm/s\u00b2, s0=%.1fm, tSafe=%.1fs, delta=%.2f)", getName(),
167                 this.a.getSI(), this.b.getSI(), this.s0.getSI(), this.tSafe.getSI(), this.delta);
168     }
169 
170     /** {@inheritDoc} */
171     @Override
172     public final void setA(final Acceleration a)
173     {
174         this.a = a;
175     }
176 
177     /** {@inheritDoc} */
178     @Override
179     public final void setT(final Duration t)
180     {
181         this.tSafe = t;
182     }
183 
184     /** {@inheritDoc} */
185     @Override
186     public final void setFspeed(final double fSpeed)
187     {
188         this.delta = fSpeed;
189     }
190 
191     // The following is inherited from CarFollowingModel
192 
193     /** {@inheritDoc} */
194     @Override
195     public final Speed desiredSpeed(final Parameters parameters, final SpeedLimitInfo speedInfo) throws ParameterException
196     {
197         throw new UnsupportedOperationException("Old car-following model does not support desired speed.");
198     }
199 
200     /** {@inheritDoc} */
201     @Override
202     public final Length desiredHeadway(final Parameters parameters, final Speed speed) throws ParameterException
203     {
204         throw new UnsupportedOperationException("Old car-following model does not support desired headway.");
205     }
206 
207     /** {@inheritDoc} */
208     @Override
209     public final Acceleration followingAcceleration(final Parameters parameters, final Speed speed,
210             final SpeedLimitInfo speedInfo, final PerceptionIterable<? extends Headway> leaders) throws ParameterException
211     {
212         Length headway;
213         Speed leaderSpeed;
214         if (leaders.isEmpty())
215         {
216             headway = new Length(Double.MAX_VALUE, LengthUnit.SI);
217             leaderSpeed = speed;
218         }
219         else
220         {
221             Headway leader = leaders.first();
222             headway = leader.getDistance();
223             leaderSpeed = leader.getSpeed();
224         }
225         return this.computeAcceleration(speed, speedInfo.getSpeedInfo(SpeedLimitTypes.MAX_VEHICLE_SPEED), leaderSpeed, headway,
226                 speedInfo.getSpeedInfo(SpeedLimitTypes.FIXED_SIGN));
227     }
228 
229     /** {@inheritDoc} */
230     @Override
231     public final String toString()
232     {
233         return "IDMOld [s0=" + this.s0 + ", a=" + this.a + ", b=" + this.b + ", tSafe=" + this.tSafe + ", stepSize="
234                 + DEFAULT_STEP_SIZE + ", delta=" + this.delta + "]";
235     }
236 
237 }