View Javadoc
1   package org.opentrafficsim.road.gtu.tactical.lmrs;
2   
3   import java.util.function.Supplier;
4   
5   import org.djunits.value.vdouble.scalar.Acceleration;
6   import org.djunits.value.vdouble.scalar.Length;
7   import org.djunits.value.vdouble.scalar.Speed;
8   import org.opentrafficsim.base.parameters.ParameterException;
9   import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
10  import org.opentrafficsim.base.parameters.ParameterTypeSpeed;
11  import org.opentrafficsim.base.parameters.ParameterTypes;
12  import org.opentrafficsim.core.gtu.GtuException;
13  import org.opentrafficsim.core.network.LateralDirectionality;
14  import org.opentrafficsim.road.gtu.LaneBasedGtu;
15  import org.opentrafficsim.road.gtu.perception.FilteredIterable;
16  import org.opentrafficsim.road.gtu.perception.PerceptionCollectable;
17  import org.opentrafficsim.road.gtu.perception.RelativeLane;
18  import org.opentrafficsim.road.gtu.perception.categories.InfrastructurePerception;
19  import org.opentrafficsim.road.gtu.perception.categories.TrafficPerception;
20  import org.opentrafficsim.road.gtu.perception.categories.neighbors.NeighborsPerception;
21  import org.opentrafficsim.road.gtu.perception.object.PerceivedGtu;
22  import org.opentrafficsim.road.gtu.tactical.TacticalContextEgo;
23  import org.opentrafficsim.road.gtu.tactical.util.CarFollowingUtil;
24  import org.opentrafficsim.road.gtu.tactical.util.lmrs.Desire;
25  
26  /**
27   * Makes a GTU follow leaders in the left lane, with limited deceleration.
28   * <p>
29   * Copyright (c) 2013-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
30   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
31   * </p>
32   * @author Alexander Verbraeck
33   * @author Peter Knoppers
34   * @author Wouter Schakel
35   */
36  public final class AccelerationNoSlowLaneOvertake implements AccelerationIncentive
37  {
38  
39      /** Speed threshold below which traffic is considered congested. */
40      public static final ParameterTypeSpeed VCONG = ParameterTypes.VCONG;
41  
42      /** Maximum adjustment deceleration, e.g. when speed limit drops. */
43      public static final ParameterTypeAcceleration B0 = ParameterTypes.B0;
44  
45      /** Supplier of mandatory desire. */
46      private Supplier<Desire> getMandatoryDesire;
47  
48      /**
49       * Constructor.
50       * @param getMandatoryDesire supplier of mandatory desire from the model
51       */
52      public AccelerationNoSlowLaneOvertake(final Supplier<Desire> getMandatoryDesire)
53      {
54          this.getMandatoryDesire = getMandatoryDesire;
55      }
56  
57      @Override
58      public Acceleration accelerate(final TacticalContextEgo context, final RelativeLane lane, final Length mergeDistance)
59              throws ParameterException, GtuException
60      {
61          // Ignore incentive if we need to change lane for the route
62          // TODO: depends on left/right traffic
63          if (!lane.isCurrent() || !context.getPerception().getLaneStructure().exists(lane.getLeft())
64                  || this.getMandatoryDesire.get().right() > 0.0 || this.getMandatoryDesire.get().left() < 0.0)
65          {
66              return NO_REASON;
67          }
68  
69          InfrastructurePerception infra = context.getPerception().getPerceptionCategory(InfrastructurePerception.class);
70          Length legal = infra.getLegalLaneChangePossibility(RelativeLane.LEFT, LateralDirectionality.RIGHT);
71          Length ignore = legal.lt0() ? legal.neg() : Length.ZERO;
72  
73          if (lane.isCurrent() && context.getPerception().getLaneStructure().exists(RelativeLane.LEFT))
74          {
75              Speed vCong = context.getParameters().getParameter(VCONG);
76              if (context.getPerception().getPerceptionCategory(TrafficPerception.class).getSpeed(RelativeLane.CURRENT,
77                      context.getDesiredSpeed()).si > vCong.si)
78              {
79                  // TODO depends on left/right traffic
80                  PerceptionCollectable<PerceivedGtu, LaneBasedGtu> leaders =
81                          context.getPerception().getPerceptionCategory(NeighborsPerception.class).getLeaders(RelativeLane.LEFT);
82                  if (!leaders.isEmpty())
83                  {
84                      for (PerceivedGtu leader : ignore.le0() ? leaders
85                              : new FilteredIterable<>(leaders, (leader) -> leader.getDistance().gt(ignore)))
86                      {
87                          if (context.getSpeed().si > leader.getSpeed().si && leader.getDistance().gt0())
88                          {
89                              Acceleration b0 = context.getParameters().getParameter(B0);
90                              Acceleration a = CarFollowingUtil.followSingleLeader(context, leader);
91                              return a.si < -b0.si ? b0.neg() : a;
92                          }
93                          else
94                          {
95                              // Stop looking for further leaders when a leader is faster
96                              return NO_REASON;
97                          }
98                      }
99                  }
100             }
101         }
102         return NO_REASON;
103     }
104 
105 }