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  
22  
23  
24  
25  
26  
27  
28  
29  
30  public class IDMOld extends AbstractGTUFollowingModelMobil implements Serializable
31  {
32      
33      private static final long serialVersionUID = 20141119L;
34  
35      
36      private final Length s0;
37  
38      
39      private Acceleration a;
40  
41      
42      private final Acceleration b;
43  
44      
45      private Duration tSafe;
46  
47      
48  
49  
50  
51      private static final Duration DEFAULT_STEP_SIZE = new Duration(0.5, DurationUnit.SECOND);
52  
53      
54  
55  
56  
57      private double delta;
58  
59      
60  
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  
73  
74  
75  
76  
77  
78  
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  
91  
92  
93  
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     
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     
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         
114         
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         
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     
142     @Override
143     public final Duration getStepSize()
144     {
145         return DEFAULT_STEP_SIZE;
146     }
147 
148     
149     @Override
150     public final Acceleration getMaximumSafeDeceleration()
151     {
152         return this.b;
153     }
154 
155     
156     @Override
157     public final String getName()
158     {
159         return "IDM";
160     }
161 
162     
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     
171     @Override
172     public final void setA(final Acceleration a)
173     {
174         this.a = a;
175     }
176 
177     
178     @Override
179     public final void setT(final Duration t)
180     {
181         this.tSafe = t;
182     }
183 
184     
185     @Override
186     public final void setFspeed(final double fSpeed)
187     {
188         this.delta = fSpeed;
189     }
190 
191     
192 
193     
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     
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     
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     
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 }