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
22
23
24
25
26
27
28
29
30 public class ChannelTaskSignal extends AbstractTask implements ChannelTask
31 {
32
33
34 public static final ParameterTypeDouble TDSIGNAL =
35 new ParameterTypeDouble("td_signal", "Signal task demand", 0.2, NumericConstraint.POSITIVEZERO);
36
37
38 public static final ParameterTypeLength X0_D = ChannelMental.X0_D;
39
40
41 private static final Set<ChannelTask> SET =
42 Set.of(new ChannelTaskSignal(LEFT), new ChannelTaskSignal(RIGHT), new ChannelTaskSignal(FRONT));
43
44
45 public static final Function<LanePerception, Set<ChannelTask>> SUPPLIER = (p) -> SET;
46
47
48 private final Object channel;
49
50
51 private final Predicate<LaneBasedGtu> predicate;
52
53
54 private final RelativeLane lane;
55
56
57
58
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 }