1 package org.opentrafficsim.road.gtu.lane.perception.categories.neighbors;
2
3 import java.util.HashMap;
4 import java.util.Map;
5 import java.util.SortedSet;
6
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djutils.exceptions.Throw;
9 import org.opentrafficsim.base.TimeStampedObject;
10 import org.opentrafficsim.base.parameters.ParameterException;
11 import org.opentrafficsim.base.parameters.ParameterTypeLength;
12 import org.opentrafficsim.base.parameters.ParameterTypes;
13 import org.opentrafficsim.core.gtu.GTUException;
14 import org.opentrafficsim.core.gtu.RelativePosition;
15 import org.opentrafficsim.core.network.LateralDirectionality;
16 import org.opentrafficsim.core.network.NetworkException;
17 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
18 import org.opentrafficsim.road.gtu.lane.perception.DownstreamNeighborsIterable;
19 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
20 import org.opentrafficsim.road.gtu.lane.perception.LaneStructureRecord;
21 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
22 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
23 import org.opentrafficsim.road.gtu.lane.perception.UpstreamNeighborsIterable;
24 import org.opentrafficsim.road.gtu.lane.perception.categories.LaneBasedAbstractPerceptionCategory;
25 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsUtil.DistanceGTU;
26 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
27
28
29
30
31
32
33
34
35
36
37
38
39 public class DirectNeighborsPerception extends LaneBasedAbstractPerceptionCategory implements NeighborsPerception
40 {
41
42
43 private static final long serialVersionUID = 20160811L;
44
45
46 protected static final ParameterTypeLength LOOKAHEAD = ParameterTypes.LOOKAHEAD;
47
48
49 protected static final ParameterTypeLength LOOKBACK = ParameterTypes.LOOKBACK;
50
51
52 private final Map<RelativeLane, TimeStampedObject<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>>> followers =
53 new HashMap<>();
54
55
56 private final Map<RelativeLane, TimeStampedObject<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>>> leaders =
57 new HashMap<>();
58
59
60 private final Map<LateralDirectionality, TimeStampedObject<SortedSet<HeadwayGTU>>> firstFollowers = new HashMap<>();
61
62
63 private final Map<LateralDirectionality, TimeStampedObject<SortedSet<HeadwayGTU>>> firstLeaders = new HashMap<>();
64
65
66 private final Map<LateralDirectionality, TimeStampedObject<Boolean>> gtuAlongside = new HashMap<>();
67
68
69 private final HeadwayGtuType headwayGtuType;
70
71
72
73
74
75 public DirectNeighborsPerception(final LanePerception perception, final HeadwayGtuType headwayGtuType)
76 {
77 super(perception);
78 this.headwayGtuType = headwayGtuType;
79 }
80
81
82 @Override
83 public final void updateAll() throws GTUException, NetworkException, ParameterException
84 {
85 this.firstLeaders.clear();
86 this.firstFollowers.clear();
87 this.gtuAlongside.clear();
88 if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.LEFT))
89 {
90 updateFirstLeaders(LateralDirectionality.LEFT);
91 updateFirstFollowers(LateralDirectionality.LEFT);
92 updateGtuAlongside(LateralDirectionality.LEFT);
93 }
94 if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.RIGHT))
95 {
96 updateFirstLeaders(LateralDirectionality.RIGHT);
97 updateFirstFollowers(LateralDirectionality.RIGHT);
98 updateGtuAlongside(LateralDirectionality.RIGHT);
99 }
100 this.leaders.clear();
101 this.followers.clear();
102 for (RelativeLane lane : getPerception().getLaneStructure().getExtendedCrossSection())
103 {
104 updateLeaders(lane);
105 updateFollowers(lane);
106 }
107 }
108
109
110 @Override
111 public final void updateFirstLeaders(final LateralDirectionality lat)
112 throws ParameterException, GTUException, NetworkException
113 {
114 checkLateralDirectionality(lat);
115 SortedSet<HeadwayGTU> headwaySet = NeighborsUtil.perceive(
116 NeighborsUtil.getFirstDownstreamGTUs(
117 getPerception().getLaneStructure().getFirstRecord(new RelativeLane(lat, 1)), getGtu().getFront(),
118 getGtu().getFront(), RelativePosition.REAR, getTimestamp()),
119 this.headwayGtuType, getGtu(), true);
120 this.firstLeaders.put(lat, new TimeStampedObject<>(headwaySet, getTimestamp()));
121 }
122
123
124 @Override
125 public final void updateFirstFollowers(final LateralDirectionality lat)
126 throws GTUException, ParameterException, NetworkException
127 {
128 checkLateralDirectionality(lat);
129 SortedSet<HeadwayGTU> headwaySet = NeighborsUtil.perceive(
130 NeighborsUtil.getFirstUpstreamGTUs(getPerception().getLaneStructure().getFirstRecord(new RelativeLane(lat, 1)),
131 getGtu().getRear(), getGtu().getRear(), RelativePosition.FRONT, getTimestamp()),
132 this.headwayGtuType, getGtu(), false);
133 this.firstFollowers.put(lat, new TimeStampedObject<>(headwaySet, getTimestamp()));
134 }
135
136
137 @Override
138 public final void updateGtuAlongside(final LateralDirectionality lat) throws GTUException, ParameterException
139 {
140
141 checkLateralDirectionality(lat);
142
143 SortedSet<DistanceGTU> headwaySet = NeighborsUtil.getFirstDownstreamGTUs(
144 getPerception().getLaneStructure().getFirstRecord(new RelativeLane(lat, 1)), getGtu().getRear(),
145 getGtu().getFront(), RelativePosition.FRONT, getTimestamp());
146 if (!headwaySet.isEmpty() && headwaySet.first().getDistance().le0())
147 {
148 this.gtuAlongside.put(lat, new TimeStampedObject<>(true, getTimestamp()));
149 return;
150 }
151
152 headwaySet =
153 NeighborsUtil.getFirstUpstreamGTUs(getPerception().getLaneStructure().getFirstRecord(new RelativeLane(lat, 1)),
154 getGtu().getFront(), getGtu().getRear(), RelativePosition.REAR, getTimestamp());
155 if (!headwaySet.isEmpty() && headwaySet.first().getDistance().le0())
156 {
157 this.gtuAlongside.put(lat, new TimeStampedObject<>(true, getTimestamp()));
158 return;
159 }
160
161 this.gtuAlongside.put(lat, new TimeStampedObject<>(false, getTimestamp()));
162
163 }
164
165
166 @Override
167 public final void updateLeaders(final RelativeLane lane) throws ParameterException, GTUException, NetworkException
168 {
169 Throw.whenNull(lane, "Lane may not be null.");
170 LaneStructureRecord record = getPerception().getLaneStructure().getFirstRecord(lane);
171 Length pos = record.getStartDistance().neg();
172 pos = record.getDirection().isPlus() ? pos.plus(getGtu().getFront().getDx()) : pos.minus(getGtu().getFront().getDx());
173 boolean ignoreIfUpstream = true;
174 PerceptionCollectable<HeadwayGTU,
175 LaneBasedGTU> it = new DownstreamNeighborsIterable(getGtu(), record, Length.max(Length.ZERO, pos),
176 getGtu().getParameters().getParameter(LOOKAHEAD), getGtu().getFront(), this.headwayGtuType, getGtu(),
177 lane, ignoreIfUpstream);
178 this.leaders.put(lane, new TimeStampedObject<>(it, getTimestamp()));
179 }
180
181
182 @Override
183 public final void updateFollowers(final RelativeLane lane) throws GTUException, NetworkException, ParameterException
184 {
185 Throw.whenNull(lane, "Lane may not be null.");
186 LaneStructureRecord record = getPerception().getLaneStructure().getFirstRecord(lane);
187 Length pos = record.getStartDistance().neg();
188 pos = record.getDirection().isPlus() ? pos.plus(getGtu().getFront().getDx()) : pos.minus(getGtu().getFront().getDx());
189 PerceptionCollectable<HeadwayGTU, LaneBasedGTU> it =
190 new UpstreamNeighborsIterable(getGtu(), record, Length.max(Length.ZERO, pos),
191 getGtu().getParameters().getParameter(LOOKBACK), getGtu().getRear(), this.headwayGtuType, lane);
192 this.followers.put(lane, new TimeStampedObject<>(it, getTimestamp()));
193 }
194
195
196 @Override
197 public final SortedSet<HeadwayGTU> getFirstLeaders(final LateralDirectionality lat)
198 throws ParameterException, NullPointerException, IllegalArgumentException
199 {
200 checkLateralDirectionality(lat);
201 return this.firstLeaders.get(lat).getObject();
202 }
203
204
205 @Override
206 public final SortedSet<HeadwayGTU> getFirstFollowers(final LateralDirectionality lat)
207 throws ParameterException, NullPointerException, IllegalArgumentException
208 {
209 checkLateralDirectionality(lat);
210 return getObjectOrNull(this.firstFollowers.get(lat));
211 }
212
213
214 @Override
215 public final boolean isGtuAlongside(final LateralDirectionality lat)
216 throws ParameterException, NullPointerException, IllegalArgumentException
217 {
218 checkLateralDirectionality(lat);
219 return getObjectOrNull(this.gtuAlongside.get(lat));
220 }
221
222
223 @Override
224 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getLeaders(final RelativeLane lane)
225 {
226 return getObjectOrNull(this.leaders.get(lane));
227 }
228
229
230 @Override
231 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getFollowers(final RelativeLane lane)
232 {
233 return getObjectOrNull(this.followers.get(lane));
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 public final TimeStampedObject<SortedSet<HeadwayGTU>> getTimeStampedFirstLeaders(final LateralDirectionality lat)
257 throws ParameterException, NullPointerException, IllegalArgumentException
258 {
259 checkLateralDirectionality(lat);
260 return this.firstLeaders.get(lat);
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284 public final TimeStampedObject<SortedSet<HeadwayGTU>> getTimeStampedFirstFollowers(final LateralDirectionality lat)
285 throws ParameterException, NullPointerException, IllegalArgumentException
286 {
287 checkLateralDirectionality(lat);
288 return this.firstFollowers.get(lat);
289 }
290
291
292
293
294
295
296
297
298
299 public final TimeStampedObject<Boolean> isGtuAlongsideTimeStamped(final LateralDirectionality lat)
300 throws ParameterException, NullPointerException, IllegalArgumentException
301 {
302 checkLateralDirectionality(lat);
303 return this.gtuAlongside.get(lat);
304 }
305
306
307
308
309
310
311
312 public final TimeStampedObject<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> getTimeStampedLeaders(
313 final RelativeLane lane)
314 {
315 return this.leaders.get(lane);
316 }
317
318
319
320
321
322
323
324 public final TimeStampedObject<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> getTimeStampedFollowers(
325 final RelativeLane lane)
326 {
327 return this.followers.get(lane);
328 }
329
330
331
332
333
334
335
336
337 private void checkLateralDirectionality(final LateralDirectionality lat)
338 throws ParameterException, NullPointerException, IllegalArgumentException
339 {
340
341 Throw.whenNull(lat, "Lateral directionality may not be null.");
342 Throw.when(lat.equals(LateralDirectionality.NONE), IllegalArgumentException.class,
343 "Lateral directionality may not be NONE.");
344 Throw.when(
345 (lat.equals(LateralDirectionality.LEFT)
346 && !getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.LEFT))
347 || (lat.equals(LateralDirectionality.RIGHT)
348 && !getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.RIGHT)),
349 IllegalArgumentException.class, "Lateral directionality may only point to an existing adjacent lane.");
350 }
351
352
353 @Override
354 public final String toString()
355 {
356 return "DirectNeighborsPesrception";
357 }
358
359 }