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