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.perception.EgoPerception;
10  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
11  import org.opentrafficsim.core.network.LateralDirectionality;
12  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
13  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
14  import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
15  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
16  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
17  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGtu;
18  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
19  import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
20  
21  /**
22   * Different forms of cooperation.
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://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
29   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
30   */
31  public interface Cooperation extends LmrsParameters
32  {
33  
34      /** Simple passive cooperation. */
35      Cooperation PASSIVE = new Cooperation()
36      {
37          /** {@inheritDoc} */
38          @Override
39          public Acceleration cooperate(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
40                  final CarFollowingModel cfm, final LateralDirectionality lat, final Desire ownDesire)
41                  throws ParameterException, OperationalPlanException
42          {
43              if (!perception.getLaneStructure().exists(lat.isRight() ? RelativeLane.RIGHT : RelativeLane.LEFT))
44              {
45                  return new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
46              }
47              Acceleration b = params.getParameter(ParameterTypes.B);
48              Acceleration a = new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
49              double dCoop = params.getParameter(DCOOP);
50              Speed ownSpeed = perception.getPerceptionCategory(EgoPerception.class).getSpeed();
51              RelativeLane relativeLane = new RelativeLane(lat, 1);
52              for (HeadwayGtu leader : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(relativeLane))
53              {
54                  Parameters params2 = leader.getParameters();
55                  double desire = lat.equals(LateralDirectionality.LEFT) ? params2.getParameter(DRIGHT)
56                          : lat.equals(LateralDirectionality.RIGHT) ? params2.getParameter(DLEFT) : 0;
57                  if (desire >= dCoop && (leader.getSpeed().gt0() || leader.getDistance().gt0()))
58                  {
59                      Acceleration aSingle = LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(),
60                              desire, params, sli, cfm);
61                      a = Acceleration.min(a, aSingle);
62                  }
63              }
64              return Acceleration.max(a, b.neg());
65          }
66  
67          /** {@inheritDoc} */
68          @Override
69          public String toString()
70          {
71              return "PASSIVE";
72          }
73      };
74  
75      /** Same as passive cooperation, except that cooperation is fully ignored if the potential lane changer brakes heavily. */
76      Cooperation PASSIVE_MOVING = new Cooperation()
77      {
78          /** {@inheritDoc} */
79          @Override
80          public Acceleration cooperate(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
81                  final CarFollowingModel cfm, final LateralDirectionality lat, final Desire ownDesire)
82                  throws ParameterException, OperationalPlanException
83          {
84              if (!perception.getLaneStructure().exists(lat.isRight() ? RelativeLane.RIGHT : RelativeLane.LEFT))
85              {
86                  return new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
87              }
88              Acceleration bCrit = params.getParameter(ParameterTypes.BCRIT);
89              Acceleration a = new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
90              double dCoop = params.getParameter(DCOOP);
91              Speed ownSpeed = perception.getPerceptionCategory(EgoPerception.class).getSpeed();
92              RelativeLane relativeLane = new RelativeLane(lat, 1);
93              NeighborsPerception neighbours = perception.getPerceptionCategory(NeighborsPerception.class);
94              PerceptionCollectable<HeadwayGtu, LaneBasedGtu> leaders = neighbours.getLeaders(RelativeLane.CURRENT);
95              Speed thresholdSpeed = Speed.instantiateSI(6.86); // 295m / 43s
96              boolean leaderInCongestion = leaders.isEmpty() ? false : leaders.first().getSpeed().lt(thresholdSpeed);
97              for (HeadwayGtu leader : neighbours.getLeaders(relativeLane))
98              {
99                  Parameters params2 = leader.getParameters();
100                 double desire = lat.equals(LateralDirectionality.LEFT) ? params2.getParameter(DRIGHT)
101                         : lat.equals(LateralDirectionality.RIGHT) ? params2.getParameter(DLEFT) : 0;
102                 // TODO: only cooperate if merger still quite fast or there's congestion downstream anyway (which we can better
103                 // estimate than only considering the direct leader
104                 if (desire >= dCoop && (leader.getSpeed().gt0() || leader.getDistance().gt0())
105                         && (leader.getSpeed().ge(thresholdSpeed) || leaderInCongestion))
106                 {
107                     Acceleration aSingle = LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(),
108                             desire, params, sli, cfm);
109                     a = Acceleration.min(a, aSingle);
110                 }
111             }
112             return Acceleration.max(a, bCrit.neg());
113         }
114 
115         /** {@inheritDoc} */
116         @Override
117         public String toString()
118         {
119             return "PASSIVE_MOVING";
120         }
121     };
122 
123     /** Cooperation similar to the default, with nuanced differences of when to ignore. */
124     Cooperation ACTIVE = new Cooperation()
125     {
126         /** {@inheritDoc} */
127         @Override
128         public Acceleration cooperate(final LanePerception perception, final Parameters params, final SpeedLimitInfo sli,
129                 final CarFollowingModel cfm, final LateralDirectionality lat, final Desire ownDesire)
130                 throws ParameterException, OperationalPlanException
131         {
132             if (!perception.getLaneStructure().exists(lat.isRight() ? RelativeLane.RIGHT : RelativeLane.LEFT))
133             {
134                 return new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
135             }
136             Acceleration a = new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
137             double dCoop = params.getParameter(DCOOP);
138             Speed ownSpeed = perception.getPerceptionCategory(EgoPerception.class).getSpeed();
139             RelativeLane relativeLane = new RelativeLane(lat, 1);
140             for (HeadwayGtu leader : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(relativeLane))
141             {
142                 Parameters params2 = leader.getParameters();
143                 double desire = lat.equals(LateralDirectionality.LEFT) ? params2.getParameter(DRIGHT)
144                         : lat.equals(LateralDirectionality.RIGHT) ? params2.getParameter(DLEFT) : 0;
145                 if (desire >= dCoop && leader.getDistance().gt0()
146                         && leader.getAcceleration().gt(params.getParameter(ParameterTypes.BCRIT).neg()))
147                 {
148                     Acceleration aSingle = LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(),
149                             desire, params, sli, cfm);
150                     a = Acceleration.min(a, Synchronization.gentleUrgency(aSingle, desire, params));
151                 }
152             }
153             return a;
154         }
155 
156         /** {@inheritDoc} */
157         @Override
158         public String toString()
159         {
160             return "ACTIVE";
161         }
162     };
163 
164     /**
165      * Determine acceleration for cooperation.
166      * @param perception LanePerception; perception
167      * @param params Parameters; parameters
168      * @param sli SpeedLimitInfo; speed limit info
169      * @param cfm CarFollowingModel; car-following model
170      * @param lat LateralDirectionality; lateral direction for cooperation
171      * @param ownDesire Desire; own lane change desire
172      * @return acceleration for synchronization
173      * @throws ParameterException if a parameter is not defined
174      * @throws OperationalPlanException perception exception
175      */
176     Acceleration cooperate(LanePerception perception, Parameters params, SpeedLimitInfo sli, CarFollowingModel cfm,
177             LateralDirectionality lat, Desire ownDesire) throws ParameterException, OperationalPlanException;
178 }