CarFollowingUtil.java

  1. package org.opentrafficsim.road.gtu.lane.tactical.util;

  2. import org.djunits.unit.AccelerationUnit;
  3. import org.djunits.unit.SpeedUnit;
  4. import org.djunits.value.vdouble.scalar.Acceleration;
  5. import org.djunits.value.vdouble.scalar.Length;
  6. import org.djunits.value.vdouble.scalar.Speed;
  7. import org.djutils.exceptions.Throw;
  8. import org.djutils.exceptions.Try;
  9. import org.opentrafficsim.base.parameters.ParameterException;
  10. import org.opentrafficsim.base.parameters.Parameters;
  11. import org.opentrafficsim.core.gtu.GTUException;
  12. import org.opentrafficsim.road.gtu.lane.perception.PerceptionIterable;
  13. import org.opentrafficsim.road.gtu.lane.perception.PerceptionIterableSet;
  14. import org.opentrafficsim.road.gtu.lane.perception.headway.AbstractHeadway;
  15. import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
  16. import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
  17. import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
  18. import org.opentrafficsim.road.network.speed.SpeedLimitInfo;

  19. /**
  20.  * Static methods regarding car-following for composition in tactical planners.
  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 May 23, 2016 <br>
  26.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  27.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  28.  */
  29. public final class CarFollowingUtil
  30. {

  31.     /**
  32.      * Do not instantiate.
  33.      */
  34.     private CarFollowingUtil()
  35.     {
  36.         //
  37.     }

  38.     /**
  39.      * Follow a set of headway GTUs.
  40.      * @param carFollowingModel CarFollowingModel; car-following model
  41.      * @param parameters Parameters; parameters
  42.      * @param speed Speed; current speed
  43.      * @param speedLimitInfo SpeedLimitInfo; speed limit info
  44.      * @param distance Length; distance
  45.      * @param leaderSpeed Speed; speed of the leader
  46.      * @return acceleration for following the leader
  47.      * @throws ParameterException if a parameter is not given or out of bounds
  48.      */
  49.     public static Acceleration followSingleLeader(final CarFollowingModel carFollowingModel, final Parameters parameters,
  50.             final Speed speed, final SpeedLimitInfo speedLimitInfo, final Length distance, final Speed leaderSpeed)
  51.             throws ParameterException
  52.     {
  53.         return carFollowingModel.followingAcceleration(parameters, speed, speedLimitInfo, createLeader(distance, leaderSpeed));
  54.     }

  55.     /**
  56.      * Follow a set of headway GTUs.
  57.      * @param carFollowingModel CarFollowingModel; car-following model
  58.      * @param parameters Parameters; parameters
  59.      * @param speed Speed; current speed
  60.      * @param speedLimitInfo SpeedLimitInfo; speed limit info
  61.      * @param leader HeadwayGTU; leader
  62.      * @return acceleration for following the leader
  63.      * @throws ParameterException if a parameter is not given or out of bounds
  64.      */
  65.     public static Acceleration followSingleLeader(final CarFollowingModel carFollowingModel, final Parameters parameters,
  66.             final Speed speed, final SpeedLimitInfo speedLimitInfo, final HeadwayGTU leader) throws ParameterException
  67.     {
  68.         return carFollowingModel.followingAcceleration(parameters, speed, speedLimitInfo, new PerceptionIterableSet<>(leader));
  69.     }

  70.     /**
  71.      * Stop within given distance.
  72.      * @param carFollowingModel CarFollowingModel; car-following model
  73.      * @param parameters Parameters; parameters
  74.      * @param speed Speed; current speed
  75.      * @param speedLimitInfo SpeedLimitInfo; speed limit info
  76.      * @param distance Length; distance to stop over
  77.      * @return acceleration to stop over distance
  78.      * @throws ParameterException if a parameter is not given or out of bounds
  79.      */
  80.     public static Acceleration stop(final CarFollowingModel carFollowingModel, final Parameters parameters, final Speed speed,
  81.             final SpeedLimitInfo speedLimitInfo, final Length distance) throws ParameterException
  82.     {
  83.         return carFollowingModel.followingAcceleration(parameters, speed, speedLimitInfo, createLeader(distance, Speed.ZERO));
  84.     }

  85.     /**
  86.      * Return constant acceleration in order to stop in specified distance. The car-following model is used to determine the
  87.      * stopping distance (i.e. distance remaining at stand still, e.g. 1-3m).
  88.      * @param carFollowingModel CarFollowingModel; car-following model
  89.      * @param parameters Parameters; parameters
  90.      * @param speed Speed; current speed
  91.      * @param distance Length; distance to stop over
  92.      * @return constant acceleration in order to stop in specified distance
  93.      * @throws ParameterException on missing parameter
  94.      */
  95.     public static Acceleration constantAccelerationStop(final CarFollowingModel carFollowingModel, final Parameters parameters,
  96.             final Speed speed, final Length distance) throws ParameterException
  97.     {
  98.         Length s0 = carFollowingModel.desiredHeadway(parameters, Speed.ZERO);
  99.         return new Acceleration(-0.5 * speed.si * speed.si / (distance.si - s0.si), AccelerationUnit.SI);
  100.     }

  101.     /**
  102.      * Calculate free acceleration.
  103.      * @param carFollowingModel CarFollowingModel; car-following model
  104.      * @param parameters Parameters; parameters
  105.      * @param speed Speed; current speed
  106.      * @param speedLimitInfo SpeedLimitInfo; speed limit info
  107.      * @return acceleration free acceleration
  108.      * @throws ParameterException if a parameter is not given or out of bounds
  109.      */
  110.     public static Acceleration freeAcceleration(final CarFollowingModel carFollowingModel, final Parameters parameters,
  111.             final Speed speed, final SpeedLimitInfo speedLimitInfo) throws ParameterException
  112.     {
  113.         PerceptionIterableSet<Headway> leaders = new PerceptionIterableSet<>();
  114.         return carFollowingModel.followingAcceleration(parameters, speed, speedLimitInfo, leaders);
  115.     }

  116.     /**
  117.      * Returns an acceleration based on the car-following model in order to adjust the speed to a given value at some location
  118.      * ahead. This is done by placing a virtual vehicle somewhere near the location. Both the location and speed of this virtual
  119.      * vehicle are dynamically adjusted to resemble a car-following situation. To explain, first consider the situation where a
  120.      * virtual vehicle is placed at the target speed and such that the equilibrium headway is in line with the location:
  121.      *
  122.      * <pre>
  123.      *
  124.      *  ___    location of target speed --)|        ___
  125.      * |___|(--------------s--------------) (--h--)|___| ))) vTar
  126.      * </pre>
  127.      *
  128.      * Here, {@code s} is the distance to the target speed, and {@code h} is the desired headway if the vehicle would drive at
  129.      * the target speed {@code vTar}.<br>
  130.      * <br>
  131.      * In this way car-following models will first underestimate the required deceleration, as the virtual vehicle is actually
  132.      * stationary and does not move with {@code vTar} at all. Because of this underestimation, strong deceleration is required
  133.      * later. This behavior is not in line with the sensitivity parameters of the car-following model.<br>
  134.      * <br>
  135.      * To correct for the fact that the virtual vehicle is actually not moving, the speed difference should be larger, i.e. the
  136.      * speed of the virtual vehicle {@code vTar'} should be lower. We require:
  137.      * <ul>
  138.      * <li>if {@code v = vTar} then {@code vTar' = vTar}, otherwise there is an incentive to accelerate or decelerate for no
  139.      * good reason</li>
  140.      * <li>if {@code vTar ~ 0} then {@code vTar' ~ 0}, as car-following models are suitable for stopping and need no additional
  141.      * incentive to decelerate in such cases</li>
  142.      * <li>if {@code 0 < vTar < v} then {@code vTar' < vTar}, introducing additional deceleration to compensate for the fact
  143.      * that the virtual vehicle does not move
  144.      * </ul>
  145.      * These requirements are met by {@code vTar' = vTar * (vTar/v) = vTar^2/v}.<br>
  146.      * <br>
  147.      * Furthermore, if {@code v < vTar} we get {@code vTar' > vTar} leading to additional acceleration. Acceleration is then
  148.      * appropriate, and possibly limited by a free term in the car-following model.<br>
  149.      * <br>
  150.      * The virtual vehicle is thus placed with speed {@code vTar'} at a distance {@code s + h'} where {@code h'} is the desired
  151.      * headway if the vehicle would drive at speed {@code vTar'}. Both {@code vTar'} and {@code h'} depend on the current speed
  152.      * of the vehicle, so the virtual vehicle in this case actually moves, but not with {@code vTar}.<br>
  153.      * <br>
  154.      * This approach has been tested with the IDM+ to deliver decelerations in line with the parameters. On a plane with initial
  155.      * speed ranging from 0 to 33.33m/s and a target speed in 300m also ranging from 0 to 33.33m/s, strongest deceleration is
  156.      * equal to the car-following model stopping from 33.33m/s to a stand-still vehicle in 300m (+ stopping distance of 3m).
  157.      * Throughout the plane the maximum deceleration of each scenario is close to this value, unless the initial speed is so
  158.      * low, and the target speed is so high, that such levels of deceleration are never required.<br>
  159.      * <br>
  160.      * @param carFollowingModel CarFollowingModel; car-following model to use
  161.      * @param parameters Parameters; parameters
  162.      * @param speed Speed; current speed
  163.      * @param speedLimitInfo SpeedLimitInfo; info regarding the desired speed for car-following
  164.      * @param distance Length; distance to the location of the target speed
  165.      * @param targetSpeed Speed; target speed
  166.      * @return acceleration acceleration based on the car-following model in order to adjust the speed
  167.      * @throws ParameterException if parameter exception occurs
  168.      * @throws NullPointerException if any input is null
  169.      * @throws IllegalArgumentException if the distance or target speed is not at least 0
  170.      */
  171.     public static Acceleration approachTargetSpeed(final CarFollowingModel carFollowingModel, final Parameters parameters,
  172.             final Speed speed, final SpeedLimitInfo speedLimitInfo, final Length distance, final Speed targetSpeed)
  173.             throws ParameterException
  174.     {
  175.         Throw.whenNull(parameters, "Parameters may not be null.");
  176.         Throw.whenNull(speed, "Speed may not be null.");
  177.         Throw.whenNull(speedLimitInfo, "Speed limit info may not be null.");
  178.         Throw.whenNull(distance, "Distance may not be null");
  179.         Throw.whenNull(targetSpeed, "Target speed may not be null");
  180.         Throw.when(distance.si < 0, IllegalArgumentException.class, "Distance must be at least 0.");
  181.         Throw.when(targetSpeed.si < 0, IllegalArgumentException.class, "Target speed must be at least 0.");
  182.         // adjust speed of virtual vehicle to add deceleration incentive as the virtual vehicle does not move
  183.         Speed virtualSpeed;
  184.         if (speed.si > 0)
  185.         {
  186.             virtualSpeed = new Speed(targetSpeed.si * targetSpeed.si / speed.si, SpeedUnit.SI);
  187.         }
  188.         else
  189.         {
  190.             virtualSpeed = new Speed(Double.MAX_VALUE, SpeedUnit.SI);
  191.         }
  192.         // set distance in line with equilibrium headway at virtual speed
  193.         Length virtualDistance = distance.plus(carFollowingModel.desiredHeadway(parameters, virtualSpeed));
  194.         // calculate acceleration towards virtual vehicle with car-following model
  195.         return carFollowingModel.followingAcceleration(parameters, speed, speedLimitInfo,
  196.                 createLeader(virtualDistance, virtualSpeed));
  197.     }

  198.     /**
  199.      * Create a single leader set.
  200.      * @param headway Length; distance to the leader
  201.      * @param speed Speed; leader speed
  202.      * @return Set; set with a single leader
  203.      */
  204.     private static PerceptionIterable<Headway> createLeader(final Length headway, final Speed speed)
  205.     {
  206.         PerceptionIterable<Headway> leaders =
  207.                 Try.assign(() -> new PerceptionIterableSet<>(new CarFollowingHeadway(headway, speed)),
  208.                         "Exception during headway creation.");
  209.         return leaders;
  210.     }

  211.     /**
  212.      * Simple headway implementation for minimum car-following information.
  213.      * <p>
  214.      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  215.      * <br>
  216.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  217.      * <p>
  218.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 26 feb. 2018 <br>
  219.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  220.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  221.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  222.      */
  223.     public static class CarFollowingHeadway extends AbstractHeadway
  224.     {
  225.         /** */
  226.         private static final long serialVersionUID = 20180226L;

  227.         /** Speed of the leader. */
  228.         private final Speed speed;

  229.         /**
  230.          * Constructor.
  231.          * @param headway Length; distance to the leader
  232.          * @param speed Speed; leader speed
  233.          * @throws GTUException on exception
  234.          */
  235.         public CarFollowingHeadway(final Length headway, final Speed speed) throws GTUException
  236.         {
  237.             super(headway);
  238.             this.speed = speed;
  239.         }

  240.         /** {@inheritDoc} */
  241.         @Override
  242.         public String getId()
  243.         {
  244.             return null;
  245.         }

  246.         /** {@inheritDoc} */
  247.         @Override
  248.         public Length getLength()
  249.         {
  250.             return null;
  251.         }

  252.         /** {@inheritDoc} */
  253.         @Override
  254.         public Speed getSpeed()
  255.         {
  256.             return this.speed;
  257.         }

  258.         /** {@inheritDoc} */
  259.         @Override
  260.         public ObjectType getObjectType()
  261.         {
  262.             return null;
  263.         }

  264.         /** {@inheritDoc} */
  265.         @Override
  266.         public Acceleration getAcceleration()
  267.         {
  268.             return null;
  269.         }
  270.     }

  271. }