1 package org.opentrafficsim.road.network.lane.conflict;
2
3 import java.util.LinkedHashMap;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.Length;
7 import org.djutils.exceptions.Throw;
8 import org.opentrafficsim.core.geometry.DirectedPoint;
9 import org.opentrafficsim.core.geometry.OtsGeometryException;
10 import org.opentrafficsim.road.network.lane.CrossSectionLink.Priority;
11 import org.opentrafficsim.road.network.lane.Lane;
12
13
14
15
16
17
18
19
20
21
22
23
24
25 public class DefaultConflictRule implements ConflictRule
26 {
27
28
29 private Map<String, ConflictPriority> map = null;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 @Override
69 public ConflictPriority determinePriority(final Conflict conflict)
70 {
71 if (this.map == null)
72 {
73 ConflictPriority[] conflictPriorities = getConflictRules(conflict.getLane(), conflict.getLongitudinalPosition(),
74 conflict.getOtherConflict().getLane(), conflict.getOtherConflict().getLongitudinalPosition(),
75 conflict.getConflictType());
76 this.map = new LinkedHashMap<>();
77 this.map.put(conflict.getId(), conflictPriorities[0]);
78 this.map.put(conflict.getOtherConflict().getId(), conflictPriorities[1]);
79 }
80 ConflictPriority out = this.map.get(conflict.getId());
81 Throw.when(out == null, IllegalArgumentException.class,
82 "Conflict %s is not related to a conflict that was used before in the same conflict rule.", conflict);
83 return out;
84 }
85
86
87
88
89
90
91
92
93
94
95 private static ConflictPriority[] getConflictRules(final Lane lane1, final Length longitudinalPosition1, final Lane lane2,
96 final Length longitudinalPosition2, final ConflictType conflictType)
97 {
98 Throw.when(conflictType.equals(ConflictType.SPLIT), UnsupportedOperationException.class,
99 "DefaultConflictRule is not for use on a split conflict. Use SplitConflictRule instead.");
100 ConflictPriority[] conflictRules = new ConflictPriority[2];
101 Priority priority1 = lane1.getParentLink().getPriority();
102 Priority priority2 = lane2.getParentLink().getPriority();
103 if (priority1.isAllStop() && priority2.isAllStop())
104 {
105 conflictRules[0] = ConflictPriority.ALL_STOP;
106 conflictRules[1] = ConflictPriority.ALL_STOP;
107 }
108 else if (priority1.equals(priority2) || (priority1.isYield() && priority2.isStop())
109 || (priority2.isYield() && priority1.isStop()))
110 {
111 Throw.when(priority1.isTurnOnRed() || priority1.isBusStop(), IllegalArgumentException.class,
112 "Both priorities are either 'turn on red' or 'bus stop', which is not allowed. "
113 + "Use BusStopConflictRule for bus stops.");
114
115 DirectedPoint p1;
116 DirectedPoint p2;
117 try
118 {
119 p1 = lane1.getCenterLine().getLocation(longitudinalPosition1);
120 p2 = lane2.getCenterLine().getLocation(longitudinalPosition2);
121 }
122 catch (OtsGeometryException exception)
123 {
124 throw new RuntimeException("Conflict position is not on its lane.", exception);
125 }
126 double diff = p2.getRotZ() - p1.getRotZ();
127 while (diff > Math.PI)
128 {
129 diff -= 2 * Math.PI;
130 }
131 while (diff < -Math.PI)
132 {
133 diff += 2 * Math.PI;
134 }
135 if (diff > 0.0)
136 {
137
138 conflictRules[0] = priority1.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
139 conflictRules[1] = ConflictPriority.PRIORITY;
140 }
141 else
142 {
143
144 conflictRules[0] = ConflictPriority.PRIORITY;
145 conflictRules[1] = priority2.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
146 }
147 }
148 else if ((priority1.isPriority() || priority1.isNone())
149 && (priority2.isNone() || priority2.isYield() || priority2.isStop()))
150 {
151 conflictRules[0] = ConflictPriority.PRIORITY;
152 conflictRules[1] = priority2.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
153 }
154 else if ((priority2.isPriority() || priority2.isNone())
155 && (priority1.isNone() || priority1.isYield() || priority1.isStop()))
156 {
157 conflictRules[0] = priority1.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
158 conflictRules[1] = ConflictPriority.PRIORITY;
159 }
160 else if (priority1.isTurnOnRed() && (priority2.isYield() || priority2.isStop()))
161 {
162 conflictRules[0] = ConflictPriority.TURN_ON_RED;
163 conflictRules[1] = ConflictPriority.PRIORITY;
164 }
165 else if (priority2.isTurnOnRed() && (priority1.isYield() || priority1.isStop()))
166 {
167 conflictRules[0] = ConflictPriority.PRIORITY;
168 conflictRules[1] = ConflictPriority.TURN_ON_RED;
169 }
170 else
171 {
172 throw new IllegalArgumentException(
173 "Could not sort out conflict priority from link priorities " + priority1 + " and " + priority2);
174 }
175 return conflictRules;
176 }
177
178
179 @Override
180 public final String toString()
181 {
182 return "DefaultConflictRule";
183 }
184
185 }