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.djutils.logger.CategoryLogger;
10 import org.opentrafficsim.core.gtu.GTUException;
11 import org.opentrafficsim.core.gtu.TurnIndicatorIntent;
12 import org.opentrafficsim.core.gtu.TurnIndicatorStatus;
13 import org.opentrafficsim.core.network.LateralDirectionality;
14 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
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.max(Acceleration.instantiateSI(-100.0), 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
87 public final void setAcceleration(final Acceleration acceleration)
88 {
89 checkAcceleration(acceleration);
90 this.acceleration = acceleration;
91 }
92
93
94
95
96 public Duration getDuration()
97 {
98 return this.duration;
99 }
100
101
102
103
104 public final boolean isLaneChange()
105 {
106 return this.laneChangeDirection != LateralDirectionality.NONE;
107 }
108
109
110
111
112 public final LateralDirectionality getLaneChangeDirection()
113 {
114 return this.laneChangeDirection;
115 }
116
117
118
119
120
121 public final void minimizeAcceleration(final Acceleration a)
122 {
123 checkAcceleration(a);
124
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
137 CategoryLogger.always().error("Model has calculated a negative infinite or negative max value acceleration.");
138 }
139 }
140
141
142
143
144 public final TurnIndicatorIntent getIndicatorIntent()
145 {
146 return this.indicatorIntent;
147 }
148
149
150
151
152 public final void setIndicatorIntentLeft()
153 {
154 if (this.indicatorObjectDistance != null)
155 {
156 return;
157 }
158 if (this.indicatorIntent.isRight())
159 {
160 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
161 }
162 else
163 {
164 this.indicatorIntent = TurnIndicatorIntent.LEFT;
165 }
166 }
167
168
169
170
171 public final void setIndicatorIntentRight()
172 {
173 if (this.indicatorObjectDistance != null)
174 {
175 return;
176 }
177 if (this.indicatorIntent.isLeft())
178 {
179 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
180 }
181 else
182 {
183 this.indicatorIntent = TurnIndicatorIntent.RIGHT;
184 }
185 }
186
187
188
189
190
191 public final void setIndicatorIntentLeft(final Length distance)
192 {
193 if (compareAndIgnore(distance))
194 {
195 return;
196 }
197 if (this.indicatorIntent.isRight())
198 {
199 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
200 }
201 else
202 {
203 this.indicatorIntent = TurnIndicatorIntent.LEFT;
204 }
205
206 }
207
208
209
210
211
212 public final void setIndicatorIntentRight(final Length distance)
213 {
214 if (compareAndIgnore(distance))
215 {
216 return;
217 }
218 if (this.indicatorIntent.isLeft())
219 {
220 this.indicatorIntent = TurnIndicatorIntent.CONFLICTING;
221 }
222 else
223 {
224 this.indicatorIntent = TurnIndicatorIntent.RIGHT;
225 }
226 }
227
228
229
230
231
232
233 private boolean compareAndIgnore(final Length distance)
234 {
235 if (this.indicatorObjectDistance != null)
236 {
237 if (this.indicatorObjectDistance.lt(distance))
238 {
239
240 return true;
241 }
242 if (this.indicatorObjectDistance.gt(distance))
243 {
244
245 this.indicatorIntent = TurnIndicatorIntent.NONE;
246 }
247 }
248 else
249 {
250
251 this.indicatorIntent = TurnIndicatorIntent.NONE;
252 }
253 return false;
254 }
255
256
257 @Override
258 @SuppressWarnings("checkstyle:designforextension")
259 public String toString()
260 {
261 return "SimpleOperationalPlan [Acceleration=" + this.acceleration + ", change=" + this.laneChangeDirection
262 + ", indicator intent=" + this.indicatorIntent + "]";
263 }
264
265
266
267
268
269 public final void setTurnIndicator(final LaneBasedGTU gtu) throws GTUException
270 {
271 if (this.indicatorIntent.isLeft())
272 {
273 gtu.setTurnIndicatorStatus(TurnIndicatorStatus.LEFT);
274 }
275 else if (this.indicatorIntent.isRight())
276 {
277 gtu.setTurnIndicatorStatus(TurnIndicatorStatus.RIGHT);
278 }
279 else
280 {
281 gtu.setTurnIndicatorStatus(TurnIndicatorStatus.NONE);
282 }
283 }
284
285 }