View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.util.lmrs;
2   
3   import org.djunits.unit.AccelerationUnit;
4   import org.djunits.value.vdouble.scalar.Acceleration;
5   import org.djunits.value.vdouble.scalar.Speed;
6   import org.opentrafficsim.base.parameters.ParameterException;
7   import org.opentrafficsim.base.parameters.ParameterTypes;
8   import org.opentrafficsim.base.parameters.Parameters;
9   import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
10  import org.opentrafficsim.core.network.LateralDirectionality;
11  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
12  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
13  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGtu;
14  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
15  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
16  
17  /**
18   * Interface for LMRS gap-acceptance models.
19   * <p>
20   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
21   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
22   * </p>
23   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
24   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
25   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
26   */
27  public interface GapAcceptance
28  {
29  
30      /** Being informed of the model and parameters of other drivers (default LMRS). */
31      GapAcceptance INFORMED = new GapAcceptance()
32      {
33          /** {@inheritDoc} */
34          @Override
35          public boolean acceptGap(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
36                  final CarFollowingModel cfm, final double desire, final Speed ownSpeed, final Acceleration ownAcceleration,
37                  final LateralDirectionality lat) throws ParameterException, OperationalPlanException
38          {
39              NeighborsPerception neighbors = perception.getPerceptionCategory(NeighborsPerception.class);
40              if (neighbors.isGtuAlongside(lat))
41              {
42                  // gtu alongside
43                  return false;
44              }
45  
46              // TODO
47              /*-
48               * Followers and are accepted if the acceleration and speed is 0, a leader is accepted if the ego speed is 0. This 
49               * is in place as vehicles that provide courtesy, will decelerate for us and overshoot the stand-still distance. As
50               * a consequence, they will cease cooperation as they are too close. A pattern will arise where followers slow down
51               * to (near) stand-still, and accelerate again, before we could ever accept the gap.
52               * 
53               * By accepting the gap in the moment that they reach stand-still, this vehicle can at least accept the gap at some 
54               * point. All of this is only a problem if the own vehicle is standing still. Otherwise the stand-still distance is 
55               * not important and movement of our own will create an acceptable situation.
56               * 
57               * What needs to be done, is to find a better way to deal with the cooperation and gap-acceptance, such that this  
58               * hack is not required.
59               */
60  
61              Acceleration b = params.getParameter(ParameterTypes.B);
62              Acceleration aFollow = new Acceleration(Double.POSITIVE_INFINITY, AccelerationUnit.SI);
63              for (HeadwayGtu follower : neighbors.getFirstFollowers(lat))
64              {
65                  if (follower.getSpeed().gt0() || follower.getAcceleration().gt0() || follower.getDistance().si < 1.0)
66                  {
67                      Acceleration a = LmrsUtil.singleAcceleration(follower.getDistance(), follower.getSpeed(), ownSpeed, desire,
68                              follower.getParameters(), follower.getSpeedLimitInfo(), follower.getCarFollowingModel());
69                      aFollow = Acceleration.min(aFollow, a);
70                  }
71              }
72  
73              Acceleration aSelf = egoAcceleration(perception, params, sli, cfm, desire, ownSpeed, lat);
74              Acceleration threshold = b.times(-desire);
75              return aFollow.ge(threshold) && aSelf.ge(threshold) && ownAcceleration.ge(threshold);
76          }
77  
78          /** {@inheritDoc} */
79          @Override
80          public String toString()
81          {
82              return "INFORMED";
83          }
84      };
85  
86      /** Being informed of the model and parameters of other drivers, but applying own headway value. */
87      GapAcceptance EGO_HEADWAY = new GapAcceptance()
88      {
89          /** {@inheritDoc} */
90          @Override
91          public boolean acceptGap(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
92                  final CarFollowingModel cfm, final double desire, final Speed ownSpeed, final Acceleration ownAcceleration,
93                  final LateralDirectionality lat) throws ParameterException, OperationalPlanException
94          {
95              NeighborsPerception neigbors = perception.getPerceptionCategory(NeighborsPerception.class);
96              if (neigbors.isGtuAlongside(lat))
97              {
98                  // gtu alongside
99                  return false;
100             }
101 
102             Acceleration b = params.getParameter(ParameterTypes.B);
103             Acceleration aFollow = new Acceleration(Double.POSITIVE_INFINITY, AccelerationUnit.SI);
104             for (HeadwayGtu follower : neigbors.getFirstFollowers(lat))
105             {
106                 if (follower.getSpeed().gt0() || follower.getAcceleration().gt0())
107                 {
108                     // Change headway parameter
109                     Parameters folParams = follower.getParameters();
110                     folParams.setParameterResettable(ParameterTypes.TMIN, params.getParameter(ParameterTypes.TMIN));
111                     folParams.setParameterResettable(ParameterTypes.TMAX, params.getParameter(ParameterTypes.TMAX));
112                     Acceleration a = LmrsUtil.singleAcceleration(follower.getDistance(), follower.getSpeed(), ownSpeed, desire,
113                             folParams, follower.getSpeedLimitInfo(), follower.getCarFollowingModel());
114                     aFollow = Acceleration.min(aFollow, a);
115                     folParams.resetParameter(ParameterTypes.TMIN);
116                     folParams.resetParameter(ParameterTypes.TMAX);
117                 }
118             }
119 
120             Acceleration aSelf = egoAcceleration(perception, params, sli, cfm, desire, ownSpeed, lat);
121             Acceleration threshold = b.times(-desire);
122             return aFollow.ge(threshold) && aSelf.ge(threshold);
123         }
124 
125         /** {@inheritDoc} */
126         @Override
127         public String toString()
128         {
129             return "EGO_HEADWAY";
130         }
131     };
132 
133     /**
134      * Determine whether a gap is acceptable.
135      * @param perception LanePerception; perception
136      * @param params Parameters; parameters
137      * @param sli SpeedLimitInfo; speed limit info
138      * @param cfm CarFollowingModel; car-following model
139      * @param desire double; level of lane change desire
140      * @param ownSpeed Speed; own speed
141      * @param lat LateralDirectionality; lateral direction for synchronization
142      * @return whether a gap is acceptable
143      * @throws ParameterException if a parameter is not defined
144      * @throws OperationalPlanException perception exception
145      */
146     static Acceleration egoAcceleration(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
147             final CarFollowingModel cfm, final double desire, final Speed ownSpeed, final LateralDirectionality lat)
148             throws ParameterException, OperationalPlanException
149     {
150         Acceleration aSelf = new Acceleration(Double.POSITIVE_INFINITY, AccelerationUnit.SI);
151         if (ownSpeed.gt0())
152         {
153             for (
154 
155             HeadwayGtu leader : perception.getPerceptionCategory(NeighborsPerception.class).getFirstLeaders(lat))
156             {
157                 Acceleration a = LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(), desire, params,
158                         sli, cfm);
159                 aSelf = Acceleration.min(aSelf, a);
160             }
161         }
162         return aSelf;
163     }
164 
165     /**
166      * Determine whether a gap is acceptable.
167      * @param perception LanePerception; perception
168      * @param params Parameters; parameters
169      * @param sli SpeedLimitInfo; speed limit info
170      * @param cfm CarFollowingModel; car-following model
171      * @param desire double; level of lane change desire
172      * @param ownSpeed Speed; own speed
173      * @param ownAcceleration Acceleration; current car-following acceleration
174      * @param lat LateralDirectionality; lateral direction for synchronization
175      * @return whether a gap is acceptable
176      * @throws ParameterException if a parameter is not defined
177      * @throws OperationalPlanException perception exception
178      */
179     boolean acceptGap(LanePerception perception, Parameters params, SpeedLimitInfo sli, CarFollowingModel cfm, double desire,
180             Speed ownSpeed, Acceleration ownAcceleration, LateralDirectionality lat)
181             throws ParameterException, OperationalPlanException;
182 
183 }