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.opentrafficsim.core.gtu.GTUException;
9 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
10 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
11 import org.opentrafficsim.road.network.lane.CrossSectionLink;
12 import org.opentrafficsim.road.network.lane.conflict.ConflictPriority;
13 import org.opentrafficsim.road.network.lane.conflict.ConflictRule;
14 import org.opentrafficsim.road.network.lane.conflict.ConflictType;
15
16 import nl.tudelft.simulation.language.Throw;
17
18
19
20
21
22
23
24
25
26
27
28 public class HeadwayConflict extends AbstractHeadwayCopy
29 {
30
31
32 private static final long serialVersionUID = 20160602L;
33
34
35 private final ConflictType conflictType;
36
37
38 private final ConflictPriority conflictPriority;
39
40
41 private final Length conflictingLength;
42
43
44
45
46
47 private final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> upstreamConflictingGTUs;
48
49
50
51
52
53 private final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> downstreamConflictingGTUs;
54
55
56 private final Length conflictingVisibility;
57
58
59 private final Speed conflictingSpeedLimit;
60
61
62 private final CrossSectionLink conflictingLink;
63
64
65 private final HeadwayStopLine stopLine;
66
67
68 private final HeadwayStopLine conflictingStopLine;
69
70
71 private final Class<? extends ConflictRule> conflictRuleType;
72
73
74 private Length conflictingTrafficLightDistance = null;
75
76
77 private boolean permitted = false;
78
79
80 private final Width width;
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) throws GTUException
108 {
109 super(ObjectType.CONFLICT, id, distance, length);
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 @SuppressWarnings("checkstyle:parameternumber")
153 public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
154 final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
155 final Length conflictingLength, final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> upstreamConflictingGTUs,
156 final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> downstreamConflictingGTUs, final Length conflictingVisibility,
157 final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width) throws GTUException
158 {
159 this(conflictType, conflictPriority, conflictRuleType, id, distance, length, conflictingLength, upstreamConflictingGTUs,
160 downstreamConflictingGTUs, conflictingVisibility, conflictingSpeedLimit, conflictingLink, width, null, null);
161 }
162
163
164
165
166
167 public final ConflictType getConflictType()
168 {
169 return this.conflictType;
170 }
171
172
173
174
175
176 public final boolean isCrossing()
177 {
178 return this.conflictType.equals(ConflictType.CROSSING);
179 }
180
181
182
183
184
185 public final boolean isMerge()
186 {
187 return this.conflictType.equals(ConflictType.MERGE);
188 }
189
190
191
192
193
194 public final boolean isSplit()
195 {
196 return this.conflictType.equals(ConflictType.SPLIT);
197 }
198
199
200
201
202
203 public final ConflictPriority getConflictPriority()
204 {
205 return this.conflictPriority;
206 }
207
208
209
210
211
212 public final Length getConflictingLength()
213 {
214 return this.conflictingLength;
215 }
216
217
218
219
220
221 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getUpstreamConflictingGTUs()
222 {
223 return this.upstreamConflictingGTUs;
224 }
225
226
227
228
229
230
231
232 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getDownstreamConflictingGTUs()
233 {
234 return this.downstreamConflictingGTUs;
235 }
236
237
238
239
240
241
242
243 public final Length getConflictingVisibility()
244 {
245 return this.conflictingVisibility;
246 }
247
248
249
250
251
252 public final Speed getConflictingSpeedLimit()
253 {
254 return this.conflictingSpeedLimit;
255 }
256
257
258
259
260
261 public final CrossSectionLink getConflictingLink()
262 {
263 return this.conflictingLink;
264 }
265
266
267
268
269
270 public final HeadwayStopLine getStopLine()
271 {
272 return this.stopLine;
273 }
274
275
276
277
278
279 public final HeadwayStopLine getConflictingStopLine()
280 {
281 return this.conflictingStopLine;
282 }
283
284
285
286
287
288 public final Class<? extends ConflictRule> getConflictRuleType()
289 {
290 return this.conflictRuleType;
291 }
292
293
294
295
296
297 public final Length getConflictingTrafficLightDistance()
298 {
299 return this.conflictingTrafficLightDistance;
300 }
301
302
303
304
305
306 public final boolean isPermitted()
307 {
308 return this.permitted;
309 }
310
311
312
313
314
315
316 public final void setConflictingTrafficLight(final Length trafficLightDistance, final boolean permittedConflict)
317 {
318 this.conflictingTrafficLightDistance = trafficLightDistance;
319 this.permitted = permittedConflict;
320 }
321
322
323
324
325
326
327 public final Length getWidthAtFraction(final double fraction)
328 {
329 try
330 {
331 return this.width.getWidth(fraction);
332 }
333 catch (ValueException exception)
334 {
335 throw new RuntimeException("Unexpected exception: fraction could not be interpolated.", exception);
336 }
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351 public static class Width
352 {
353
354
355 private final double[] fractions;
356
357
358 private final LengthVector width;
359
360
361
362
363
364 public Width(final double[] fractions, final LengthVector width)
365 {
366 Throw.whenNull(fractions, "Fractions may not be null.");
367 Throw.whenNull(width, "Width may not be null.");
368 Throw.when(fractions.length != width.size(), IllegalArgumentException.class,
369 "Array and vector are not of equal length.");
370 Throw.when(fractions.length < 2, IllegalArgumentException.class, "Input should at least contain 2 values.");
371 Throw.when(fractions[0] != 0.0 || fractions[fractions.length - 1] != 1.0, IllegalArgumentException.class,
372 "Fractions should range from 0 to 1.");
373 for (int i = 1; i < fractions.length; i++)
374 {
375 Throw.when(fractions[i] <= fractions[i - 1], IllegalArgumentException.class, "Fractions are not increasing.");
376 }
377 this.fractions = fractions;
378 this.width = width;
379 }
380
381
382
383
384
385
386
387 public Length getWidth(final double fraction) throws ValueException
388 {
389 Throw.when(fraction < 0.0 || fraction > 1.0, IllegalArgumentException.class, "Fraction should be between 0 and 1.");
390 if (fraction == 1.0)
391 {
392 return this.width.get(this.width.size() - 1);
393 }
394 for (int i = 0; i < this.fractions.length - 1; i++)
395 {
396 if (this.fractions[i] <= fraction && this.fractions[i + 1] > fraction)
397 {
398 double r = (fraction - this.fractions[i]) / (this.fractions[i + 1] - this.fractions[i]);
399 return Length.interpolate(this.width.get(i), this.width.get(i + 1), r);
400 }
401 }
402 throw new RuntimeException("Unexpected exception: fraction could not be interpolated.");
403 }
404
405
406
407
408
409
410
411 public static Width linear(final Length startWidth, final Length endWidth)
412 {
413 Throw.whenNull(startWidth, "Start width may not be null.");
414 Throw.whenNull(endWidth, "End width may not be null.");
415 try
416 {
417 return new Width(new double[] { 0.0, 1.0 },
418 new LengthVector(new Length[] { startWidth, endWidth }, StorageType.DENSE));
419 }
420 catch (ValueException exception)
421 {
422 throw new RuntimeException("Unexpected exception: widths could not be put in a vector.", exception);
423 }
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 }