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 import java.util.TreeSet;
7
8 import org.djunits.value.vdouble.scalar.Acceleration;
9 import org.djunits.value.vdouble.scalar.Duration;
10 import org.djunits.value.vdouble.scalar.Length;
11 import org.djunits.value.vdouble.scalar.Speed;
12 import org.djunits.value.vdouble.scalar.Time;
13 import org.djutils.exceptions.Throw;
14 import org.opentrafficsim.base.TimeStampedObject;
15 import org.opentrafficsim.base.parameters.ParameterException;
16 import org.opentrafficsim.base.parameters.ParameterTypeDouble;
17 import org.opentrafficsim.base.parameters.ParameterTypeDuration;
18 import org.opentrafficsim.base.parameters.Parameters;
19 import org.opentrafficsim.base.parameters.constraint.ConstraintInterface;
20 import org.opentrafficsim.core.gtu.GTUException;
21 import org.opentrafficsim.core.gtu.perception.EgoPerception;
22 import org.opentrafficsim.core.gtu.perception.PerceptionException;
23 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
24 import org.opentrafficsim.core.network.LateralDirectionality;
25 import org.opentrafficsim.core.network.OTSNetwork;
26 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
27 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
28 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
29 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
30 import org.opentrafficsim.road.gtu.lane.perception.SortedSetPerceptionIterable;
31 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Anticipation.NeighborTriplet;
32 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
33
34 import nl.tudelft.simulation.jstats.distributions.DistNormal;
35
36
37
38
39
40
41
42
43
44
45
46
47 public class DelayedNeighborsPerception extends AbstractDelayedNeighborsPerception
48 {
49
50
51 public static final ParameterTypeDuration TA =
52 new ParameterTypeDuration("ta", "anticipation time in future", Duration.ZERO, ConstraintInterface.POSITIVEZERO);
53
54
55 public static final ParameterTypeDuration TAUE =
56 new ParameterTypeDuration("tau_e", "error correlation time", Duration.createSI(20), ConstraintInterface.POSITIVE);
57
58
59 public static final ParameterTypeDouble SERROR =
60 new ParameterTypeDouble("s_error", "distance error factor", 0.1, ConstraintInterface.POSITIVEZERO);
61
62
63 public static final ParameterTypeDouble VERROR =
64 new ParameterTypeDouble("v_error", "speed error factor", 0.1, ConstraintInterface.POSITIVEZERO);
65
66
67 public static final ParameterTypeDouble AERROR =
68 new ParameterTypeDouble("a_error", "acceleration error factor", 0.2, ConstraintInterface.POSITIVEZERO);
69
70
71 private static final double MARGIN = 1e-6;
72
73
74 private static final long serialVersionUID = 20170217L;
75
76
77 private final Anticipation anticipation;
78
79
80 private Time rearrangeTime;
81
82
83 private final Map<RelativeLane, PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> followers = new HashMap<>();
84
85
86 private final Map<RelativeLane, PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> leaders = new HashMap<>();
87
88
89 private final Map<LateralDirectionality, SortedSet<HeadwayGTU>> firstFollowers = new HashMap<>();
90
91
92 private final Map<LateralDirectionality, SortedSet<HeadwayGTU>> firstLeaders = new HashMap<>();
93
94
95 private final Map<LateralDirectionality, Boolean> gtuAlongside = new HashMap<>();
96
97
98 private HashMap<String, ErrorValue> errors = new HashMap<>();
99
100
101 private final DistNormal norm;
102
103
104
105
106
107 public DelayedNeighborsPerception(final LanePerception perception, final Anticipation anticipation)
108 {
109 super(perception);
110 Throw.whenNull(anticipation, "Anticipation may not be null.");
111 this.anticipation = anticipation;
112 try
113 {
114 this.norm = new DistNormal(perception.getGtu().getSimulator().getReplication().getStream("perception"));
115 }
116 catch (GTUException exception)
117 {
118 throw new RuntimeException("GTU not initialized.", exception);
119 }
120 }
121
122
123
124
125 private void rearrangeNeighbors()
126 {
127 Time time;
128 Duration ta;
129 Duration taue;
130 Length length;
131 Length traveledDistance;
132 double distanceError;
133 double speedError;
134 double accelerationError;
135 Speed egoSpeed;
136 Duration dt;
137 try
138 {
139 time = getPerception().getGtu().getSimulator().getSimulatorTime();
140 if (time.equals(this.rearrangeTime))
141 {
142 return;
143 }
144 Parameters params = getPerception().getGtu().getParameters();
145 ta = params.getParameter(TA);
146 taue = params.getParameter(TAUE);
147 distanceError = params.getParameter(SERROR);
148 speedError = params.getParameter(VERROR);
149 accelerationError = params.getParameter(AERROR);
150 length = getPerception().getGtu().getLength();
151 EgoPerception ego = getPerception().getPerceptionCategory(EgoPerception.class);
152 egoSpeed = ego.getSpeed();
153 dt = params.getParameter(DT);
154 try
155 {
156 traveledDistance = getPerception().getGtu().getOdometer().minus(getInfo(ODOMETER).getObject());
157 }
158 catch (PerceptionException exception)
159 {
160 throw new RuntimeException("Odometer not percieved.", exception);
161 }
162 if (!ta.eq0())
163 {
164 Acceleration acceleration = ego.getAcceleration();
165 traveledDistance = traveledDistance.plus(this.anticipation.egoAnticipation(egoSpeed, acceleration, ta));
166 }
167 this.rearrangeTime = time;
168 }
169 catch (GTUException exception)
170 {
171 throw new RuntimeException("GTU not initialized while rearranging neighbors.", exception);
172 }
173 catch (ParameterException exception)
174 {
175 throw new RuntimeException("Could not obtain parameter.", exception);
176 }
177 catch (OperationalPlanException exception)
178 {
179 throw new RuntimeException("No ego perception.", exception);
180 }
181 this.firstFollowers.clear();
182 this.firstLeaders.clear();
183 this.gtuAlongside.clear();
184 this.followers.clear();
185 this.leaders.clear();
186 try
187 {
188 for (RelativeLane lane : getDelayedCrossSection())
189 {
190
191
192 if (lane.getNumLanes() == 1)
193 {
194
195 boolean gtuAlongSide = getInfo(NeighborsInfoType.getBooleanType(GTUALONGSIDE), lane).getObject();
196
197
198 SortedSet<HeadwayGTU> firstFollowersSet = new TreeSet<>();
199 this.firstFollowers.put(lane.getLateralDirectionality(), firstFollowersSet);
200 TimeStampedObject<SortedSet<HeadwayGTU>> delayedFirstFollowers =
201 getInfo(NeighborsInfoType.getSortedSetType(FIRSTFOLLOWERS), lane);
202 Duration d = time.minus(delayedFirstFollowers.getTimestamp()).plus(ta);
203 for (HeadwayGTU gtu : delayedFirstFollowers.getObject())
204 {
205 NeighborTriplet info = this.anticipation.anticipate(erroneousTriplet(gtu.getDistance().neg(),
206 gtu.getSpeed(), gtu.getAcceleration(), getError(gtu.getId(), taue, dt), distanceError,
207 speedError, accelerationError, egoSpeed), d, traveledDistance, false);
208 if (info.getHeadway().le0())
209 {
210 firstFollowersSet.add(gtu.moved(info.getHeadway().neg(), info.getSpeed(), info.getAcceleration()));
211 }
212 else
213 {
214 gtuAlongSide = true;
215 }
216 }
217
218
219 SortedSet<HeadwayGTU> firstLeaderssSet = new TreeSet<>();
220 this.firstLeaders.put(lane.getLateralDirectionality(), firstLeaderssSet);
221 TimeStampedObject<SortedSet<HeadwayGTU>> delayedFirstLeaders =
222 getInfo(NeighborsInfoType.getSortedSetType(FIRSTLEADERS), lane);
223 d = time.minus(delayedFirstLeaders.getTimestamp()).plus(ta);
224 for (HeadwayGTU gtu : delayedFirstLeaders.getObject())
225 {
226 NeighborTriplet info = this.anticipation.anticipate(erroneousTriplet(gtu.getDistance(), gtu.getSpeed(),
227 gtu.getAcceleration(), getError(gtu.getId(), taue, dt), distanceError, speedError,
228 accelerationError, egoSpeed), d, traveledDistance, true);
229 if (info.getHeadway().ge0())
230 {
231 firstLeaderssSet.add(gtu.moved(info.getHeadway(), info.getSpeed(), info.getAcceleration()));
232 }
233 else
234 {
235 gtuAlongSide = true;
236 }
237 }
238
239
240 this.gtuAlongside.put(lane.getLateralDirectionality(), gtuAlongSide);
241 }
242
243
244 SortedSetPerceptionIterable<HeadwayGTU> followersSet = new SortedSetPerceptionIterable<>(
245 (OTSNetwork) getPerception().getGtu().getReferencePosition().getLane().getParentLink().getNetwork());
246 this.followers.put(lane, followersSet);
247 SortedSetPerceptionIterable<HeadwayGTU> leadersSet = new SortedSetPerceptionIterable<>(
248 (OTSNetwork) getPerception().getGtu().getReferencePosition().getLane().getParentLink().getNetwork());
249 this.leaders.put(lane, leadersSet);
250
251
252 TimeStampedObject<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> delayedFollowers =
253 getInfo(NeighborsInfoType.getIterableType(FOLLOWERS), lane);
254 Duration d = time.minus(delayedFollowers.getTimestamp()).plus(ta);
255
256 PerceptionCollectable<HeadwayGTU, LaneBasedGTU> perc = delayedFollowers.getObject();
257 for (HeadwayGTU gtu : delayedFollowers.getObject())
258 {
259 NeighborTriplet info = this.anticipation.anticipate(
260 erroneousTriplet(gtu.getDistance().neg(), gtu.getSpeed(), gtu.getAcceleration(),
261 getError(gtu.getId(), taue, dt), distanceError, speedError, accelerationError, egoSpeed),
262 d, traveledDistance, false);
263 if (info.getHeadway().le(length) || lane.isCurrent())
264 {
265 followersSet.add(gtu.moved(info.getHeadway().neg(), info.getSpeed(), info.getAcceleration()));
266 }
267 else
268 {
269 leadersSet.add(gtu.moved(info.getHeadway().minus(length).minus(gtu.getLength()), info.getSpeed(),
270 info.getAcceleration()));
271 }
272 }
273
274
275 TimeStampedObject<PerceptionCollectable<HeadwayGTU, LaneBasedGTU>> delayedLeaders =
276 getInfo(NeighborsInfoType.getIterableType(LEADERS), lane);
277 d = time.minus(delayedLeaders.getTimestamp()).plus(ta);
278 for (HeadwayGTU gtu : delayedLeaders.getObject())
279 {
280
281 NeighborTriplet info = this.anticipation.anticipate(
282 erroneousTriplet(gtu.getDistance(), gtu.getSpeed(), gtu.getAcceleration(),
283 getError(gtu.getId(), taue, dt), distanceError, speedError, accelerationError, egoSpeed),
284 d, traveledDistance, true);
285 if (info.getHeadway().ge(gtu.getLength().neg()) || lane.isCurrent())
286 {
287 leadersSet.add(gtu.moved(info.getHeadway(), info.getSpeed(), info.getAcceleration()));
288 }
289 else
290 {
291 followersSet.add(gtu.moved(info.getHeadway().plus(length).plus(gtu.getLength()).neg(), info.getSpeed(),
292 info.getAcceleration()));
293 }
294 }
295
296 }
297
298 }
299 catch (PerceptionException | GTUException exception)
300 {
301
302 }
303
304 try
305 {
306
307 for (RelativeLane lane : getPerception().getLaneStructure().getExtendedCrossSection())
308 {
309 if (!this.followers.containsKey(lane))
310 {
311 this.followers.put(lane, new SortedSetPerceptionIterable<>((OTSNetwork) getPerception().getGtu()
312 .getReferencePosition().getLane().getParentLink().getNetwork()));
313 }
314 if (!this.leaders.containsKey(lane))
315 {
316 this.leaders.put(lane, new SortedSetPerceptionIterable<>((OTSNetwork) getPerception().getGtu()
317 .getReferencePosition().getLane().getParentLink().getNetwork()));
318 }
319 if (lane.isLeft() || lane.isRight())
320 {
321 if (!this.firstFollowers.containsKey(lane.getLateralDirectionality()))
322 {
323 this.firstFollowers.put(lane.getLateralDirectionality(), new TreeSet<>());
324 }
325 if (!this.firstLeaders.containsKey(lane.getLateralDirectionality()))
326 {
327 this.firstLeaders.put(lane.getLateralDirectionality(), new TreeSet<>());
328 }
329 if (!this.gtuAlongside.containsKey(lane.getLateralDirectionality()))
330 {
331 this.gtuAlongside.put(lane.getLateralDirectionality(), false);
332 }
333 }
334 }
335 }
336 catch (ParameterException | GTUException pe)
337 {
338
339 }
340
341 }
342
343
344
345
346
347
348
349
350 private double getError(final String gtuId, final Duration tau, final Duration dt)
351 {
352 Time now;
353 try
354 {
355 now = getTimestamp();
356 }
357 catch (GTUException exception)
358 {
359 throw new RuntimeException("Could not get time stamp.", exception);
360 }
361
362 double err;
363 ErrorValue errorValue;
364 if (!this.errors.containsKey(gtuId))
365 {
366 err = this.norm.draw();
367 errorValue = new ErrorValue();
368 this.errors.put(gtuId, errorValue);
369 }
370 else
371 {
372 errorValue = this.errors.get(gtuId);
373 if (errorValue.getTime().eq(now))
374 {
375 return errorValue.getError();
376 }
377 double dtErr = now.si - errorValue.getTime().si;
378 if (dtErr <= dt.si + MARGIN)
379 {
380 err = Math.exp(-dtErr / tau.si) * errorValue.getError() + Math.sqrt((2 * dtErr) / tau.si) * this.norm.draw();
381 }
382 else
383 {
384
385 err = this.norm.draw();
386 }
387 }
388 errorValue.set(now, err);
389 return err;
390
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404
405 @SuppressWarnings("checkstyle:parameternumber")
406 private NeighborTriplet erroneousTriplet(final Length distance, final Speed speed, final Acceleration acceleration,
407 final double error, final double distanceError, final double speedError, final double accelerationError,
408 final Speed egoSpeed)
409 {
410 Length s = Length.createSI(distance.si * (1 + ((distance.ge0() ? error : -error) * distanceError)));
411 Speed v = Speed.createSI(speed.si + (error * speedError * distance.si));
412 if (v.lt0())
413 {
414 v = Speed.ZERO;
415 }
416 Acceleration a = Acceleration.createSI(acceleration.si * (1 + error * accelerationError));
417 return new NeighborTriplet(s, v, a);
418 }
419
420
421 @Override
422 public final SortedSet<HeadwayGTU> getFirstLeaders(final LateralDirectionality lat)
423 throws ParameterException, NullPointerException, IllegalArgumentException
424 {
425 rearrangeNeighbors();
426 return this.firstLeaders.get(lat);
427 }
428
429
430 @Override
431 public final SortedSet<HeadwayGTU> getFirstFollowers(final LateralDirectionality lat)
432 throws ParameterException, NullPointerException, IllegalArgumentException
433 {
434 rearrangeNeighbors();
435 return this.firstFollowers.get(lat);
436 }
437
438
439 @Override
440 public final boolean isGtuAlongside(final LateralDirectionality lat)
441 throws ParameterException, NullPointerException, IllegalArgumentException
442 {
443 if (isGtuAlongsideOverride(lat))
444 {
445 return true;
446 }
447 rearrangeNeighbors();
448 if (this.gtuAlongside.containsKey(lat))
449 {
450 return this.gtuAlongside.get(lat);
451 }
452
453
454 return true;
455 }
456
457
458 @Override
459 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getLeaders(final RelativeLane lane)
460 {
461 rearrangeNeighbors();
462 return this.leaders.get(lane);
463 }
464
465
466 @Override
467 public final PerceptionCollectable<HeadwayGTU, LaneBasedGTU> getFollowers(final RelativeLane lane)
468 {
469 rearrangeNeighbors();
470 return this.followers.get(lane);
471 }
472
473
474
475
476
477
478
479
480
481
482
483
484 private class ErrorValue
485 {
486
487
488 private Time time;
489
490
491 private double error;
492
493
494
495
496 ErrorValue()
497 {
498 }
499
500
501
502
503 public Time getTime()
504 {
505 return this.time;
506 }
507
508
509
510
511 public double getError()
512 {
513 return this.error;
514 }
515
516
517
518
519
520 public void set(final Time t, final double err)
521 {
522 this.time = t;
523 this.error = err;
524 }
525
526
527 @Override
528 public final String toString()
529 {
530 return "ErrorValue [time=" + this.time + ", error=" + this.error + "]";
531 }
532
533 }
534
535
536 @Override
537 public final String toString()
538 {
539 return "DelayedNeighborsPerception [anticipation=" + this.anticipation + ", rearrangeTime=" + this.rearrangeTime
540 + ", followers=" + this.followers + ", leaders=" + this.leaders + ", firstFollowers=" + this.firstFollowers
541 + ", firstLeaders=" + this.firstLeaders + ", gtuAlongside=" + this.gtuAlongside + ", errors=" + this.errors
542 + ", norm=" + this.norm + "]";
543 }
544 }