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  
31  
32  
33  public class IDMPlusOld extends AbstractGTUFollowingModelMobil implements Serializable
34  {
35      
36      private static final long serialVersionUID = 20140704L;
37  
38      
39      private final Length s0;
40  
41      
42      private Acceleration a;
43  
44      
45      private final Acceleration b;
46  
47      
48      private Duration tSafe;
49  
50      
51  
52  
53  
54      private double delta;
55  
56      
57  
58  
59  
60      private static final Duration DEFAULT_STEP_SIZE = new Duration(0.5, DurationUnit.SECOND);
61  
62      
63  
64  
65  
66  
67  
68      public IDMPlusOld()
69      {
70          this.a = new Acceleration(1.56, AccelerationUnit.METER_PER_SECOND_2);
71          this.b = new Acceleration(2.09, AccelerationUnit.METER_PER_SECOND_2);
72          this.s0 = new Length(3, LengthUnit.METER);
73          this.tSafe = new Duration(1.2, DurationUnit.SECOND);
74          this.delta = 1d;
75      }
76  
77      
78  
79  
80  
81  
82  
83  
84  
85  
86      public IDMPlusOld(final Acceleration a, final Acceleration b, final Length s0, final Duration tSafe, final double delta)
87      {
88          this.a = a;
89          this.b = b;
90          this.s0 = s0;
91          this.tSafe = tSafe;
92          this.delta = delta;
93      }
94  
95      
96  
97  
98  
99  
100 
101     private Speed vDes(final Speed speedLimit, final Speed followerMaximumSpeed)
102     {
103         return new Speed(Math.min(this.delta * speedLimit.getSI(), followerMaximumSpeed.getSI()), SpeedUnit.SI);
104     }
105 
106     
107     @Override
108     public final Acceleration computeAcceleration(final Speed followerSpeed, final Speed followerMaximumSpeed,
109             final Speed leaderSpeed, final Length headway, final Speed speedLimit)
110     {
111         return computeAcceleration(followerSpeed, followerMaximumSpeed, leaderSpeed, headway, speedLimit, DEFAULT_STEP_SIZE);
112     }
113 
114     
115     @Override
116     public final Acceleration computeAcceleration(final Speed followerSpeed, final Speed followerMaximumSpeed,
117             final Speed leaderSpeed, final Length headway, final Speed speedLimit, final Duration stepSize)
118     {
119         
120         double leftComponent = 1 - Math.pow(followerSpeed.getSI() / vDes(speedLimit, followerMaximumSpeed).getSI(), 4);
121         if (Double.isNaN(leftComponent))
122         {
123             leftComponent = 0;
124         }
125         
126         if (leftComponent * this.a.si < -0.5)
127         {
128             leftComponent = -0.5 / this.a.si;
129         }
130         Acceleration logWeightedAccelerationTimes2 =
131                 new Acceleration(Math.sqrt(this.a.getSI() * this.b.getSI()), AccelerationUnit.SI).times(2);
132         
133 
134         Speed dV = followerSpeed.minus(leaderSpeed);
135         Length sStar = this.s0.plus(followerSpeed.times(this.tSafe))
136                 .plus(dV.times(followerSpeed.divide(logWeightedAccelerationTimes2)));
137 
138         
139 
140 
141 
142         if (sStar.getSI() < 0)
143         {
144             
145             
146             sStar = new Length(0, LengthUnit.SI);
147         }
148 
149         double rightComponent = 1 - Math.pow(sStar.getSI() / headway.getSI(), 2);
150         Acceleration newAcceleration = new Acceleration(this.a).times(Math.min(leftComponent, rightComponent));
151         if (newAcceleration.getSI() * stepSize.getSI() + followerSpeed.getSI() < 0)
152         {
153             newAcceleration = new Acceleration(-followerSpeed.getSI() / stepSize.getSI(), AccelerationUnit.SI);
154         }
155         return newAcceleration;
156     }
157 
158     
159     @Override
160     public final Duration getStepSize()
161     {
162         return DEFAULT_STEP_SIZE;
163     }
164 
165     
166     @Override
167     public final Acceleration getMaximumSafeDeceleration()
168     {
169         return this.b;
170     }
171 
172     
173     @Override
174     public final String getName()
175     {
176         return "IDM+";
177     }
178 
179     
180     @Override
181     public final String getLongName()
182     {
183         return String.format("%s (a=%.1fm/s\u00b2, b=%.1fm/s\u00b2, s0=%.1fm, tSafe=%.1fs, delta=%.2f)", getName(),
184                 this.a.getSI(), this.b.getSI(), this.s0.getSI(), this.tSafe.getSI(), this.delta);
185     }
186 
187     
188     @Override
189     public final void setA(final Acceleration a)
190     {
191         this.a = a;
192     }
193 
194     
195     @Override
196     public final void setT(final Duration t)
197     {
198         this.tSafe = t;
199     }
200 
201     
202     @Override
203     public final void setFspeed(final double fSpeed)
204     {
205         this.delta = fSpeed;
206     }
207 
208     
209 
210     
211     @Override
212     public final Speed desiredSpeed(final Parameters parameters, final SpeedLimitInfo speedInfo) throws ParameterException
213     {
214         throw new UnsupportedOperationException("Old car-following model does not support desired speed.");
215     }
216 
217     
218     @Override
219     public final Length desiredHeadway(final Parameters parameters, final Speed speed) throws ParameterException
220     {
221         throw new UnsupportedOperationException("Old car-following model does not support desired headway.");
222     }
223 
224     
225     @Override
226     public final Acceleration followingAcceleration(final Parameters parameters, final Speed speed,
227             final SpeedLimitInfo speedInfo, final PerceptionIterable<? extends Headway> leaders) throws ParameterException
228     {
229         Length headway;
230         Speed leaderSpeed;
231         if (leaders.isEmpty())
232         {
233             headway = new Length(Double.MAX_VALUE, LengthUnit.SI);
234             leaderSpeed = speed;
235         }
236         else
237         {
238             Headway leader = leaders.first();
239             headway = leader.getDistance();
240             leaderSpeed = leader.getSpeed();
241         }
242         return this.computeAcceleration(speed, speedInfo.getSpeedInfo(SpeedLimitTypes.MAX_VEHICLE_SPEED), leaderSpeed, headway,
243                 speedInfo.getSpeedInfo(SpeedLimitTypes.FIXED_SIGN));
244     }
245 
246     
247     @Override
248     public final String toString()
249     {
250         return "IDMPlusOld [s0=" + this.s0 + ", a=" + this.a + ", b=" + this.b + ", tSafe=" + this.tSafe + ", delta="
251                 + this.delta + ", stepSize=" + DEFAULT_STEP_SIZE + "]";
252     }
253 
254 }