View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception.headway;
2   
3   import org.djunits.value.vdouble.scalar.Length;
4   import org.djutils.exceptions.Throw;
5   import org.opentrafficsim.core.gtu.GTUException;
6   
7   /**
8    * Super class for non-delayed and non-erroneous perception. Sub classes should wrap the actual simulation object to obtain
9    * information. One exception to this is {@link AbstractHeadwayCopy} (and all it's sub classes), which contains such information
10   * directly, and is a super class for delayed and/or erroneous perception.
11   * <p>
12   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
13   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
14   * <p>
15   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 24 mrt. 2017 <br>
16   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
17   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
18   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
19   */
20  public abstract class AbstractHeadway implements Headway
21  {
22  
23      /** */
24      private static final long serialVersionUID = 20170324L;
25  
26      /** The (perceived) distance to the other object. When objects are parallel, the distance is null. */
27      private final Length distance;
28  
29      /**
30       * The (perceived) front overlap to the other object. This value should be null if there is no overlap. In the figure below
31       * for two GTUs, it is distance c, positive for GTU1, negative for GTU2.
32       * 
33       * <pre>
34       * ----------
35       * |  GTU 1 |          -----&gt;
36       * ----------
37       *      ---------------
38       *      |    GTU 2    |          -----&gt;
39       *      ---------------
40       * | a  | b |     c   |
41       * </pre>
42       */
43      private final Length overlapFront;
44  
45      /**
46       * The (perceived) rear overlap to the other object. This value should be null if there is no overlap. In the figure below
47       * for two GTUs, it is distance a, positive for GTU1, negative for GTU2.
48       * 
49       * <pre>
50       * ----------
51       * |  GTU 1 |          -----&gt;
52       * ----------
53       *      ---------------
54       *      |    GTU 2    |          -----&gt;
55       *      ---------------
56       * | a  | b |     c   |
57       * </pre>
58       */
59      private final Length overlapRear;
60  
61      /**
62       * The (perceived) overlap with the other object. This value should be null if there is no overlap. In the figure below for
63       * two GTUs, it is distance b, positive for GTU1 and GTU2.
64       * 
65       * <pre>
66       * ----------
67       * |  GTU 1 |          -----&gt;
68       * ----------
69       *      ---------------
70       *      |    GTU 2    |          -----&gt;
71       *      ---------------
72       * | a  | b |     c   |
73       * </pre>
74       */
75      private final Length overlap;
76  
77      /**
78       * Construct a new Headway information object, for an object in front, behind, or in parallel with us. <br>
79       * @param distance Length; the distance to the other object
80       * @param overlapFront Length; the front-front distance to the other object
81       * @param overlap Length; the 'center' overlap with the other object
82       * @param overlapRear Length; the rear-rear distance to the other object
83       * @throws GTUException when id is null, or parameters are inconsistent
84       */
85      protected AbstractHeadway(final Length distance, final Length overlapFront, final Length overlap, final Length overlapRear)
86              throws GTUException
87      {
88          Throw.when(distance != null && (overlap != null || overlapFront != null || overlapRear != null), GTUException.class,
89                  "overlap parameter cannot be null for front / rear headway");
90          this.distance = distance;
91  
92          Throw.when(distance == null && (overlap == null || overlapFront == null || overlapRear == null), GTUException.class,
93                  "overlap parameter cannot be null for parallel headway");
94          Throw.when(overlap != null && overlap.si < 0, GTUException.class, "overlap cannot be negative");
95          this.overlap = overlap;
96          this.overlapFront = overlapFront;
97          this.overlapRear = overlapRear;
98      }
99  
100     /**
101      * Construct a new Headway information object, for an object ahead of us or behind us.
102      * @param distance the distance to the other object; if this constructor is used, distance cannot be null.
103      * @throws GTUException when id is null, or parameters are inconsistent
104      */
105     public AbstractHeadway(final Length distance) throws GTUException
106     {
107         this(distance, null, null, null);
108     }
109 
110     /**
111      * Construct a new Headway information object, for an object parallel with us.
112      * @param overlapFront the front-front distance to the other object; if this constructor is used, this value cannot be null.
113      * @param overlap the 'center' overlap with the other object; if this constructor is used, this value cannot be null.
114      * @param overlapRear the rear-rear distance to the other object; if this constructor is used, this value cannot be null.
115      * @throws GTUException when id is null, or parameters are inconsistent
116      */
117     @SuppressWarnings("checkstyle:parameternumber")
118     public AbstractHeadway(final Length overlapFront, final Length overlap, final Length overlapRear) throws GTUException
119     {
120         this(null, overlapFront, overlap, overlapRear);
121     }
122 
123     /** {@inheritDoc} */
124     @Override
125     public final Length getDistance()
126     {
127         return this.distance;
128     }
129 
130     /** {@inheritDoc} */
131     @Override
132     public final Length getOverlapFront()
133     {
134         return this.overlapFront;
135     }
136 
137     /** {@inheritDoc} */
138     @Override
139     public final Length getOverlapRear()
140     {
141         return this.overlapRear;
142     }
143 
144     /** {@inheritDoc} */
145     @Override
146     public final Length getOverlap()
147     {
148         return this.overlap;
149     }
150 
151     /** {@inheritDoc} */
152     @Override
153     public final boolean isAhead()
154     {
155         return this.distance != null && this.distance.si > 0.0;
156     }
157 
158     /** {@inheritDoc} */
159     @Override
160     public final boolean isBehind()
161     {
162         return this.distance != null && this.distance.si < 0.0;
163     }
164 
165     /** {@inheritDoc} */
166     @Override
167     public final boolean isParallel()
168     {
169         return this.overlap != null;
170     }
171 
172     /** {@inheritDoc} */
173     @SuppressWarnings("checkstyle:designforextension")
174     @Override
175     public int hashCode()
176     {
177         final int prime = 31;
178         int result = 1;
179         result = prime * result + ((this.distance == null) ? 0 : this.distance.hashCode());
180         result = prime * result + ((this.overlap == null) ? 0 : this.overlap.hashCode());
181         result = prime * result + ((this.overlapFront == null) ? 0 : this.overlapFront.hashCode());
182         result = prime * result + ((this.overlapRear == null) ? 0 : this.overlapRear.hashCode());
183         return result;
184     }
185 
186     /** {@inheritDoc} */
187     @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces"})
188     @Override
189     public boolean equals(final Object obj)
190     {
191         if (this == obj)
192             return true;
193         if (obj == null)
194             return false;
195         if (getClass() != obj.getClass())
196             return false;
197         AbstractHeadway other = (AbstractHeadway) obj;
198         if (this.distance == null)
199         {
200             if (other.distance != null)
201                 return false;
202         }
203         else if (!this.distance.equals(other.distance))
204             return false;
205         if (this.overlap == null)
206         {
207             if (other.overlap != null)
208                 return false;
209         }
210         else if (!this.overlap.equals(other.overlap))
211             return false;
212         if (this.overlapFront == null)
213         {
214             if (other.overlapFront != null)
215                 return false;
216         }
217         else if (!this.overlapFront.equals(other.overlapFront))
218             return false;
219         if (this.overlapRear == null)
220         {
221             if (other.overlapRear != null)
222                 return false;
223         }
224         else if (!this.overlapRear.equals(other.overlapRear))
225             return false;
226         return true;
227     }
228 
229     /** {@inheritDoc} */
230     @SuppressWarnings("checkstyle:designforextension")
231     @Override
232     public String toString()
233     {
234         if (isParallel())
235         {
236             return String.format("Parallel to object %s of type %s with speed %s", getId(), getObjectType(), getSpeed());
237         }
238         return String.format("Headway %s to object %s of type %s with speed %s", getDistance(), getId(), getObjectType(),
239                 getSpeed());
240     }
241 
242 }