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