View Javadoc
1   package org.opentrafficsim.road.gtu.perception.mental.channel;
2   
3   import java.util.Iterator;
4   import java.util.NoSuchElementException;
5   import java.util.Set;
6   import java.util.function.Function;
7   
8   import org.djunits.value.vdouble.scalar.Length;
9   import org.opentrafficsim.base.DistancedObject;
10  import org.opentrafficsim.base.OtsRuntimeException;
11  import org.opentrafficsim.base.parameters.ParameterException;
12  import org.opentrafficsim.base.parameters.ParameterTypeDouble;
13  import org.opentrafficsim.base.parameters.ParameterTypeLength;
14  import org.opentrafficsim.road.gtu.LaneBasedGtu;
15  import org.opentrafficsim.road.gtu.perception.LanePerception;
16  import org.opentrafficsim.road.gtu.perception.RelativeLane;
17  import org.opentrafficsim.road.gtu.perception.categories.neighbors.NeighborsPerception;
18  import org.opentrafficsim.road.gtu.perception.mental.AbstractTask;
19  import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsParameters;
20  
21  /**
22   * Task demand for potential cut-in or cooperation. This is defined as the maximum value of {@code d*(1-s/x0)} where {@code d}
23   * is lane change desire towards the ego lane of any leader in either the left or right adjacent lane, {@code s} is the distance
24   * to the leader with lane change desire and {@code x0} is the look-ahead distance.
25   * <p>
26   * Copyright (c) 2024-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
27   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
28   * </p>
29   * @author Wouter Schakel
30   */
31  public final class ChannelTaskCooperation extends AbstractTask implements ChannelTask
32  {
33  
34      /** Distance discount range. */
35      public static final ParameterTypeLength X0_D = ChannelMental.X0_D;
36  
37      /** Standard set of left and right cooperation task. */
38      private static final Set<ChannelTask> SET = Set.of(new ChannelTaskCooperation(true), new ChannelTaskCooperation(false));
39  
40      /** Standard supplier that supplies instances for left and right cooperation task. */
41      public static final Function<LanePerception, Set<ChannelTask>> SUPPLIER = (p) -> SET;
42  
43      /** Whether this task instance regards the left side. */
44      private final boolean left;
45  
46      /**
47       * Constructor.
48       * @param left whether this task instance regards the left side.
49       */
50      private ChannelTaskCooperation(final boolean left)
51      {
52          super("cooperation");
53          this.left = left;
54      }
55  
56      @Override
57      public String getId()
58      {
59          return this.left ? "cooperation (left)" : "cooperation (right)";
60      }
61  
62      @Override
63      public Object getChannel()
64      {
65          return this.left ? LEFT : RIGHT;
66      }
67  
68      @Override
69      public double calculateTaskDemand(final LanePerception perception)
70      {
71          NeighborsPerception neighbors = perception.getPerceptionCategoryOptional(NeighborsPerception.class)
72                  .orElseThrow(() -> new NoSuchElementException("NeighborsPerception not present."));
73          Iterator<DistancedObject<LaneBasedGtu>> leaders =
74                  neighbors.getLeaders(this.left ? RelativeLane.LEFT : RelativeLane.RIGHT).underlyingWithDistance();
75          ParameterTypeDouble param = this.left ? LmrsParameters.DRIGHT : LmrsParameters.DLEFT;
76          Length x0 = perception.getGtu().getParameters().getOptionalParameter(X0_D)
77                  .orElseThrow(() -> new OtsRuntimeException("Parameter x0_d not present."));
78          double dMax = 0.0;
79          while (leaders.hasNext())
80          {
81              DistancedObject<LaneBasedGtu> leader = leaders.next();
82              if (leader.distance().gt(x0))
83              {
84                  break;
85              }
86              double d;
87              try
88              {
89                  d = leader.object().getParameters().getParameter(param) * (1.0 - leader.distance().si / x0.si);
90                  dMax = Math.max(dMax, d);
91              }
92              catch (ParameterException ex)
93              {
94                  // leader does not provide lane change desire, ignore
95              }
96          }
97          return Math.min(0.999, dMax);
98      }
99  
100 }