1 package org.opentrafficsim.road.gtu.lane.perceptionold;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.LinkedHashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11 import java.util.SortedSet;
12 import java.util.TreeSet;
13
14 import org.djunits.unit.LengthUnit;
15 import org.djunits.unit.SpeedUnit;
16 import org.djunits.value.vdouble.scalar.Length;
17 import org.djunits.value.vdouble.scalar.Speed;
18 import org.djunits.value.vdouble.scalar.Time;
19 import org.opentrafficsim.core.Throw;
20 import org.opentrafficsim.core.gtu.GTUDirectionality;
21 import org.opentrafficsim.core.gtu.GTUException;
22 import org.opentrafficsim.core.gtu.RelativePosition;
23 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
24 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
25 import org.opentrafficsim.core.gtu.perception.AbstractPerception;
26 import org.opentrafficsim.core.gtu.perception.TimeStampedObject;
27 import org.opentrafficsim.core.network.LateralDirectionality;
28 import org.opentrafficsim.core.network.NetworkException;
29 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
30 import org.opentrafficsim.road.gtu.lane.perception.InfrastructureLaneChangeInfo;
31 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
32 import org.opentrafficsim.road.gtu.lane.perception.headway.AbstractHeadwayGTU;
33 import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
34 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayConflict;
35 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayDistance;
36 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTUSimple;
37 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayTrafficLight;
38 import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
39 import org.opentrafficsim.road.gtu.lane.tactical.LanePathInfo;
40 import org.opentrafficsim.road.network.lane.Lane;
41 import org.opentrafficsim.road.network.lane.LaneDirection;
42 import org.opentrafficsim.road.network.speed.SpeedLimitProspect;
43 import org.opentrafficsim.road.network.speed.SpeedLimitTypes;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public abstract class AbstractLanePerception extends AbstractPerception implements LanePerception
64 {
65
66 private static final long serialVersionUID = 20151128L;
67
68
69 private TimeStampedObject<Headway> forwardHeadway;
70
71
72 private TimeStampedObject<Headway> backwardHeadway;
73
74
75 private TimeStampedObject<Speed> speedLimit;
76
77
78 private TimeStampedObject<Map<Lane, Set<Lane>>> accessibleAdjacentLanesLeft;
79
80
81 private TimeStampedObject<Map<Lane, Set<Lane>>> accessibleAdjacentLanesRight;
82
83
84 private TimeStampedObject<Collection<Headway>> parallelHeadwaysLeft;
85
86
87 private TimeStampedObject<Collection<Headway>> parallelHeadwaysRight;
88
89
90 private TimeStampedObject<Collection<Headway>> neighboringHeadwaysLeft;
91
92
93 private TimeStampedObject<Collection<Headway>> neighboringHeadwaysRight;
94
95
96 private TimeStampedObject<LanePathInfo> lanePathInfo;
97
98
99
100
101
102
103
104
105
106
107 public AbstractLanePerception(final LaneBasedGTU gtu)
108 {
109 super(gtu);
110 }
111
112
113
114
115
116
117 private Time getTimestamp() throws GTUException
118 {
119 if (getGtu() == null)
120 {
121 throw new GTUException("gtu value has not been initialized for LanePerception when perceiving.");
122 }
123 return getGtu().getSimulator().getSimulatorTime().getTime();
124 }
125
126
127
128
129
130
131 public final void updateLanePathInfo() throws GTUException, NetworkException, ParameterException
132 {
133 Time timestamp = getTimestamp();
134 this.lanePathInfo = new TimeStampedObject<LanePathInfo>(AbstractLaneBasedTacticalPlanner.buildLanePathInfo(getGtu(),
135 getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKAHEAD)), timestamp);
136 }
137
138
139 @Override
140 public final void updateSpeedLimit() throws GTUException, NetworkException
141 {
142 Time timestamp = getTimestamp();
143
144 this.speedLimit = new TimeStampedObject<>(new Speed(Double.MAX_VALUE, SpeedUnit.SI), timestamp);
145 for (Lane lane : getGtu().getLanes().keySet())
146 {
147 if (lane.getSpeedLimit(getGtu().getGTUType()).lt(this.speedLimit.getObject()))
148 {
149 this.speedLimit = new TimeStampedObject<>(lane.getSpeedLimit(getGtu().getGTUType()), timestamp);
150 }
151 }
152 }
153
154
155 @Override
156 public final void updateForwardHeadway() throws GTUException, NetworkException, ParameterException
157 {
158 Time timestamp = getTimestamp();
159 if (this.lanePathInfo == null || this.lanePathInfo.getTimestamp().ne(timestamp))
160 {
161 updateLanePathInfo();
162 }
163 Length maximumForwardHeadway = getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKAHEAD);
164 this.forwardHeadway = new TimeStampedObject<>(forwardHeadway(maximumForwardHeadway), timestamp);
165 }
166
167
168 @Override
169 public final void updateBackwardHeadway() throws GTUException, NetworkException, ParameterException
170 {
171 Time timestamp = getTimestamp();
172 Length maximumReverseHeadway = getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKBACKOLD);
173 this.backwardHeadway = new TimeStampedObject<>(backwardHeadway(maximumReverseHeadway), timestamp);
174 }
175
176
177 @Override
178 public final void updateAccessibleAdjacentLanesLeft() throws GTUException
179 {
180 Time timestamp = getTimestamp();
181 Map<Lane, Set<Lane>> accessibleAdjacentLanesMap = new HashMap<>();
182 for (Lane lane : getGtu().getLanes().keySet())
183 {
184 Set<Lane> adjacentLanes = new HashSet<Lane>(1);
185 adjacentLanes.addAll(lane.accessibleAdjacentLanes(LateralDirectionality.LEFT, getGtu().getGTUType()));
186 accessibleAdjacentLanesMap.put(lane, adjacentLanes);
187 }
188 this.accessibleAdjacentLanesLeft = new TimeStampedObject<>(accessibleAdjacentLanesMap, timestamp);
189 }
190
191
192 @Override
193 public final void updateAccessibleAdjacentLanesRight() throws GTUException
194 {
195 Time timestamp = getTimestamp();
196 Map<Lane, Set<Lane>> accessibleAdjacentLanesMap = new HashMap<>();
197 for (Lane lane : getGtu().getLanes().keySet())
198 {
199 Set<Lane> adjacentLanes = new HashSet<Lane>(1);
200 adjacentLanes.addAll(lane.accessibleAdjacentLanes(LateralDirectionality.RIGHT, getGtu().getGTUType()));
201 accessibleAdjacentLanesMap.put(lane, adjacentLanes);
202 }
203 this.accessibleAdjacentLanesRight = new TimeStampedObject<>(accessibleAdjacentLanesMap, timestamp);
204 }
205
206
207 @Override
208 public final void updateParallelHeadwaysLeft() throws GTUException
209 {
210 Time timestamp = getTimestamp();
211 if (this.accessibleAdjacentLanesLeft == null || !timestamp.equals(this.accessibleAdjacentLanesLeft.getTimestamp()))
212 {
213 updateAccessibleAdjacentLanesLeft();
214 }
215 Set<Headway> parallelHeadwaySet = new HashSet<>();
216 for (Lane lane : this.accessibleAdjacentLanesLeft.getObject().keySet())
217 {
218 for (Lane adjacentLane : this.accessibleAdjacentLanesLeft.getObject().get(lane))
219 {
220 parallelHeadwaySet.addAll(parallel(adjacentLane, timestamp));
221 }
222 }
223 this.parallelHeadwaysLeft = new TimeStampedObject<>(parallelHeadwaySet, timestamp);
224 }
225
226
227 @Override
228 public final void updateParallelHeadwaysRight() throws GTUException
229 {
230 Time timestamp = getTimestamp();
231 if (this.accessibleAdjacentLanesRight == null || !timestamp.equals(this.accessibleAdjacentLanesRight.getTimestamp()))
232 {
233 updateAccessibleAdjacentLanesRight();
234 }
235 Set<Headway> parallelHeadwaySet = new HashSet<>();
236 for (Lane lane : this.accessibleAdjacentLanesRight.getObject().keySet())
237 {
238 for (Lane adjacentLane : this.accessibleAdjacentLanesRight.getObject().get(lane))
239 {
240 parallelHeadwaySet.addAll(parallel(adjacentLane, timestamp));
241 }
242 }
243 this.parallelHeadwaysRight = new TimeStampedObject<>(parallelHeadwaySet, timestamp);
244 }
245
246
247 @Override
248 public final void updateLaneTrafficLeft() throws GTUException, NetworkException, ParameterException
249 {
250 Time timestamp = getTimestamp();
251 if (this.accessibleAdjacentLanesLeft == null || !timestamp.equals(this.accessibleAdjacentLanesLeft.getTimestamp()))
252 {
253 updateAccessibleAdjacentLanesLeft();
254 }
255
256 if (this.parallelHeadwaysLeft == null || !timestamp.equals(this.parallelHeadwaysLeft.getTimestamp()))
257 {
258 updateParallelHeadwaysLeft();
259 }
260
261
262 Length maximumForwardHeadway = getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKAHEAD);
263 Length maximumReverseHeadway = getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKBACKOLD);
264 this.neighboringHeadwaysLeft = new TimeStampedObject<>(
265 collectNeighborLaneTraffic(LateralDirectionality.LEFT, timestamp, maximumForwardHeadway, maximumReverseHeadway),
266 timestamp);
267 }
268
269
270 @Override
271 public final void updateLaneTrafficRight() throws GTUException, NetworkException, ParameterException
272 {
273 Time timestamp = getTimestamp();
274 if (this.accessibleAdjacentLanesRight == null || !timestamp.equals(this.accessibleAdjacentLanesRight.getTimestamp()))
275 {
276 updateAccessibleAdjacentLanesRight();
277 }
278
279 if (this.parallelHeadwaysRight == null || !timestamp.equals(this.parallelHeadwaysRight.getTimestamp()))
280 {
281 updateParallelHeadwaysRight();
282 }
283
284
285 Length maximumForwardHeadway = getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKAHEAD);
286 Length maximumReverseHeadway = getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKBACKOLD);
287 this.neighboringHeadwaysRight = new TimeStampedObject<>(collectNeighborLaneTraffic(LateralDirectionality.RIGHT,
288 timestamp, maximumForwardHeadway, maximumReverseHeadway), timestamp);
289 }
290
291
292 @Override
293 public final Map<Lane, Set<Lane>> accessibleAdjacentLaneMap(final LateralDirectionality lateralDirection)
294 {
295 return lateralDirection.equals(LateralDirectionality.LEFT) ? this.accessibleAdjacentLanesLeft.getObject()
296 : this.accessibleAdjacentLanesRight.getObject();
297 }
298
299
300 @Override
301 public final Collection<Headway> getNeighboringHeadways(final LateralDirectionality lateralDirection)
302 {
303 return lateralDirection.equals(LateralDirectionality.LEFT) ? this.parallelHeadwaysLeft.getObject()
304 : this.parallelHeadwaysRight.getObject();
305 }
306
307
308 @Override
309 public final Collection<Headway> getParallelHeadways(final LateralDirectionality lateralDirection)
310 {
311 return lateralDirection.equals(LateralDirectionality.LEFT) ? this.neighboringHeadwaysLeft.getObject()
312 : this.neighboringHeadwaysRight.getObject();
313 }
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 private Headway forwardHeadway(final Length maxDistance) throws GTUException, NetworkException
336 {
337 LanePathInfo lpi = getLanePathInfo();
338 return forwardHeadway(lpi, maxDistance);
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359 private Headway forwardHeadway(final LanePathInfo lpi, final Length maxDistance) throws GTUException, NetworkException
360 {
361 Throw.when(maxDistance.le(Length.ZERO), GTUException.class, "forwardHeadway: maxDistance should be positive");
362
363 int ldIndex = 0;
364 LaneDirection ld = lpi.getReferenceLaneDirection();
365 double gtuPosFrontSI = lpi.getReferencePosition().si;
366 if (lpi.getReferenceLaneDirection().getDirection().isPlus())
367 {
368 gtuPosFrontSI += getGtu().getFront().getDx().si;
369 }
370 else
371 {
372 gtuPosFrontSI -= getGtu().getFront().getDx().si;
373 }
374
375
376
377 while ((gtuPosFrontSI > ld.getLane().getLength().si || gtuPosFrontSI < 0.0)
378 && ldIndex < lpi.getLaneDirectionList().size() - 1)
379 {
380 ldIndex++;
381 if (ld.getDirection().isPlus())
382 {
383 if (lpi.getLaneDirectionList().get(ldIndex).getDirection().isPlus())
384 {
385 gtuPosFrontSI -= ld.getLane().getLength().si;
386 }
387 else
388 {
389 gtuPosFrontSI = lpi.getLaneDirectionList().get(ldIndex).getLane().getLength().si - gtuPosFrontSI;
390 }
391 ld = lpi.getLaneDirectionList().get(ldIndex);
392 }
393 else
394
395 {
396 if (lpi.getLaneDirectionList().get(ldIndex).getDirection().isPlus())
397 {
398 gtuPosFrontSI += ld.getLane().getLength().si;
399 }
400 else
401 {
402 gtuPosFrontSI += lpi.getLaneDirectionList().get(ldIndex).getLane().getLength().si;
403 }
404 ld = lpi.getLaneDirectionList().get(ldIndex);
405 }
406 }
407
408 double maxDistanceSI = maxDistance.si;
409 Time time = getGtu().getSimulator().getSimulatorTime().getTime();
410
411
412 Headway closest = headwayLane(ld, gtuPosFrontSI, 0.0, time);
413 if (closest != null)
414 {
415 if (closest.getDistance().si > maxDistanceSI)
416 {
417 return new HeadwayDistance(maxDistanceSI);
418 }
419 return closest;
420 }
421 double cumDistSI = ld.getDirection().isPlus() ? ld.getLane().getLength().si - gtuPosFrontSI : gtuPosFrontSI;
422 for (int i = ldIndex + 1; i < lpi.getLaneDirectionList().size(); i++)
423 {
424 ld = lpi.getLaneDirectionList().get(i);
425 closest = headwayLane(ld, ld.getDirection().isPlus() ? 0.0 : ld.getLane().getLength().si, cumDistSI, time);
426 if (closest != null)
427 {
428 if (closest.getDistance().si > maxDistanceSI)
429 {
430 return new HeadwayDistance(maxDistanceSI);
431 }
432 return closest;
433 }
434 cumDistSI += ld.getLane().getLength().si;
435 }
436 return new HeadwayDistance(maxDistanceSI);
437 }
438
439
440
441
442
443
444
445
446
447
448
449 private Headway headwayLane(final LaneDirection laneDirection, final double startPosSI, final double cumDistSI,
450 final Time now) throws GTUException
451 {
452 Lane lane = laneDirection.getLane();
453 LaneBasedGTU laneBasedGTU = lane.getGtuAhead(new Length(startPosSI, LengthUnit.SI), laneDirection.getDirection(),
454 RelativePosition.REAR, now);
455 if (laneBasedGTU == null)
456 {
457 return null;
458 }
459 double distanceSI = Math.abs(laneBasedGTU.position(lane, laneBasedGTU.getRear()).si - startPosSI);
460 return new HeadwayGTUSimple(laneBasedGTU.getId(), laneBasedGTU.getGTUType(),
461 new Length(cumDistSI + distanceSI, LengthUnit.SI), laneBasedGTU.getLength(), laneBasedGTU.getSpeed(),
462 laneBasedGTU.getAcceleration());
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479 private Headway backwardHeadway(final Length maxDistance) throws GTUException, NetworkException
480 {
481 Throw.when(maxDistance.ge(Length.ZERO), GTUException.class, "backwardHeadway: maxDistance should be negative");
482 Time time = getGtu().getSimulator().getSimulatorTime().getTime();
483 double maxDistanceSI = maxDistance.si;
484 Headway foundHeadway = new HeadwayDistance(-maxDistanceSI);
485 for (Lane lane : getGtu().positions(getGtu().getRear()).keySet())
486 {
487 Headway closest = headwayRecursiveBackwardSI(lane, getGtu().getLanes().get(lane),
488 getGtu().position(lane, getGtu().getRear(), time).getSI(), 0.0, -maxDistanceSI, time);
489 if (closest.getDistance().si < -maxDistanceSI && closest.getDistance().si < -foundHeadway.getDistance().si)
490 {
491 foundHeadway = closest;
492 }
493 }
494 if (foundHeadway instanceof AbstractHeadwayGTU)
495 {
496 return new HeadwayGTUSimple(foundHeadway.getId(), ((AbstractHeadwayGTU) foundHeadway).getGtuType(),
497 foundHeadway.getDistance().multiplyBy(-1.0), foundHeadway.getLength(), foundHeadway.getSpeed(), null);
498 }
499 if (foundHeadway instanceof HeadwayDistance)
500 {
501 return new HeadwayDistance(foundHeadway.getDistance().multiplyBy(-1.0));
502 }
503
504 throw new GTUException("backwardHeadway not implemented yet for other object types than GTU");
505 }
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 private Headway headwayRecursiveBackwardSI(final Lane lane, final GTUDirectionality direction, final double lanePositionSI,
524 final double cumDistanceSI, final double maxDistanceSI, final Time when) throws GTUException
525 {
526 LaneBasedGTU otherGTU =
527 lane.getGtuBehind(new Length(lanePositionSI, LengthUnit.SI), direction, RelativePosition.FRONT, when);
528 if (otherGTU != null)
529 {
530 double distanceM = cumDistanceSI + lanePositionSI - otherGTU.position(lane, otherGTU.getFront(), when).getSI();
531 if (distanceM > 0 && distanceM <= maxDistanceSI)
532 {
533 return new HeadwayGTUSimple(otherGTU.getId(), otherGTU.getGTUType(), new Length(distanceM, LengthUnit.SI),
534 otherGTU.getLength(), otherGTU.getSpeed(), null);
535 }
536 return new HeadwayDistance(Double.MAX_VALUE);
537 }
538
539
540 if (cumDistanceSI + lanePositionSI < maxDistanceSI)
541 {
542
543 if (lane.prevLanes(getGtu().getGTUType()).size() > 0)
544 {
545 Headway foundMaxGTUDistanceSI = new HeadwayDistance(Double.MAX_VALUE);
546 for (Lane prevLane : lane.prevLanes(getGtu().getGTUType()).keySet())
547 {
548
549 double traveledDistanceSI = cumDistanceSI + lanePositionSI;
550
551 Headway closest = headwayRecursiveBackwardSI(prevLane, direction, prevLane.getLength().getSI(),
552 traveledDistanceSI, maxDistanceSI, when);
553 if (closest.getDistance().si < maxDistanceSI
554 && closest.getDistance().si < foundMaxGTUDistanceSI.getDistance().si)
555 {
556 foundMaxGTUDistanceSI = closest;
557 }
558 }
559 return foundMaxGTUDistanceSI;
560 }
561 }
562
563
564 return new HeadwayDistance(Double.MAX_VALUE);
565 }
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581 private Collection<Headway> parallel(final Lane lane, final Time when) throws GTUException
582 {
583 Collection<Headway> headwayCollection = new LinkedHashSet<Headway>();
584 for (Lane l : getGtu().getLanes().keySet())
585 {
586
587 if (l.getParentLink().equals(lane.getParentLink()))
588 {
589
590 double posFractionRef = getGtu().fractionalPosition(l, getGtu().getReference(), when);
591 double posFractionFront = Math.max(0.0, posFractionRef + getGtu().getFront().getDx().si / lane.getLength().si);
592 double posFractionRear = Math.min(1.0, posFractionRef + getGtu().getRear().getDx().si / lane.getLength().si);
593
594
595 double posMin = Math.min(posFractionFront, posFractionRear);
596 double posMax = Math.max(posFractionFront, posFractionRear);
597 for (LaneBasedGTU otherGTU : lane.getGtuList())
598 {
599 if (!otherGTU.equals(this))
600 {
601
602
603
604
605 double gtuFractionRef = otherGTU.fractionalPosition(lane, otherGTU.getReference(), when);
606 double gtuFractionFront =
607 Math.max(0.0, gtuFractionRef + otherGTU.getFront().getDx().si / lane.getLength().si);
608 double gtuFractionRear =
609 Math.min(1.0, gtuFractionRef + otherGTU.getRear().getDx().si / lane.getLength().si);
610 double gtuMin = Math.min(gtuFractionFront, gtuFractionRear);
611 double gtuMax = Math.max(gtuFractionFront, gtuFractionRear);
612
613 Length overlapFront = new Length(1.0, LengthUnit.SI);
614 Length overlap = new Length(1.0, LengthUnit.SI);
615 Length overlapRear = new Length(1.0, LengthUnit.SI);
616 if ((gtuMin >= posMin && gtuMin <= posMax) || (gtuMax >= posMin && gtuMax <= posMax)
617 || (posMin >= gtuMin && posMin <= gtuMax) || (posMax >= gtuMin && posMax <= gtuMax))
618 {
619 headwayCollection.add(new HeadwayGTUSimple(otherGTU.getId(), otherGTU.getGTUType(), overlapFront,
620 overlap, overlapRear, otherGTU.getLength(), otherGTU.getSpeed(),
621 otherGTU.getAcceleration()));
622 }
623 }
624 }
625 }
626 }
627 return headwayCollection;
628 }
629
630
631
632
633
634
635
636
637
638
639
640
641 private Collection<Headway> parallel(final LateralDirectionality lateralDirection, final Time when) throws GTUException
642 {
643 Collection<Headway> gtuSet = new LinkedHashSet<Headway>();
644 for (Lane lane : getGtu().getLanes().keySet())
645 {
646 for (Lane adjacentLane : accessibleAdjacentLaneMap(lateralDirection).get(lane))
647 {
648 gtuSet.addAll(parallel(adjacentLane, when));
649 }
650 }
651 return gtuSet;
652 }
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675 public final Lane bestAccessibleAdjacentLane(final Lane currentLane, final LateralDirectionality lateralDirection,
676 final Length longitudinalPosition)
677 {
678 Set<Lane> candidates = accessibleAdjacentLaneMap(lateralDirection).get(currentLane);
679 if (candidates.isEmpty())
680 {
681 return null;
682 }
683 if (candidates.size() == 1)
684 {
685 return candidates.iterator().next();
686 }
687
688 Lane bestLane = null;
689 double widestSeen = Double.NEGATIVE_INFINITY;
690 for (Lane lane : candidates)
691 {
692 if (lane.getWidth(longitudinalPosition).getSI() > widestSeen)
693 {
694 widestSeen = lane.getWidth(longitudinalPosition).getSI();
695 bestLane = lane;
696 }
697 }
698 return bestLane;
699 }
700
701
702
703
704
705
706
707
708
709
710
711
712
713 private Collection<Headway> collectNeighborLaneTraffic(final LateralDirectionality directionality, final Time when,
714 final Length maximumForwardHeadway, final Length maximumReverseHeadway)
715 throws NetworkException, GTUException, ParameterException
716 {
717 Collection<Headway> result = new HashSet<Headway>();
718 for (Headway p : parallel(directionality, when))
719 {
720
721 result.add(new HeadwayGTUSimple(p.getId(), ((AbstractHeadwayGTU) p).getGtuType(),
722 new Length(Double.NaN, LengthUnit.SI), p.getLength(), p.getSpeed(), p.getAcceleration()));
723 }
724
725
726 for (Lane adjacentLane : accessibleAdjacentLaneMap(directionality).get(getLanePathInfo().getReferenceLane()))
727 {
728 LanePathInfo lpiAdjacent = buildLanePathInfoAdjacent(adjacentLane, directionality, when);
729 Headway leader = forwardHeadway(lpiAdjacent, maximumForwardHeadway);
730 if (null != leader.getId() && !result.contains(leader))
731 {
732 result.add(leader);
733 }
734 }
735
736
737 for (Lane lane : getGtu().getLanes().keySet())
738 {
739 for (Lane adjacentLane : accessibleAdjacentLaneMap(directionality).get(lane))
740 {
741 Headway follower = headwayRecursiveBackwardSI(adjacentLane, getGtu().getLanes().get(lane),
742 getGtu().projectedPosition(adjacentLane, getGtu().getRear(), when).getSI(), 0.0,
743 -maximumReverseHeadway.getSI(), when);
744 if (follower instanceof AbstractHeadwayGTU)
745 {
746 boolean found = false;
747 for (Headway headway : result)
748 {
749 if (headway.getId().equals(follower.getId()))
750 {
751 found = true;
752 }
753 }
754 if (!found)
755 {
756 result.add(new HeadwayGTUSimple(follower.getId(), ((AbstractHeadwayGTU) follower).getGtuType(),
757 follower.getDistance().multiplyBy(-1.0), follower.getLength(), follower.getSpeed(), null));
758 }
759 }
760 else if (follower instanceof HeadwayDistance)
761 {
762 result.add(new HeadwayDistance(follower.getDistance().multiplyBy(-1.0)));
763 }
764 else
765 {
766 throw new GTUException(
767 "collectNeighborLaneTraffic not yet suited to observe obstacles on neighboring lanes");
768 }
769 }
770 }
771 return result;
772 }
773
774
775
776
777
778
779
780
781
782
783
784
785 private LanePathInfo buildLanePathInfoAdjacent(final Lane adjacentLane, final LateralDirectionality direction,
786 final Time when) throws GTUException, NetworkException, ParameterException
787 {
788 if (this.lanePathInfo == null || this.lanePathInfo.getTimestamp().ne(when))
789 {
790 updateLanePathInfo();
791 }
792 LanePathInfo lpi = getLanePathInfo();
793 List<LaneDirection> laneDirectionList = new ArrayList<>();
794 laneDirectionList.add(new LaneDirection(adjacentLane, lpi.getReferenceLaneDirection().getDirection()));
795 Length referencePosition = getGtu().projectedPosition(adjacentLane, getGtu().getReference(), when);
796 for (int i = 1; i < lpi.getLaneDirectionList().size(); i++)
797 {
798 LaneDirection ld = lpi.getLaneDirectionList().get(i);
799 Set<Lane> accessibleLanes = ld.getLane().accessibleAdjacentLanes(direction, getGtu().getGTUType());
800 Lane adjLane = null;
801 for (Lane lane : accessibleLanes)
802 {
803 if (lane.getParentLink().equals(ld.getLane().getParentLink()))
804 {
805 adjLane = lane;
806 }
807 }
808 if (adjLane == null)
809 {
810 break;
811 }
812 laneDirectionList.add(new LaneDirection(adjLane, ld.getDirection()));
813 }
814 return new LanePathInfo(null, laneDirectionList, referencePosition);
815 }
816
817
818
819
820
821
822 @Override
823 public final LaneBasedGTU getGtu()
824 {
825 return (LaneBasedGTU) super.getGtu();
826 }
827
828
829
830
831
832 public final LanePathInfo getLanePathInfo()
833 {
834 return this.lanePathInfo.getObject();
835 }
836
837
838 @Override
839 public final Headway getForwardHeadway()
840 {
841 return this.forwardHeadway.getObject();
842 }
843
844
845 @Override
846 public final Headway getBackwardHeadway()
847 {
848 return this.backwardHeadway.getObject();
849 }
850
851
852 @Override
853 public final Map<Lane, Set<Lane>> getAccessibleAdjacentLanesLeft()
854 {
855 return this.accessibleAdjacentLanesLeft.getObject();
856 }
857
858
859 @Override
860 public final Map<Lane, Set<Lane>> getAccessibleAdjacentLanesRight()
861 {
862 return this.accessibleAdjacentLanesRight.getObject();
863 }
864
865
866 @Override
867 public final Collection<Headway> getNeighboringHeadwaysLeft()
868 {
869 return this.neighboringHeadwaysLeft.getObject();
870 }
871
872
873 @Override
874 public final Collection<Headway> getNeighboringHeadwaysRight()
875 {
876 return this.neighboringHeadwaysRight.getObject();
877 }
878
879
880 @Override
881 public final Collection<Headway> getParallelHeadwaysLeft()
882 {
883 return this.parallelHeadwaysLeft.getObject();
884 }
885
886
887 @Override
888 public final Collection<Headway> getParallelHeadwaysRight()
889 {
890 return this.parallelHeadwaysRight.getObject();
891 }
892
893
894 @Override
895 public final Speed getSpeedLimit()
896 {
897 return this.speedLimit.getObject();
898 }
899
900
901 @Override
902 public final TimeStampedObject<Headway> getTimeStampedForwardHeadway()
903 {
904 return this.forwardHeadway;
905 }
906
907
908 @Override
909 public final TimeStampedObject<Headway> getTimeStampedBackwardHeadway()
910 {
911 return this.backwardHeadway;
912 }
913
914
915 @Override
916 public final TimeStampedObject<Map<Lane, Set<Lane>>> getTimeStampedAccessibleAdjacentLanesLeft()
917 {
918 return this.accessibleAdjacentLanesLeft;
919 }
920
921
922 @Override
923 public final TimeStampedObject<Map<Lane, Set<Lane>>> getTimeStampedAccessibleAdjacentLanesRight()
924 {
925 return this.accessibleAdjacentLanesRight;
926 }
927
928
929 @Override
930 public final TimeStampedObject<Collection<Headway>> getTimeStampedNeighboringHeadwaysLeft()
931 {
932 return this.neighboringHeadwaysLeft;
933 }
934
935
936 @Override
937 public final TimeStampedObject<Collection<Headway>> getTimeStampedNeighboringHeadwaysRight()
938 {
939 return this.neighboringHeadwaysRight;
940 }
941
942
943 @Override
944 public final TimeStampedObject<Collection<Headway>> getTimeStampedParallelHeadwaysLeft()
945 {
946 return this.parallelHeadwaysLeft;
947 }
948
949
950 @Override
951 public final TimeStampedObject<Collection<Headway>> getTimeStampedParallelHeadwaysRight()
952 {
953 return this.parallelHeadwaysRight;
954 }
955
956
957 @Override
958 public final TimeStampedObject<Speed> getTimeStampedSpeedLimit()
959 {
960 return this.speedLimit;
961 }
962
963
964 @Override
965 public SortedSet<AbstractHeadwayGTU> getFirstLeaders(LateralDirectionality lat)
966 {
967 if (lat == null)
968 {
969 return getLeaders(RelativeLane.CURRENT);
970 }
971 else if (lat.isLeft())
972 {
973 return getLeaders(RelativeLane.LEFT);
974 }
975 return getLeaders(RelativeLane.RIGHT);
976 }
977
978
979 @Override
980 public SortedSet<AbstractHeadwayGTU> getFirstFollowers(LateralDirectionality lat)
981 {
982 if (lat == null)
983 {
984 return getFollowers(RelativeLane.CURRENT);
985 }
986 else if (lat.isLeft())
987 {
988 return getFollowers(RelativeLane.LEFT);
989 }
990 return getFollowers(RelativeLane.RIGHT);
991 }
992
993
994 @Override
995 public boolean existsGtuAlongside(LateralDirectionality lat)
996 {
997 for (Headway headway : getNeighboringHeadways(lat))
998 {
999 if (headway.isParallel())
1000 {
1001 return true;
1002 }
1003 }
1004 return false;
1005 }
1006
1007
1008 @Override
1009 public SortedSet<AbstractHeadwayGTU> getLeaders(RelativeLane lane)
1010 {
1011 SortedSet<AbstractHeadwayGTU> leaders = new TreeSet<>();
1012 if (lane.isCurrent())
1013 {
1014 if (getForwardHeadway() instanceof AbstractHeadwayGTU)
1015 {
1016 leaders.add((AbstractHeadwayGTU) getForwardHeadway());
1017 }
1018 }
1019 else
1020 {
1021 for (Headway headway : getNeighboringHeadways(lane.getLateralDirectionality()))
1022 {
1023 if (headway instanceof AbstractHeadwayGTU && headway.isAhead())
1024 {
1025 leaders.add((AbstractHeadwayGTU) headway);
1026 }
1027 }
1028 }
1029 return leaders;
1030 }
1031
1032
1033 @Override
1034 public SortedSet<AbstractHeadwayGTU> getFollowers(RelativeLane lane)
1035 {
1036 SortedSet<AbstractHeadwayGTU> followers = new TreeSet<>();
1037 if (lane.isCurrent())
1038 {
1039 if (getBackwardHeadway() instanceof AbstractHeadwayGTU)
1040 {
1041 followers.add((AbstractHeadwayGTU) getBackwardHeadway());
1042 }
1043 }
1044 else
1045 {
1046 for (Headway headway : getNeighboringHeadways(lane.getLateralDirectionality()))
1047 {
1048 if (headway instanceof AbstractHeadwayGTU && headway.isBehind())
1049 {
1050 followers.add((AbstractHeadwayGTU) headway);
1051 }
1052 }
1053 }
1054 return followers;
1055 }
1056
1057
1058 @Override
1059 public SortedSet<InfrastructureLaneChangeInfo> getInfrastructureLaneChangeInfo(RelativeLane lane)
1060 {
1061 return new TreeSet<>();
1062 }
1063
1064
1065 @Override
1066 public int getSplitNumber(InfrastructureLaneChangeInfo info)
1067 {
1068 return 0;
1069 }
1070
1071
1072 @Override
1073 public SpeedLimitProspect getSpeedLimitProspect(RelativeLane lane)
1074 {
1075 SpeedLimitProspect slp = new SpeedLimitProspect();
1076 slp.addSpeedInfo(Length.ZERO, SpeedLimitTypes.FIXED_SIGN, getSpeedLimit());
1077 slp.addSpeedInfo(Length.ZERO, SpeedLimitTypes.MAX_VEHICLE_SPEED, getGtu().getMaximumSpeed());
1078 return slp;
1079 }
1080
1081
1082 @Override
1083 public Length getLegalLaneChangePossibility(RelativeLane fromLane, LateralDirectionality lat)
1084 {
1085 return Length.ZERO;
1086 }
1087
1088
1089 @Override
1090 public Length getPhysicalLaneChangePossibility(RelativeLane fromLane, LateralDirectionality lat)
1091 {
1092 return Length.ZERO;
1093 }
1094
1095
1096 @Override
1097 public SortedSet<RelativeLane> getCurrentCrossSection()
1098 {
1099 return new TreeSet<>();
1100 }
1101
1102
1103 @Override
1104 public SortedSet<HeadwayTrafficLight> getTrafficLights()
1105 {
1106 return new TreeSet<>();
1107 }
1108
1109
1110 @Override
1111 public SortedSet<HeadwayConflict> getIntersectionConflicts(RelativeLane lane)
1112 {
1113 return new TreeSet<>();
1114 }
1115
1116
1117 @Override
1118 public TimeStampedObject<SortedSet<AbstractHeadwayGTU>> getTimeStampedFirstLeaders(LateralDirectionality lat)
1119 {
1120 return null;
1121 }
1122
1123
1124 @Override
1125 public TimeStampedObject<SortedSet<AbstractHeadwayGTU>> getTimeStampedFirstFollowers(LateralDirectionality lat)
1126 {
1127 return null;
1128 }
1129
1130
1131 @Override
1132 public TimeStampedObject<Boolean> existsGtuAlongsideTimeStamped(LateralDirectionality lat)
1133 {
1134 return null;
1135 }
1136
1137
1138 @Override
1139 public TimeStampedObject<SortedSet<AbstractHeadwayGTU>> getTimeStampedLeaders(RelativeLane lane)
1140 {
1141 return null;
1142 }
1143
1144
1145 @Override
1146 public TimeStampedObject<SortedSet<AbstractHeadwayGTU>> getTimeStampedFollowers(RelativeLane lane)
1147 {
1148 return null;
1149 }
1150
1151
1152 @Override
1153 public TimeStampedObject<SortedSet<InfrastructureLaneChangeInfo>> getTimeStampedInfrastructureLaneChangeInfo(
1154 RelativeLane lane)
1155 {
1156 return null;
1157 }
1158
1159
1160 @Override
1161 public TimeStampedObject<Integer> getTimeStampedSplitNumber(InfrastructureLaneChangeInfo info)
1162 {
1163 return null;
1164 }
1165
1166
1167 @Override
1168 public TimeStampedObject<SpeedLimitProspect> getTimeStampedSpeedLimitProspect(RelativeLane lane)
1169 {
1170 return null;
1171 }
1172
1173
1174 @Override
1175 public TimeStampedObject<Length> getTimeStampedLegalLaneChangePossibility(RelativeLane fromLane, LateralDirectionality lat)
1176 {
1177 return null;
1178 }
1179
1180
1181 @Override
1182 public TimeStampedObject<Length> getTimeStampedPhysicalLaneChangePossibility(RelativeLane fromLane,
1183 LateralDirectionality lat)
1184 {
1185 return null;
1186 }
1187
1188
1189 @Override
1190 public TimeStampedObject<SortedSet<RelativeLane>> getTimeStampedCurrentCrossSection()
1191 {
1192 return null;
1193 }
1194
1195
1196 @Override
1197 public TimeStampedObject<SortedSet<HeadwayTrafficLight>> getTimeStampedTrafficLights()
1198 {
1199 return null;
1200 }
1201
1202
1203 @Override
1204 public TimeStampedObject<SortedSet<HeadwayConflict>> getTimeStampedIntersectionConflicts(RelativeLane lane)
1205 {
1206 return null;
1207 }
1208
1209
1210 @Override
1211 public void updateFirstLeaders()
1212 {
1213 }
1214
1215
1216 @Override
1217 public void updateFirstFollowers()
1218 {
1219 }
1220
1221
1222 @Override
1223 public void updateGtuAlongside()
1224 {
1225 }
1226
1227
1228 @Override
1229 public void updateLeaders()
1230 {
1231 }
1232
1233
1234 @Override
1235 public void updateFollowers()
1236 {
1237 }
1238
1239
1240 @Override
1241 public void updateInfrastructureLaneChangeInfo()
1242 {
1243 }
1244
1245
1246 @Override
1247 public void updateSplitNumber()
1248 {
1249 }
1250
1251
1252 @Override
1253 public void updateSpeedLimitProspect()
1254 {
1255 }
1256
1257
1258 @Override
1259 public void updateLegalLaneChangePossibility()
1260 {
1261 }
1262
1263
1264 @Override
1265 public void updatePhysicalLaneChangePossibility()
1266 {
1267 }
1268
1269
1270 @Override
1271 public void updateCurrentCrossSection()
1272 {
1273 }
1274
1275
1276 @Override
1277 public void updateTrafficLights()
1278 {
1279 }
1280
1281
1282 @Override
1283 public void updateIntersectionConflicts()
1284 {
1285 }
1286
1287 }