View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.util.lmrs;
2   
3   import static org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating.socialPressure;
4   
5   import org.djunits.value.vdouble.scalar.Duration;
6   import org.djunits.value.vdouble.scalar.Length;
7   import org.djunits.value.vdouble.scalar.Speed;
8   import org.djutils.exceptions.Try;
9   import org.opentrafficsim.base.parameters.ParameterException;
10  import org.opentrafficsim.base.parameters.ParameterTypeDouble;
11  import org.opentrafficsim.base.parameters.ParameterTypes;
12  import org.opentrafficsim.base.parameters.Parameters;
13  import org.opentrafficsim.base.parameters.constraint.ConstraintInterface;
14  import org.opentrafficsim.core.gtu.perception.EgoPerception;
15  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
16  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
17  import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
18  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
19  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
20  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGtu;
21  
22  /**
23   * Interface for LMRS tailgating behavior.
24   * <p>
25   * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
26   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
27   * </p>
28   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
29   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
30   * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
31   */
32  public interface Tailgating
33  {
34  
35      /** Social pressure applied to the leader. */
36      ParameterTypeDouble RHO = new ParameterTypeDouble("rho", "Social pressure", 0.0, ConstraintInterface.UNITINTERVAL);
37  
38      /** No tailgating. */
39      Tailgating NONE = new Tailgating()
40      {
41          /** {@inheritDoc} */
42          @Override
43          public void tailgate(final LanePerception perception, final Parameters parameters)
44          {
45              //
46          }
47      };
48  
49      /** No tailgating, but social pressure exists. */
50      Tailgating RHO_ONLY = new Tailgating()
51      {
52          /** {@inheritDoc} */
53          @Override
54          public void tailgate(final LanePerception perception, final Parameters parameters)
55          {
56              PerceptionCollectable<HeadwayGtu, LaneBasedGtu> leaders =
57                      perception.getPerceptionCategoryOrNull(NeighborsPerception.class).getLeaders(RelativeLane.CURRENT);
58              if (leaders == null || leaders.isEmpty())
59              {
60                  return;
61              }
62              try
63              {
64                  Speed speed = perception.getPerceptionCategoryOrNull(EgoPerception.class).getSpeed();
65                  Speed vCong = parameters.getParameter(ParameterTypes.VCONG);
66                  Length x0 = parameters.getParameter(ParameterTypes.LOOKAHEAD);
67                  Speed vGain = parameters.getParameter(LmrsParameters.VGAIN);
68                  HeadwayGtu leader = leaders.first();
69                  Speed desiredSpeed = Try.assign(() -> perception.getGtu().getDesiredSpeed(), "Could not obtain the GTU.");
70                  double rho = socialPressure(speed, vCong, desiredSpeed, leader.getSpeed(), vGain, leader.getDistance(), x0);
71                  parameters.setParameter(RHO, rho);
72              }
73              catch (ParameterException exception)
74              {
75                  throw new RuntimeException("Could not obtain or set parameter value.", exception);
76              }
77          }
78      };
79  
80      /** Tailgating based on speed pressure. */
81      Tailgating PRESSURE = new Tailgating()
82      {
83          /** {@inheritDoc} */
84          @Override
85          public void tailgate(final LanePerception perception, final Parameters parameters)
86          {
87              PerceptionCollectable<HeadwayGtu, LaneBasedGtu> leaders =
88                      perception.getPerceptionCategoryOrNull(NeighborsPerception.class).getLeaders(RelativeLane.CURRENT);
89              if (leaders == null || leaders.isEmpty())
90              {
91                  return;
92              }
93              try
94              {
95                  Speed speed = perception.getPerceptionCategoryOrNull(EgoPerception.class).getSpeed();
96                  Speed vCong = parameters.getParameter(ParameterTypes.VCONG);
97                  Duration t = parameters.getParameter(ParameterTypes.T);
98                  Duration tMin = parameters.getParameter(ParameterTypes.TMIN);
99                  Duration tMax = parameters.getParameter(ParameterTypes.TMAX);
100                 Length x0 = parameters.getParameter(ParameterTypes.LOOKAHEAD);
101                 Speed vGain = parameters.getParameter(LmrsParameters.VGAIN);
102                 HeadwayGtu leader = leaders.first();
103                 Speed desiredSpeed = Try.assign(() -> perception.getGtu().getDesiredSpeed(), "Could not obtain the GTU.");
104                 double rho = socialPressure(speed, vCong, desiredSpeed, leader.getSpeed(), vGain, leader.getDistance(), x0);
105                 parameters.setParameter(RHO, rho);
106                 double tNew = rho * tMin.si + (1.0 - rho) * tMax.si;
107                 if (tNew < t.si)
108                 {
109                     parameters.setParameter(ParameterTypes.T, Duration.instantiateSI(tNew));
110                 }
111             }
112             catch (ParameterException exception)
113             {
114                 throw new RuntimeException("Could not obtain or set parameter value.", exception);
115             }
116         }
117     };
118 
119     /**
120      * Returns a normalized social pressure, equal to (vDesired - vLead) / vGain.
121      * @param speed Speed; speed
122      * @param vCong Speed; speed indicating congestion
123      * @param desiredSpeed Speed; desired speed
124      * @param leaderSpeed Speed; leader speed
125      * @param vGain Speed; vGain parameter
126      * @param headway Length; headway to the leader
127      * @param x0 Length; anticipation distance
128      * @return normalized social pressure
129      */
130     static double socialPressure(final Speed speed, final Speed vCong, final Speed desiredSpeed, final Speed leaderSpeed,
131             final Speed vGain, final Length headway, final Length x0)
132     {
133         double dv = desiredSpeed.si - leaderSpeed.si;
134         if (dv < 0 || headway.gt(x0)) // larger headway may happen due to perception errors
135         {
136             return 0.0;
137         }
138         return 1.0 - Math.exp(-(dv / vGain.si) * (1.0 - (headway.si / x0.si)));
139     }
140 
141     /**
142      * Apply tailgating.
143      * @param perception LanePerception; perception
144      * @param parameters Parameters; parameters
145      */
146     void tailgate(LanePerception perception, Parameters parameters);
147 
148 }