View Javadoc
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   * <p>
20   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
21   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
22   * </p>
23   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
24   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
25   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
26   */
27  public class HeadwayConflict extends AbstractHeadwayLaneBasedObject
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&lt;? extends ConflictRule&gt;; 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&lt;HeadwayGtu,LaneBasedGtu&gt;; conflicting GTU's upstream of the
91       *            &lt;i&gt;start&lt;/i&gt; of the conflict
92       * @param downstreamConflictingGTUs PerceptionCollectable&lt;HeadwayGtu,LaneBasedGtu&gt;; conflicting GTU's downstream of
93       *            the &lt;i&gt;start&lt;/i&gt; 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      * @param lane Lane; the lane
101      * @throws GtuException when id is null, or parameters are inconsistent
102      */
103     @SuppressWarnings("checkstyle:parameternumber")
104     public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
105             final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
106             final Length conflictingLength, final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs,
107             final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs, final Length conflictingVisibility,
108             final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width,
109             final HeadwayStopLine stopLine, final HeadwayStopLine conflictingStopLine, final Lane lane) throws GtuException
110     {
111         super(ObjectType.CONFLICT, id, distance, length, lane);
112         Throw.whenNull(conflictType, "Conflict type may not be null.");
113         Throw.whenNull(conflictPriority, "Conflict priority may not be null.");
114         Throw.whenNull(conflictRuleType, "Conflict rule type may not be null.");
115         Throw.whenNull(id, "Conflict id may not be null.");
116         Throw.whenNull(distance, "Conflict distance may not be null.");
117         Throw.whenNull(conflictingLength, "Conflict length may not be null.");
118         Throw.whenNull(upstreamConflictingGTUs, "Upstreaem conflicting GTU's may not be null.");
119         Throw.whenNull(downstreamConflictingGTUs, "Downstream conflicting GTU's may not be null.");
120         Throw.whenNull(width, "Width may not be null.");
121         Throw.whenNull(conflictingVisibility, "Conflict visibility may not be null.");
122         Throw.whenNull(conflictingSpeedLimit, "Conflict speed limit may not be null.");
123         this.conflictType = conflictType;
124         this.conflictPriority = conflictPriority;
125         this.conflictRuleType = conflictRuleType;
126         this.conflictingLength = conflictingLength;
127         this.upstreamConflictingGTUs = upstreamConflictingGTUs;
128         this.downstreamConflictingGTUs = downstreamConflictingGTUs;
129         this.conflictingVisibility = conflictingVisibility;
130         this.conflictingSpeedLimit = conflictingSpeedLimit;
131         this.conflictingLink = conflictingLink;
132         this.width = width;
133         this.stopLine = stopLine;
134         this.conflictingStopLine = conflictingStopLine;
135     }
136 
137     /**
138      * Constructor without stop lines.
139      * @param conflictType ConflictType; conflict type
140      * @param conflictPriority ConflictPriority; conflict priority
141      * @param conflictRuleType Class&lt;? extends ConflictRule&gt;; conflict rule type
142      * @param id String; id
143      * @param distance Length; distance
144      * @param length Length; length of the conflict
145      * @param conflictingLength Length; length of the conflict on the conflicting lane
146      * @param upstreamConflictingGTUs PerceptionCollectable&lt;HeadwayGtu,LaneBasedGtu&gt;; conflicting GTU's upstream of the
147      *            &lt;i&gt;start&lt;/i&gt; of the conflict
148      * @param downstreamConflictingGTUs PerceptionCollectable&lt;HeadwayGtu,LaneBasedGtu&gt;; conflicting GTU's downstream of
149      *            the &lt;i&gt;start&lt;/i&gt; of the conflict
150      * @param conflictingVisibility Length; visibility on the conflicting lane within which conflicting vehicles are visible
151      * @param conflictingSpeedLimit Speed; speed limit on the conflicting lane
152      * @param conflictingLink CrossSectionLink; conflicting link
153      * @param width Width; width progression of conflict
154      * @param lane Lane; the lane
155      * @throws GtuException when id is null, or parameters are inconsistent
156      */
157     @SuppressWarnings("checkstyle:parameternumber")
158     public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
159             final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
160             final Length conflictingLength, final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs,
161             final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs, final Length conflictingVisibility,
162             final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width, final Lane lane)
163             throws GtuException
164     {
165         this(conflictType, conflictPriority, conflictRuleType, id, distance, length, conflictingLength, upstreamConflictingGTUs,
166                 downstreamConflictingGTUs, conflictingVisibility, conflictingSpeedLimit, conflictingLink, width, null, null,
167                 lane);
168     }
169 
170     /**
171      * Returns the conflict type.
172      * @return conflict type
173      */
174     public final ConflictType getConflictType()
175     {
176         return this.conflictType;
177     }
178 
179     /**
180      * Returns whether this is a crossing conflict.
181      * @return whether this is a crossing conflict
182      */
183     public final boolean isCrossing()
184     {
185         return this.conflictType.equals(ConflictType.CROSSING);
186     }
187 
188     /**
189      * Returns whether this is a merge conflict.
190      * @return whether this is a merge conflict
191      */
192     public final boolean isMerge()
193     {
194         return this.conflictType.equals(ConflictType.MERGE);
195     }
196 
197     /**
198      * Returns whether this is a split conflict.
199      * @return whether this is a split conflict
200      */
201     public final boolean isSplit()
202     {
203         return this.conflictType.equals(ConflictType.SPLIT);
204     }
205 
206     /**
207      * Returns the conflict priority.
208      * @return conflict priority
209      */
210     public final ConflictPriority getConflictPriority()
211     {
212         return this.conflictPriority;
213     }
214 
215     /**
216      * Returns the length of the conflict on the conflicting lane.
217      * @return length of the conflict on the conflicting lane
218      */
219     public final Length getConflictingLength()
220     {
221         return this.conflictingLength;
222     }
223 
224     /**
225      * Returns a set of conflicting GTU's upstream of the <i>start</i> of the conflict ordered close to far from the conflict.
226      * @return set of conflicting GTU's upstream of the <i>start</i> of the conflict ordered close to far from the conflict
227      */
228     public final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> getUpstreamConflictingGTUs()
229     {
230         return this.upstreamConflictingGTUs;
231     }
232 
233     /**
234      * Returns a set of conflicting GTU's downstream of the <i>start</i> of the conflict ordered close to far from the conflict.
235      * Distance is given relative to the <i>end</i> of the conflict, or null for conflicting vehicles on the conflict. In the
236      * latter case the overlap is used.
237      * @return set of conflicting GTU's downstream of the <i>start</i> of the conflict ordered close to far from the conflict
238      */
239     public final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> getDownstreamConflictingGTUs()
240     {
241         return this.downstreamConflictingGTUs;
242     }
243 
244     /**
245      * Returns the visibility on the conflicting lane within which conflicting vehicles are visible. All upstream conflicting
246      * GTUs have a distance smaller than the visibility. Depending on a limited visibility, a certain (lower) speed may be
247      * required while approaching the conflict.
248      * @return visibility on the conflicting lane within which conflicting vehicles are visible
249      */
250     public final Length getConflictingVisibility()
251     {
252         return this.conflictingVisibility;
253     }
254 
255     /**
256      * Returns the speed limit on the conflicting lane.
257      * @return speed limit on the conflicting lane
258      */
259     public final Speed getConflictingSpeedLimit()
260     {
261         return this.conflictingSpeedLimit;
262     }
263 
264     /**
265      * Returns the conflicting link.
266      * @return the conflicting link
267      */
268     public final CrossSectionLink getConflictingLink()
269     {
270         return this.conflictingLink;
271     }
272 
273     /**
274      * Returns the stop line.
275      * @return stop line
276      */
277     public final HeadwayStopLine getStopLine()
278     {
279         return this.stopLine;
280     }
281 
282     /**
283      * Returns the stop line on the conflicting lane.
284      * @return stop line
285      */
286     public final HeadwayStopLine getConflictingStopLine()
287     {
288         return this.conflictingStopLine;
289     }
290 
291     /**
292      * Returns the conflict rule type.
293      * @return conflict rule type
294      */
295     public final Class<? extends ConflictRule> getConflictRuleType()
296     {
297         return this.conflictRuleType;
298     }
299 
300     /**
301      * Returns the distance of a traffic light upstream on the conflicting lane.
302      * @return distance of a traffic light upstream on the conflicting lane, or {@code null} if no traffic light
303      */
304     public final Length getConflictingTrafficLightDistance()
305     {
306         return this.conflictingTrafficLightDistance;
307     }
308 
309     /**
310      * Whether the conflict is permitted by the traffic light.
311      * @return whether the conflict is permitted by the traffic light
312      */
313     public final boolean isPermitted()
314     {
315         return this.permitted;
316     }
317 
318     /**
319      * Set the distance of a traffic light upstream on the conflicting lane.
320      * @param trafficLightDistance Length; distance of a traffic light upstream on the conflicting lane.
321      * @param permittedConflict boolean; whether the conflict is permitted by the traffic light
322      */
323     public final void setConflictingTrafficLight(final Length trafficLightDistance, final boolean permittedConflict)
324     {
325         this.conflictingTrafficLightDistance = trafficLightDistance;
326         this.permitted = permittedConflict;
327     }
328 
329     /**
330      * Returns the width at the given fraction.
331      * @param fraction double; fraction from 0 to 1
332      * @return Length; width at the given fraction
333      */
334     public final Length getWidthAtFraction(final double fraction)
335     {
336         try
337         {
338             return this.width.getWidth(fraction);
339         }
340         catch (ValueRuntimeException exception)
341         {
342             throw new RuntimeException("Unexpected exception: fraction could not be interpolated.", exception);
343         }
344     }
345 
346     /**
347      * Width progression of conflict.
348      * <p>
349      * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
350      * <br>
351      * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
352      * </p>
353      * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
354      * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
355      * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
356      */
357     public static class Width
358     {
359 
360         /** Fractions, from 0 to 1. */
361         private final double[] fractions;
362 
363         /** Vector with widths. */
364         private final LengthVector width;
365 
366         /**
367          * @param fractions double[]; fractions, from 0 to 1
368          * @param width LengthVector; vector of equal length with widths
369          */
370         public Width(final double[] fractions, final LengthVector width)
371         {
372             Throw.whenNull(fractions, "Fractions may not be null.");
373             Throw.whenNull(width, "Width may not be null.");
374             Throw.when(fractions.length != width.size(), IllegalArgumentException.class,
375                     "Array and vector are not of equal length.");
376             Throw.when(fractions.length < 2, IllegalArgumentException.class, "Input should at least contain 2 values.");
377             Throw.when(fractions[0] != 0.0 || fractions[fractions.length - 1] != 1.0, IllegalArgumentException.class,
378                     "Fractions should range from 0 to 1.");
379             for (int i = 1; i < fractions.length; i++)
380             {
381                 Throw.when(fractions[i] <= fractions[i - 1], IllegalArgumentException.class, "Fractions are not increasing.");
382             }
383             this.fractions = fractions;
384             this.width = width;
385         }
386 
387         /**
388          * Returns the width at the given fraction.
389          * @param fraction double; fraction from 0 to 1
390          * @return Length; width at the given fraction
391          * @throws ValueRuntimeException when index is out of bounds
392          */
393         public Length getWidth(final double fraction) throws ValueRuntimeException
394         {
395             Throw.when(fraction < 0.0 || fraction > 1.0, IllegalArgumentException.class, "Fraction should be between 0 and 1.");
396             if (fraction == 1.0)
397             {
398                 return this.width.get(this.width.size() - 1);
399             }
400             for (int i = 0; i < this.fractions.length - 1; i++)
401             {
402                 if (this.fractions[i] <= fraction && this.fractions[i + 1] > fraction)
403                 {
404                     double r = (fraction - this.fractions[i]) / (this.fractions[i + 1] - this.fractions[i]);
405                     return Length.interpolate(this.width.get(i), this.width.get(i + 1), r);
406                 }
407             }
408             throw new RuntimeException("Unexpected exception: fraction could not be interpolated.");
409         }
410 
411         /**
412          * Returns a linear width progression.
413          * @param startWidth Length; start width
414          * @param endWidth Length; end width
415          * @return Width; linear width progression
416          */
417         public static Width linear(final Length startWidth, final Length endWidth)
418         {
419             Throw.whenNull(startWidth, "Start width may not be null.");
420             Throw.whenNull(endWidth, "End width may not be null.");
421             try
422             {
423                 return new Width(new double[] {0.0, 1.0}, new LengthVector(new Length[] {startWidth, endWidth}, LengthUnit.SI));
424             }
425             catch (ValueRuntimeException exception)
426             {
427                 throw new RuntimeException("Unexpected exception: widths could not be put in a vector.", exception);
428             }
429         }
430 
431     }
432 
433     /** {@inheritDoc} */
434     @Override
435     public final String toString()
436     {
437         return String.format("Headway %s to object %s of type %s", getDistance(), getId(), getObjectType());
438     }
439 
440 }