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.Length;
10  import org.djunits.value.vdouble.scalar.Speed;
11  import org.djunits.value.vdouble.scalar.Time;
12  import org.opentrafficsim.core.gtu.GTUException;
13  import org.opentrafficsim.core.gtu.RelativePosition;
14  import org.opentrafficsim.core.network.LateralDirectionality;
15  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
16  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractGTUFollowingModelMobil;
17  import org.opentrafficsim.road.gtu.lane.tactical.following.DualAccelerationStep;
18  import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
19  import org.opentrafficsim.road.gtu.lane.tactical.following.HeadwayGTU;
20  import org.opentrafficsim.road.network.lane.Lane;
21  
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-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
27   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
28   * <p>
29   * @version $Revision: 1401 $, $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, by $Author: averbraeck $,
30   *          initial version 4 nov. 2014 <br>
31   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
32   */
33  public abstract class AbstractDirectedLaneChangeModel implements DirectedLaneChangeModel
34  {
35      /** Attempt to overcome rounding errors. */
36      private static Acceleration extraThreshold = new Acceleration(0.000001, AccelerationUnit.SI);
37  
38      /** {@inheritDoc} */
39      @Override
40      public final DirectedLaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGTU gtu,
41              final LateralDirectionality direction, final Collection<HeadwayGTU> sameLaneGTUs,
42              final Collection<HeadwayGTU> otherLaneGTUs, final Length.Rel maxDistance, final Speed speedLimit,
43              final Acceleration otherLaneRouteIncentive, final Acceleration laneChangeThreshold, final Time.Rel laneChangeTime)
44              throws GTUException
45      {
46          Map<Lane, Length.Rel> positions = gtu.positions(RelativePosition.REFERENCE_POSITION);
47          Lane lane = positions.keySet().iterator().next();
48          Length.Rel longitudinalPosition = positions.get(lane);
49          Lane otherLane = gtu.getPerception().bestAccessibleAdjacentLane(lane, direction, longitudinalPosition);
50          GTUFollowingModelOld gtuFollowingModel = gtu.getBehavioralCharacteristics().getGTUFollowingModel();
51          if (null == gtuFollowingModel)
52          {
53              throw new Error(gtu + " has null GTUFollowingModel");
54          }
55          DualAccelerationStep thisLaneAccelerationSteps =
56                  gtuFollowingModel.computeDualAccelerationStep(gtu, sameLaneGTUs, maxDistance, speedLimit, laneChangeTime);
57          if (thisLaneAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
58          {
59              System.out.println(gtu + " has a problem: straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999");
60          }
61          Acceleration straightA = applyDriverPersonality(thisLaneAccelerationSteps).plus(laneChangeThreshold);
62          DualAccelerationStep otherLaneAccelerationSteps =
63                  null == otherLane ? null : gtuFollowingModel.computeDualAccelerationStep(gtu, otherLaneGTUs, maxDistance,
64                          speedLimit, laneChangeTime);
65          if (null != otherLaneAccelerationSteps
66                  && otherLaneAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getBehavioralCharacteristics()
67                          .getGTUFollowingModel().getMaximumSafeDeceleration().getSI())
68          {
69              otherLaneAccelerationSteps = AbstractGTUFollowingModelMobil.TOODANGEROUS;
70          }
71          Acceleration otherLaneAcceleration = null == otherLane ? null : applyDriverPersonality(otherLaneAccelerationSteps);
72          if (null == otherLaneAcceleration)
73          {
74              // No lane change possible; this is definitely the easy case
75              return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
76          }
77          // A merge to the other lane is possible
78          if (DoubleScalar.plus(otherLaneAcceleration, otherLaneRouteIncentive).plus(extraThreshold).ge(straightA))
79          {
80              // Merge to the other lane
81              return new DirectedLaneMovementStep(otherLaneAccelerationSteps.getLeaderAccelerationStep(), direction);
82          }
83          else
84          {
85              // Stay in current lane
86              return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
87          }
88      }
89  
90      /**
91       * Return the weighted acceleration as described by the personality. This incorporates the personality of the driver to the
92       * lane change decisions.
93       * @param accelerationStep DualAccelerationStep; the DualAccelerationStep that contains the AccelerationStep that the
94       *            reference GTU will make and the AccelerationStep that the (new) follower GTU will make
95       * @return Acceleration; the acceleration that the personality of the driver uses (in a comparison to a similarly computed
96       *         acceleration in the non-, or different-lane-changed state) to decide if a lane change should be performed
97       */
98      public abstract Acceleration applyDriverPersonality(DualAccelerationStep accelerationStep);
99  }