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