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.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-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
23   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
24   * <p>
25   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 9 okt. 2017 <br>
26   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
27   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
28   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
29   */
30  public interface GapAcceptance
31  {
32  
33      /** Being informed of the model and parameters of other drivers (default LMRS). */
34      GapAcceptance INFORMED = new GapAcceptance()
35      {
36  
37          @Override
38          public boolean acceptGap(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
39                  final CarFollowingModel cfm, final double desire, final Speed ownSpeed, final Acceleration ownAcceleration,
40                  final LateralDirectionality lat) throws ParameterException, OperationalPlanException
41          {
42              NeighborsPerception neighbors = perception.getPerceptionCategory(NeighborsPerception.class);
43              if (neighbors.isGtuAlongside(lat))
44              {
45                  // gtu alongside
46                  return false;
47              }
48  
49              // TODO
50              /*-
51               * Followers and are accepted if the acceleration and speed is 0, a leader is accepted if the ego speed is 0. This 
52               * is in place as vehicles that provide courtesy, will decelerate for us and overshoot the stand-still distance. As
53               * a consequence, they will cease cooperation as they are too close. A pattern will arise where followers slow down
54               * to (near) stand-still, and accelerate again, before we could ever accept the gap.
55               * 
56               * By accepting the gap in the moment that they reach stand-still, this vehicle can at least accept the gap at some 
57               * point. All of this is only a problem if the own vehicle is standing still. Otherwise the stand-still distance is 
58               * not important and movement of our own will create an acceptable situation.
59               * 
60               * What needs to be done, is to find a better way to deal with the cooperation and gap-acceptance, such that this  
61               * hack is not required.
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())
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.multiplyBy(-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  
89      /** Being informed of the model and parameters of other drivers, but applying own headway value. */
90      GapAcceptance EGO_HEADWAY = new GapAcceptance()
91      {
92  
93          @Override
94          public boolean acceptGap(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
95                  final CarFollowingModel cfm, final double desire, final Speed ownSpeed, final Acceleration ownAcceleration,
96                  final LateralDirectionality lat) throws ParameterException, OperationalPlanException
97          {
98              NeighborsPerception neigbors = perception.getPerceptionCategory(NeighborsPerception.class);
99              if (neigbors.isGtuAlongside(lat))
100             {
101                 // gtu alongside
102                 return false;
103             }
104 
105             Acceleration b = params.getParameter(ParameterTypes.B);
106             Acceleration aFollow = new Acceleration(Double.POSITIVE_INFINITY, AccelerationUnit.SI);
107             for (HeadwayGTU follower : neigbors.getFirstFollowers(lat))
108             {
109                 if (follower.getSpeed().gt0() || follower.getAcceleration().gt0())
110                 {
111                     // Change headway parameter
112                     Parameters folParams = follower.getParameters();
113                     folParams.setParameterResettable(ParameterTypes.TMIN, params.getParameter(ParameterTypes.TMIN));
114                     folParams.setParameterResettable(ParameterTypes.TMAX, params.getParameter(ParameterTypes.TMAX));
115                     Acceleration a = LmrsUtil.singleAcceleration(follower.getDistance(), follower.getSpeed(), ownSpeed, desire,
116                             folParams, follower.getSpeedLimitInfo(), follower.getCarFollowingModel());
117                     aFollow = Acceleration.min(aFollow, a);
118                     folParams.resetParameter(ParameterTypes.TMIN);
119                     folParams.resetParameter(ParameterTypes.TMAX);
120                 }
121             }
122 
123             Acceleration aSelf = egoAcceleration(perception, params, sli, cfm, desire, ownSpeed, lat);
124             Acceleration threshold = b.multiplyBy(-desire);
125             return aFollow.ge(threshold) && aSelf.ge(threshold);
126         }
127 
128         /** {@inheritDoc} */
129         @Override
130         public String toString()
131         {
132             return "EGO_HEADWAY";
133         }
134 
135     };
136 
137     /**
138      * Determine whether a gap is acceptable.
139      * @param perception perception
140      * @param params parameters
141      * @param sli speed limit info
142      * @param cfm car-following model
143      * @param desire level of lane change desire
144      * @param ownSpeed own speed
145      * @param lat lateral direction for synchronization
146      * @return whether a gap is acceptable
147      * @throws ParameterException if a parameter is not defined
148      * @throws OperationalPlanException perception exception
149      */
150     static Acceleration egoAcceleration(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
151             final CarFollowingModel cfm, final double desire, final Speed ownSpeed, final LateralDirectionality lat)
152             throws ParameterException, OperationalPlanException
153     {
154         Acceleration aSelf = new Acceleration(Double.POSITIVE_INFINITY, AccelerationUnit.SI);
155         if (ownSpeed.gt0())
156         {
157             for (
158 
159             HeadwayGTU leader : perception.getPerceptionCategory(NeighborsPerception.class).getFirstLeaders(lat))
160             {
161                 Acceleration a = LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(), desire, params,
162                         sli, cfm);
163                 aSelf = Acceleration.min(aSelf, a);
164             }
165         }
166         return aSelf;
167     }
168 
169     /**
170      * Determine whether a gap is acceptable.
171      * @param perception perception
172      * @param params parameters
173      * @param sli speed limit info
174      * @param cfm car-following model
175      * @param desire level of lane change desire
176      * @param ownSpeed own speed
177      * @param ownAcceleration current car-following acceleration
178      * @param lat lateral direction for synchronization
179      * @return whether a gap is acceptable
180      * @throws ParameterException if a parameter is not defined
181      * @throws OperationalPlanException perception exception
182      */
183     boolean acceptGap(LanePerception perception, Parameters params, SpeedLimitInfo sli, CarFollowingModel cfm, double desire,
184             Speed ownSpeed, Acceleration ownAcceleration, LateralDirectionality lat)
185             throws ParameterException, OperationalPlanException;
186 
187 }