1 package org.opentrafficsim.road.gtu.lane.tactical.util;
2
3 import java.io.Serializable;
4
5 import org.djunits.unit.DurationUnit;
6 import org.djunits.unit.LengthUnit;
7 import org.djunits.value.vdouble.scalar.Acceleration;
8 import org.djunits.value.vdouble.scalar.Duration;
9 import org.djunits.value.vdouble.scalar.Length;
10 import org.djunits.value.vdouble.scalar.Speed;
11 import org.opentrafficsim.base.parameters.ParameterException;
12 import org.opentrafficsim.base.parameters.Parameters;
13 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
14 import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
15
16
17
18
19
20
21
22
23
24
25
26
27 public final class AnticipationInfo implements Serializable
28 {
29
30
31 private static final long serialVersionUID = 20160811L;
32
33
34 private final Duration duration;
35
36
37 private final Speed endSpeed;
38
39
40
41
42
43 public AnticipationInfo(final Duration duration, final Speed endSpeed)
44 {
45 this.duration = duration;
46 this.endSpeed = endSpeed;
47 }
48
49
50
51
52 public Duration getDuration()
53 {
54 return this.duration;
55 }
56
57
58
59
60 public Speed getEndSpeed()
61 {
62 return this.endSpeed;
63 }
64
65
66
67
68
69
70
71
72 public static AnticipationInfo anticipateMovement(final Length distance, final Speed initialSpeed,
73 final Acceleration acceleration)
74 {
75 return anticipateMovementSpeedLimited(distance, initialSpeed, acceleration, Speed.POSITIVE_INFINITY);
76 }
77
78
79
80
81
82
83
84
85
86 public static AnticipationInfo anticipateMovementSpeedLimited(final Length distance, final Speed initialSpeed,
87 final Acceleration acceleration, final Speed maxSpeed)
88 {
89 if (distance.lt0())
90 {
91 return new AnticipationInfo(Duration.ZERO, initialSpeed);
92 }
93
94 if (acceleration.eq(Acceleration.ZERO))
95 {
96 if (initialSpeed.gt0())
97 {
98 return new AnticipationInfo(distance.divideBy(initialSpeed), initialSpeed);
99 }
100
101 return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, DurationUnit.SI), Speed.ZERO);
102 }
103
104 double tmp = initialSpeed.si * initialSpeed.si + 2.0 * acceleration.si * distance.si;
105 if (tmp < 0)
106 {
107
108 return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, DurationUnit.SI), Speed.ZERO);
109 }
110
111 Duration d = new Duration((Math.sqrt(tmp) - initialSpeed.si) / acceleration.si, DurationUnit.SI);
112
113 Speed endSpeed = initialSpeed.plus(acceleration.multiplyBy(d));
114 if (endSpeed.le(maxSpeed))
115 {
116 return new AnticipationInfo(d, endSpeed);
117 }
118
119 Duration d1 = maxSpeed.minus(initialSpeed).divideBy(acceleration);
120 Length x2 = new Length(distance.si - initialSpeed.si * d1.si - .5 * acceleration.si * d1.si * d1.si, LengthUnit.SI);
121 return new AnticipationInfo(d1.plus(x2.divideBy(maxSpeed)), maxSpeed);
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135 public static AnticipationInfo anticipateMovementFreeAcceleration(final Length distance, final Speed initialSpeed,
136 final Parameters parameters, final CarFollowingModel carFollowingModel,
137 final SpeedLimitInfo speedLimitInfo, final Duration timeStep) throws ParameterException
138 {
139 if (distance.lt0())
140 {
141 return new AnticipationInfo(Duration.ZERO, initialSpeed);
142 }
143 Duration out = Duration.ZERO;
144 if (distance.lt0())
145 {
146 return new AnticipationInfo(out, initialSpeed);
147 }
148 Length xCumul = Length.ZERO;
149 Speed speed = initialSpeed;
150 while (xCumul.lt(distance))
151 {
152 Acceleration a =
153 CarFollowingUtil.freeAcceleration(carFollowingModel, parameters, speed, speedLimitInfo);
154 Length add = new Length(speed.si * timeStep.si + .5 * a.si * timeStep.si * timeStep.si, LengthUnit.SI);
155 Length remain = distance.minus(xCumul);
156 if (add.lt(remain))
157 {
158 xCumul = xCumul.plus(add);
159 speed = speed.plus(a.multiplyBy(timeStep));
160 out = out.plus(timeStep);
161 }
162 else
163 {
164 Duration timeInStep;
165 double tmp = Math.sqrt(2 * a.si * remain.si + speed.si * speed.si) - speed.si;
166 if (tmp < 0.000001)
167 {
168
169 timeInStep = remain.divideBy(speed);
170 }
171 else
172 {
173 timeInStep = new Duration(tmp / a.si, DurationUnit.SI);
174 speed = speed.plus(a.multiplyBy(timeInStep));
175 }
176 out = out.plus(timeInStep);
177 return new AnticipationInfo(out, speed);
178 }
179 }
180
181 throw new RuntimeException("Distance for anticipation of conflict movement is surpassed.");
182 }
183
184
185 @Override
186 public String toString()
187 {
188 return "AnticipationInfo [duration = " + this.duration + ", endSpeed = " + this.endSpeed + "]";
189 }
190
191 }