View Javadoc
1   package org.opentrafficsim.road.gtu.lane.changing;
2   
3   import java.util.Collection;
4   import java.util.Map;
5   
6   import org.djunits.value.vdouble.scalar.DoubleScalar;
7   import org.opentrafficsim.core.gtu.RelativePosition;
8   import org.opentrafficsim.core.network.LateralDirectionality;
9   import org.opentrafficsim.core.network.NetworkException;
10  import org.opentrafficsim.road.gtu.following.AbstractGTUFollowingModel;
11  import org.opentrafficsim.road.gtu.following.DualAccelerationStep;
12  import org.opentrafficsim.road.gtu.following.GTUFollowingModel;
13  import org.opentrafficsim.road.gtu.following.HeadwayGTU;
14  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
15  import org.opentrafficsim.road.network.lane.Lane;
16  
17  /**
18   * Common code for a family of lane change models like in M. Treiber and A. Kesting <i>Traffic Flow Dynamics</i>,
19   * Springer-Verlag Berlin Heidelberg 2013, pp 239-244.
20   * <p>
21   * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
22   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
23   * <p>
24   * @version $Revision: 1401 $, $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, by $Author: averbraeck $,
25   *          initial version 4 nov. 2014 <br>
26   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
27   */
28  public abstract class AbstractLaneChangeModel implements LaneChangeModel
29  {
30      /** {@inheritDoc} */
31      @SuppressWarnings("checkstyle:parameternumber")
32      @Override
33      public final LaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGTU gtu,
34          final Collection<HeadwayGTU> sameLaneGTUs, final Collection<HeadwayGTU> preferredLaneGTUs,
35          final Collection<HeadwayGTU> nonPreferredLaneGTUs, final Speed.Abs speedLimit,
36          final Acceleration.Rel preferredLaneRouteIncentive, final Acceleration.Rel laneChangeThreshold,
37          final Acceleration.Rel nonPreferredLaneRouteIncentive) 
38      {
39          try
40          {
41              Map<Lane, Length.Rel> positions = gtu.positions(RelativePosition.REFERENCE_POSITION);
42              Lane lane = positions.keySet().iterator().next();
43              Length.Rel longitudinalPosition = positions.get(lane);
44              // TODO make this driving side dependent; i.e. implement a general way to figure out on which side of the
45              // road cars are supposed to drive
46              final LateralDirectionality preferred = LateralDirectionality.RIGHT;
47              final LateralDirectionality nonPreferred = LateralDirectionality.LEFT;
48              Lane nonPreferredLane = gtu.bestAccessibleAdjacentLane(lane, nonPreferred, longitudinalPosition);
49              Lane preferredLane = gtu.bestAccessibleAdjacentLane(lane, preferred, longitudinalPosition);
50              GTUFollowingModel gtuFollowingModel = gtu.getGTUFollowingModel();
51              if (null == gtuFollowingModel)
52              {
53                  throw new Error("GTU " + gtu + " has null GTUFollowingModel");
54              }
55              DualAccelerationStep straightAccelerationSteps =
56                  gtuFollowingModel.computeAcceleration(gtu, sameLaneGTUs, speedLimit);
57              if (straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
58              {
59                  System.out.println("Problem");
60                  gtu.getGTUFollowingModel().computeAcceleration(gtu, sameLaneGTUs, speedLimit);
61              }
62              Acceleration.Abs straightA = applyDriverPersonality(straightAccelerationSteps).plus(laneChangeThreshold);
63              DualAccelerationStep nonPreferrredAccelerationSteps =
64                  null == nonPreferredLane ? null : gtu.getGTUFollowingModel().computeAcceleration(gtu, nonPreferredLaneGTUs,
65                      speedLimit);
66              if (null != nonPreferrredAccelerationSteps
67                  && nonPreferrredAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getGTUFollowingModel()
68                      .maximumSafeDeceleration().getSI())
69              {
70                  nonPreferrredAccelerationSteps = AbstractGTUFollowingModel.TOODANGEROUS;
71              }
72              Acceleration.Abs nonPreferredA =
73                  null == nonPreferredLane ? null : applyDriverPersonality(nonPreferrredAccelerationSteps);
74              DualAccelerationStep preferredAccelerationSteps =
75                  null == preferredLane ? null : gtu.getGTUFollowingModel().computeAcceleration(gtu, preferredLaneGTUs,
76                      speedLimit);
77              if (null != preferredAccelerationSteps
78                  && preferredAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getGTUFollowingModel()
79                      .maximumSafeDeceleration().getSI())
80              {
81                  preferredAccelerationSteps = AbstractGTUFollowingModel.TOODANGEROUS;
82              }
83              Acceleration.Abs preferredA = null == preferredLane ? null : applyDriverPersonality(preferredAccelerationSteps);
84              if (null == preferredA)
85              {
86                  // Lane change to the preferred lane is not possible
87                  if (null == nonPreferredA)
88                  {
89                      // No lane change possible; this is definitely the easy case
90                      return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
91                  }
92                  else
93                  {
94                      // Merge to nonPreferredLane is possible; merge to preferredLane is NOT possible
95                      if (DoubleScalar.plus(nonPreferredA, nonPreferredLaneRouteIncentive).gt(straightA))
96                      {
97                          // Merge to the nonPreferred lane; i.e. start an overtaking procedure
98                          return new LaneMovementStep(nonPreferrredAccelerationSteps.getLeaderAccelerationStep(), nonPreferred);
99                      }
100                     else
101                     {
102                         // Stay in the current lane
103                         return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
104                     }
105                 }
106             }
107             // A merge to the preferredLane is possible
108             if (null == nonPreferredA)
109             {
110                 // Merge to preferredLane is possible; merge to nonPreferred lane is NOT possible
111                 if (DoubleScalar.plus(preferredA, preferredLaneRouteIncentive).gt(straightA))
112                 {
113                     // Merge to the preferred lane; i.e. finish (or cancel) an overtaking procedure
114                     return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
115                 }
116                 else
117                 {
118                     // Stay in current lane
119                     return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
120                 }
121             }
122             // All merges are possible
123             Acceleration.Rel preferredAttractiveness = preferredA.plus(preferredLaneRouteIncentive).minus(straightA);
124             Acceleration.Rel nonPreferredAttractiveness =
125                 nonPreferredA.plus(nonPreferredLaneRouteIncentive).minus(straightA);
126             if (preferredAttractiveness.getSI() <= 0 && nonPreferredAttractiveness.getSI() < 0)
127             {
128                 // Stay in current lane
129                 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
130 
131             }
132             if (preferredAttractiveness.getSI() > 0 && preferredAttractiveness.gt(nonPreferredAttractiveness))
133             {
134                 // Merge to the preferred lane; i.e. finish (or cancel) an overtaking procedure
135                 return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
136             }
137             // Merge to the adjacent nonPreferred lane; i.e. start an overtaking procedure
138             return new LaneMovementStep(nonPreferrredAccelerationSteps.getLeaderAccelerationStep(), nonPreferred);
139         }
140         catch (NetworkException exception)
141         {
142             exception.printStackTrace();
143         }
144         throw new Error("Cannot happen: computeLaneChangeAndAcceleration failed to decide whether or not to change lane");
145     }
146 
147     /**
148      * Return the weighted acceleration as described by the personality. This incorporates the personality of the driver to the
149      * lane change decisions.
150      * @param accelerationSteps DualAccelerationStep; the DualAccelerationStep that contains the AccelerationStep that the
151      *            reference GTU will make and the AccelerationStep that the (new) follower GTU will make
152      * @return DoubleScalar.Abs&lt;AccelerationUnit&gt;; the acceleration that the personality of the driver uses (in a
153      *         comparison to a similarly computed acceleration in the non-, or different-lane-changed state) to decide if a lane
154      *         change should be performed
155      */
156     public abstract Acceleration.Abs applyDriverPersonality(DualAccelerationStep accelerationSteps);
157 }