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-2020 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 | ----->
36 * ----------
37 * ---------------
38 * | GTU 2 | ----->
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 | ----->
52 * ----------
53 * ---------------
54 * | GTU 2 | ----->
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 | ----->
68 * ----------
69 * ---------------
70 * | GTU 2 | ----->
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/../../../../org/opentrafficsim/road/gtu/lane/perception/headway/AbstractHeadway.html#AbstractHeadway">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 }