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 * <p>
22 * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
23 * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
24 * <p>
25 * @version $Revision$, $LastChangedDate$, by $Author$, initial version Jun 2, 2016 <br>
26 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
27 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
28 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
29 */
30 public class HeadwayConflict extends AbstractHeadwayLaneBasedObject
31 {
32
33 /** */
34 private static final long serialVersionUID = 20160602L;
35
36 /** Conflict type. */
37 private final ConflictType conflictType;
38
39 /** Conflict priority. */
40 private final ConflictPriority conflictPriority;
41
42 /** Length of the conflict in the conflicting directions. */
43 private final Length conflictingLength;
44
45 /**
46 * Set of conflicting GTU's <i>completely</i> upstream of the <i>start</i> of the conflict ordered close to far from the
47 * start of the conflict. Distance and overlap info concerns the conflict.
48 */
49 private final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> upstreamConflictingGTUs;
50
51 /**
52 * Set of conflicting GTU's (partially) downstream of the <i>start</i> of the conflict ordered close to far from the start
53 * of conflict. Distance and overlap info concerns the conflict.
54 */
55 private final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> downstreamConflictingGTUs;
56
57 /** Visibility on the conflicting lane within which conflicting vehicles are visible. */
58 private final Length conflictingVisibility;
59
60 /** Speed limit on the conflicting lane. */
61 private final Speed conflictingSpeedLimit;
62
63 /** Link of conflicting conflict. */
64 private final CrossSectionLink conflictingLink;
65
66 /** Stop line on the own lane. */
67 private final HeadwayStopLine stopLine;
68
69 /** Stop line on the conflicting lane. */
70 private final HeadwayStopLine conflictingStopLine;
71
72 /** Type of conflict rule. */
73 private final Class<? extends ConflictRule> conflictRuleType;
74
75 /** Distance of traffic light upstream on conflicting lane. */
76 private Length conflictingTrafficLightDistance = null;
77
78 /** Whether the conflict is permitted by the traffic light. */
79 private boolean permitted = false;
80
81 /** Width progression of conflict. */
82 private final Width width;
83
84 /**
85 * Constructor.
86 * @param conflictType ConflictType; conflict type
87 * @param conflictPriority ConflictPriority; conflict priority
88 * @param conflictRuleType Class<? extends ConflictRule>; conflict rule type
89 * @param id String; id
90 * @param distance Length; distance
91 * @param length Length; length of the conflict
92 * @param conflictingLength Length; length of the conflict on the conflicting lane
93 * @param upstreamConflictingGTUs PerceptionCollectable<HeadwayGTU,LaneBasedGTU>; conflicting GTU's upstream of the
94 * <i>start</i> of the conflict
95 * @param downstreamConflictingGTUs PerceptionCollectable<HeadwayGTU,LaneBasedGTU>; conflicting GTU's downstream of
96 * the <i>start</i> of the conflict
97 * @param conflictingVisibility Length; visibility on the conflicting lane within which conflicting vehicles are visible
98 * @param conflictingSpeedLimit Speed; speed limit on the conflicting lane
99 * @param conflictingLink CrossSectionLink; conflicting link
100 * @param width Width; width progression of conflict
101 * @param stopLine HeadwayStopLine; stop line on the own lane
102 * @param conflictingStopLine HeadwayStopLine; stop line on the conflicting lane
103 * @param lane Lane; the lane
104 * @throws GTUException when id is null, or parameters are inconsistent
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 HeadwayStopLinee/perception/headway/HeadwayStopLine.html#HeadwayStopLine">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 * Constructor without stop lines.
142 * @param conflictType ConflictType; conflict type
143 * @param conflictPriority ConflictPriority; conflict priority
144 * @param conflictRuleType Class<? extends ConflictRule>; conflict rule type
145 * @param id String; id
146 * @param distance Length; distance
147 * @param length Length; length of the conflict
148 * @param conflictingLength Length; length of the conflict on the conflicting lane
149 * @param upstreamConflictingGTUs PerceptionCollectable<HeadwayGTU,LaneBasedGTU>; conflicting GTU's upstream of the
150 * <i>start</i> of the conflict
151 * @param downstreamConflictingGTUs PerceptionCollectable<HeadwayGTU,LaneBasedGTU>; conflicting GTU's downstream of
152 * the <i>start</i> of the conflict
153 * @param conflictingVisibility Length; visibility on the conflicting lane within which conflicting vehicles are visible
154 * @param conflictingSpeedLimit Speed; speed limit on the conflicting lane
155 * @param conflictingLink CrossSectionLink; conflicting link
156 * @param width Width; width progression of conflict
157 * @param lane Lane; the lane
158 * @throws GTUException when id is null, or parameters are inconsistent
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 * Returns the conflict type.
175 * @return conflict type
176 */
177 public final ConflictType getConflictType()
178 {
179 return this.conflictType;
180 }
181
182 /**
183 * Returns whether this is a crossing conflict.
184 * @return whether this is a crossing conflict
185 */
186 public final boolean isCrossing()
187 {
188 return this.conflictType.equals(ConflictType.CROSSING);
189 }
190
191 /**
192 * Returns whether this is a merge conflict.
193 * @return whether this is a merge conflict
194 */
195 public final boolean isMerge()
196 {
197 return this.conflictType.equals(ConflictType.MERGE);
198 }
199
200 /**
201 * Returns whether this is a split conflict.
202 * @return whether this is a split conflict
203 */
204 public final boolean isSplit()
205 {
206 return this.conflictType.equals(ConflictType.SPLIT);
207 }
208
209 /**
210 * Returns the conflict priority.
211 * @return conflict priority
212 */
213 public final ConflictPriority getConflictPriority()
214 {
215 return this.conflictPriority;
216 }
217
218 /**
219 * Returns the length of the conflict on the conflicting lane.
220 * @return length of the conflict on the conflicting lane
221 */
222 public final Length getConflictingLength()
223 {
224 return this.conflictingLength;
225 }
226
227 /**
228 * Returns a set of conflicting GTU's upstream of the <i>start</i> of the conflict ordered close to far from the conflict.
229 * @return set of conflicting GTU's upstream of the <i>start</i> of the conflict ordered close to far from the conflict
230 */
231 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getUpstreamConflictingGTUs()
232 {
233 return this.upstreamConflictingGTUs;
234 }
235
236 /**
237 * Returns a set of conflicting GTU's downstream of the <i>start</i> of the conflict ordered close to far from the conflict.
238 * Distance is given relative to the <i>end</i> of the conflict, or null for conflicting vehicles on the conflict. In the
239 * latter case the overlap is used.
240 * @return set of conflicting GTU's downstream of the <i>start</i> of the conflict ordered close to far from the conflict
241 */
242 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getDownstreamConflictingGTUs()
243 {
244 return this.downstreamConflictingGTUs;
245 }
246
247 /**
248 * Returns the visibility on the conflicting lane within which conflicting vehicles are visible. All upstream conflicting
249 * GTUs have a distance smaller than the visibility. Depending on a limited visibility, a certain (lower) speed may be
250 * required while approaching the conflict.
251 * @return visibility on the conflicting lane within which conflicting vehicles are visible
252 */
253 public final Length getConflictingVisibility()
254 {
255 return this.conflictingVisibility;
256 }
257
258 /**
259 * Returns the speed limit on the conflicting lane.
260 * @return speed limit on the conflicting lane
261 */
262 public final Speed getConflictingSpeedLimit()
263 {
264 return this.conflictingSpeedLimit;
265 }
266
267 /**
268 * Returns the conflicting link.
269 * @return the conflicting link
270 */
271 public final CrossSectionLink getConflictingLink()
272 {
273 return this.conflictingLink;
274 }
275
276 /**
277 * Returns the stop line.
278 * @return stop line
279 */
280 public final HeadwayStopLine getStopLine()
281 {
282 return this.stopLine;
283 }
284
285 /**
286 * Returns the stop line on the conflicting lane.
287 * @return stop line
288 */
289 public final HeadwayStopLine getConflictingStopLine()
290 {
291 return this.conflictingStopLine;
292 }
293
294 /**
295 * Returns the conflict rule type.
296 * @return conflict rule type
297 */
298 public final Class<? extends ConflictRule> getConflictRuleType()
299 {
300 return this.conflictRuleType;
301 }
302
303 /**
304 * Returns the distance of a traffic light upstream on the conflicting lane.
305 * @return distance of a traffic light upstream on the conflicting lane, or {@code null} if no traffic light
306 */
307 public final Length getConflictingTrafficLightDistance()
308 {
309 return this.conflictingTrafficLightDistance;
310 }
311
312 /**
313 * Whether the conflict is permitted by the traffic light.
314 * @return whether the conflict is permitted by the traffic light
315 */
316 public final boolean isPermitted()
317 {
318 return this.permitted;
319 }
320
321 /**
322 * Set the distance of a traffic light upstream on the conflicting lane.
323 * @param trafficLightDistance Length; distance of a traffic light upstream on the conflicting lane.
324 * @param permittedConflict boolean; whether the conflict is permitted by the traffic light
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 * Returns the width at the given fraction.
334 * @param fraction double; fraction from 0 to 1
335 * @return Length; width at the given fraction
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 * Width progression of conflict.
351 * <p>
352 * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
353 * <br>
354 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
355 * <p>
356 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 11 aug. 2018 <br>
357 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
358 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
359 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
360 */
361 public static class Width
362 {
363
364 /** Fractions, from 0 to 1. */
365 private final double[] fractions;
366
367 /** Vector with widths. */
368 private final LengthVector width;
369
370 /**
371 * @param fractions double[]; fractions, from 0 to 1
372 * @param width LengthVector; vector of equal length with widths
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 * Returns the width at the given fraction.
393 * @param fraction double; fraction from 0 to 1
394 * @return Length; width at the given fraction
395 * @throws ValueRuntimeException when index is out of bounds
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 * Returns a linear width progression.
417 * @param startWidth Length; start width
418 * @param endWidth Length; end width
419 * @return Width; linear width progression
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 /** {@inheritDoc} */
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 }