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