View Javadoc
1   package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2   
3   import java.util.SortedSet;
4   
5   import org.djunits.value.vdouble.scalar.Speed;
6   import org.opentrafficsim.base.parameters.ParameterException;
7   import org.opentrafficsim.base.parameters.ParameterTypeDouble;
8   import org.opentrafficsim.base.parameters.ParameterTypeSpeed;
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.road.gtu.lane.perception.InfrastructureLaneChangeInfo;
13  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
14  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
15  import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
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.gtu.lane.tactical.util.lmrs.Desire;
20  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
21  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
22  
23  /**
24   * Incentive that lets drivers queue in an adjacent lane as soon as the speed is low in the adjacent lane, and stopping in the
25   * current lane might block traffic towards other directions.
26   * <p>
27   * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
28   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
29   * </p>
30   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
31   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
32   * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
33   */
34  public class IncentiveGetInLane implements MandatoryIncentive
35  {
36  
37      /** Congestion speed threshold parameter type. */
38      protected static final ParameterTypeSpeed VCONG = ParameterTypes.VCONG;
39  
40      /** Hierarchy parameter. */
41      protected static final ParameterTypeDouble SOCIO = LmrsParameters.SOCIO;
42  
43      /** {@inheritDoc} */
44      @Override
45      public Desire determineDesire(final Parameters parameters, final LanePerception perception,
46              final CarFollowingModel carFollowingModel, final Desire mandatoryDesire)
47              throws ParameterException, OperationalPlanException
48      {
49  
50          Speed vCong = parameters.getParameter(VCONG);
51          double socio = parameters.getParameter(SOCIO);
52          InfrastructurePerception infra = perception.getPerceptionCategory(InfrastructurePerception.class);
53          NeighborsPerception neighbors = perception.getPerceptionCategory(NeighborsPerception.class);
54          SortedSet<InfrastructureLaneChangeInfo> info = infra.getInfrastructureLaneChangeInfo(RelativeLane.CURRENT);
55          double dCur = info.isEmpty() ? Double.POSITIVE_INFINITY
56                  : info.first().getRemainingDistance().si / info.first().getRequiredNumberOfLaneChanges();
57          double left = 0;
58          double right = 0;
59          double vCur = Double.POSITIVE_INFINITY;
60  
61          for (RelativeLane lane : new RelativeLane[] {RelativeLane.LEFT, RelativeLane.RIGHT})
62          {
63              if (infra.getCrossSection().contains(lane))
64              {
65                  SortedSet<InfrastructureLaneChangeInfo> adjInfo = infra.getInfrastructureLaneChangeInfo(lane);
66                  double dAdj = adjInfo.isEmpty() ? Double.POSITIVE_INFINITY
67                          : adjInfo.first().getRemainingDistance().si / adjInfo.first().getRequiredNumberOfLaneChanges();
68                  if (!info.isEmpty() && !info.first().isDeadEnd() && dCur < dAdj)
69                  {
70                      double v = Double.POSITIVE_INFINITY;
71                      for (HeadwayGtu neighbor : neighbors.getLeaders(lane))
72                      {
73                          v = Math.min(v, neighbor.getSpeed().si);
74                      }
75                      if (lane.isLeft())
76                      {
77                          double d = Math.max(0.0, 1.0 - v / vCong.si);
78                          left += d;
79                          // right -= d;
80                      }
81                      else
82                      {
83                          double d = Math.max(0.0, 1.0 - v / vCong.si);
84                          right += d;
85                          // left -= d;
86                      }
87                  }
88                  if (!adjInfo.isEmpty() && !adjInfo.first().isDeadEnd()
89                          && (info.isEmpty() || (!info.isEmpty() && !info.first().isDeadEnd())) && dCur > dAdj)
90                  {
91                      if (Double.isInfinite(vCur))
92                      {
93                          for (HeadwayGtu neighbor : neighbors.getLeaders(RelativeLane.CURRENT))
94                          {
95                              vCur = Math.min(vCur, neighbor.getSpeed().si);
96                          }
97                      }
98                      if (lane.isLeft())
99                      {
100                         left -= Math.max(0.0, 1.0 - vCur / vCong.si);
101                     }
102                     else
103                     {
104                         right -= Math.max(0.0, 1.0 - vCur / vCong.si);
105                     }
106                 }
107             }
108         }
109         return new Desire(left * socio, right * socio);
110     }
111 
112     /** {@inheritDoc} */
113     @Override
114     public final String toString()
115     {
116         return "IncentiveGetInLane";
117     }
118 
119 }