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