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, final SpeedLimitInfo speedLimitInfo,
137 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 = CarFollowingUtil.freeAcceleration(carFollowingModel, parameters, speed, speedLimitInfo);
153 Length add = new Length(speed.si * timeStep.si + .5 * a.si * timeStep.si * timeStep.si, LengthUnit.SI);
154 Length remain = distance.minus(xCumul);
155 if (add.lt(remain))
156 {
157 xCumul = xCumul.plus(add);
158 speed = speed.plus(a.multiplyBy(timeStep));
159 out = out.plus(timeStep);
160 }
161 else
162 {
163 Duration timeInStep;
164 double tmp = Math.sqrt(2 * a.si * remain.si + speed.si * speed.si) - speed.si;
165 if (tmp < 0.000001)
166 {
167
168 timeInStep = remain.divideBy(speed);
169 }
170 else
171 {
172 timeInStep = new Duration(tmp / a.si, DurationUnit.SI);
173 speed = speed.plus(a.multiplyBy(timeInStep));
174 }
175 out = out.plus(timeInStep);
176 return new AnticipationInfo(out, speed);
177 }
178 }
179
180 throw new RuntimeException("Distance for anticipation of conflict movement is surpassed.");
181 }
182
183
184 @Override
185 public String toString()
186 {
187 return "AnticipationInfo [duration = " + this.duration + ", endSpeed = " + this.endSpeed + "]";
188 }
189
190 }