1 package org.opentrafficsim.road.gtu.lane.perception.headway;
2
3 import org.djunits.value.StorageType;
4 import org.djunits.value.ValueException;
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.conflict.ConflictPriority;
14 import org.opentrafficsim.road.network.lane.conflict.ConflictRule;
15 import org.opentrafficsim.road.network.lane.conflict.ConflictType;
16
17
18
19
20
21
22
23
24
25
26
27 public class HeadwayConflict extends AbstractHeadwayCopy
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 @SuppressWarnings("checkstyle:parameternumber")
103 public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
104 final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
105 final Length conflictingLength, final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> upstreamConflictingGTUs,
106 final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> downstreamConflictingGTUs, final Length conflictingVisibility,
107 final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width,
108 final HeadwayStopLine stopLine, final HeadwayStopLine conflictingStopLine) throws GTUException
109 {
110 super(ObjectType.CONFLICT, id, distance, length);
111 Throw.whenNull(conflictType, "Conflict type may not be null.");
112 Throw.whenNull(conflictPriority, "Conflict priority may not be null.");
113 Throw.whenNull(conflictRuleType, "Conflict rule type may not be null.");
114 Throw.whenNull(id, "Conflict id may not be null.");
115 Throw.whenNull(distance, "Conflict distance may not be null.");
116 Throw.whenNull(conflictingLength, "Conflict length may not be null.");
117 Throw.whenNull(upstreamConflictingGTUs, "Upstreaem conflicting GTU's may not be null.");
118 Throw.whenNull(downstreamConflictingGTUs, "Downstream conflicting GTU's may not be null.");
119 Throw.whenNull(width, "Width may not be null.");
120 Throw.whenNull(conflictingVisibility, "Conflict visibility may not be null.");
121 Throw.whenNull(conflictingSpeedLimit, "Conflict speed limit may not be null.");
122 this.conflictType = conflictType;
123 this.conflictPriority = conflictPriority;
124 this.conflictRuleType = conflictRuleType;
125 this.conflictingLength = conflictingLength;
126 this.upstreamConflictingGTUs = upstreamConflictingGTUs;
127 this.downstreamConflictingGTUs = downstreamConflictingGTUs;
128 this.conflictingVisibility = conflictingVisibility;
129 this.conflictingSpeedLimit = conflictingSpeedLimit;
130 this.conflictingLink = conflictingLink;
131 this.width = width;
132 this.stopLine = stopLine;
133 this.conflictingStopLine = conflictingStopLine;
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 @SuppressWarnings("checkstyle:parameternumber")
156 public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
157 final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
158 final Length conflictingLength, final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> upstreamConflictingGTUs,
159 final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> downstreamConflictingGTUs, final Length conflictingVisibility,
160 final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width) throws GTUException
161 {
162 this(conflictType, conflictPriority, conflictRuleType, id, distance, length, conflictingLength, upstreamConflictingGTUs,
163 downstreamConflictingGTUs, conflictingVisibility, conflictingSpeedLimit, conflictingLink, width, null, null);
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 (ValueException 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
354 public static class Width
355 {
356
357
358 private final double[] fractions;
359
360
361 private final LengthVector width;
362
363
364
365
366
367 public Width(final double[] fractions, final LengthVector width)
368 {
369 Throw.whenNull(fractions, "Fractions may not be null.");
370 Throw.whenNull(width, "Width may not be null.");
371 Throw.when(fractions.length != width.size(), IllegalArgumentException.class,
372 "Array and vector are not of equal length.");
373 Throw.when(fractions.length < 2, IllegalArgumentException.class, "Input should at least contain 2 values.");
374 Throw.when(fractions[0] != 0.0 || fractions[fractions.length - 1] != 1.0, IllegalArgumentException.class,
375 "Fractions should range from 0 to 1.");
376 for (int i = 1; i < fractions.length; i++)
377 {
378 Throw.when(fractions[i] <= fractions[i - 1], IllegalArgumentException.class, "Fractions are not increasing.");
379 }
380 this.fractions = fractions;
381 this.width = width;
382 }
383
384
385
386
387
388
389
390 public Length getWidth(final double fraction) throws ValueException
391 {
392 Throw.when(fraction < 0.0 || fraction > 1.0, IllegalArgumentException.class, "Fraction should be between 0 and 1.");
393 if (fraction == 1.0)
394 {
395 return this.width.get(this.width.size() - 1);
396 }
397 for (int i = 0; i < this.fractions.length - 1; i++)
398 {
399 if (this.fractions[i] <= fraction && this.fractions[i + 1] > fraction)
400 {
401 double r = (fraction - this.fractions[i]) / (this.fractions[i + 1] - this.fractions[i]);
402 return Length.interpolate(this.width.get(i), this.width.get(i + 1), r);
403 }
404 }
405 throw new RuntimeException("Unexpected exception: fraction could not be interpolated.");
406 }
407
408
409
410
411
412
413
414 public static Width linear(final Length startWidth, final Length endWidth)
415 {
416 Throw.whenNull(startWidth, "Start width may not be null.");
417 Throw.whenNull(endWidth, "End width may not be null.");
418 try
419 {
420 return new Width(new double[] {0.0, 1.0},
421 new LengthVector(new Length[] {startWidth, endWidth}, StorageType.DENSE));
422 }
423 catch (ValueException exception)
424 {
425 throw new RuntimeException("Unexpected exception: widths could not be put in a vector.", exception);
426 }
427 }
428
429 }
430
431
432 @Override
433 public final String toString()
434 {
435 return String.format("Headway %s to object %s of type %s", getDistance(), getId(), getObjectType());
436 }
437
438 }