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