AbstractDirectedLaneChangeModel.java

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

  2. import java.util.Collection;

  3. import org.djunits.unit.AccelerationUnit;
  4. import org.djunits.value.vdouble.scalar.Acceleration;
  5. import org.djunits.value.vdouble.scalar.Duration;
  6. import org.djunits.value.vdouble.scalar.Length;
  7. import org.djunits.value.vdouble.scalar.Speed;
  8. import org.djunits.value.vdouble.scalar.base.DoubleScalar;
  9. import org.opentrafficsim.base.parameters.ParameterException;
  10. import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
  11. import org.opentrafficsim.base.parameters.ParameterTypes;
  12. import org.opentrafficsim.core.gtu.GtuException;
  13. import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
  14. import org.opentrafficsim.core.network.LateralDirectionality;
  15. import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
  16. import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
  17. import org.opentrafficsim.road.gtu.lane.perception.categories.DefaultSimplePerception;
  18. import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
  19. import org.opentrafficsim.road.gtu.lane.tactical.following.DualAccelerationStep;
  20. import org.opentrafficsim.road.gtu.lane.tactical.following.GtuFollowingModelOld;
  21. import org.opentrafficsim.road.network.lane.Lane;

  22. /**
  23.  * Common code for a family of lane change models like in M. Treiber and A. Kesting <i>Traffic Flow Dynamics</i>,
  24.  * Springer-Verlag Berlin Heidelberg 2013, pp 239-244.
  25.  * <p>
  26.  * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  27.  * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  28.  * </p>
  29.  * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
  30.  */
  31. public abstract class AbstractDirectedLaneChangeModel implements DirectedLaneChangeModel
  32. {
  33.     /** Attempt to overcome rounding errors. */
  34.     private static Acceleration extraThreshold = new Acceleration(0.000001, AccelerationUnit.SI);

  35.     /** Comfortable deceleration parameter type. */
  36.     protected static final ParameterTypeAcceleration B = ParameterTypes.B;

  37.     /** the perception. */
  38.     private final LanePerception perception;

  39.     /**
  40.      * Construct a DirectedLaneChangeModel.
  41.      * @param perception the perception.
  42.      */
  43.     public AbstractDirectedLaneChangeModel(final LanePerception perception)
  44.     {
  45.         this.perception = perception;
  46.     }

  47.     @Override
  48.     public final DirectedLaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGtu gtu,
  49.             final LateralDirectionality direction, final Collection<Headway> sameLaneGTUs,
  50.             final Collection<Headway> otherLaneGTUs, final Length maxDistance, final Speed speedLimit,
  51.             final Acceleration otherLaneRouteIncentive, final Acceleration laneChangeThreshold, final Duration laneChangeTime)
  52.             throws GtuException, ParameterException
  53.     {
  54.         Lane lane = gtu.getReferencePosition().lane();
  55.         Length longitudinalPosition = gtu.getReferencePosition().position();
  56.         Lane otherLane = getPerception().getPerceptionCategory(DefaultSimplePerception.class).bestAccessibleAdjacentLane(lane,
  57.                 direction, longitudinalPosition);
  58.         GtuFollowingModelOld gtuFollowingModel = (GtuFollowingModelOld) gtu.getTacticalPlanner().getCarFollowingModel();
  59.         if (null == gtuFollowingModel)
  60.         {
  61.             throw new GtuException(gtu + " has null GtuFollowingModel");
  62.         }
  63.         DualAccelerationStep thisLaneAccelerationSteps =
  64.                 gtuFollowingModel.computeDualAccelerationStep(gtu, sameLaneGTUs, maxDistance, speedLimit, laneChangeTime);
  65.         if (thisLaneAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
  66.         {
  67.             System.out.println(gtu + " has a problem: straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999");
  68.         }
  69.         Acceleration straightA = applyDriverPersonality(thisLaneAccelerationSteps).plus(laneChangeThreshold);
  70.         DualAccelerationStep otherLaneAccelerationSteps = null == otherLane ? null
  71.                 : gtuFollowingModel.computeDualAccelerationStep(gtu, otherLaneGTUs, maxDistance, speedLimit, laneChangeTime);
  72.         if (null != otherLaneAccelerationSteps
  73.                 && otherLaneAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getParameters().getParameter(B).getSI())
  74.         {
  75.             otherLane = null; // do not change to the other lane
  76.         }
  77.         Acceleration otherLaneAcceleration = (null == otherLane) ? null : applyDriverPersonality(otherLaneAccelerationSteps);
  78.         if (null == otherLaneAcceleration)
  79.         {
  80.             // No lane change possible; this is definitely the easy case
  81.             return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
  82.         }
  83.         // A merge to the other lane is possible
  84.         if (DoubleScalar.plus(otherLaneAcceleration, otherLaneRouteIncentive).plus(extraThreshold).ge(straightA))
  85.         {
  86.             // Merge to the other lane
  87.             return new DirectedLaneMovementStep(otherLaneAccelerationSteps.getLeaderAccelerationStep(), direction);
  88.         }
  89.         else
  90.         {
  91.             // Stay in current lane
  92.             return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
  93.         }
  94.     }

  95.     /**
  96.      * Return the weighted acceleration as described by the personality. This incorporates the personality of the driver to the
  97.      * lane change decisions.
  98.      * @param accelerationStep the DualAccelerationStep that contains the AccelerationStep that the reference GTU will make and
  99.      *            the AccelerationStep that the (new) follower GTU will make
  100.      * @return the acceleration that the personality of the driver uses (in a comparison to a similarly computed acceleration in
  101.      *         the non-, or different-lane-changed state) to decide if a lane change should be performed
  102.      */
  103.     public abstract Acceleration applyDriverPersonality(DualAccelerationStep accelerationStep);

  104.     @Override
  105.     public final LanePerception getPerception()
  106.     {
  107.         return this.perception;
  108.     }
  109. }