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