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