1   package org.opentrafficsim.road.gtu.lane.tactical.directedlanechange;
2   
3   import java.util.Collection;
4   
5   import org.djunits.unit.AccelerationUnit;
6   import org.djunits.value.vdouble.scalar.Acceleration;
7   import org.djunits.value.vdouble.scalar.DoubleScalar;
8   import org.djunits.value.vdouble.scalar.Duration;
9   import org.djunits.value.vdouble.scalar.Length;
10  import org.djunits.value.vdouble.scalar.Speed;
11  import org.opentrafficsim.base.parameters.ParameterException;
12  import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
13  import org.opentrafficsim.base.parameters.ParameterTypes;
14  import org.opentrafficsim.core.gtu.GTUException;
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.following.DualAccelerationStep;
22  import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
23  import org.opentrafficsim.road.network.lane.Lane;
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  public abstract class AbstractDirectedLaneChangeModel implements DirectedLaneChangeModel
37  {
38      
39      private static Acceleration extraThreshold = new Acceleration(0.000001, AccelerationUnit.SI);
40  
41      
42      protected static final ParameterTypeAcceleration B = ParameterTypes.B;
43  
44      
45      private final LanePerception perception;
46  
47      
48  
49  
50  
51      public AbstractDirectedLaneChangeModel(final LanePerception perception)
52      {
53          this.perception = perception;
54      }
55  
56      
57      @Override
58      public final DirectedLaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGTU gtu,
59              final LateralDirectionality direction, final Collection<Headway> sameLaneGTUs,
60              final Collection<Headway> otherLaneGTUs, final Length maxDistance, final Speed speedLimit,
61              final Acceleration otherLaneRouteIncentive, final Acceleration laneChangeThreshold, final Duration laneChangeTime)
62              throws GTUException, ParameterException, OperationalPlanException
63      {
64          Lane lane = gtu.getReferencePosition().getLane();
65          Length longitudinalPosition = gtu.getReferencePosition().getPosition();
66          Lane otherLane = getPerception().getPerceptionCategory(DefaultSimplePerception.class).bestAccessibleAdjacentLane(lane,
67                  direction, longitudinalPosition);
68          GTUFollowingModelOld gtuFollowingModel = (GTUFollowingModelOld) gtu.getTacticalPlanner().getCarFollowingModel();
69          if (null == gtuFollowingModel)
70          {
71              throw new GTUException(gtu + " has null GTUFollowingModel");
72          }
73          DualAccelerationStep thisLaneAccelerationSteps =
74                  gtuFollowingModel.computeDualAccelerationStep(gtu, sameLaneGTUs, maxDistance, speedLimit, laneChangeTime);
75          if (thisLaneAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
76          {
77              System.out.println(gtu + " has a problem: straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999");
78          }
79          Acceleration straightA = applyDriverPersonality(thisLaneAccelerationSteps).plus(laneChangeThreshold);
80          DualAccelerationStep otherLaneAccelerationSteps = null == otherLane ? null
81                  : gtuFollowingModel.computeDualAccelerationStep(gtu, otherLaneGTUs, maxDistance, speedLimit, laneChangeTime);
82          if (null != otherLaneAccelerationSteps
83                  && otherLaneAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getParameters().getParameter(B).getSI())
84          {
85              otherLane = null; 
86          }
87          Acceleration otherLaneAcceleration = (null == otherLane) ? null : applyDriverPersonality(otherLaneAccelerationSteps);
88          if (null == otherLaneAcceleration)
89          {
90              
91              return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
92          }
93          
94          if (DoubleScalar.plus(otherLaneAcceleration, otherLaneRouteIncentive).plus(extraThreshold).ge(straightA))
95          {
96              
97              return new DirectedLaneMovementStep(otherLaneAccelerationSteps.getLeaderAccelerationStep(), direction);
98          }
99          else
100         {
101             
102             return new DirectedLaneMovementStep(thisLaneAccelerationSteps.getLeaderAccelerationStep(), null);
103         }
104     }
105 
106     
107 
108 
109 
110 
111 
112 
113 
114     public abstract Acceleration applyDriverPersonality(DualAccelerationStep accelerationStep);
115 
116     
117     @Override
118     public final LanePerception getPerception()
119     {
120         return this.perception;
121     }
122 }