HeadwayConflict.java

  1. package org.opentrafficsim.road.gtu.lane.perception.headway;

  2. import org.djunits.unit.LengthUnit;
  3. import org.djunits.value.ValueRuntimeException;
  4. import org.djunits.value.vdouble.scalar.Length;
  5. import org.djunits.value.vdouble.scalar.Speed;
  6. import org.djunits.value.vdouble.vector.LengthVector;
  7. import org.djutils.exceptions.Throw;
  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.Lane;
  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.  * <p>
  18.  * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  19.  * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  20.  * </p>
  21.  * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
  22.  * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
  23.  * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
  24.  */
  25. public class HeadwayConflict extends AbstractHeadwayLaneBasedObject
  26. {

  27.     /** */
  28.     private static final long serialVersionUID = 20160602L;

  29.     /** Conflict type. */
  30.     private final ConflictType conflictType;

  31.     /** Conflict priority. */
  32.     private final ConflictPriority conflictPriority;

  33.     /** Length of the conflict in the conflicting directions. */
  34.     private final Length conflictingLength;

  35.     /**
  36.      * Set of conflicting GTU's <i>completely</i> upstream of the <i>start</i> of the conflict ordered close to far from the
  37.      * start of the conflict. Distance and overlap info concerns the conflict.
  38.      */
  39.     private final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs;

  40.     /**
  41.      * Set of conflicting GTU's (partially) downstream of the <i>start</i> of the conflict ordered close to far from the start
  42.      * of conflict. Distance and overlap info concerns the conflict.
  43.      */
  44.     private final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs;

  45.     /** Visibility on the conflicting lane within which conflicting vehicles are visible. */
  46.     private final Length conflictingVisibility;

  47.     /** Speed limit on the conflicting lane. */
  48.     private final Speed conflictingSpeedLimit;

  49.     /** Link of conflicting conflict. */
  50.     private final CrossSectionLink conflictingLink;

  51.     /** Stop line on the own lane. */
  52.     private final HeadwayStopLine stopLine;

  53.     /** Stop line on the conflicting lane. */
  54.     private final HeadwayStopLine conflictingStopLine;

  55.     /** Type of conflict rule. */
  56.     private final Class<? extends ConflictRule> conflictRuleType;

  57.     /** Distance of traffic light upstream on conflicting lane. */
  58.     private Length conflictingTrafficLightDistance = null;

  59.     /** Whether the conflict is permitted by the traffic light. */
  60.     private boolean permitted = false;

  61.     /** Width progression of conflict. */
  62.     private final Width width;

  63.     /**
  64.      * Constructor.
  65.      * @param conflictType conflict type
  66.      * @param conflictPriority conflict priority
  67.      * @param conflictRuleType conflict rule type
  68.      * @param id id
  69.      * @param distance distance
  70.      * @param length length of the conflict
  71.      * @param conflictingLength length of the conflict on the conflicting lane
  72.      * @param upstreamConflictingGTUs conflicting GTU's upstream of the &lt;i&gt;start&lt;/i&gt; of the conflict
  73.      * @param downstreamConflictingGTUs conflicting GTU's downstream of the &lt;i&gt;start&lt;/i&gt; of the conflict
  74.      * @param conflictingVisibility visibility on the conflicting lane within which conflicting vehicles are visible
  75.      * @param conflictingSpeedLimit speed limit on the conflicting lane
  76.      * @param conflictingLink conflicting link
  77.      * @param width width progression of conflict
  78.      * @param stopLine stop line on the own lane
  79.      * @param conflictingStopLine stop line on the conflicting lane
  80.      * @param lane the lane
  81.      * @throws GtuException when id is null, or parameters are inconsistent
  82.      */
  83.     @SuppressWarnings("checkstyle:parameternumber")
  84.     public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
  85.             final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
  86.             final Length conflictingLength, final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs,
  87.             final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs, final Length conflictingVisibility,
  88.             final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width,
  89.             final HeadwayStopLine stopLine, final HeadwayStopLine conflictingStopLine, final Lane lane) throws GtuException
  90.     {
  91.         super(ObjectType.CONFLICT, id, distance, length, lane);
  92.         Throw.whenNull(conflictType, "Conflict type may not be null.");
  93.         Throw.whenNull(conflictPriority, "Conflict priority may not be null.");
  94.         Throw.whenNull(conflictRuleType, "Conflict rule type may not be null.");
  95.         Throw.whenNull(id, "Conflict id may not be null.");
  96.         Throw.whenNull(distance, "Conflict distance may not be null.");
  97.         Throw.whenNull(conflictingLength, "Conflict length may not be null.");
  98.         Throw.whenNull(upstreamConflictingGTUs, "Upstreaem conflicting GTU's may not be null.");
  99.         Throw.whenNull(downstreamConflictingGTUs, "Downstream conflicting GTU's may not be null.");
  100.         Throw.whenNull(width, "Width may not be null.");
  101.         Throw.whenNull(conflictingVisibility, "Conflict visibility may not be null.");
  102.         Throw.whenNull(conflictingSpeedLimit, "Conflict speed limit may not be null.");
  103.         this.conflictType = conflictType;
  104.         this.conflictPriority = conflictPriority;
  105.         this.conflictRuleType = conflictRuleType;
  106.         this.conflictingLength = conflictingLength;
  107.         this.upstreamConflictingGTUs = upstreamConflictingGTUs;
  108.         this.downstreamConflictingGTUs = downstreamConflictingGTUs;
  109.         this.conflictingVisibility = conflictingVisibility;
  110.         this.conflictingSpeedLimit = conflictingSpeedLimit;
  111.         this.conflictingLink = conflictingLink;
  112.         this.width = width;
  113.         this.stopLine = stopLine;
  114.         this.conflictingStopLine = conflictingStopLine;
  115.     }

  116.     /**
  117.      * Constructor without stop lines.
  118.      * @param conflictType conflict type
  119.      * @param conflictPriority conflict priority
  120.      * @param conflictRuleType conflict rule type
  121.      * @param id id
  122.      * @param distance distance
  123.      * @param length length of the conflict
  124.      * @param conflictingLength length of the conflict on the conflicting lane
  125.      * @param upstreamConflictingGTUs conflicting GTU's upstream of the &lt;i&gt;start&lt;/i&gt; of the conflict
  126.      * @param downstreamConflictingGTUs conflicting GTU's downstream of the &lt;i&gt;start&lt;/i&gt; of the conflict
  127.      * @param conflictingVisibility visibility on the conflicting lane within which conflicting vehicles are visible
  128.      * @param conflictingSpeedLimit speed limit on the conflicting lane
  129.      * @param conflictingLink conflicting link
  130.      * @param width width progression of conflict
  131.      * @param lane the lane
  132.      * @throws GtuException when id is null, or parameters are inconsistent
  133.      */
  134.     @SuppressWarnings("checkstyle:parameternumber")
  135.     public HeadwayConflict(final ConflictType conflictType, final ConflictPriority conflictPriority,
  136.             final Class<? extends ConflictRule> conflictRuleType, final String id, final Length distance, final Length length,
  137.             final Length conflictingLength, final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> upstreamConflictingGTUs,
  138.             final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> downstreamConflictingGTUs, final Length conflictingVisibility,
  139.             final Speed conflictingSpeedLimit, final CrossSectionLink conflictingLink, final Width width, final Lane lane)
  140.             throws GtuException
  141.     {
  142.         this(conflictType, conflictPriority, conflictRuleType, id, distance, length, conflictingLength, upstreamConflictingGTUs,
  143.                 downstreamConflictingGTUs, conflictingVisibility, conflictingSpeedLimit, conflictingLink, width, null, null,
  144.                 lane);
  145.     }

  146.     /**
  147.      * Returns the conflict type.
  148.      * @return conflict type
  149.      */
  150.     public final ConflictType getConflictType()
  151.     {
  152.         return this.conflictType;
  153.     }

  154.     /**
  155.      * Returns whether this is a crossing conflict.
  156.      * @return whether this is a crossing conflict
  157.      */
  158.     public final boolean isCrossing()
  159.     {
  160.         return this.conflictType.equals(ConflictType.CROSSING);
  161.     }

  162.     /**
  163.      * Returns whether this is a merge conflict.
  164.      * @return whether this is a merge conflict
  165.      */
  166.     public final boolean isMerge()
  167.     {
  168.         return this.conflictType.equals(ConflictType.MERGE);
  169.     }

  170.     /**
  171.      * Returns whether this is a split conflict.
  172.      * @return whether this is a split conflict
  173.      */
  174.     public final boolean isSplit()
  175.     {
  176.         return this.conflictType.equals(ConflictType.SPLIT);
  177.     }

  178.     /**
  179.      * Returns the conflict priority.
  180.      * @return conflict priority
  181.      */
  182.     public final ConflictPriority getConflictPriority()
  183.     {
  184.         return this.conflictPriority;
  185.     }

  186.     /**
  187.      * Returns the length of the conflict on the conflicting lane.
  188.      * @return length of the conflict on the conflicting lane
  189.      */
  190.     public final Length getConflictingLength()
  191.     {
  192.         return this.conflictingLength;
  193.     }

  194.     /**
  195.      * Returns a set of conflicting GTU's upstream of the <i>start</i> of the conflict ordered close to far from the conflict.
  196.      * @return set of conflicting GTU's upstream of the <i>start</i> of the conflict ordered close to far from the conflict
  197.      */
  198.     public final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> getUpstreamConflictingGTUs()
  199.     {
  200.         return this.upstreamConflictingGTUs;
  201.     }

  202.     /**
  203.      * Returns a set of conflicting GTU's downstream of the <i>start</i> of the conflict ordered close to far from the conflict.
  204.      * Distance is given relative to the <i>end</i> of the conflict, or null for conflicting vehicles on the conflict. In the
  205.      * latter case the overlap is used.
  206.      * @return set of conflicting GTU's downstream of the <i>start</i> of the conflict ordered close to far from the conflict
  207.      */
  208.     public final PerceptionCollectable<HeadwayGtu, LaneBasedGtu> getDownstreamConflictingGTUs()
  209.     {
  210.         return this.downstreamConflictingGTUs;
  211.     }

  212.     /**
  213.      * Returns the visibility on the conflicting lane within which conflicting vehicles are visible. All upstream conflicting
  214.      * GTUs have a distance smaller than the visibility. Depending on a limited visibility, a certain (lower) speed may be
  215.      * required while approaching the conflict.
  216.      * @return visibility on the conflicting lane within which conflicting vehicles are visible
  217.      */
  218.     public final Length getConflictingVisibility()
  219.     {
  220.         return this.conflictingVisibility;
  221.     }

  222.     /**
  223.      * Returns the speed limit on the conflicting lane.
  224.      * @return speed limit on the conflicting lane
  225.      */
  226.     public final Speed getConflictingSpeedLimit()
  227.     {
  228.         return this.conflictingSpeedLimit;
  229.     }

  230.     /**
  231.      * Returns the conflicting link.
  232.      * @return the conflicting link
  233.      */
  234.     public final CrossSectionLink getConflictingLink()
  235.     {
  236.         return this.conflictingLink;
  237.     }

  238.     /**
  239.      * Returns the stop line.
  240.      * @return stop line
  241.      */
  242.     public final HeadwayStopLine getStopLine()
  243.     {
  244.         return this.stopLine;
  245.     }

  246.     /**
  247.      * Returns the stop line on the conflicting lane.
  248.      * @return stop line
  249.      */
  250.     public final HeadwayStopLine getConflictingStopLine()
  251.     {
  252.         return this.conflictingStopLine;
  253.     }

  254.     /**
  255.      * Returns the conflict rule type.
  256.      * @return conflict rule type
  257.      */
  258.     public final Class<? extends ConflictRule> getConflictRuleType()
  259.     {
  260.         return this.conflictRuleType;
  261.     }

  262.     /**
  263.      * Returns the distance of a traffic light upstream on the conflicting lane.
  264.      * @return distance of a traffic light upstream on the conflicting lane, or {@code null} if no traffic light
  265.      */
  266.     public final Length getConflictingTrafficLightDistance()
  267.     {
  268.         return this.conflictingTrafficLightDistance;
  269.     }

  270.     /**
  271.      * Whether the conflict is permitted by the traffic light.
  272.      * @return whether the conflict is permitted by the traffic light
  273.      */
  274.     public final boolean isPermitted()
  275.     {
  276.         return this.permitted;
  277.     }

  278.     /**
  279.      * Set the distance of a traffic light upstream on the conflicting lane.
  280.      * @param trafficLightDistance distance of a traffic light upstream on the conflicting lane.
  281.      * @param permittedConflict whether the conflict is permitted by the traffic light
  282.      */
  283.     public final void setConflictingTrafficLight(final Length trafficLightDistance, final boolean permittedConflict)
  284.     {
  285.         this.conflictingTrafficLightDistance = trafficLightDistance;
  286.         this.permitted = permittedConflict;
  287.     }

  288.     /**
  289.      * Returns the width at the given fraction.
  290.      * @param fraction fraction from 0 to 1
  291.      * @return width at the given fraction
  292.      */
  293.     public final Length getWidthAtFraction(final double fraction)
  294.     {
  295.         try
  296.         {
  297.             return this.width.getWidth(fraction);
  298.         }
  299.         catch (ValueRuntimeException exception)
  300.         {
  301.             throw new RuntimeException("Unexpected exception: fraction could not be interpolated.", exception);
  302.         }
  303.     }

  304.     /**
  305.      * Width progression of conflict.
  306.      * <p>
  307.      * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  308.      * <br>
  309.      * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  310.      * </p>
  311.      * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
  312.      * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
  313.      * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
  314.      */
  315.     public static class Width
  316.     {

  317.         /** Fractions, from 0 to 1. */
  318.         private final double[] fractions;

  319.         /** Vector with widths. */
  320.         private final LengthVector width;

  321.         /**
  322.          * @param fractions fractions, from 0 to 1
  323.          * @param width vector of equal length with widths
  324.          */
  325.         public Width(final double[] fractions, final LengthVector width)
  326.         {
  327.             Throw.whenNull(fractions, "Fractions may not be null.");
  328.             Throw.whenNull(width, "Width may not be null.");
  329.             Throw.when(fractions.length != width.size(), IllegalArgumentException.class,
  330.                     "Array and vector are not of equal length.");
  331.             Throw.when(fractions.length < 2, IllegalArgumentException.class, "Input should at least contain 2 values.");
  332.             Throw.when(fractions[0] != 0.0 || fractions[fractions.length - 1] != 1.0, IllegalArgumentException.class,
  333.                     "Fractions should range from 0 to 1.");
  334.             for (int i = 1; i < fractions.length; i++)
  335.             {
  336.                 Throw.when(fractions[i] <= fractions[i - 1], IllegalArgumentException.class, "Fractions are not increasing.");
  337.             }
  338.             this.fractions = fractions;
  339.             this.width = width;
  340.         }

  341.         /**
  342.          * Returns the width at the given fraction.
  343.          * @param fraction fraction from 0 to 1
  344.          * @return width at the given fraction
  345.          * @throws ValueRuntimeException when index is out of bounds
  346.          */
  347.         public Length getWidth(final double fraction) throws ValueRuntimeException
  348.         {
  349.             Throw.when(fraction < 0.0 || fraction > 1.0, IllegalArgumentException.class, "Fraction should be between 0 and 1.");
  350.             if (fraction == 1.0)
  351.             {
  352.                 return this.width.get(this.width.size() - 1);
  353.             }
  354.             for (int i = 0; i < this.fractions.length - 1; i++)
  355.             {
  356.                 if (this.fractions[i] <= fraction && this.fractions[i + 1] > fraction)
  357.                 {
  358.                     double r = (fraction - this.fractions[i]) / (this.fractions[i + 1] - this.fractions[i]);
  359.                     return Length.interpolate(this.width.get(i), this.width.get(i + 1), r);
  360.                 }
  361.             }
  362.             throw new RuntimeException("Unexpected exception: fraction could not be interpolated.");
  363.         }

  364.         /**
  365.          * Returns a linear width progression.
  366.          * @param startWidth start width
  367.          * @param endWidth end width
  368.          * @return linear width progression
  369.          */
  370.         public static Width linear(final Length startWidth, final Length endWidth)
  371.         {
  372.             Throw.whenNull(startWidth, "Start width may not be null.");
  373.             Throw.whenNull(endWidth, "End width may not be null.");
  374.             try
  375.             {
  376.                 return new Width(new double[] {0.0, 1.0}, new LengthVector(new Length[] {startWidth, endWidth}, LengthUnit.SI));
  377.             }
  378.             catch (ValueRuntimeException exception)
  379.             {
  380.                 throw new RuntimeException("Unexpected exception: widths could not be put in a vector.", exception);
  381.             }
  382.         }

  383.     }

  384.     @Override
  385.     public final String toString()
  386.     {
  387.         return String.format("Headway %s to object %s of type %s", getDistance(), getId(), getObjectType());
  388.     }

  389. }