1 package org.opentrafficsim.core.gtu.following;
2
3 import org.opentrafficsim.core.unit.AccelerationUnit;
4 import org.opentrafficsim.core.unit.LengthUnit;
5 import org.opentrafficsim.core.unit.SpeedUnit;
6 import org.opentrafficsim.core.unit.TimeUnit;
7 import org.opentrafficsim.core.value.conversions.Calc;
8 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar;
9 import org.opentrafficsim.core.value.vdouble.scalar.MutableDoubleScalar;
10
11
12
13
14
15
16
17
18
19
20
21 public class IDM extends AbstractGTUFollowingModel
22 {
23
24 private final DoubleScalar.Rel<LengthUnit> s0;
25
26
27 private final DoubleScalar.Abs<AccelerationUnit> a;
28
29
30 private final DoubleScalar.Abs<AccelerationUnit> b;
31
32
33 private final DoubleScalar.Rel<TimeUnit> tSafe;
34
35
36
37
38
39 private final DoubleScalar.Rel<TimeUnit> stepSize = new DoubleScalar.Rel<TimeUnit>(0.5, TimeUnit.SECOND);
40
41
42
43
44
45 private final double delta;
46
47
48
49
50 public IDM()
51 {
52 this.a = new DoubleScalar.Abs<AccelerationUnit>(1.56, AccelerationUnit.METER_PER_SECOND_2);
53 this.b = new DoubleScalar.Abs<AccelerationUnit>(2.09, AccelerationUnit.METER_PER_SECOND_2);
54 this.s0 = new DoubleScalar.Rel<LengthUnit>(3, LengthUnit.METER);
55 this.tSafe = new DoubleScalar.Rel<TimeUnit>(1.2, TimeUnit.SECOND);
56 this.delta = 1d;
57 }
58
59
60
61
62
63
64
65
66
67
68
69
70 public IDM(final DoubleScalar.Abs<AccelerationUnit> a, final DoubleScalar.Abs<AccelerationUnit> b,
71 final DoubleScalar.Rel<LengthUnit> s0, final DoubleScalar.Rel<TimeUnit> tSafe, final double delta)
72 {
73 this.a = a;
74 this.b = b;
75 this.s0 = s0;
76 this.tSafe = tSafe;
77 this.delta = delta;
78 }
79
80
81
82
83
84
85
86 private DoubleScalar.Rel<SpeedUnit> vDes(final DoubleScalar.Abs<SpeedUnit> speedLimit,
87 final DoubleScalar.Abs<SpeedUnit> followerMaximumSpeed)
88 {
89 return new DoubleScalar.Rel<SpeedUnit>(Math.min(this.delta * speedLimit.getSI(), followerMaximumSpeed.getSI()),
90 SpeedUnit.METER_PER_SECOND);
91 }
92
93
94 public final DoubleScalar.Abs<AccelerationUnit> computeAcceleration(
95 final DoubleScalar.Abs<SpeedUnit> followerSpeed, final DoubleScalar.Abs<SpeedUnit> followerMaximumSpeed,
96 final DoubleScalar.Abs<SpeedUnit> leaderSpeed, final DoubleScalar.Rel<LengthUnit> headway,
97 final DoubleScalar.Abs<SpeedUnit> speedLimit)
98 {
99
100
101 DoubleScalar.Rel<SpeedUnit> dV = DoubleScalar.minus(followerSpeed, leaderSpeed).immutable();
102 DoubleScalar.Abs<AccelerationUnit> aFree =
103 new DoubleScalar.Abs<AccelerationUnit>(this.a.getSI()
104 * (1 - Math.pow(followerSpeed.getSI() / vDes(speedLimit, followerMaximumSpeed).getSI(), 4)),
105 AccelerationUnit.METER_PER_SECOND_2);
106 if (Double.isNaN(aFree.getSI()))
107 {
108 aFree = new DoubleScalar.Abs<AccelerationUnit>(0, AccelerationUnit.SI);
109 }
110 MutableDoubleScalar.Rel<AccelerationUnit> logWeightedAccelerationTimes2 =
111 new MutableDoubleScalar.Rel<AccelerationUnit>(Math.sqrt(this.a.getSI() * this.b.getSI()),
112 AccelerationUnit.METER_PER_SECOND_2);
113 logWeightedAccelerationTimes2.multiply(2);
114
115
116
117
118
119
120
121 DoubleScalar.Rel<LengthUnit> right =
122 DoubleScalar.plus(
123 Calc.speedTimesTime(followerSpeed, this.tSafe),
124 Calc.speedTimesTime(
125 dV,
126 Calc.speedDividedByAcceleration(followerSpeed,
127 logWeightedAccelerationTimes2.immutable()))).immutable();
128 if (right.getSI() < 0)
129 {
130
131 right = new DoubleScalar.Rel<LengthUnit>(0, LengthUnit.METER);
132 }
133 DoubleScalar.Rel<LengthUnit> sStar = DoubleScalar.plus(this.s0, right).immutable();
134 if (sStar.getSI() < 0)
135 {
136 System.out.println("sStar is negative");
137 sStar = new DoubleScalar.Rel<LengthUnit>(0, LengthUnit.METER);
138 }
139
140 DoubleScalar.Rel<AccelerationUnit> aInteraction =
141 new DoubleScalar.Rel<AccelerationUnit>(-Math.pow(this.a.getSI() * sStar.getSI() / headway.getSI(), 2),
142 AccelerationUnit.METER_PER_SECOND_2);
143 DoubleScalar.Abs<AccelerationUnit> newAcceleration = DoubleScalar.plus(aFree, aInteraction).immutable();
144 if (newAcceleration.getSI() * this.stepSize.getSI() + followerSpeed.getSI() < 0)
145 {
146
147 newAcceleration =
148 new DoubleScalar.Abs<AccelerationUnit>(-followerSpeed.getSI() / this.stepSize.getSI(),
149 AccelerationUnit.METER_PER_SECOND_2);
150 }
151
152 return newAcceleration;
153 }
154
155
156 @Override
157 public final DoubleScalar.Rel<TimeUnit> getStepSize()
158 {
159 return new DoubleScalar.Rel<TimeUnit>(this.stepSize);
160 }
161
162
163 @Override
164 public final DoubleScalar.Abs<AccelerationUnit> maximumSafeDeceleration()
165 {
166 return this.b;
167 }
168
169
170 @Override
171 public final String getName()
172 {
173 return "IDM";
174 }
175
176
177 @Override
178 public final String getLongName()
179 {
180 return String.format("%s (a=%.1fm/s\u00b2, b=%.1fm/s\u00b2, s0=%.1fm, tSafe=%.1fs, delta=%.2f)", getName(),
181 this.a.getSI(), this.b.getSI(), this.s0.getSI(), this.tSafe.getSI(), this.delta);
182 }
183
184 }