View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception;
2   
3   import org.djunits.value.vdouble.scalar.Length;
4   import org.opentrafficsim.base.parameters.ParameterException;
5   import org.opentrafficsim.core.gtu.GtuException;
6   import org.opentrafficsim.core.gtu.RelativePosition;
7   import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
8   import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType;
9   import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGtu;
10  
11  /**
12   * Iterable to find upstream GTU's.
13   * <p>
14   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
16   * </p>
17   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
18   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
19   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
20   */
21  public class UpstreamNeighborsIterable extends AbstractPerceptionIterable<HeadwayGtu, LaneBasedGtu, Integer>
22  {
23  
24      /** Margin in case of a left lane. */
25      private static final Length LEFT = Length.instantiateSI(0.000001);
26  
27      /** Margin in case of a right lane. */
28      private static final Length RIGHT = Length.instantiateSI(-0.000001);
29  
30      /** Headway GTU type that should be used. */
31      private final HeadwayGtuType headwayGtuType;
32  
33      /**
34       * Margin used for neighbor search in some cases to prevent possible deadlock. This does not affect calculated distances to
35       * neighbors, but only whether they are considered a leader or follower.
36       */
37      private final Length margin;
38  
39      /**
40       * Constructor.
41       * @param perceivingGtu LaneBasedGtu; perceiving GTU
42       * @param root LaneRecord&lt;?&gt;; root record
43       * @param initialPosition Length; position on the root record
44       * @param maxDistance Length; maximum distance to search
45       * @param relativePosition RelativePosition; position to which distance are calculated by subclasses
46       * @param headwayGtuType HeadwayGtuType; type of HeadwayGtu to return
47       * @param lane RelativeLane; relative lane (used for a left/right distinction to prevent dead-locks)
48       */
49      public UpstreamNeighborsIterable(final LaneBasedGtu perceivingGtu, final LaneRecordInterface<?> root,
50              final Length initialPosition, final Length maxDistance, final RelativePosition relativePosition,
51              final HeadwayGtuType headwayGtuType, final RelativeLane lane)
52      {
53          super(perceivingGtu, root, initialPosition, false, maxDistance, relativePosition, null);
54          this.headwayGtuType = headwayGtuType;
55          this.margin = lane.getLateralDirectionality().isLeft() ? LEFT : RIGHT;
56      }
57  
58      /** {@inheritDoc} */
59      @Override
60      protected Entry getNext(final LaneRecordInterface<?> record, final Length position, final Integer counter)
61              throws GtuException
62      {
63          int n;
64          LaneBasedGtu next;
65          Length pos;
66          if (counter == null)
67          {
68              if (position.ge(record.getLane().getLength()))
69              {
70                  next = record.getLane().getLastGtu();
71              }
72              else
73              {
74                  Length searchPos = position.plus(this.margin);
75                  next = record.getLane().getGtuBehind(searchPos, RelativePosition.FRONT,
76                          record.getLane().getLink().getSimulator().getSimulatorAbsTime());
77              }
78              if (next == null)
79              {
80                  return null;
81              }
82              n = record.getLane().indexOfGtu(next);
83              pos = next.position(record.getLane(), next.getFront());
84  
85              if (this.getGtu() != null && next.getId().equals(this.getGtu().getId()))
86              {
87                  // ignore self
88                  pos = pos.minus(next.getLength());
89                  return getNext(record, pos, n);
90              }
91          }
92          else
93          {
94              n = counter - 1;
95              if (n < 0 || n >= record.getLane().numberOfGtus())
96              {
97                  return null;
98              }
99              next = record.getLane().getGtu(n);
100             pos = next.position(record.getLane(), next.getFront());
101         }
102         return new Entry(next, n, pos);
103     }
104 
105     /** {@inheritDoc} */
106     @Override
107     protected Length getDistance(final LaneBasedGtu object, final LaneRecordInterface<?> record, final Length position)
108     {
109         return record.getDistanceToPosition(position).neg().plus(getDx());
110     }
111 
112     /** {@inheritDoc} */
113     @Override
114     public HeadwayGtu perceive(final LaneBasedGtu perceivingGtu, final LaneBasedGtu object, final Length distance)
115             throws GtuException, ParameterException
116     {
117         return this.headwayGtuType.createUpstreamGtu(perceivingGtu, object, distance);
118     }
119 
120 }