1 package org.opentrafficsim.road.gtu.lane.perception.mental.ar;
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.core.gtu.Stateless;
9 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
10 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
11 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
12 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
13 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.TaskHeadwayCollector;
14 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
15
16
17
18
19
20
21
22
23
24
25 public final class ArTaskLaneChanging extends ArTaskHeadwayBased implements Stateless<ArTaskLaneChanging>
26 {
27
28
29 public static final ArTaskLaneChanging SINGLETON = new ArTaskLaneChanging();
30
31
32
33
34 private ArTaskLaneChanging()
35 {
36 super("lane-changing");
37 }
38
39 @Override
40 protected Duration getHeadway(final LanePerception perception, final LaneBasedGtu gtu, final Parameters parameters)
41 throws ParameterException
42 {
43 NeighborsPerception neighbors = Try.assign(() -> perception.getPerceptionCategory(NeighborsPerception.class),
44 "NeighborsPerception not available.");
45 double lat = Try.assign(() -> getConsideration(perception, gtu, parameters), "Exception during lateral consideration.");
46 RelativeLane lane;
47 if (Math.abs(lat) < 1e-9)
48 {
49 return null;
50 }
51 if (lat < 0.0)
52 {
53 lane = RelativeLane.LEFT;
54 lat = -lat;
55 }
56 else
57 {
58 lane = RelativeLane.RIGHT;
59 }
60 if (perception.getLaneStructure().exists(lane) && neighbors.isGtuAlongside(lane.getLateralDirectionality()))
61 {
62 return Duration.ZERO;
63 }
64 Duration h1 = neighbors.getLeaders(lane).collect(new TaskHeadwayCollector(getSpeed()));
65 Duration h2 = neighbors.getFollowers(lane).collect(new TaskHeadwayCollector(getSpeed()));
66 if (h1 == null)
67 {
68 return h2 == null ? null : h2.divide(lat);
69 }
70 if (h2 == null)
71 {
72 return h1 == null ? null : h1.divide(lat);
73 }
74 if (h1.eq0() && h2.eq0())
75 {
76 return Duration.ZERO;
77 }
78 if (h1.eq(Duration.POSITIVE_INFINITY) && h2.eq(Duration.POSITIVE_INFINITY))
79 {
80 return Duration.POSITIVE_INFINITY;
81 }
82 return Duration.ofSI(h1.si * h2.si / (lat * (h1.si + h2.si)));
83 }
84
85
86
87
88
89
90
91
92
93
94 private double getConsideration(final LanePerception perception, final LaneBasedGtu gtu, final Parameters parameters)
95 throws ParameterException, GtuException
96 {
97 double dLeft = gtu.getParameters().getParameter(LmrsParameters.DLEFT);
98 double dRight = gtu.getParameters().getParameter(LmrsParameters.DRIGHT);
99 if (dLeft > dRight && dLeft > 0.0)
100 {
101 return dLeft > 1.0 ? -1.0 : -dLeft;
102 }
103 else if (dRight > dLeft && dRight > 0.0)
104 {
105 return dRight > 1.0 ? 1.0 : dRight;
106 }
107 return 0.0;
108 }
109
110 @Override
111 public ArTaskLaneChanging get()
112 {
113 return SINGLETON;
114 }
115
116 }