View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.directedlanechange;
2   
3   import java.util.Collection;
4   
5   import org.djunits.unit.AccelerationUnit;
6   import org.djunits.value.vdouble.scalar.Acceleration;
7   import org.djunits.value.vdouble.scalar.Duration;
8   import org.djunits.value.vdouble.scalar.Length;
9   import org.djunits.value.vdouble.scalar.Speed;
10  import org.djunits.value.vdouble.scalar.base.DoubleScalar;
11  import org.opentrafficsim.base.parameters.ParameterException;
12  import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
13  import org.opentrafficsim.base.parameters.ParameterTypes;
14  import org.opentrafficsim.core.gtu.GtuException;
15  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
16  import org.opentrafficsim.core.network.LateralDirectionality;
17  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
18  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
19  import org.opentrafficsim.road.gtu.lane.perception.categories.DefaultSimplePerception;
20  import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
21  import org.opentrafficsim.road.gtu.lane.tactical.following.DualAccelerationStep;
22  import org.opentrafficsim.road.gtu.lane.tactical.following.GtuFollowingModelOld;
23  import org.opentrafficsim.road.network.lane.Lane;
24  
25  /**
26   * Common code for a family of lane change models like in M. Treiber and A. Kesting <i>Traffic Flow Dynamics</i>,
27   * Springer-Verlag Berlin Heidelberg 2013, pp 239-244.
28   * <p>
29   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
30   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
31   * </p>
32   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
33   */
34  public abstract class AbstractDirectedLaneChangeModel implements DirectedLaneChangeModel
35  {
36      /** Attempt to overcome rounding errors. */
37      private static Acceleration extraThreshold = new Acceleration(0.000001, AccelerationUnit.SI);
38  
39      /** Comfortable deceleration parameter type. */
40      protected static final ParameterTypeAcceleration B = ParameterTypes.B;
41  
42      /** the perception. */
43      private final LanePerception perception;
44  
45      /**
46       * Construct a DirectedLaneChangeModel.
47       * @param perception the perception.
48       */
49      public AbstractDirectedLaneChangeModel(final LanePerception perception)
50      {
51          this.perception = perception;
52      }
53  
54      @Override
55      public final DirectedLaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGtu gtu,
56              final LateralDirectionality direction, final Collection<Headway> sameLaneGTUs,
57              final Collection<Headway> otherLaneGTUs, final Length maxDistance, final Speed speedLimit,
58              final Acceleration otherLaneRouteIncentive, final Acceleration laneChangeThreshold, final Duration laneChangeTime)
59              throws GtuException, ParameterException
60      {
61          Lane lane = gtu.getReferencePosition().lane();
62          Length longitudinalPosition = gtu.getReferencePosition().position();
63          Lane otherLane = getPerception().getPerceptionCategory(DefaultSimplePerception.class).bestAccessibleAdjacentLane(lane,
64                  direction, longitudinalPosition);
65          GtuFollowingModelOld gtuFollowingModel = (GtuFollowingModelOld) gtu.getTacticalPlanner().getCarFollowingModel();
66          if (null == gtuFollowingModel)
67          {
68              throw new GtuException(gtu + " has null GtuFollowingModel");
69          }
70          DualAccelerationStep thisLaneAccelerationSteps =
71                  gtuFollowingModel.computeDualAccelerationStep(gtu, sameLaneGTUs, maxDistance, speedLimit, laneChangeTime);
72          if (thisLaneAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
73          {
74              System.out.println(gtu + " has a problem: straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999");
75          }
76          Acceleration straightA = applyDriverPersonality(thisLaneAccelerationSteps).plus(laneChangeThreshold);
77          DualAccelerationStep otherLaneAccelerationSteps = null == otherLane ? null
78                  : gtuFollowingModel.computeDualAccelerationStep(gtu, otherLaneGTUs, maxDistance, speedLimit, laneChangeTime);
79          if (null != otherLaneAccelerationSteps
80                  && otherLaneAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getParameters().getParameter(B).getSI())
81          {
82              otherLane = null; // do not change to the other lane
83          }
84          Acceleration otherLaneAcceleration = (null == otherLane) ? null : applyDriverPersonality(otherLaneAccelerationSteps);
85          if (null == otherLaneAcceleration)
86          {
87              // No lane change possible; this is definitely the easy case
88              return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
89          }
90          // A merge to the other lane is possible
91          if (DoubleScalar.plus(otherLaneAcceleration, otherLaneRouteIncentive).plus(extraThreshold).ge(straightA))
92          {
93              // Merge to the other lane
94              return new DirectedLaneMovementStep(otherLaneAccelerationSteps.getLeaderAccelerationStep(), direction);
95          }
96          else
97          {
98              // Stay in current lane
99              return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
100         }
101     }
102 
103     /**
104      * Return the weighted acceleration as described by the personality. This incorporates the personality of the driver to the
105      * lane change decisions.
106      * @param accelerationStep the DualAccelerationStep that contains the AccelerationStep that the reference GTU will make and
107      *            the AccelerationStep that the (new) follower GTU will make
108      * @return the acceleration that the personality of the driver uses (in a comparison to a similarly computed acceleration in
109      *         the non-, or different-lane-changed state) to decide if a lane change should be performed
110      */
111     public abstract Acceleration applyDriverPersonality(DualAccelerationStep accelerationStep);
112 
113     @Override
114     public final LanePerception getPerception()
115     {
116         return this.perception;
117     }
118 }