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.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-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
16   * <p>
17   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 19 feb. 2018 <br>
18   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
20   * @author <a href="http://www.transport.citg.tudelft.nl">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.createSI(0.000001);
27  
28      /** Margin in case of a right lane. */
29      private static final Length RIGHT = Length.createSI(-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 R; 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 LaneRecord<?> root, final Length initialPosition,
51              final Length maxDistance, final RelativePosition relativePosition, final HeadwayGtuType headwayGtuType,
52              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 LaneRecord<?> record, final Length position, final Integer counter) throws GTUException
62      {
63          int n;
64          LaneBasedGTU next;
65          Length pos;
66          boolean plus = record.getDirection().isPlus();
67          if (counter == null)
68          {
69              if (plus ? position.ge(record.getLane().getLength()) : position.eq0())
70              {
71                  next = record.getLane().getLastGtu(record.getDirection());
72              }
73              else
74              {
75                  Length searchPos = (plus ? position.plus(this.margin) : position.minus(this.margin));
76                  next = record.getLane().getGtuBehind(searchPos, record.getDirection(), RelativePosition.FRONT,
77                          record.getLane().getParentLink().getSimulator().getSimulatorTime());
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.gtu != null && next.getId().equals(this.gtu.getId()))
87              {
88                  // ignore self
89                  pos = plus ? pos.minus(next.getLength()) : pos.plus(next.getLength());
90                  return getNext(record, pos, n);
91              }
92          }
93          else
94          {
95              n = plus ? counter - 1 : 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 LaneRecord<?> 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.createHeadwayGtu(perceivingGtu, object, distance.neg(), false);
119     }
120 
121 }