1 package org.opentrafficsim.core.gtu.following;
2
3 import java.rmi.RemoteException;
4 import java.util.Collection;
5
6 import org.opentrafficsim.core.gtu.lane.LaneBasedGTU;
7 import org.opentrafficsim.core.network.NetworkException;
8 import org.opentrafficsim.core.unit.AccelerationUnit;
9 import org.opentrafficsim.core.unit.LengthUnit;
10 import org.opentrafficsim.core.unit.SpeedUnit;
11 import org.opentrafficsim.core.unit.TimeUnit;
12 import org.opentrafficsim.core.value.conversions.Calc;
13 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar;
14 import org.opentrafficsim.core.value.vdouble.scalar.MutableDoubleScalar;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 public abstract class AbstractGTUFollowingModel implements GTUFollowingModel
30 {
31
32 private static final AccelerationStep PROHIBITIVEACCELERATIONSTEP = new AccelerationStep(
33 new DoubleScalar.Abs<AccelerationUnit>(Double.NEGATIVE_INFINITY, AccelerationUnit.SI),
34 new DoubleScalar.Abs<TimeUnit>(Double.NaN, TimeUnit.SI));
35
36
37 public static final DualAccelerationStep TOODANGEROUS = new DualAccelerationStep(PROHIBITIVEACCELERATIONSTEP,
38 PROHIBITIVEACCELERATIONSTEP);
39
40
41 @Override
42 public final DualAccelerationStep computeAcceleration(final LaneBasedGTU<?> referenceGTU,
43 final Collection<HeadwayGTU> otherGTUs, final DoubleScalar.Abs<SpeedUnit> speedLimit)
44 throws RemoteException, NetworkException
45 {
46 DoubleScalar.Abs<TimeUnit> when = referenceGTU.getSimulator().getSimulatorTime().get();
47
48 for (HeadwayGTU headwayGTU : otherGTUs)
49 {
50 if (headwayGTU.getOtherGTU() != referenceGTU && null == headwayGTU.getDistance())
51 {
52 return TOODANGEROUS;
53 }
54 }
55 AccelerationStep followerAccelerationStep = null;
56 AccelerationStep referenceGTUAccelerationStep = null;
57 GTUFollowingModel gfm = referenceGTU.getGTUFollowingModel();
58
59 for (HeadwayGTU headwayGTU : otherGTUs)
60 {
61 if (null == headwayGTU.getOtherGTU())
62 {
63 System.out.println("FollowAcceleration.acceleration: Cannot happen");
64 }
65 if (headwayGTU.getOtherGTU() == referenceGTU)
66 {
67 continue;
68 }
69 if (headwayGTU.getDistanceSI() < 0)
70 {
71
72 AccelerationStep as =
73 gfm.computeAcceleration(headwayGTU.getOtherGTU(), referenceGTU.getLongitudinalVelocity(when),
74 new DoubleScalar.Rel<LengthUnit>(-headwayGTU.getDistanceSI(), LengthUnit.SI),
75 speedLimit);
76 if (null == followerAccelerationStep
77 || as.getAcceleration().getSI() < followerAccelerationStep.getAcceleration().getSI())
78 {
79
80
81
82
83 followerAccelerationStep = as;
84 }
85 }
86 else
87 {
88
89 AccelerationStep as =
90 gfm.computeAcceleration(referenceGTU, headwayGTU.getOtherGTU().getLongitudinalVelocity(when),
91 headwayGTU.getDistance(), speedLimit);
92 if (null == referenceGTUAccelerationStep
93 || as.getAcceleration().getSI() < referenceGTUAccelerationStep.getAcceleration().getSI())
94 {
95 referenceGTUAccelerationStep = as;
96 }
97 }
98 }
99 if (null == followerAccelerationStep)
100 {
101 followerAccelerationStep = gfm.computeAccelerationWithNoLeader(referenceGTU, speedLimit);
102 }
103 if (null == referenceGTUAccelerationStep)
104 {
105 referenceGTUAccelerationStep = gfm.computeAccelerationWithNoLeader(referenceGTU, speedLimit);
106 }
107 return new DualAccelerationStep(referenceGTUAccelerationStep, followerAccelerationStep);
108 }
109
110
111 @Override
112 public final AccelerationStep computeAcceleration(final LaneBasedGTU<?> follower,
113 final DoubleScalar.Abs<SpeedUnit> leaderSpeed, final DoubleScalar.Rel<LengthUnit> headway,
114 final DoubleScalar.Abs<SpeedUnit> speedLimit) throws RemoteException
115 {
116 final DoubleScalar.Abs<TimeUnit> currentTime = follower.getNextEvaluationTime();
117 final DoubleScalar.Abs<SpeedUnit> followerSpeed = follower.getLongitudinalVelocity(currentTime);
118 final DoubleScalar.Abs<SpeedUnit> followerMaximumSpeed = follower.getMaximumVelocity();
119 DoubleScalar.Abs<AccelerationUnit> newAcceleration =
120 computeAcceleration(followerSpeed, followerMaximumSpeed, leaderSpeed, headway, speedLimit);
121 MutableDoubleScalar.Abs<TimeUnit> nextEvaluationTime = currentTime.mutable();
122 nextEvaluationTime.incrementBy(getStepSize());
123 return new AccelerationStep(newAcceleration, nextEvaluationTime.immutable());
124
125 }
126
127
128 @Override
129 public final AccelerationStep computeAccelerationWithNoLeader(final LaneBasedGTU<?> gtu,
130 final DoubleScalar.Abs<SpeedUnit> speedLimit) throws RemoteException, NetworkException
131 {
132 return computeAcceleration(gtu, gtu.getLongitudinalVelocity(),
133 Calc.speedSquaredDividedByDoubleAcceleration(gtu.getMaximumVelocity(), maximumSafeDeceleration()),
134 speedLimit);
135 }
136
137
138 @Override
139 public final DoubleScalar.Rel<LengthUnit> minimumHeadway(final DoubleScalar.Abs<SpeedUnit> followerSpeed,
140 final DoubleScalar.Abs<SpeedUnit> leaderSpeed, final DoubleScalar.Rel<LengthUnit> precision,
141 final DoubleScalar.Abs<SpeedUnit> speedLimit, final DoubleScalar.Abs<SpeedUnit> followerMaximumSpeed)
142 throws RemoteException
143 {
144 if (precision.getSI() <= 0)
145 {
146 throw new Error("Precision has bad value (must be > 0; got " + precision + ")");
147 }
148 double maximumDeceleration = -maximumSafeDeceleration().getSI();
149
150 double minimumSI = 0;
151 double minimumSIDeceleration =
152 computeAcceleration(followerSpeed, followerSpeed, leaderSpeed,
153 new DoubleScalar.Rel<LengthUnit>(minimumSI, LengthUnit.SI), speedLimit).getSI();
154 if (minimumSIDeceleration >= maximumDeceleration)
155 {
156
157 return new DoubleScalar.Rel<LengthUnit>(0, LengthUnit.SI);
158 }
159 double maximumSI = 1;
160 double maximumSIDeceleration = Double.NaN;
161
162 for (int step = 0; step < 20; step++)
163 {
164 maximumSIDeceleration =
165 computeAcceleration(followerSpeed, followerMaximumSpeed, leaderSpeed,
166 new DoubleScalar.Rel<LengthUnit>(maximumSI, LengthUnit.SI), speedLimit).getSI();
167 if (maximumSIDeceleration > maximumDeceleration)
168 {
169 break;
170 }
171 maximumSI *= 2;
172 }
173 if (maximumSIDeceleration < maximumDeceleration)
174 {
175 throw new Error("Cannot find headway that results in an acceptable deceleration");
176 }
177
178 final int maximumStep = (int) Math.ceil(Math.log((maximumSI - minimumSI) / precision.getSI()) / Math.log(2));
179 for (int step = 0; step < maximumStep; step++)
180 {
181 double midSI = (minimumSI + maximumSI) / 2;
182 double midSIAcceleration =
183 computeAcceleration(followerSpeed, followerMaximumSpeed, leaderSpeed,
184 new DoubleScalar.Rel<LengthUnit>(midSI, LengthUnit.SI), speedLimit).getSI();
185 if (midSIAcceleration < maximumDeceleration)
186 {
187 minimumSI = midSI;
188 }
189 else
190 {
191 maximumSI = midSI;
192 }
193 }
194 DoubleScalar.Rel<LengthUnit> result =
195 new DoubleScalar.Rel<LengthUnit>((minimumSI + maximumSI) / 2, LengthUnit.SI);
196 computeAcceleration(followerSpeed, followerMaximumSpeed, leaderSpeed,
197 new DoubleScalar.Rel<LengthUnit>(result.getSI(), LengthUnit.SI), speedLimit).getSI();
198 return result;
199 }
200 }