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