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