View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception.mental.channel;
2   
3   import java.util.Iterator;
4   import java.util.Set;
5   import java.util.function.Function;
6   import java.util.function.Predicate;
7   
8   import org.djunits.value.vdouble.scalar.Length;
9   import org.djutils.exceptions.Try;
10  import org.opentrafficsim.base.parameters.ParameterTypeDouble;
11  import org.opentrafficsim.base.parameters.ParameterTypeLength;
12  import org.opentrafficsim.base.parameters.constraint.NumericConstraint;
13  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
14  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
15  import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable.UnderlyingDistance;
16  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
17  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
18  import org.opentrafficsim.road.gtu.lane.perception.mental.AbstractTask;
19  
20  /**
21   * Task demand for signal (front: brake lights, left: right indicator, right: left indicator). This applies to the first leader
22   * with signal, and is defined as {@code TD_signal * (1 - s/x0)}, where {@code TD_signal} is a constant, {@code s} is the
23   * distance to the leader with signal and {@code x0} is the look-ahead distance.
24   * <p>
25   * Copyright (c) 2024-2025 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
26   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
27   * </p>
28   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
29   */
30  public class ChannelTaskSignal extends AbstractTask implements ChannelTask
31  {
32  
33      /** Signal task demand. */
34      public static final ParameterTypeDouble TDSIGNAL =
35              new ParameterTypeDouble("td_signal", "Signal task demand", 0.2, NumericConstraint.POSITIVEZERO);
36  
37      /** Distance discount range. */
38      public static final ParameterTypeLength X0_D = ChannelMental.X0_D;
39  
40      /** Standard set of left, right and front signal task. */
41      private static final Set<ChannelTask> SET =
42              Set.of(new ChannelTaskSignal(LEFT), new ChannelTaskSignal(RIGHT), new ChannelTaskSignal(FRONT));
43  
44      /** Standard supplier that supplies instances for left, right and front signal task. */
45      public static final Function<LanePerception, Set<ChannelTask>> SUPPLIER = (p) -> SET;
46  
47      /** Channel. */
48      private final Object channel;
49  
50      /** Predicate to test the signal on a GTU. */
51      private final Predicate<LaneBasedGtu> predicate;
52  
53      /** Relative lane that applies. */
54      private final RelativeLane lane;
55  
56      /**
57       * Constructor.
58       * @param channel channel.
59       */
60      public ChannelTaskSignal(final Object channel)
61      {
62          super("signal");
63          this.channel = channel;
64          if (channel.equals(FRONT))
65          {
66              this.predicate = (t) -> t.isBrakingLightsOn();
67              this.lane = RelativeLane.CURRENT;
68          }
69          else if (channel.equals(LEFT))
70          {
71              this.predicate = (t) -> t.getTurnIndicatorStatus().isRightOrBoth();
72              this.lane = RelativeLane.LEFT;
73          }
74          else if (channel.equals(RIGHT))
75          {
76              this.predicate = (t) -> t.getTurnIndicatorStatus().isLeftOrBoth();
77              this.lane = RelativeLane.RIGHT;
78          }
79          else
80          {
81              throw new IllegalArgumentException("Channel " + channel + " is not supported by signal channel.");
82          }
83      }
84  
85      @Override
86      public String getId()
87      {
88          return String.format("signal (%s)", this.channel);
89      }
90  
91      @Override
92      public Object getChannel()
93      {
94          return this.channel;
95      }
96  
97      @Override
98      public double calculateTaskDemand(final LanePerception perception)
99      {
100         NeighborsPerception neighbors = Try.assign(() -> perception.getPerceptionCategory(NeighborsPerception.class),
101                 "NeighborsPerception not present.");
102         Iterator<UnderlyingDistance<LaneBasedGtu>> leaders = neighbors.getLeaders(this.lane).underlyingWithDistance();
103         while (leaders.hasNext())
104         {
105             UnderlyingDistance<LaneBasedGtu> leader = leaders.next();
106             if (this.predicate.test(leader.object()))
107             {
108                 Length x0 =
109                         Try.assign(() -> perception.getGtu().getParameters().getParameter(X0_D), "Parameter x0_d not present.");
110                 double tdSignal = Try.assign(() -> perception.getGtu().getParameters().getParameter(TDSIGNAL),
111                         "Parameter td_signal not available.");
112                 return tdSignal * (1.0 - leader.distance().si / x0.si);
113             }
114         }
115         return 0.0;
116     }
117 
118 }