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