View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.djunits.unit.DurationUnit;
7   import org.djunits.value.vdouble.scalar.Duration;
8   import org.djunits.value.vdouble.scalar.Length;
9   import org.djunits.value.vdouble.scalar.Time;
10  import org.opentrafficsim.base.parameters.ParameterException;
11  import org.opentrafficsim.core.geometry.DirectedPoint;
12  import org.opentrafficsim.core.gtu.GtuException;
13  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
14  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan.Segment;
15  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
16  import org.opentrafficsim.core.network.NetworkException;
17  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
18  import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
19  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
20  import org.opentrafficsim.road.gtu.lane.perception.categories.DefaultSimplePerception;
21  import org.opentrafficsim.road.gtu.lane.perception.categories.DirectDefaultSimplePerception;
22  import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
23  import org.opentrafficsim.road.gtu.lane.tactical.following.AccelerationStep;
24  import org.opentrafficsim.road.gtu.lane.tactical.following.GtuFollowingModelOld;
25  
26  /**
27   * Lane-based tactical planner that implements car following behavior. This tactical planner retrieves the car following model
28   * from the strategical planner and will generate an operational plan for the GTU.
29   * <p>
30   * This lane-based tactical planner makes decisions based on headway (GTU following model). It can ask the strategic planner for
31   * assistance on the route to take when the network splits.
32   * <p>
33   * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
34   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
35   * </p>
36   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
37   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
38   */
39  public class LaneBasedGtuFollowingTacticalPlanner extends AbstractLaneBasedTacticalPlanner
40  {
41      /** */
42      private static final long serialVersionUID = 20151125L;
43  
44      /**
45       * Instantiate a tactical planner with just GTU following behavior and no lane changes.
46       * @param carFollowingModel GtuFollowingModelOld; Car-following model.
47       * @param gtu LaneBasedGtu; GTU
48       */
49      public LaneBasedGtuFollowingTacticalPlanner(final GtuFollowingModelOld carFollowingModel, final LaneBasedGtu gtu)
50      {
51          super(carFollowingModel, gtu, new CategoricalLanePerception(gtu));
52          getPerception().addPerceptionCategory(new DirectDefaultSimplePerception(getPerception()));
53      }
54  
55      /** {@inheritDoc} */
56      @Override
57      public final OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
58              throws OperationalPlanException, NetworkException, GtuException, ParameterException
59      {
60          // ask Perception for the local situation
61          LaneBasedGtu laneBasedGTU = getGtu();
62          LanePerception perception = getPerception();
63  
64          // if the GTU's maximum speed is zero (block), generate a stand still plan for one second
65          if (laneBasedGTU.getMaximumSpeed().si < OperationalPlan.DRIFTING_SPEED_SI)
66          {
67              return new OperationalPlan(getGtu(), locationAtStartTime, startTime, new Duration(1.0, DurationUnit.SECOND));
68          }
69  
70          // see how far we can drive
71          Length maxDistance = laneBasedGTU.getParameters().getParameter(LOOKAHEAD);
72          LanePathInfo lanePathInfo = buildLanePathInfo(laneBasedGTU, maxDistance);
73  
74          // look at the conditions for headway from a GTU in front
75          DefaultSimplePerception simplePerception = perception.getPerceptionCategory(DefaultSimplePerception.class);
76          Headway headwayGTU = simplePerception.getForwardHeadwayGtu();
77          AccelerationStep accelerationStepGTU = null;
78          if (headwayGTU.getDistance().ge(maxDistance))
79          {
80              // TODO I really don't like this -- if there is a lane drop at 20 m, the GTU should stop...
81              accelerationStepGTU = ((GtuFollowingModelOld) getCarFollowingModel()).computeAccelerationStepWithNoLeader(
82                      laneBasedGTU, lanePathInfo.getPath().getLength(), simplePerception.getSpeedLimit());
83          }
84          else
85          {
86              accelerationStepGTU =
87                      ((GtuFollowingModelOld) getCarFollowingModel()).computeAccelerationStep(laneBasedGTU, headwayGTU.getSpeed(),
88                              headwayGTU.getDistance(), lanePathInfo.getPath().getLength(), simplePerception.getSpeedLimit());
89          }
90  
91          // look at the conditions for headway from an object in front
92          Headway headwayObject = simplePerception.getForwardHeadwayObject();
93          AccelerationStep accelerationStepObject = null;
94          if (headwayObject.getDistance().ge(maxDistance))
95          {
96              accelerationStepObject = ((GtuFollowingModelOld) getCarFollowingModel()).computeAccelerationStepWithNoLeader(
97                      laneBasedGTU, lanePathInfo.getPath().getLength(), simplePerception.getSpeedLimit());
98          }
99          else
100         {
101             accelerationStepObject = ((GtuFollowingModelOld) getCarFollowingModel()).computeAccelerationStep(laneBasedGTU,
102                     headwayObject.getSpeed(), headwayObject.getDistance(), lanePathInfo.getPath().getLength(),
103                     simplePerception.getSpeedLimit());
104         }
105 
106         // see which one is most limiting
107         AccelerationStep accelerationStep = accelerationStepGTU.getAcceleration().lt(accelerationStepObject.getAcceleration())
108                 ? accelerationStepGTU : accelerationStepObject;
109 
110         // see if we have to continue standing still. In that case, generate a stand still plan
111         if (accelerationStep.getAcceleration().si < 1E-6 && laneBasedGTU.getSpeed().si < OperationalPlan.DRIFTING_SPEED_SI)
112         {
113             return new OperationalPlan(getGtu(), locationAtStartTime, startTime, accelerationStep.getDuration());
114         }
115 
116         List<Segment> operationalPlanSegmentList = new ArrayList<>();
117         if (accelerationStep.getAcceleration().si == 0.0)
118         {
119             Segment segment = new OperationalPlan.SpeedSegment(accelerationStep.getDuration());
120             operationalPlanSegmentList.add(segment);
121         }
122         else
123         {
124             Segment segment =
125                     new OperationalPlan.AccelerationSegment(accelerationStep.getDuration(), accelerationStep.getAcceleration());
126             operationalPlanSegmentList.add(segment);
127         }
128         OperationalPlan op = new OperationalPlan(getGtu(), lanePathInfo.getPath(), startTime, getGtu().getSpeed(),
129                 operationalPlanSegmentList);
130         return op;
131     }
132 
133     /** {@inheritDoc} */
134     @Override
135     public final String toString()
136     {
137         return "LaneBasedGtuFollowingTacticalPlanner [carFollowingModel=" + getCarFollowingModel() + "]";
138     }
139 }