1 package org.opentrafficsim.road.gtu.lane.perception.headway;
2
3 import org.djunits.unit.LengthUnit;
4 import org.djunits.value.ValueRuntimeException;
5 import org.djunits.value.vdouble.scalar.Length;
6 import org.djunits.value.vdouble.scalar.Speed;
7 import org.djunits.value.vdouble.vector.LengthVector;
8 import org.djutils.exceptions.Throw;
9 import org.opentrafficsim.core.gtu.GtuException;
10 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
11 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
12 import org.opentrafficsim.road.network.lane.CrossSectionLink;
13 import org.opentrafficsim.road.network.lane.Lane;
14 import org.opentrafficsim.road.network.lane.conflict.ConflictPriority;
15 import org.opentrafficsim.road.network.lane.conflict.ConflictRule;
16 import org.opentrafficsim.road.network.lane.conflict.ConflictType;
17
18
19
20
21
22
23
24
25
26
27 public class HeadwayConflict extends AbstractHeadwayLaneBasedObject
28 {
29
30
31 private static final long serialVersionUID = 20160602L;
32
33
34 private final ConflictType conflictType;
35
36
37 private final ConflictPriority conflictPriority;
38
39
40 private final Length conflictingLength;
41
42
43
44
45
46 private final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs;
47
48
49
50
51
52 private final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs;
53
54
55 private final Length conflictingVisibility;
56
57
58 private final Speed conflictingSpeedLimit;
59
60
61 private final CrossSectionLink conflictingLink;
62
63
64 private final HeadwayStopLine stopLine;
65
66
67 private final HeadwayStopLine conflictingStopLine;
68
69
70 private final Class<? extends ConflictRule> conflictRuleType;
71
72
73 private Length conflictingTrafficLightDistance = null;
74
75
76 private boolean permitted = false;
77
78
79 private final Width width;
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 @SuppressWarnings("checkstyle:parameternumber")
104 public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
105 final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
106 final Length conflictingLength, final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs,
107 final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs, final Length conflictingVisibility,
108 final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width,
109 final HeadwayStopLine stopLine, final HeadwayStopLine conflictingStopLine, final Lane lane) throws GtuException
110 {
111 super(ObjectType.CONFLICT, id, distance, length, lane);
112 Throw.whenNull(conflictType, "Conflict type may not be null.");
113 Throw.whenNull(conflictPriority, "Conflict priority may not be null.");
114 Throw.whenNull(conflictRuleType, "Conflict rule type may not be null.");
115 Throw.whenNull(id, "Conflict id may not be null.");
116 Throw.whenNull(distance, "Conflict distance may not be null.");
117 Throw.whenNull(conflictingLength, "Conflict length may not be null.");
118 Throw.whenNull(upstreamConflictingGTUs, "Upstreaem conflicting GTU's may not be null.");
119 Throw.whenNull(downstreamConflictingGTUs, "Downstream conflicting GTU's may not be null.");
120 Throw.whenNull(width, "Width may not be null.");
121 Throw.whenNull(conflictingVisibility, "Conflict visibility may not be null.");
122 Throw.whenNull(conflictingSpeedLimit, "Conflict speed limit may not be null.");
123 this.conflictType = conflictType;
124 this.conflictPriority = conflictPriority;
125 this.conflictRuleType = conflictRuleType;
126 this.conflictingLength = conflictingLength;
127 this.upstreamConflictingGTUs = upstreamConflictingGTUs;
128 this.downstreamConflictingGTUs = downstreamConflictingGTUs;
129 this.conflictingVisibility = conflictingVisibility;
130 this.conflictingSpeedLimit = conflictingSpeedLimit;
131 this.conflictingLink = conflictingLink;
132 this.width = width;
133 this.stopLine = stopLine;
134 this.conflictingStopLine = conflictingStopLine;
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 @SuppressWarnings("checkstyle:parameternumber")
158 public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
159 final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
160 final Length conflictingLength, final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs,
161 final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs, final Length conflictingVisibility,
162 final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width, final Lane lane)
163 throws GtuException
164 {
165 this(conflictType, conflictPriority, conflictRuleType, id, distance, length, conflictingLength, upstreamConflictingGTUs,
166 downstreamConflictingGTUs, conflictingVisibility, conflictingSpeedLimit, conflictingLink, width, null, null,
167 lane);
168 }
169
170
171
172
173
174 public final ConflictType getConflictType()
175 {
176 return this.conflictType;
177 }
178
179
180
181
182
183 public final boolean isCrossing()
184 {
185 return this.conflictType.equals(ConflictType.CROSSING);
186 }
187
188
189
190
191
192 public final boolean isMerge()
193 {
194 return this.conflictType.equals(ConflictType.MERGE);
195 }
196
197
198
199
200
201 public final boolean isSplit()
202 {
203 return this.conflictType.equals(ConflictType.SPLIT);
204 }
205
206
207
208
209
210 public final ConflictPriority getConflictPriority()
211 {
212 return this.conflictPriority;
213 }
214
215
216
217
218
219 public final Length getConflictingLength()
220 {
221 return this.conflictingLength;
222 }
223
224
225
226
227
228 public final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> getUpstreamConflictingGTUs()
229 {
230 return this.upstreamConflictingGTUs;
231 }
232
233
234
235
236
237
238
239 public final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> getDownstreamConflictingGTUs()
240 {
241 return this.downstreamConflictingGTUs;
242 }
243
244
245
246
247
248
249
250 public final Length getConflictingVisibility()
251 {
252 return this.conflictingVisibility;
253 }
254
255
256
257
258
259 public final Speed getConflictingSpeedLimit()
260 {
261 return this.conflictingSpeedLimit;
262 }
263
264
265
266
267
268 public final CrossSectionLink getConflictingLink()
269 {
270 return this.conflictingLink;
271 }
272
273
274
275
276
277 public final HeadwayStopLine getStopLine()
278 {
279 return this.stopLine;
280 }
281
282
283
284
285
286 public final HeadwayStopLine getConflictingStopLine()
287 {
288 return this.conflictingStopLine;
289 }
290
291
292
293
294
295 public final Class<? extends ConflictRule> getConflictRuleType()
296 {
297 return this.conflictRuleType;
298 }
299
300
301
302
303
304 public final Length getConflictingTrafficLightDistance()
305 {
306 return this.conflictingTrafficLightDistance;
307 }
308
309
310
311
312
313 public final boolean isPermitted()
314 {
315 return this.permitted;
316 }
317
318
319
320
321
322
323 public final void setConflictingTrafficLight(final Length trafficLightDistance, final boolean permittedConflict)
324 {
325 this.conflictingTrafficLightDistance = trafficLightDistance;
326 this.permitted = permittedConflict;
327 }
328
329
330
331
332
333
334 public final Length getWidthAtFraction(final double fraction)
335 {
336 try
337 {
338 return this.width.getWidth(fraction);
339 }
340 catch (ValueRuntimeException exception)
341 {
342 throw new RuntimeException("Unexpected exception: fraction could not be interpolated.", exception);
343 }
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357 public static class Width
358 {
359
360
361 private final double[] fractions;
362
363
364 private final LengthVector width;
365
366
367
368
369
370 public Width(final double[] fractions, final LengthVector width)
371 {
372 Throw.whenNull(fractions, "Fractions may not be null.");
373 Throw.whenNull(width, "Width may not be null.");
374 Throw.when(fractions.length != width.size(), IllegalArgumentException.class,
375 "Array and vector are not of equal length.");
376 Throw.when(fractions.length < 2, IllegalArgumentException.class, "Input should at least contain 2 values.");
377 Throw.when(fractions[0] != 0.0 || fractions[fractions.length - 1] != 1.0, IllegalArgumentException.class,
378 "Fractions should range from 0 to 1.");
379 for (int i = 1; i < fractions.length; i++)
380 {
381 Throw.when(fractions[i] <= fractions[i - 1], IllegalArgumentException.class, "Fractions are not increasing.");
382 }
383 this.fractions = fractions;
384 this.width = width;
385 }
386
387
388
389
390
391
392
393 public Length getWidth(final double fraction) throws ValueRuntimeException
394 {
395 Throw.when(fraction < 0.0 || fraction > 1.0, IllegalArgumentException.class, "Fraction should be between 0 and 1.");
396 if (fraction == 1.0)
397 {
398 return this.width.get(this.width.size() - 1);
399 }
400 for (int i = 0; i < this.fractions.length - 1; i++)
401 {
402 if (this.fractions[i] <= fraction && this.fractions[i + 1] > fraction)
403 {
404 double r = (fraction - this.fractions[i]) / (this.fractions[i + 1] - this.fractions[i]);
405 return Length.interpolate(this.width.get(i), this.width.get(i + 1), r);
406 }
407 }
408 throw new RuntimeException("Unexpected exception: fraction could not be interpolated.");
409 }
410
411
412
413
414
415
416
417 public static Width linear(final Length startWidth, final Length endWidth)
418 {
419 Throw.whenNull(startWidth, "Start width may not be null.");
420 Throw.whenNull(endWidth, "End width may not be null.");
421 try
422 {
423 return new Width(new double[] {0.0, 1.0}, new LengthVector(new Length[] {startWidth, endWidth}, LengthUnit.SI));
424 }
425 catch (ValueRuntimeException exception)
426 {
427 throw new RuntimeException("Unexpected exception: widths could not be put in a vector.", exception);
428 }
429 }
430
431 }
432
433
434 @Override
435 public final String toString()
436 {
437 return String.format("Headway %s to object %s of type %s", getDistance(), getId(), getObjectType());
438 }
439
440 }