1 package org.opentrafficsim.road.gtu.lane.tactical.util;
2
3 import org.djunits.unit.DurationUnit;
4 import org.djunits.unit.LengthUnit;
5 import org.djunits.value.vdouble.scalar.Acceleration;
6 import org.djunits.value.vdouble.scalar.Duration;
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djunits.value.vdouble.scalar.Speed;
9 import org.opentrafficsim.base.OtsRuntimeException;
10 import org.opentrafficsim.base.parameters.ParameterException;
11 import org.opentrafficsim.base.parameters.Parameters;
12 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
13 import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
14
15
16
17
18
19
20
21
22
23
24
25
26
27 public record AnticipationInfo(Duration duration, Speed endSpeed)
28 {
29
30
31
32
33
34
35
36
37 public static AnticipationInfo anticipateMovement(final Length distance, final Speed initialSpeed,
38 final Acceleration acceleration)
39 {
40 return anticipateMovementSpeedLimited(distance, initialSpeed, acceleration, Speed.POSITIVE_INFINITY);
41 }
42
43
44
45
46
47
48
49
50
51 public static AnticipationInfo anticipateMovementSpeedLimited(final Length distance, final Speed initialSpeed,
52 final Acceleration acceleration, final Speed maxSpeed)
53 {
54 if (distance.lt0())
55 {
56 return new AnticipationInfo(Duration.ZERO, initialSpeed);
57 }
58
59 if (acceleration.eq(Acceleration.ZERO))
60 {
61 if (initialSpeed.gt0())
62 {
63 return new AnticipationInfo(distance.divide(initialSpeed), initialSpeed);
64 }
65
66 return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, DurationUnit.SI), Speed.ZERO);
67 }
68
69 double tmp = initialSpeed.si * initialSpeed.si + 2.0 * acceleration.si * distance.si;
70 if (tmp < 0)
71 {
72
73 return new AnticipationInfo(new Duration(Double.POSITIVE_INFINITY, DurationUnit.SI), Speed.ZERO);
74 }
75
76 Duration d = new Duration((Math.sqrt(tmp) - initialSpeed.si) / acceleration.si, DurationUnit.SI);
77
78 Speed endSpeed = initialSpeed.plus(acceleration.times(d));
79 if (endSpeed.le(maxSpeed))
80 {
81 return new AnticipationInfo(d, endSpeed);
82 }
83
84 Duration d1 = maxSpeed.minus(initialSpeed).divide(acceleration);
85 Length x2 = new Length(distance.si - initialSpeed.si * d1.si - .5 * acceleration.si * d1.si * d1.si, LengthUnit.SI);
86 return new AnticipationInfo(d1.plus(x2.divide(maxSpeed)), maxSpeed);
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100 public static AnticipationInfo anticipateMovementFreeAcceleration(final Length distance, final Speed initialSpeed,
101 final Parameters parameters, final CarFollowingModel carFollowingModel, final SpeedLimitInfo speedLimitInfo,
102 final Duration timeStep) throws ParameterException
103 {
104 Duration out = Duration.ZERO;
105 if (distance.lt0())
106 {
107 return new AnticipationInfo(out, initialSpeed);
108 }
109 Length xCumul = Length.ZERO;
110 Speed speed = initialSpeed;
111 while (xCumul.lt(distance))
112 {
113 Acceleration a = CarFollowingUtil.freeAcceleration(carFollowingModel, parameters, speed, speedLimitInfo);
114 Length add = new Length(speed.si * timeStep.si + .5 * a.si * timeStep.si * timeStep.si, LengthUnit.SI);
115 Length remain = distance.minus(xCumul);
116 if (add.lt(remain))
117 {
118 xCumul = xCumul.plus(add);
119 speed = speed.plus(a.times(timeStep));
120 out = out.plus(timeStep);
121 }
122 else
123 {
124 Duration timeInStep;
125 double tmp = Math.sqrt(2 * a.si * remain.si + speed.si * speed.si) - speed.si;
126 if (tmp < 0.000001)
127 {
128
129 timeInStep = remain.divide(speed);
130 }
131 else
132 {
133 timeInStep = new Duration(tmp / a.si, DurationUnit.SI);
134 speed = speed.plus(a.times(timeInStep));
135 }
136 out = out.plus(timeInStep);
137 return new AnticipationInfo(out, speed);
138 }
139 }
140
141 throw new OtsRuntimeException("Distance for anticipation of conflict movement is surpassed.");
142 }
143
144 }