1 package org.opentrafficsim.road.gtu.lane.perception.categories.neighbors;
2
3 import java.util.HashMap;
4 import java.util.HashSet;
5 import java.util.Map;
6 import java.util.Set;
7 import java.util.SortedSet;
8
9 import org.djunits.value.vdouble.scalar.Duration;
10 import org.djunits.value.vdouble.scalar.Length;
11 import org.djunits.value.vdouble.scalar.Time;
12 import org.opentrafficsim.base.TimeStampedObject;
13 import org.opentrafficsim.base.parameters.ParameterException;
14 import org.opentrafficsim.base.parameters.ParameterTypeDuration;
15 import org.opentrafficsim.base.parameters.ParameterTypes;
16 import org.opentrafficsim.base.parameters.Parameters;
17 import org.opentrafficsim.core.gtu.GTUException;
18 import org.opentrafficsim.core.gtu.perception.PerceptionException;
19 import org.opentrafficsim.core.network.LateralDirectionality;
20 import org.opentrafficsim.core.network.NetworkException;
21 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
22 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
23 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
24 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
25 import org.opentrafficsim.road.gtu.lane.perception.categories.AbstractDelayedPerceptionCategory;
26 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
27
28 import nl.tudelft.simulation.dsol.SimRuntimeException;
29
30
31
32
33
34
35
36
37
38
39
40 public abstract class AbstractDelayedNeighborsPerception extends AbstractDelayedPerceptionCategory
41 implements NeighborsPerception
42 {
43
44
45 private static final long serialVersionUID = 20170217L;
46
47
48 protected static final ParameterTypeDuration TR = ParameterTypes.TR;
49
50
51 protected static final ParameterTypeDuration DT = ParameterTypes.DT;
52
53
54 private Time initialTime = null;
55
56
57 private final DirectNeighborsPerception direct;
58
59
60 private Duration reactionTime = null;
61
62
63 private Duration plannerTimeStep = null;
64
65
66 private Duration remainder = null;
67
68
69 public static final String FIRSTLEADERS = "firstLeaders";
70
71
72 public static final String FIRSTFOLLOWERS = "firstFollower";
73
74
75 public static final String GTUALONGSIDE = "gtuAlongside";
76
77
78 public static final String LEADERS = "leaders";
79
80
81 public static final String FOLLOWERS = "followers";
82
83
84 public static final NeighborsInfoType<SortedSet<RelativeLane>> CROSSSECTION = new NeighborsInfoType<>("cross-section");
85
86
87 public static final NeighborsInfoType<Length> ODOMETER = new NeighborsInfoType<>("odometer");
88
89
90 private boolean gtuAlongsideLeftOverride = false;
91
92
93 private boolean gtuAlongsideRightOverride = false;
94
95
96
97
98
99 public AbstractDelayedNeighborsPerception(final LanePerception perception)
100 {
101 super(perception);
102 this.direct = new DirectNeighborsPerception(perception, HeadwayGtuType.COPY);
103 }
104
105
106 @Override
107 public final void updateAll() throws GTUException, NetworkException, ParameterException
108 {
109
110 if (this.remainder == null)
111 {
112 try
113 {
114
115 Parameters params = getPerception().getGtu().getParameters();
116 this.reactionTime = params.getParameter(TR);
117 this.plannerTimeStep = params.getParameter(DT);
118 double rem;
119 if (this.reactionTime.eq0())
120 {
121 rem = 0;
122 }
123 else if (this.reactionTime.gt(this.plannerTimeStep))
124 {
125 rem = this.reactionTime.si % this.plannerTimeStep.si;
126 }
127 else
128 {
129 rem = this.plannerTimeStep.si - this.reactionTime.si;
130 }
131 this.remainder = Duration.createSI(rem);
132 }
133 catch (ParameterException | GTUException exception)
134 {
135 throw new RuntimeException("Exception while setting up delayed neighors perception.", exception);
136 }
137 }
138
139
140 Time now = getPerception().getGtu().getSimulator().getSimulatorTime();
141 if (this.initialTime == null)
142 {
143 this.initialTime = now;
144 }
145 if (now.minus(this.initialTime).le(this.reactionTime))
146 {
147 updateAllDelayed();
148 return;
149 }
150
151 if (this.remainder.eq0())
152 {
153
154 updateAllDelayed();
155 }
156 else
157 {
158
159 Time scheduledTime = now.plus(this.remainder);
160 try
161 {
162 getPerception().getGtu().getSimulator().scheduleEventAbs(scheduledTime, this, this, "updateAllDelayed", null);
163 }
164 catch (SimRuntimeException exception)
165 {
166 throw new RuntimeException("Scheduling perception update in the past.", exception);
167 }
168 }
169
170
171
172
173
174
175
176
177 if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.LEFT))
178 {
179 this.direct.updateFirstFollowers(LateralDirectionality.LEFT);
180 this.direct.updateFirstLeaders(LateralDirectionality.LEFT);
181 this.direct.updateGtuAlongside(LateralDirectionality.LEFT);
182 this.gtuAlongsideLeftOverride = newFirstLeaderOrFollower(getFollowers(RelativeLane.LEFT),
183 this.direct.getFirstFollowers(LateralDirectionality.LEFT))
184 || newFirstLeaderOrFollower(getLeaders(RelativeLane.LEFT),
185 this.direct.getFirstLeaders(LateralDirectionality.LEFT))
186 || this.direct.isGtuAlongside(LateralDirectionality.LEFT);
187 }
188 if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.RIGHT))
189 {
190 this.direct.updateFirstFollowers(LateralDirectionality.RIGHT);
191 this.direct.updateFirstLeaders(LateralDirectionality.RIGHT);
192 this.direct.updateGtuAlongside(LateralDirectionality.RIGHT);
193 this.gtuAlongsideRightOverride = newFirstLeaderOrFollower(getFollowers(RelativeLane.RIGHT),
194 this.direct.getFirstFollowers(LateralDirectionality.RIGHT))
195 || newFirstLeaderOrFollower(getLeaders(RelativeLane.RIGHT),
196 this.direct.getFirstLeaders(LateralDirectionality.RIGHT))
197 || this.direct.isGtuAlongside(LateralDirectionality.RIGHT);
198 }
199
200 }
201
202
203
204
205
206
207
208 private boolean newFirstLeaderOrFollower(final Iterable<? extends HeadwayGTU> delayedSet,
209 final Set<? extends HeadwayGTU> currentSet)
210 {
211 Set<String> set = new HashSet<>();
212 for (HeadwayGTU gtu : delayedSet)
213 {
214 set.add(gtu.getId());
215 }
216 for (HeadwayGTU gtu : currentSet)
217 {
218 if (!set.contains(gtu.getId()) && gtu.getDistance().si < 50)
219 {
220 return true;
221 }
222 }
223 return false;
224 }
225
226
227
228
229
230
231 public final boolean isGtuAlongsideOverride(final LateralDirectionality lat)
232 {
233 return lat.isLeft() ? this.gtuAlongsideLeftOverride : this.gtuAlongsideRightOverride;
234 }
235
236
237
238
239
240
241
242
243 protected void updateAllDelayed() throws GTUException, NetworkException, ParameterException
244 {
245
246 try
247 {
248 getGtu().getReferencePosition();
249 }
250 catch (GTUException exception)
251 {
252
253 return;
254 }
255
256 this.direct.updateAll();
257
258 if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.LEFT))
259 {
260 updateFirstLeaders(LateralDirectionality.LEFT);
261 updateFirstFollowers(LateralDirectionality.LEFT);
262 updateGtuAlongside(LateralDirectionality.LEFT);
263 }
264 if (getPerception().getLaneStructure().getExtendedCrossSection().contains(RelativeLane.RIGHT))
265 {
266 updateFirstLeaders(LateralDirectionality.RIGHT);
267 updateFirstFollowers(LateralDirectionality.RIGHT);
268 updateGtuAlongside(LateralDirectionality.RIGHT);
269 }
270 for (RelativeLane lane : getPerception().getLaneStructure().getExtendedCrossSection())
271 {
272 updateLeaders(lane);
273 updateFollowers(lane);
274 }
275 setInfo(CROSSSECTION,
276 new TimeStampedObject<>(getPerception().getLaneStructure().getExtendedCrossSection(), getTimestamp()));
277 setInfo(ODOMETER, new TimeStampedObject<>(getGtu().getOdometer(), getTimestamp()));
278 }
279
280
281 @Override
282 public final void updateFirstLeaders(final LateralDirectionality lat)
283 throws ParameterException, GTUException, NetworkException
284 {
285 setInfo(NeighborsInfoType.getSortedSetType(FIRSTLEADERS), new RelativeLane(lat, 1),
286 this.direct.getTimeStampedFirstLeaders(lat));
287 }
288
289
290 @Override
291 public final void updateFirstFollowers(final LateralDirectionality lat)
292 throws GTUException, ParameterException, NetworkException
293 {
294 setInfo(NeighborsInfoType.getSortedSetType(FIRSTFOLLOWERS), new RelativeLane(lat, 1),
295 this.direct.getTimeStampedFirstFollowers(lat));
296 }
297
298
299 @Override
300 public final void updateGtuAlongside(final LateralDirectionality lat) throws GTUException, ParameterException
301 {
302 setInfo(NeighborsInfoType.getBooleanType(GTUALONGSIDE), new RelativeLane(lat, 1),
303 this.direct.isGtuAlongsideTimeStamped(lat));
304 }
305
306
307 @Override
308 public final void updateLeaders(final RelativeLane lane) throws ParameterException, GTUException, NetworkException
309 {
310 setInfo(NeighborsInfoType.getIterableType(LEADERS), lane, this.direct.getTimeStampedLeaders(lane));
311 }
312
313
314 @Override
315 public final void updateFollowers(final RelativeLane lane) throws GTUException, NetworkException, ParameterException
316 {
317 setInfo(NeighborsInfoType.getIterableType(FOLLOWERS), lane, this.direct.getTimeStampedFollowers(lane));
318 }
319
320
321
322
323
324 public final SortedSet<RelativeLane> getDelayedCrossSection()
325 {
326 try
327 {
328 return getInfo(CROSSSECTION).getObject();
329 }
330 catch (PerceptionException exception)
331 {
332 throw new RuntimeException("Crosssection was not perceived.", exception);
333 }
334 }
335
336
337
338
339
340 public static final class NeighborsInfoType<T> extends DelayedInfoType<T>
341 {
342
343
344 private static final Map<String, NeighborsInfoType<?>> LANEINFOTYPES = new HashMap<>();
345
346
347
348
349
350 public NeighborsInfoType(final String id)
351 {
352 super(id, TR);
353 }
354
355
356
357
358
359
360 @SuppressWarnings("unchecked")
361 public static NeighborsInfoType<SortedSet<HeadwayGTU>> getSortedSetType(final String id)
362 {
363 if (!LANEINFOTYPES.containsKey(id))
364 {
365 LANEINFOTYPES.put(id, new NeighborsInfoType<SortedSet<HeadwayGTU>>(id));
366 }
367 return (NeighborsInfoType<SortedSet<HeadwayGTU>>) LANEINFOTYPES.get(id);
368 }
369
370
371
372
373
374
375 @SuppressWarnings("unchecked")
376 public static NeighborsInfoType<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> getIterableType(final String id)
377 {
378 if (!LANEINFOTYPES.containsKey(id))
379 {
380 LANEINFOTYPES.put(id, new NeighborsInfoType<SortedSet<HeadwayGTU>>(id));
381 }
382 return (NeighborsInfoType<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>>) LANEINFOTYPES.get(id);
383 }
384
385
386
387
388
389
390 @SuppressWarnings("unchecked")
391 public static NeighborsInfoType<Boolean> getBooleanType(final String id)
392 {
393 if (!LANEINFOTYPES.containsKey(id))
394 {
395 LANEINFOTYPES.put(id, new NeighborsInfoType<SortedSet<HeadwayGTU>>(id));
396 }
397 return (NeighborsInfoType<Boolean>) LANEINFOTYPES.get(id);
398 }
399
400
401 @Override
402 public String toString()
403 {
404 return "NeighborsInfoType []";
405 }
406
407 }
408
409 }