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