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