View Javadoc
1   package org.opentrafficsim.core.gtu.lane.changing;
2   
3   import java.rmi.RemoteException;
4   import java.util.Collection;
5   import java.util.Map;
6   
7   import org.opentrafficsim.core.gtu.RelativePosition;
8   import org.opentrafficsim.core.gtu.following.AbstractGTUFollowingModel;
9   import org.opentrafficsim.core.gtu.following.DualAccelerationStep;
10  import org.opentrafficsim.core.gtu.following.GTUFollowingModel;
11  import org.opentrafficsim.core.gtu.following.HeadwayGTU;
12  import org.opentrafficsim.core.gtu.lane.LaneBasedGTU;
13  import org.opentrafficsim.core.network.LateralDirectionality;
14  import org.opentrafficsim.core.network.NetworkException;
15  import org.opentrafficsim.core.network.lane.Lane;
16  import org.opentrafficsim.core.unit.AccelerationUnit;
17  import org.opentrafficsim.core.unit.LengthUnit;
18  import org.opentrafficsim.core.unit.SpeedUnit;
19  import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar;
20  import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar.Rel;
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-2014 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights
27   * reserved. <br>
28   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
29   * <p>
30   * @version 4 nov. 2014 <br>
31   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
32   */
33  public abstract class AbstractLaneChangeModel implements LaneChangeModel
34  {
35      /** {@inheritDoc} */
36      @SuppressWarnings("checkstyle:parameternumber")
37      @Override
38      public final LaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGTU<?> gtu,
39              final Collection<HeadwayGTU> sameLaneGTUs, final Collection<HeadwayGTU> preferredLaneGTUs,
40              final Collection<HeadwayGTU> nonPreferredLaneGTUs, final DoubleScalar.Abs<SpeedUnit> speedLimit,
41              final DoubleScalar.Rel<AccelerationUnit> preferredLaneRouteIncentive,
42              final DoubleScalar.Rel<AccelerationUnit> laneChangeThreshold,
43              final DoubleScalar.Rel<AccelerationUnit> nonPreferredLaneRouteIncentive) throws RemoteException
44      {
45          try
46          {
47              // System.out.println(String.format(
48              // "Route desire to merge to preferredLane: %s, route desire to merge to overtakingLane: %s",
49              // preferredLaneRouteIncentive, nonPreferredLaneRouteIncentive));
50              /*
51               * if (gtu.getId().toString().equals("29")) { System.out.println("LaneMovementStep for " + gtu); }
52               */
53              Map<Lane, Rel<LengthUnit>> positions = gtu.positions(RelativePosition.REFERENCE_POSITION);
54              Lane lane = positions.keySet().iterator().next();
55              DoubleScalar.Rel<LengthUnit> 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                      lane.bestAccessibleAdjacentLane(nonPreferred, longitudinalPosition, gtu.getGTUType());
62              Lane preferredLane = lane.bestAccessibleAdjacentLane(preferred, longitudinalPosition, gtu.getGTUType());
63              GTUFollowingModel gtuFollowingModel = gtu.getGTUFollowingModel();
64              if (null == gtuFollowingModel)
65              {
66                  throw new Error("GTU " + gtu + " has null GTUFollowingModel");
67              }
68              DualAccelerationStep straightAccelerationSteps =
69                      gtuFollowingModel.computeAcceleration(gtu, sameLaneGTUs, speedLimit);
70              if (straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
71              {
72                  System.out.println("Problem");
73                  gtu.getGTUFollowingModel().computeAcceleration(gtu, sameLaneGTUs, speedLimit);
74              }
75              DoubleScalar.Abs<AccelerationUnit> straightA =
76                      DoubleScalar.plus(applyDriverPersonality(straightAccelerationSteps), laneChangeThreshold)
77                              .immutable();
78              DualAccelerationStep nonPreferrredAccelerationSteps =
79                      null == nonPreferredLane ? null : gtu.getGTUFollowingModel().computeAcceleration(gtu,
80                              nonPreferredLaneGTUs, speedLimit);
81              if (null != nonPreferrredAccelerationSteps
82                      && nonPreferrredAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getGTUFollowingModel()
83                              .maximumSafeDeceleration().getSI())
84              {
85                  nonPreferrredAccelerationSteps = AbstractGTUFollowingModel.TOODANGEROUS;
86              }
87              DoubleScalar.Abs<AccelerationUnit> nonPreferredA =
88                      null == nonPreferredLane ? null : applyDriverPersonality(nonPreferrredAccelerationSteps);
89              DualAccelerationStep preferredAccelerationSteps =
90                      null == preferredLane ? null : gtu.getGTUFollowingModel().computeAcceleration(gtu,
91                              preferredLaneGTUs, speedLimit);
92              if (null != preferredAccelerationSteps
93                      && preferredAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getGTUFollowingModel()
94                              .maximumSafeDeceleration().getSI())
95              {
96                  preferredAccelerationSteps = AbstractGTUFollowingModel.TOODANGEROUS;
97              }
98              DoubleScalar.Abs<AccelerationUnit> preferredA =
99                      null == preferredLane ? null : applyDriverPersonality(preferredAccelerationSteps);
100             if (null == preferredA)
101             {
102                 // Lane change to the preferred lane is not possible
103                 if (null == nonPreferredA)
104                 {
105                     // No lane change possible; this is definitely the easy case
106                     return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
107                 }
108                 else
109                 {
110                     // Merge to nonPreferredLane is possible; merge to preferredLane is NOT possible
111                     if (DoubleScalar.plus(nonPreferredA, nonPreferredLaneRouteIncentive).getSI() > straightA.getSI())
112                     {
113                         // Merge to the nonPreferred lane; i.e. start an overtaking procedure
114                         return new LaneMovementStep(nonPreferrredAccelerationSteps.getLeaderAccelerationStep(),
115                                 nonPreferred);
116                     }
117                     else
118                     {
119                         // Stay in the current lane
120                         return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
121                     }
122                 }
123             }
124             // A merge to the preferredLane is possible
125             if (null == nonPreferredA)
126             {
127                 // Merge to preferredLane is possible; merge to nonPreferred lane is NOT possible
128                 if (DoubleScalar.plus(preferredA, preferredLaneRouteIncentive).getSI() > straightA.getSI())
129                 {
130                     // Merge to the preferred lane; i.e. finish (or cancel) an overtaking procedure
131                     return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
132                 }
133                 else
134                 {
135                     // Stay in current lane
136                     return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
137                 }
138             }
139             // All merges are possible
140             DoubleScalar.Rel<AccelerationUnit> preferredAttractiveness =
141                     DoubleScalar.minus(DoubleScalar.plus(preferredA, preferredLaneRouteIncentive).immutable(),
142                             straightA).immutable();
143             DoubleScalar.Rel<AccelerationUnit> nonPreferredAttractiveness =
144                     DoubleScalar.minus(DoubleScalar.plus(nonPreferredA, nonPreferredLaneRouteIncentive).immutable(),
145                             straightA).immutable();
146             if (preferredAttractiveness.getSI() <= 0 && nonPreferredAttractiveness.getSI() < 0)
147             {
148                 // Stay in current lane
149                 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
150 
151             }
152             if (preferredAttractiveness.getSI() > 0
153                     && preferredAttractiveness.getSI() > nonPreferredAttractiveness.getSI())
154             {
155                 // Merge to the preferred lane; i.e. finish (or cancel) an overtaking procedure
156                 return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
157             }
158             // Merge to the adjacent nonPreferred lane; i.e. start an overtaking procedure
159             return new LaneMovementStep(nonPreferrredAccelerationSteps.getLeaderAccelerationStep(), nonPreferred);
160         }
161         catch (NetworkException exception)
162         {
163             exception.printStackTrace();
164         }
165         throw new Error(
166                 "Cannot happen: computeLaneChangeAndAcceleration failed to decide whether or not to change lane");
167     }
168 
169     /**
170      * Return the weighted acceleration as described by the personality. This incorporates the personality of the driver
171      * to the lane change decisions.
172      * @param accelerationSteps DualAccelerationStep; the DualAccelerationStep that contains the AccelerationStep that
173      *            the reference GTU will make and the AccelerationStep that the (new) follower GTU will make
174      * @return DoubleScalar.Abs&lt;AccelerationUnit&gt;; the acceleration that the personality of the driver uses (in a
175      *         comparison to a similarly computed acceleration in the non-, or different-lane-changed state) to decide
176      *         if a lane change should be performed
177      */
178     public abstract DoubleScalar.Abs<AccelerationUnit> applyDriverPersonality(DualAccelerationStep accelerationSteps);
179 }