1 package org.opentrafficsim.road.gtu.lane.tactical;
2
3 import java.util.Set;
4
5 import org.djunits.value.vdouble.scalar.Length;
6 import org.opentrafficsim.base.parameters.ParameterException;
7 import org.opentrafficsim.base.parameters.ParameterTypes;
8 import org.opentrafficsim.core.gtu.plan.tactical.TacticalPlanner;
9 import org.opentrafficsim.core.network.Link;
10 import org.opentrafficsim.core.network.Node;
11 import org.opentrafficsim.core.network.route.Route;
12 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
13 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
14 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
15 import org.opentrafficsim.road.network.lane.LaneDirection;
16
17
18
19
20
21
22
23
24
25
26
27
28 public interface LaneBasedTacticalPlanner extends TacticalPlanner<LaneBasedGTU, LanePerception>
29 {
30
31
32
33
34 CarFollowingModel getCarFollowingModel();
35
36
37
38
39
40
41
42 default LaneDirection chooseLaneAtSplit(final Set<LaneDirection> lanes) throws ParameterException
43 {
44 Route route = getGtu().getStrategicalPlanner().getRoute();
45 if (route == null)
46 {
47
48 LaneDirection rightMost = null;
49 for (LaneDirection lane : lanes)
50 {
51 rightMost = rightMost == null ? lane : rightMost(rightMost, lane);
52 }
53 return rightMost;
54 }
55 Length maxDistance = Length.NEGATIVE_INFINITY;
56 LaneDirection best = null;
57 for (LaneDirection lane : lanes)
58 {
59 LaneDirection next = lane.getNextLaneDirection(getGtu());
60 if (next != null)
61 {
62 Length okDistance = okDistance(next, lane.getLength(), route,
63 getGtu().getParameters().getParameter(ParameterTypes.PERCEPTION));
64 if (maxDistance.eq(okDistance))
65 {
66 best = rightMost(best, lane);
67 }
68 else if (okDistance.gt(maxDistance))
69 {
70 maxDistance = okDistance;
71 best = lane;
72 }
73 }
74 }
75 return best;
76 }
77
78
79
80
81
82
83
84
85
86
87
88 default Length okDistance(final LaneDirection lane, final Length distance, final Route route, final Length maxDistance)
89 {
90 if (distance.gt(maxDistance))
91 {
92 return maxDistance;
93 }
94 LaneDirection next = lane.getNextLaneDirection(getGtu());
95 if (next == null)
96 {
97 Node endNode = lane.getDirection().isPlus() ? lane.getLane().getParentLink().getEndNode()
98 : lane.getLane().getParentLink().getStartNode();
99 Set<Link> links = endNode.getLinks().toSet();
100 links.remove(lane.getLane().getParentLink());
101 if (route.contains(endNode) && (links.isEmpty() || links.iterator().next().getLinkType().isConnector()))
102 {
103
104 return maxDistance;
105 }
106
107 return distance.plus(lane.getLength());
108 }
109 return okDistance(next, distance.plus(lane.getLength()), route, maxDistance);
110 }
111
112
113
114
115
116
117
118
119 default LaneDirection rightMost(final LaneDirection lane1, final LaneDirection lane2)
120 {
121 Length offset1 = lane1.getLane().getDesignLineOffsetAtBegin().plus(lane1.getLane().getDesignLineOffsetAtEnd());
122 offset1 = lane1.getDirection().isPlus() ? offset1 : offset1.neg();
123 Length offset2 = lane2.getLane().getDesignLineOffsetAtBegin().plus(lane2.getLane().getDesignLineOffsetAtEnd());
124 offset2 = lane2.getDirection().isPlus() ? offset2 : offset2.neg();
125 return offset1.lt(offset2) ? lane1 : lane2;
126 }
127
128 }