IncentiveSpeedWithCourtesy.java

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

  2. import org.djunits.unit.DimensionlessUnit;
  3. import org.djunits.value.vdouble.scalar.Acceleration;
  4. import org.djunits.value.vdouble.scalar.Dimensionless;
  5. import org.djunits.value.vdouble.scalar.Speed;
  6. import org.djutils.exceptions.Try;
  7. import org.opentrafficsim.base.parameters.ParameterException;
  8. import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
  9. import org.opentrafficsim.base.parameters.ParameterTypeSpeed;
  10. import org.opentrafficsim.base.parameters.ParameterTypes;
  11. import org.opentrafficsim.base.parameters.Parameters;
  12. import org.opentrafficsim.core.gtu.perception.EgoPerception;
  13. import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
  14. import org.opentrafficsim.core.network.LateralDirectionality;
  15. import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
  16. import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
  17. import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
  18. import org.opentrafficsim.road.gtu.lane.perception.categories.TrafficPerception;
  19. import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
  20. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
  21. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
  22. import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;

  23. /**
  24.  * Determines lane change desire for speed. The anticipation speed in the current and adjacent lanes are compared. The larger
  25.  * the difference, the larger the lane change desire. For negative differences, negative desire results. Anticipation speed
  26.  * involves the the most critical vehicle considered to be in a lane. Vehicles are more critical if their speed is lower, and if
  27.  * they are closer. The set of vehicles considered to be on a lane includes drivers on adjacent lanes of the considered lane,
  28.  * with a lane change desire towards the considered lane above a certain certain threshold. If such vehicles have low speeds
  29.  * (i.e. vehicle accelerating to merge), this may result in a courtesy lane change, or in not changing lane out of courtesy from
  30.  * the 2nd lane of the mainline. Vehicle on the current lane of the driver, are not considered on adjacent lanes. This would
  31.  * maintain a large speed difference between the lanes where all drivers do not change lane as they consider leading vehicles to
  32.  * be on the adjacent lane, lowering the anticipation speed on the adjacent lane. The desire for speed is reduced as
  33.  * acceleration is larger, preventing over-assertive lane changes as acceleration out of congestion in the adjacent lane has
  34.  * progressed more.<br>
  35.  * <br>
  36.  * <b>Note:</b> This incentive includes speed, and a form of courtesy. It should therefore not be combined with incentives
  37.  * solely for speed, or solely for courtesy.
  38.  * <p>
  39.  * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  40.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
  41.  * <p>
  42.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 13, 2016 <br>
  43.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  44.  */
  45. public class IncentiveSpeedWithCourtesy implements VoluntaryIncentive
  46. {

  47.     /** Acceleration parameter type. */
  48.     protected static final ParameterTypeAcceleration A = ParameterTypes.A;

  49.     /** Anticipation speed difference parameter type. */
  50.     protected static final ParameterTypeSpeed VGAIN = LmrsParameters.VGAIN;

  51.     /** Speed threshold below which traffic is considered congested. */
  52.     protected static final ParameterTypeSpeed VCONG = ParameterTypes.VCONG;

  53.     /** {@inheritDoc} */
  54.     @Override
  55.     public final Desire determineDesire(final Parameters parameters, final LanePerception perception,
  56.             final CarFollowingModel carFollowingModel, final Desire mandatoryDesire, final Desire voluntaryDesire)
  57.             throws ParameterException, OperationalPlanException
  58.     {

  59.         // zero if no lane change is possible
  60.         InfrastructurePerception infra = perception.getPerceptionCategory(InfrastructurePerception.class);
  61.         TrafficPerception traffic = perception.getPerceptionCategory(TrafficPerception.class);
  62.         EgoPerception ego = perception.getPerceptionCategory(EgoPerception.class);
  63.         double leftDist = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.LEFT).si;
  64.         double rightDist = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.RIGHT).si;

  65.         // gather some info
  66.         Speed vCur = traffic.getSpeed(RelativeLane.CURRENT);
  67.         Speed vGain = parameters.getParameter(VGAIN);

  68.         // calculate aGain (default 1; lower as acceleration is higher than 0)
  69.         Dimensionless aGain;
  70.         /*
  71.          * Instead of instantaneous car-following acceleration, use current acceleration; only then is the acceleration factor
  72.          * consistent with possible lane change incentives pertaining to speed (which used to be only vehicles in the original
  73.          * LMRS, but can be any number of reasons here. E.g. traffic lights, conflicts, etc.)
  74.          */
  75.         Acceleration aCur = ego.getAcceleration();

  76.         /*
  77.          * The idea to let aCur simply be the current acceleration is wrong; aCur -should- only describe the car-following
  78.          * relation, as this describes a sense of sticking to a lane as the leader is getting away.
  79.          */
  80.         aCur = Try.assign(() -> perception.getGtu().getCarFollowingAcceleration(), "Could not obtain the GTU.");
  81.         if (aCur.si > 0)
  82.         {
  83.             Acceleration a = parameters.getParameter(A);
  84.             aGain = a.minus(aCur).divideBy(a);
  85.         }
  86.         else
  87.         {
  88.             aGain = new Dimensionless(1, DimensionlessUnit.SI);
  89.         }

  90.         // left desire
  91.         double dLeft;
  92.         if (leftDist > 0.0 && infra.getCrossSection().contains(RelativeLane.LEFT))
  93.         {
  94.             Speed vLeft = traffic.getSpeed(RelativeLane.LEFT);
  95.             dLeft = aGain.si * (vLeft.si - vCur.si) / vGain.si;
  96.         }
  97.         else
  98.         {
  99.             dLeft = 0.0;
  100.         }

  101.         // right desire
  102.         double dRight;
  103.         if (rightDist > 0.0 && infra.getCrossSection().contains(RelativeLane.RIGHT))
  104.         {
  105.             Speed vRight = traffic.getSpeed(RelativeLane.RIGHT);
  106.             if (vCur.si >= parameters.getParameter(VCONG).si)
  107.             {
  108.                 dRight = aGain.si * Math.min(vRight.si - vCur.si, 0) / vGain.si;
  109.             }
  110.             else
  111.             {
  112.                 dRight = aGain.si * (vRight.si - vCur.si) / vGain.si;
  113.             }
  114.         }
  115.         else
  116.         {
  117.             dRight = 0.0;
  118.         }

  119.         // return desire
  120.         return new Desire(dLeft, dRight);
  121.     }

  122.     /** {@inheritDoc} */
  123.     @Override
  124.     public final String toString()
  125.     {
  126.         return "IncentiveSpeedWithCourtesy";
  127.     }

  128. }