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.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&lt;? extends ConflictRule&gt;; 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&lt;HeadwayGTU,LaneBasedGTU&gt;; conflicting GTU's upstream of the
94       *            &lt;i&gt;start&lt;/i&gt; of the conflict
95       * @param downstreamConflictingGTUs PerceptionCollectable&lt;HeadwayGTU,LaneBasedGTU&gt;; conflicting GTU's downstream of
96       *            the &lt;i&gt;start&lt;/i&gt; 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&lt;? extends ConflictRule&gt;; 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&lt;HeadwayGTU,LaneBasedGTU&gt;; conflicting GTU's upstream of the
150      *            &lt;i&gt;start&lt;/i&gt; of the conflict
151      * @param downstreamConflictingGTUs PerceptionCollectable&lt;HeadwayGTU,LaneBasedGTU&gt;; conflicting GTU's downstream of
152      *            the &lt;i&gt;start&lt;/i&gt; 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 }