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