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