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