View Javadoc
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.value.vdouble.scalar.Length;
9   import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
10  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
11  import org.opentrafficsim.core.geometry.OTSGeometryException;
12  import org.opentrafficsim.core.geometry.OTSLine3D;
13  import org.opentrafficsim.core.geometry.OTSPoint3D;
14  import org.opentrafficsim.core.gtu.GTUDirectionality;
15  import org.opentrafficsim.core.gtu.GTUType;
16  import org.opentrafficsim.core.network.LongitudinalDirectionality;
17  import org.opentrafficsim.core.network.NetworkException;
18  import org.opentrafficsim.road.network.animation.ConflictAnimation;
19  import org.opentrafficsim.road.network.lane.CrossSectionElement;
20  import org.opentrafficsim.road.network.lane.Lane;
21  import org.opentrafficsim.road.network.lane.object.AbstractLaneBasedObject;
22  
23  import nl.tudelft.simulation.language.Throw;
24  
25  /**
26   * Conflicts deal with traffic on different links/roads that need to consider each other as their paths may be in conflict
27   * spatially. A single {@code Conflict} represents the one-sided consideration of a conflicting situation. I.e., what is
28   * considered <i>a single conflict in traffic theory, is represented by two {@code Conflict}s</i>, one on each of the
29   * conflicting {@code Lane}s.
30   * <p>
31   * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
32   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
33   * <p>
34   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Sep 7, 2016 <br>
35   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
36   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
37   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
38   */
39  public final class Conflict extends AbstractLaneBasedObject
40  {
41  
42      /** */
43      private static final long serialVersionUID = 20160915L;
44  
45      /** Conflict type, i.e. crossing, merge or split. */
46      private final ConflictType conflictType;
47  
48      /** Conflict rule, i.e. priority, give way, stop or all-stop. */
49      private final ConflictRule conflictRule;
50  
51      /** Accompanying other conflict. */
52      private Conflict otherConflict;
53  
54      /** The length of the conflict along the lane centerline. */
55      private final Length length;
56  
57      /** GTU direction. */
58      private final GTUDirectionality direction;
59  
60      /** Simulator for animation and timed events. */
61      private final OTSSimulatorInterface simulator;
62  
63      /** GTU type. */
64      private final GTUType gtuType;
65  
66      /** Whether the conflict is a permitted conflict in traffic light control. */
67      private final boolean permitted;
68  
69      /** Lock object for cloning a pair of conflicts. */
70      private final Object cloneLock;
71  
72      /**
73       * @param lane lane where this conflict starts
74       * @param longitudinalPosition position of start of conflict on lane
75       * @param length length of the conflict along the lane centerline
76       * @param direction GTU direction
77       * @param geometry geometry of conflict
78       * @param conflictRule conflict rule, i.e. determines priority, give way, stop or all-stop
79       * @param conflictType conflict type, i.e. crossing, merge or split
80       * @param simulator the simulator for animation and timed events
81       * @param permitted whether the conflict is permitted in traffic light control
82       * @param gtuType gtu type
83       * @param cloneLock lock object for cloning a pair of conflicts
84       * @throws NetworkException when the position on the lane is out of bounds
85       */
86      @SuppressWarnings("checkstyle:parameternumber")
87      private Conflict(final Lane lane, final Length longitudinalPosition, final Length length, final GTUDirectionality direction,
88              final OTSLine3D geometry, final ConflictType conflictType, final ConflictRule conflictRule,
89              final OTSSimulatorInterface simulator, final GTUType gtuType, final boolean permitted, final Object cloneLock)
90              throws NetworkException
91      {
92          super(UUID.randomUUID().toString(), lane, Throw.whenNull(direction, "Direction may not be null.").isPlus()
93                  ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS, longitudinalPosition, geometry);
94          this.length = length;
95          this.direction = direction;
96          this.conflictType = conflictType;
97          this.conflictRule = conflictRule;
98          this.simulator = simulator;
99          this.gtuType = gtuType;
100         this.permitted = permitted;
101         this.cloneLock = cloneLock;
102 
103         try
104         {
105             new ConflictAnimation(this, simulator);
106         }
107         catch (RemoteException | NamingException exception)
108         {
109             throw new NetworkException(exception);
110         }
111 
112         // Create conflict end
113         if (conflictType.equals(ConflictType.SPLIT) || conflictType.equals(ConflictType.MERGE))
114         {
115             Length position =
116                     conflictType.equals(ConflictType.SPLIT) ? (direction.isPlus() ? length : lane.getLength().minus(length))
117                             : (direction.isPlus() ? lane.getLength() : Length.ZERO);
118             try
119             {
120                 new ConflictEnd(this, lane,
121                         direction.isPlus() ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS,
122                         position);
123             }
124             catch (OTSGeometryException exception)
125             {
126                 // does not happen
127                 throw new RuntimeException("Could not create dummy geometry for ConflictEnd.", exception);
128             }
129         }
130     }
131 
132     /**
133      * @return conflictType.
134      */
135     public ConflictType getConflictType()
136     {
137         return this.conflictType;
138     }
139 
140     /**
141      * @return conflictRule.
142      */
143     public ConflictRule getConflictRule()
144     {
145         return this.conflictRule;
146     }
147 
148     /**
149      * @return conflictPriority.
150      */
151     public ConflictPriority conflictPriority()
152     {
153         return this.conflictRule.determinePriority(this);
154     }
155 
156     /**
157      * @return length.
158      */
159     public Length getLength()
160     {
161         return this.length;
162     }
163 
164     /**
165      * @return otherConflict.
166      */
167     public Conflict getOtherConflict()
168     {
169         return this.otherConflict;
170     }
171 
172     /**
173      * @return gtuType.
174      */
175     public GTUType getGtuType()
176     {
177         return this.gtuType;
178     }
179 
180     /**
181      * If permitted, traffic upstream of traffic lights may not be ignored, as these can have green light.
182      * @return permitted.
183      */
184     public boolean isPermitted()
185     {
186         return this.permitted;
187     }
188 
189     /**
190      * Creates a pair of conflicts.
191      * @param conflictType conflict type, i.e. crossing, merge or split
192      * @param conflictRule conflict rule
193      * @param permitted whether the conflict is permitted in traffic light control
194      * @param lane1 lane of conflict 1
195      * @param longitudinalPosition1 longitudinal position of conflict 1
196      * @param length1 {@code Length} of conflict 1
197      * @param direction1 GTU direction of conflict 1
198      * @param geometry1 geometry of conflict 1
199      * @param gtuType1 gtu type of conflict 1
200      * @param lane2 lane of conflict 2
201      * @param longitudinalPosition2 longitudinal position of conflict 2
202      * @param length2 {@code Length} of conflict 2
203      * @param direction2 GTU direction of conflict 2
204      * @param geometry2 geometry of conflict 2
205      * @param gtuType2 gtu type of conflict 2
206      * @param simulator the simulator for animation and timed events
207      * @throws NetworkException if the combination of conflict type and both conflict rules is not correct
208      */
209     @SuppressWarnings("checkstyle:parameternumber")
210     public static void generateConflictPair(final ConflictType conflictType, final ConflictRule conflictRule,
211             final boolean permitted, final Lane lane1, final Length longitudinalPosition1, final Length length1,
212             final GTUDirectionality direction1, final OTSLine3D geometry1, final GTUType gtuType1, final Lane lane2,
213             final Length longitudinalPosition2, final Length length2, final GTUDirectionality direction2,
214             final OTSLine3D geometry2, final GTUType gtuType2, final OTSDEVSSimulatorInterface simulator)
215             throws NetworkException
216     {
217         // lane, longitudinalPosition, length and geometry are checked in AbstractLaneBasedObject
218         Throw.whenNull(conflictType, "Conflict type may not be null.");
219 
220         Object cloneLock = new Object();
221         Conflict conf1 = new Conflict(lane1, longitudinalPosition1, length1, direction1, geometry1, conflictType, conflictRule,
222                 simulator, gtuType1, permitted, cloneLock);
223         Conflict conf2 = new Conflict(lane2, longitudinalPosition2, length2, direction2, geometry2, conflictType, conflictRule,
224                 simulator, gtuType2, permitted, cloneLock);
225         conf1.otherConflict = conf2;
226         conf2.otherConflict = conf1;
227     }
228 
229     /** {@inheritDoc} */
230     @Override
231     public String toString()
232     {
233         return "Conflict [conflictType=" + this.conflictType + ", conflictRule=" + this.conflictRule + "]";
234     }
235 
236     /**
237      * Clone of other conflict.
238      */
239     private Conflict otherClone;
240 
241     /** {@inheritDoc} */
242     @Override
243     public Conflict clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator, final boolean animation)
244             throws NetworkException
245     {
246         Throw.when(!(newCSE instanceof Lane), NetworkException.class, "sensors can only be cloned for Lanes");
247         Throw.when(!(newSimulator instanceof OTSDEVSSimulatorInterface), NetworkException.class,
248                 "simulator should be a DEVSSimulator");
249         Conflict out = new Conflict((Lane) newCSE, getLongitudinalPosition(), this.length, this.direction, getGeometry(),
250                 this.conflictType, this.conflictRule.clone(newSimulator), newSimulator, this.gtuType, this.permitted,
251                 this.cloneLock);
252         synchronized (this.cloneLock)
253         {
254             // couple both clones
255             if (this.otherClone == null || this.otherClone.simulator != newSimulator)
256             {
257                 // other clone will do it
258                 this.otherConflict.otherClone = out;
259             }
260             else
261             {
262                 out.otherConflict = this.otherClone;
263                 this.otherClone.otherConflict = out;
264             }
265             // reset successful clone of pair, or remove otherClone from other simulator (or was already null)
266             this.otherClone = null;
267         }
268         return out;
269     }
270 
271     /**
272      * <p>
273      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
274      * <br>
275      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
276      * <p>
277      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 14 dec. 2016 <br>
278      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
279      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
280      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
281      */
282     public class ConflictEnd extends AbstractLaneBasedObject
283     {
284 
285         /** */
286         private static final long serialVersionUID = 20161214L;
287 
288         /** Conflict. */
289         private final Conflict conflict;
290 
291         /**
292          * @param conflict conflict
293          * @param lane lane
294          * @param direction valid direction
295          * @param longitudinalPosition position
296          * @throws NetworkException on network exception
297          * @throws OTSGeometryException does not happen
298          */
299         ConflictEnd(final Conflict conflict, final Lane lane, final LongitudinalDirectionality direction,
300                 final Length longitudinalPosition) throws NetworkException, OTSGeometryException
301         {
302             super(conflict.getId() + "End", lane, direction, longitudinalPosition,
303                     new OTSLine3D(new OTSPoint3D(0, 0, 0), new OTSPoint3D(1, 0, 0)));
304             this.conflict = conflict;
305         }
306 
307         /**
308          * @return conflict
309          */
310         public final Conflict getConflict()
311         {
312             return this.conflict;
313         }
314 
315         /** {@inheritDoc} */
316         @Override
317         public final AbstractLaneBasedObject clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator,
318                 final boolean animation) throws NetworkException
319         {
320             // Constructor of Conflict creates these.
321             return null;
322         }
323 
324     }
325 
326 }