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