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