1 package org.opentrafficsim.road.gtu.lane.plan.operational;
2
3 import java.io.Serializable;
4
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.opentrafficsim.core.gtu.GTUException;
9 import org.opentrafficsim.core.gtu.TurnIndicatorIntent;
10 import org.opentrafficsim.core.gtu.TurnIndicatorStatus;
11 import org.opentrafficsim.core.network.LateralDirectionality;
12 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
13
14 import nl.tudelft.simulation.language.Throw;
15
16
17
18
19
20
21
22
23
24
25
26
27
28 public class SimpleOperationalPlan implements Serializable
29 {
30
31
32 private static final long serialVersionUID = 20160811L;
33
34
35 private Acceleration acceleration;
36
37
38 private final LateralDirectionality laneChangeDirection;
39
40
41 private TurnIndicatorIntent indicatorIntent = TurnIndicatorIntent.NONE;
42
43
44 private Length indicatorObjectDistance = null;
45
46
47 private final Duration duration;
48
49
50
51
52
53 public SimpleOperationalPlan(final Acceleration acceleration, final Duration duration)
54 {
55 this(acceleration, duration, LateralDirectionality.NONE);
56 }
57
58
59
60
61
62
63 public SimpleOperationalPlan(final Acceleration acceleration, final Duration duration,
64 final LateralDirectionality laneChangeDirection)
65 {
66 Throw.whenNull(acceleration, "Acceleration may not be null.");
67 Throw.whenNull(duration, "Duration may not be null.");
68 Throw.whenNull(laneChangeDirection, "Lane change direction may not be null.");
69 checkAcceleration(acceleration);
70 this.acceleration = acceleration;
71 this.duration = duration;
72 this.laneChangeDirection = laneChangeDirection;
73 }
74
75
76
77
78 public final Acceleration getAcceleration()
79 {
80 return this.acceleration;
81 }
82
83
84
85
86 public Duration getDuration()
87 {
88 return this.duration;
89 }
90
91
92
93
94 public final boolean isLaneChange()
95 {
96 return this.laneChangeDirection != LateralDirectionality.NONE;
97 }
98
99
100
101
102 public final LateralDirectionality getLaneChangeDirection()
103 {
104 return this.laneChangeDirection;
105 }
106
107
108
109
110
111 public final void minimizeAcceleration(final Acceleration a)
112 {
113 checkAcceleration(a);
114 this.acceleration = Acceleration.min(this.acceleration, a);
115 }
116
117
118
119
120
121 private void checkAcceleration(final Acceleration a)
122 {
123 if (a.equals(Acceleration.NEGATIVE_INFINITY) || a.equals(Acceleration.NEG_MAXVALUE))
124 {
125 throw new RuntimeException("Model has calculated a negative infinite or negative max value acceleration.");
126 }
127 }
128
129
130
131
132 public final TurnIndicatorIntent getIndicatorIntent()
133 {
134 return this.indicatorIntent;
135 }
136
137
138
139
140 public final void setIndicatorIntentLeft()
141 {
142 if (this.indicatorObjectDistance != null)
143 {
144 return;
145 }
146 if (this.indicatorIntent.isRight())
147 {
148 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
149 }
150 else
151 {
152 this.indicatorIntent = TurnIndicatorIntent.LEFT;
153 }
154 }
155
156
157
158
159 public final void setIndicatorIntentRight()
160 {
161 if (this.indicatorObjectDistance != null)
162 {
163 return;
164 }
165 if (this.indicatorIntent.isLeft())
166 {
167 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
168 }
169 else
170 {
171 this.indicatorIntent = TurnIndicatorIntent.RIGHT;
172 }
173 }
174
175
176
177
178
179 public final void setIndicatorIntentLeft(final Length distance)
180 {
181 if (compareAndIgnore(distance))
182 {
183 return;
184 }
185 if (this.indicatorIntent.isRight())
186 {
187 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
188 }
189 else
190 {
191 this.indicatorIntent = TurnIndicatorIntent.LEFT;
192 }
193
194 }
195
196
197
198
199
200 public final void setIndicatorIntentRight(final Length distance)
201 {
202 if (compareAndIgnore(distance))
203 {
204 return;
205 }
206 if (this.indicatorIntent.isLeft())
207 {
208 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
209 }
210 else
211 {
212 this.indicatorIntent = TurnIndicatorIntent.RIGHT;
213 }
214 }
215
216
217
218
219
220
221 private boolean compareAndIgnore(final Length distance)
222 {
223 if (this.indicatorObjectDistance != null)
224 {
225 if (this.indicatorObjectDistance.lt(distance))
226 {
227
228 return true;
229 }
230 if (this.indicatorObjectDistance.gt(distance))
231 {
232
233 this.indicatorIntent = TurnIndicatorIntent.NONE;
234 }
235 }
236 else
237 {
238
239 this.indicatorIntent = TurnIndicatorIntent.NONE;
240 }
241 return false;
242 }
243
244
245 @Override
246 @SuppressWarnings("checkstyle:designforextension")
247 public String toString()
248 {
249 return "SimpleOperationalPlan [Acceleration=" + this.acceleration + ", change=" + this.laneChangeDirection
250 + ", indicator intent=" + this.indicatorIntent + "]";
251 }
252
253
254
255
256
257 public final void setTurnIndicator(final LaneBasedGTU gtu) throws GTUException
258 {
259 if (this.indicatorIntent.isLeft())
260 {
261 gtu.setTurnIndicatorStatus(TurnIndicatorStatus.LEFT);
262 }
263 else if (this.indicatorIntent.isRight())
264 {
265 gtu.setTurnIndicatorStatus(TurnIndicatorStatus.RIGHT);
266 }
267 else
268 {
269 gtu.setTurnIndicatorStatus(TurnIndicatorStatus.NONE);
270 }
271 }
272
273 }