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