View Javadoc
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&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      * @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&lt;? extends ConflictRule&gt;; 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&lt;HeadwayGTU,LaneBasedGTU&gt;; conflicting GTU's upstream of the
146      *            &lt;i&gt;start&lt;/i&gt; of the conflict
147      * @param downstreamConflictingGTUs PerceptionCollectable&lt;HeadwayGTU,LaneBasedGTU&gt;; conflicting GTU's downstream of
148      *            the &lt;i&gt;start&lt;/i&gt; 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 }