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