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-2024 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://github.com/wjschakel">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          /** {@inheritDoc} */
49          @Override
50          public String toString()
51          {
52              return "NONE";
53          }
54      };
55  
56      /** No tailgating, but social pressure exists. */
57      Tailgating RHO_ONLY = new Tailgating()
58      {
59          /** {@inheritDoc} */
60          @Override
61          public void tailgate(final LanePerception perception, final Parameters parameters)
62          {
63              PerceptionCollectable<HeadwayGtu, LaneBasedGtu> leaders =
64                      perception.getPerceptionCategoryOrNull(NeighborsPerception.class).getLeaders(RelativeLane.CURRENT);
65              if (leaders == null || leaders.isEmpty())
66              {
67                  return;
68              }
69              try
70              {
71                  Speed speed = perception.getPerceptionCategoryOrNull(EgoPerception.class).getSpeed();
72                  Speed vCong = parameters.getParameter(ParameterTypes.VCONG);
73                  Length x0 = parameters.getParameter(ParameterTypes.LOOKAHEAD);
74                  Speed vGain = parameters.getParameter(LmrsParameters.VGAIN);
75                  HeadwayGtu leader = leaders.first();
76                  Speed desiredSpeed = Try.assign(() -> perception.getGtu().getDesiredSpeed(), "Could not obtain the GTU.");
77                  double rho = socialPressure(speed, vCong, desiredSpeed, leader.getSpeed(), vGain, leader.getDistance(), x0);
78                  parameters.setParameter(RHO, rho);
79              }
80              catch (ParameterException exception)
81              {
82                  throw new RuntimeException("Could not obtain or set parameter value.", exception);
83              }
84          }
85          
86          /** {@inheritDoc} */
87          @Override
88          public String toString()
89          {
90              return "RHO_ONLY";
91          }
92      };
93  
94      /** Tailgating based on speed pressure. */
95      Tailgating PRESSURE = new Tailgating()
96      {
97          /** {@inheritDoc} */
98          @Override
99          public void tailgate(final LanePerception perception, final Parameters parameters)
100         {
101             PerceptionCollectable<HeadwayGtu, LaneBasedGtu> leaders =
102                     perception.getPerceptionCategoryOrNull(NeighborsPerception.class).getLeaders(RelativeLane.CURRENT);
103             if (leaders == null || leaders.isEmpty())
104             {
105                 return;
106             }
107             try
108             {
109                 Speed speed = perception.getPerceptionCategoryOrNull(EgoPerception.class).getSpeed();
110                 Speed vCong = parameters.getParameter(ParameterTypes.VCONG);
111                 Duration t = parameters.getParameter(ParameterTypes.T);
112                 Duration tMin = parameters.getParameter(ParameterTypes.TMIN);
113                 Duration tMax = parameters.getParameter(ParameterTypes.TMAX);
114                 Length x0 = parameters.getParameter(ParameterTypes.LOOKAHEAD);
115                 Speed vGain = parameters.getParameter(LmrsParameters.VGAIN);
116                 HeadwayGtu leader = leaders.first();
117                 Speed desiredSpeed = Try.assign(() -> perception.getGtu().getDesiredSpeed(), "Could not obtain the GTU.");
118                 double rho = socialPressure(speed, vCong, desiredSpeed, leader.getSpeed(), vGain, leader.getDistance(), x0);
119                 parameters.setParameter(RHO, rho);
120                 double tNew = rho * tMin.si + (1.0 - rho) * tMax.si;
121                 if (tNew < t.si)
122                 {
123                     parameters.setParameter(ParameterTypes.T, Duration.instantiateSI(tNew));
124                 }
125             }
126             catch (ParameterException exception)
127             {
128                 throw new RuntimeException("Could not obtain or set parameter value.", exception);
129             }
130         }
131         
132         /** {@inheritDoc} */
133         @Override
134         public String toString()
135         {
136             return "PRESSURE";
137         }
138     };
139 
140     /**
141      * Returns a normalized social pressure, equal to (vDesired - vLead) / vGain.
142      * @param speed Speed; speed
143      * @param vCong Speed; speed indicating congestion
144      * @param desiredSpeed Speed; desired speed
145      * @param leaderSpeed Speed; leader speed
146      * @param vGain Speed; vGain parameter
147      * @param headway Length; headway to the leader
148      * @param x0 Length; anticipation distance
149      * @return normalized social pressure
150      */
151     static double socialPressure(final Speed speed, final Speed vCong, final Speed desiredSpeed, final Speed leaderSpeed,
152             final Speed vGain, final Length headway, final Length x0)
153     {
154         double dv = desiredSpeed.si - leaderSpeed.si;
155         if (dv < 0 || headway.gt(x0)) // larger headway may happen due to perception errors
156         {
157             return 0.0;
158         }
159         return 1.0 - Math.exp(-(dv / vGain.si) * (1.0 - (headway.si / x0.si)));
160     }
161 
162     /**
163      * Apply tailgating.
164      * @param perception LanePerception; perception
165      * @param parameters Parameters; parameters
166      */
167     void tailgate(LanePerception perception, Parameters parameters);
168 
169 }