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