1 package org.opentrafficsim.core.gtu.plan.operational;
2
3 import java.util.ArrayList;
4
5 import org.djunits.unit.AccelerationUnit;
6 import org.djunits.unit.DurationUnit;
7 import org.djunits.unit.SpeedUnit;
8 import org.djunits.value.ValueException;
9 import org.djunits.value.vdouble.scalar.Acceleration;
10 import org.djunits.value.vdouble.scalar.Duration;
11 import org.djunits.value.vdouble.scalar.Length;
12 import org.djunits.value.vdouble.scalar.Speed;
13 import org.djunits.value.vdouble.scalar.Time;
14 import org.opentrafficsim.core.geometry.OTSGeometryException;
15 import org.opentrafficsim.core.geometry.OTSLine3D;
16 import org.opentrafficsim.core.geometry.OTSPoint3D;
17 import org.opentrafficsim.core.gtu.GTU;
18 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan.SpeedSegment;
19 import org.opentrafficsim.core.math.Solver;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public final class OperationalPlanBuilder
37 {
38
39 private static final Acceleration MAX_ACCELERATION = new Acceleration(1E12, AccelerationUnit.SI);
40
41
42 private static final Acceleration MAX_DECELERATION = new Acceleration(-1E12, AccelerationUnit.SI);
43
44
45 private OperationalPlanBuilder()
46 {
47
48 }
49
50
51
52
53
54
55
56
57
58
59
60 public static OperationalPlan buildConstantSpeedPlan(final GTU gtu, final OTSLine3D path, final Time startTime,
61 final Speed speed) throws OperationalPlanException
62 {
63 Length length = path.getLength();
64 OperationalPlan.Segment segment;
65 segment = new SpeedSegment(length.divideBy(speed));
66 ArrayList<OperationalPlan.Segment> segmentList = new ArrayList<>();
67 segmentList.add(segment);
68 return new OperationalPlan(gtu, path, startTime, speed, segmentList);
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public static OperationalPlan buildGradualAccelerationPlan(final GTU gtu, final OTSLine3D path, final Time startTime,
87 final Speed startSpeed, final Speed endSpeed, final Acceleration maxAcceleration,
88 final Acceleration maxDeceleration) throws OperationalPlanException
89 {
90 Length length = path.getLength();
91 OperationalPlan.Segment segment;
92 if (startSpeed.eq(endSpeed))
93 {
94 segment = new SpeedSegment(length.divideBy(startSpeed));
95 }
96 else
97 {
98
99 Duration duration = length.multiplyBy(2.0).divideBy(endSpeed.plus(startSpeed));
100 Acceleration acceleration = endSpeed.minus(startSpeed).divideBy(duration);
101 try
102 {
103 if (acceleration.si < 0.0 && acceleration.lt(maxDeceleration))
104 {
105 acceleration = maxDeceleration;
106
107 duration = new Duration(Solver.firstSolutionAfter(0, acceleration.si / 2, startSpeed.si, -length.si),
108 DurationUnit.SI);
109 }
110 if (acceleration.si > 0.0 && acceleration.gt(maxAcceleration))
111 {
112 acceleration = maxAcceleration;
113
114 duration = new Duration(Solver.firstSolutionAfter(0, acceleration.si / 2, startSpeed.si, -length.si),
115 DurationUnit.SI);
116 }
117 }
118 catch (ValueException exception)
119 {
120 throw new OperationalPlanException("Caught unexpected exception: " + exception);
121 }
122 segment = new OperationalPlan.AccelerationSegment(duration, acceleration);
123 }
124 ArrayList<OperationalPlan.Segment> segmentList = new ArrayList<>();
125 segmentList.add(segment);
126 return new OperationalPlan(gtu, path, startTime, startSpeed, segmentList);
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 public static OperationalPlan buildGradualAccelerationPlan(final GTU gtu, final OTSLine3D path, final Time startTime,
143 final Speed startSpeed, final Speed endSpeed) throws OperationalPlanException
144 {
145 return buildGradualAccelerationPlan(gtu, path, startTime, startSpeed, endSpeed, MAX_ACCELERATION, MAX_DECELERATION);
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public static OperationalPlan buildMaximumAccelerationPlan(final GTU gtu, final OTSLine3D path, final Time startTime,
165 final Speed startSpeed, final Speed endSpeed, final Acceleration acceleration, final Acceleration deceleration)
166 throws OperationalPlanException
167 {
168 Length length = path.getLength();
169 ArrayList<OperationalPlan.Segment> segmentList = new ArrayList<>();
170 if (startSpeed.eq(endSpeed))
171 {
172 segmentList.add(new OperationalPlan.SpeedSegment(length.divideBy(startSpeed)));
173 }
174 else
175 {
176 try
177 {
178 if (endSpeed.gt(startSpeed))
179 {
180 Duration t = endSpeed.minus(startSpeed).divideBy(acceleration);
181 Length x = startSpeed.multiplyBy(t).plus(acceleration.multiplyBy(0.5).multiplyBy(t).multiplyBy(t));
182 if (x.ge(length))
183 {
184
185
186
187 Duration duration = new Duration(
188 Solver.firstSolutionAfter(0, acceleration.si / 2, startSpeed.si, -length.si), DurationUnit.SI);
189 segmentList.add(new OperationalPlan.AccelerationSegment(duration, acceleration));
190 }
191 else
192 {
193
194 segmentList.add(new OperationalPlan.AccelerationSegment(t, acceleration));
195 Duration duration = length.minus(x).divideBy(endSpeed);
196 segmentList.add(new OperationalPlan.SpeedSegment(duration));
197 }
198 }
199 else
200 {
201 Duration t = endSpeed.minus(startSpeed).divideBy(deceleration);
202 Length x = startSpeed.multiplyBy(t).plus(deceleration.multiplyBy(0.5).multiplyBy(t).multiplyBy(t));
203 if (x.ge(length))
204 {
205
206
207
208 Duration duration = new Duration(
209 Solver.firstSolutionAfter(0, deceleration.si / 2, startSpeed.si, -length.si), DurationUnit.SI);
210 segmentList.add(new OperationalPlan.AccelerationSegment(duration, deceleration));
211 }
212 else
213 {
214 if (endSpeed.si == 0.0)
215 {
216
217 OTSLine3D partialPath = path.truncate(x.si);
218 segmentList.add(new OperationalPlan.AccelerationSegment(t, deceleration));
219 return new OperationalPlan(gtu, partialPath, startTime, startSpeed, segmentList);
220 }
221
222 segmentList.add(new OperationalPlan.AccelerationSegment(t, deceleration));
223 Duration duration = length.minus(x).divideBy(endSpeed);
224 segmentList.add(new OperationalPlan.SpeedSegment(duration));
225 }
226 }
227 }
228 catch (ValueException | OTSGeometryException exception)
229 {
230 throw new OperationalPlanException("Caught unexpected exception: " + exception);
231 }
232 }
233 return new OperationalPlan(gtu, path, startTime, startSpeed, segmentList);
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 public static OperationalPlan buildStopPlan(final GTU gtu, final OTSLine3D path, final Time startTime,
250 final Speed startSpeed, final Acceleration deceleration) throws OperationalPlanException
251 {
252 return buildMaximumAccelerationPlan(gtu, path, startTime, startSpeed, Speed.ZERO,
253 new Acceleration(1.0, AccelerationUnit.SI), deceleration);
254 }
255
256
257
258
259
260
261
262 public static void main(final String[] args) throws OperationalPlanException, OTSGeometryException
263 {
264 OTSLine3D path1 = new OTSLine3D(new OTSPoint3D[] {new OTSPoint3D(0.0, 0.0), new OTSPoint3D(100.0, 0.0)});
265
266
267 OperationalPlan plan1 =
268 buildGradualAccelerationPlan(null, path1, Time.ZERO, Speed.ZERO, new Speed(10.0, SpeedUnit.METER_PER_SECOND));
269 System.out.println(plan1);
270
271
272
273 OperationalPlan plan2 = buildGradualAccelerationPlan(null, path1, Time.ZERO, Speed.ZERO,
274 new Speed(10.0, SpeedUnit.METER_PER_SECOND), new Acceleration(0.1, AccelerationUnit.METER_PER_SECOND_2),
275 new Acceleration(-0.1, AccelerationUnit.METER_PER_SECOND_2));
276 System.out.println(plan2);
277
278
279
280 OperationalPlan plan3 = buildMaximumAccelerationPlan(null, path1, Time.ZERO, Speed.ZERO,
281 new Speed(10.0, SpeedUnit.METER_PER_SECOND), new Acceleration(1.0, AccelerationUnit.METER_PER_SECOND_2),
282 new Acceleration(-1.0, AccelerationUnit.METER_PER_SECOND_2));
283 System.out.println(plan3);
284
285
286
287 OperationalPlan plan4 =
288 buildMaximumAccelerationPlan(null, path1, Time.ZERO, new Speed(10.0, SpeedUnit.METER_PER_SECOND),
289 new Speed(0.0, SpeedUnit.METER_PER_SECOND), new Acceleration(1.0, AccelerationUnit.METER_PER_SECOND_2),
290 new Acceleration(-1.0, AccelerationUnit.METER_PER_SECOND_2));
291 System.out.println(plan4);
292
293
294
295 OperationalPlan plan5 = buildStopPlan(null, path1, Time.ZERO, new Speed(10.0, SpeedUnit.METER_PER_SECOND),
296 new Acceleration(-2.0, AccelerationUnit.METER_PER_SECOND_2));
297 System.out.println(plan5);
298
299 }
300 }