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