1 package org.opentrafficsim.road.network.lane.conflict;
2
3 import java.rmi.RemoteException;
4 import java.util.UUID;
5
6 import javax.naming.NamingException;
7
8 import org.djunits.unit.LengthUnit;
9 import org.djunits.value.vdouble.scalar.Length;
10 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
11 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
12 import org.opentrafficsim.core.geometry.OTSGeometryException;
13 import org.opentrafficsim.core.geometry.OTSLine3D;
14 import org.opentrafficsim.core.geometry.OTSPoint3D;
15 import org.opentrafficsim.core.gtu.GTUDirectionality;
16 import org.opentrafficsim.core.gtu.GTUType;
17 import org.opentrafficsim.core.network.LongitudinalDirectionality;
18 import org.opentrafficsim.core.network.NetworkException;
19 import org.opentrafficsim.road.network.animation.ConflictAnimation;
20 import org.opentrafficsim.road.network.lane.CrossSectionElement;
21 import org.opentrafficsim.road.network.lane.Lane;
22 import org.opentrafficsim.road.network.lane.object.AbstractLaneBasedObject;
23
24 import nl.tudelft.simulation.language.Throw;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public final class Conflict extends AbstractLaneBasedObject
41 {
42
43
44 private static final long serialVersionUID = 20160915L;
45
46
47 private final ConflictType conflictType;
48
49
50 private final ConflictRule conflictRule;
51
52
53 private Conflict otherConflict;
54
55
56 private final Length length;
57
58
59 private final GTUDirectionality direction;
60
61
62 private final OTSDEVSSimulatorInterface simulator;
63
64
65 private final GTUType gtuType;
66
67
68 private final boolean permitted;
69
70
71 private final Object cloneLock;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 @SuppressWarnings("checkstyle:parameternumber")
88 private Conflict(final Lane lane, final Length longitudinalPosition, final Length length, final GTUDirectionality direction,
89 final OTSLine3D geometry, final ConflictType conflictType, final ConflictRule conflictRule,
90 final OTSDEVSSimulatorInterface simulator, final GTUType gtuType, final boolean permitted, final Object cloneLock)
91 throws NetworkException
92 {
93 super(UUID.randomUUID().toString(), lane, Throw.whenNull(direction, "Direction may not be null.").isPlus()
94 ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS, longitudinalPosition, geometry);
95 this.length = length;
96 this.direction = direction;
97 this.conflictType = conflictType;
98 this.conflictRule = conflictRule;
99 this.simulator = simulator;
100 this.gtuType = gtuType;
101 this.permitted = permitted;
102 this.cloneLock = cloneLock;
103
104 try
105 {
106 new ConflictAnimation(this, simulator);
107 }
108 catch (RemoteException | NamingException exception)
109 {
110 throw new NetworkException(exception);
111 }
112
113
114 if (conflictType.equals(ConflictType.SPLIT) || conflictType.equals(ConflictType.MERGE))
115 {
116 Length position =
117 conflictType.equals(ConflictType.SPLIT) ? (direction.isPlus() ? length : lane.getLength().minus(length))
118 : (direction.isPlus() ? lane.getLength() : Length.ZERO);
119 try
120 {
121 new ConflictEnd(this, lane,
122 direction.isPlus() ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS,
123 position);
124 }
125 catch (OTSGeometryException exception)
126 {
127
128 throw new RuntimeException("Could not create dummy geometry for ConflictEnd.", exception);
129 }
130 }
131 }
132
133
134
135
136 public ConflictType getConflictType()
137 {
138 return this.conflictType;
139 }
140
141
142
143
144 public ConflictRule getConflictRule()
145 {
146 return this.conflictRule;
147 }
148
149
150
151
152 public Length getLength()
153 {
154 return this.length;
155 }
156
157
158
159
160 public Conflict getOtherConflict()
161 {
162 return this.otherConflict;
163 }
164
165
166
167
168 public GTUType getGtuType()
169 {
170 return this.gtuType;
171 }
172
173
174
175
176
177 public boolean isPermitted()
178 {
179 return this.permitted;
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 @SuppressWarnings("checkstyle:parameternumber")
204 public static void generateConflictPair(final ConflictType conflictType, final boolean permitted, final Lane lane1,
205 final Length longitudinalPosition1, final Length length1, final GTUDirectionality direction1,
206 final OTSLine3D geometry1, final ConflictRule conflictRule1, final GTUType gtuType1, final Lane lane2,
207 final Length longitudinalPosition2, final Length length2, final GTUDirectionality direction2,
208 final OTSLine3D geometry2, final ConflictRule conflictRule2, final GTUType gtuType2,
209 final OTSDEVSSimulatorInterface simulator) throws NetworkException
210 {
211
212 Throw.whenNull(conflictType, "Conflict type may not be null.");
213 Throw.whenNull(conflictRule1, "Conflict rule may not be null.");
214 Throw.whenNull(conflictRule2, "Conflict rule may not be null.");
215 if (conflictType.equals(ConflictType.SPLIT))
216 {
217
218 Throw.when(!conflictRule1.equals(ConflictRule.SPLIT) || !conflictRule2.equals(ConflictRule.SPLIT),
219 NetworkException.class, "Both conflict rules should be split for conflict type split.");
220 }
221 else
222 {
223
224 boolean check1 = conflictRule1.equals(ConflictRule.PRIORITY) && !conflictRule2.equals(ConflictRule.GIVE_WAY)
225 && !conflictRule2.equals(ConflictRule.STOP);
226 boolean check2 = conflictRule2.equals(ConflictRule.PRIORITY) && !conflictRule1.equals(ConflictRule.GIVE_WAY)
227 && !conflictRule1.equals(ConflictRule.STOP);
228 boolean check3 = conflictRule1.equals(ConflictRule.GIVE_WAY) && !conflictRule2.equals(ConflictRule.PRIORITY);
229 boolean check4 = conflictRule2.equals(ConflictRule.GIVE_WAY) && !conflictRule1.equals(ConflictRule.PRIORITY);
230 boolean check5 = conflictRule1.equals(ConflictRule.STOP) && !conflictRule2.equals(ConflictRule.PRIORITY);
231 boolean check6 = conflictRule2.equals(ConflictRule.STOP) && !conflictRule1.equals(ConflictRule.PRIORITY);
232 Throw.when(check1 || check2 || check3 || check4 || check5 || check6, NetworkException.class,
233 "Conflict rules need to be a combination of 'PRIORITY' and 'GIVE_WAY' or 'STOP', "
234 + "if any of these types is used.");
235
236 boolean check7 = conflictRule1.equals(ConflictRule.ALL_STOP) && !conflictRule2.equals(ConflictRule.ALL_STOP);
237 boolean check8 = conflictRule2.equals(ConflictRule.ALL_STOP) && !conflictRule1.equals(ConflictRule.ALL_STOP);
238 Throw.when(check7 || check8, NetworkException.class,
239 "Conflict rule 'ALL_STOP' can only be combined with a conflict rule 'ALL_STOP'.");
240
241 Throw.when(conflictRule1.equals(ConflictRule.SPLIT) || conflictRule2.equals(ConflictRule.SPLIT),
242 NetworkException.class, "Conflict rule 'SPLIT' may only be used on conflicts of type SPLIT.");
243 }
244 Object cloneLock = new Object();
245 Conflict conf1 = new Conflict(lane1, longitudinalPosition1, length1, direction1, geometry1, conflictType, conflictRule1,
246 simulator, gtuType1, permitted, cloneLock);
247 Conflict conf2 = new Conflict(lane2, longitudinalPosition2, length2, direction2, geometry2, conflictType, conflictRule2,
248 simulator, gtuType2, permitted, cloneLock);
249 conf1.otherConflict = conf2;
250 conf2.otherConflict = conf1;
251 }
252
253
254 @Override
255 public String toString()
256 {
257 return "Conflict [conflictType=" + this.conflictType + ", conflictRule=" + this.conflictRule + "]";
258 }
259
260
261
262
263 private Conflict otherClone;
264
265
266 @Override
267 public Conflict clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator, final boolean animation)
268 throws NetworkException
269 {
270 Throw.when(!(newCSE instanceof Lane), NetworkException.class, "sensors can only be cloned for Lanes");
271 Throw.when(!(newSimulator instanceof OTSDEVSSimulatorInterface), NetworkException.class,
272 "simulator should be a DEVSSimulator");
273 Conflict out = new Conflict((Lane) newCSE, getLongitudinalPosition(), this.length, this.direction, getGeometry(),
274 this.conflictType, this.conflictRule, this.simulator, this.gtuType, this.permitted, this.cloneLock);
275 synchronized (this.cloneLock)
276 {
277
278 if (this.otherClone == null || this.otherClone.simulator != newSimulator)
279 {
280
281 this.otherConflict.otherClone = out;
282 }
283 else
284 {
285 out.otherConflict = this.otherClone;
286 this.otherClone.otherConflict = out;
287 }
288
289 this.otherClone = null;
290 }
291 return out;
292 }
293
294
295
296
297
298
299
300
301
302
303
304
305 public class ConflictEnd extends AbstractLaneBasedObject
306 {
307
308
309 private static final long serialVersionUID = 20161214L;
310
311
312 private final Conflict conflict;
313
314
315
316
317
318
319
320
321
322 ConflictEnd(final Conflict conflict, final Lane lane, final LongitudinalDirectionality direction,
323 final Length longitudinalPosition) throws NetworkException, OTSGeometryException
324 {
325 super(conflict.getId() + "End", lane, direction, longitudinalPosition,
326 new OTSLine3D(new OTSPoint3D(0, 0, 0), new OTSPoint3D(1, 0, 0)));
327 this.conflict = conflict;
328 }
329
330
331
332
333 public final Conflict getConflict()
334 {
335 return this.conflict;
336 }
337
338
339 @Override
340 public final AbstractLaneBasedObject clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator,
341 final boolean animation) throws NetworkException
342 {
343
344 return null;
345 }
346
347 }
348
349 }