1 package org.opentrafficsim.road.gtu.lane.perception.mental;
2
3 import org.djunits.value.vdouble.scalar.Duration;
4 import org.djutils.exceptions.Try;
5 import org.opentrafficsim.base.parameters.ParameterException;
6 import org.opentrafficsim.base.parameters.Parameters;
7 import org.opentrafficsim.core.gtu.GTUException;
8 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
9 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
10 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
11 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
12 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
13
14
15
16
17
18
19
20
21
22
23
24
25
26 public class TaskLaneChanging extends TaskHeadwayBased
27 {
28
29
30 private final LateralConsideration lateralConsideration;
31
32
33
34
35
36 public TaskLaneChanging(final LateralConsideration lateralConsideration)
37 {
38 super("lane-changing");
39 this.lateralConsideration = lateralConsideration;
40 }
41
42
43 @Override
44 protected Duration getHeadway(final LanePerception perception, final LaneBasedGTU gtu, final Parameters parameters)
45 throws ParameterException
46 {
47 NeighborsPerception neighbors = Try.assign(() -> perception.getPerceptionCategory(NeighborsPerception.class),
48 "NeighborsPerception not available.");
49 double lat = Try.assign(() -> this.lateralConsideration.getConsideration(perception, gtu, parameters),
50 "Exception during lateral consideration.");
51 RelativeLane lane;
52 if (Math.abs(lat) < 1e-9)
53 {
54 return null;
55 }
56 if (lat < 0.0)
57 {
58 lane = RelativeLane.LEFT;
59 lat = -lat;
60 }
61 else
62 {
63 lane = RelativeLane.RIGHT;
64 }
65 if (neighbors.isGtuAlongside(lane.getLateralDirectionality()))
66 {
67 return Duration.ZERO;
68 }
69 Duration h1 = neighbors.getLeaders(lane).collect(new TaskHeadwayCollector(getSpeed()));
70 Duration h2 = neighbors.getFollowers(lane).collect(new TaskHeadwayCollector(getSpeed()));
71 if (h1 == null)
72 {
73 return h2 == null ? null : h2.divideBy(lat);
74 }
75 if (h2 == null)
76 {
77 return h1 == null ? null : h1.divideBy(lat);
78 }
79 if (h1.eq0() && h2.eq0())
80 {
81 return Duration.ZERO;
82 }
83 return Duration.createSI(h1.si * h2.si / (lat * (h1.si + h2.si)));
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97
98 public interface LateralConsideration
99 {
100
101
102 LateralConsideration DESIRE = new LateralConsideration()
103 {
104 @Override
105 public double getConsideration(final LanePerception perception, final LaneBasedGTU gtu, final Parameters parameters)
106 throws ParameterException, GTUException
107 {
108 double dLeft = gtu.getParameters().getParameter(LmrsParameters.DLEFT);
109 double dRight = gtu.getParameters().getParameter(LmrsParameters.DRIGHT);
110 if (dLeft > dRight && dLeft > 0.0)
111 {
112 return dLeft > 1.0 ? -1.0 : -dLeft;
113 }
114 else if (dRight > dLeft && dRight > 0.0)
115 {
116 return dRight > 1.0 ? 1.0 : dRight;
117 }
118 return 0.0;
119 }
120 };
121
122
123
124
125
126
127
128
129
130
131
132 double getConsideration(LanePerception perception, LaneBasedGTU gtu, Parameters parameters)
133 throws ParameterException, GTUException;
134 }
135
136 }