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
92 if (acceleration.eq(Acceleration.ZERO))
93 {
94 if (initialSpeed.gt(Speed.ZERO))
95 {
96 return new AnticipationInfo(distance.divideBy(initialSpeed), initialSpeed);
97 }
98
99 return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, TimeUnit.SI), Speed.ZERO);
100 }
101
102 double tmp = initialSpeed.si * initialSpeed.si + 2.0 * acceleration.si * distance.si;
103 if (tmp < 0)
104 {
105
106 return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, TimeUnit.SI), Speed.ZERO);
107 }
108
109 Duration d = new Duration((Math.sqrt(tmp) - initialSpeed.si) / acceleration.si, TimeUnit.SI);
110
111 Speed endSpeed = initialSpeed.plus(acceleration.multiplyBy(d));
112 if (endSpeed.le(maxSpeed))
113 {
114 return new AnticipationInfo(d, endSpeed);
115 }
116
117 Duration d1 = maxSpeed.minus(initialSpeed).divideBy(acceleration);
118 Length x2 = new Length(distance.si - initialSpeed.si * d1.si - .5 * acceleration.si * d1.si * d1.si, LengthUnit.SI);
119 return new AnticipationInfo(d1.plus(x2.divideBy(maxSpeed)), maxSpeed);
120 }
121
122
123
124
125
126
127
128
129
130
131
132
133 public static AnticipationInfo anticipateMovementFreeAcceleration(final Length distance, final Speed initialSpeed,
134 final BehavioralCharacteristics behavioralCharacteristics, final CarFollowingModel carFollowingModel,
135 final SpeedLimitInfo speedLimitInfo, final Duration timeStep) throws ParameterException
136 {
137 Duration out = Duration.ZERO;
138 Length xCumul = Length.ZERO;
139 Speed speed = initialSpeed;
140 while (xCumul.lt(distance))
141 {
142 Acceleration a =
143 CarFollowingUtil.freeAcceleration(carFollowingModel, behavioralCharacteristics, speed, speedLimitInfo);
144 Length add = new Length(speed.si * timeStep.si + .5 * a.si * timeStep.si * timeStep.si, LengthUnit.SI);
145 Length remain = distance.minus(xCumul);
146 if (add.lt(remain))
147 {
148 xCumul = xCumul.plus(add);
149 speed = speed.plus(a.multiplyBy(timeStep));
150 out = out.plus(timeStep);
151 }
152 else
153 {
154 Duration timeInStep;
155 double tmp = Math.sqrt(2 * a.si * remain.si + speed.si * speed.si) - speed.si;
156 if (tmp < 0.000001)
157 {
158
159 timeInStep = remain.divideBy(speed);
160 }
161 else
162 {
163 timeInStep = new Duration(tmp / a.si, TimeUnit.SI);
164 speed = speed.plus(a.multiplyBy(timeInStep));
165 }
166 out = out.plus(timeInStep);
167 return new AnticipationInfo(out, speed);
168 }
169 }
170
171 throw new RuntimeException("Distance for anticipation of conflict movement is surpassed.");
172 }
173
174
175 @Override
176 public String toString()
177 {
178 return "AnticipationInfo [duration = " + this.duration + ", endSpeed = " + this.endSpeed + "]";
179 }
180
181 }