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