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.Break;
8   import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
9   import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType;
10  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  public class UpstreamNeighborsIterable extends AbstractPerceptionIterable<HeadwayGTU, LaneBasedGTU, Integer>
24  {
25  
26      
27      private static final Length LEFT = Length.createSI(0.000001);
28  
29      
30      private static final Length RIGHT = Length.createSI(-0.000001);
31  
32      
33      private final HeadwayGtuType headwayGtuType;
34  
35      
36  
37  
38  
39      private final Length margin;
40  
41      
42  
43  
44  
45  
46  
47  
48  
49  
50  
51      public UpstreamNeighborsIterable(final LaneBasedGTU perceivingGtu, final LaneRecord<?> root, final Length initialPosition,
52              final Length maxDistance, final RelativePosition relativePosition, final HeadwayGtuType headwayGtuType,
53              final RelativeLane lane)
54      {
55          super(perceivingGtu, root, initialPosition, false, maxDistance, relativePosition, null);
56          this.headwayGtuType = headwayGtuType;
57          this.margin = lane.getLateralDirectionality().isLeft() ? LEFT : RIGHT;
58      }
59  
60      
61      @Override
62      protected Entry getNext(final LaneRecord<?> record, final Length position, final Integer counter) throws GTUException
63      {
64          int n;
65          LaneBasedGTU next;
66          Length pos;
67          boolean plus = record.getDirection().isPlus();
68          if (counter == null)
69          {
70              if (plus ? position.ge(record.getLane().getLength()) : position.eq0())
71              {
72                  next = record.getLane().getLastGtu(record.getDirection());
73              }
74              else
75              {
76                  Length searchPos = (plus ? position.plus(this.margin) : position.minus(this.margin));
77                  next = record.getLane().getGtuBehind(searchPos, record.getDirection(), RelativePosition.FRONT,
78                          record.getLane().getParentLink().getSimulator().getSimulatorTime());
79              }
80              if (next == null)
81              {
82                  return null;
83              }
84              n = record.getLane().indexOfGtu(next);
85              pos = next.position(record.getLane(), next.getFront());
86  
87              if (this.getGtu() != null && next.getId().equals(this.getGtu().getId()))
88              {
89                  
90                  pos = plus ? pos.minus(next.getLength()) : pos.plus(next.getLength());
91                  return getNext(record, pos, n);
92              }
93          }
94          else
95          {
96              n = plus ? counter - 1 : counter + 1;
97              if (n < 0 || n >= record.getLane().numberOfGtus())
98              {
99                  return null;
100             }
101             next = record.getLane().getGtu(n);
102             pos = next.position(record.getLane(), next.getFront());
103         }
104         Break.on(next, "44", 4 * 60 + 0.99, record.getLane().getFullId().equals("BB1.LANE"));
105         return new Entry(next, n, pos);
106     }
107 
108     
109     @Override
110     protected Length getDistance(final LaneBasedGTU object, final LaneRecord<?> record, final Length position)
111     {
112         return record.getDistanceToPosition(position).neg().plus(getDx());
113     }
114 
115     
116     @Override
117     public HeadwayGTU perceive(final LaneBasedGTU perceivingGtu, final LaneBasedGTU object, final Length distance)
118             throws GTUException, ParameterException
119     {
120         return this.headwayGtuType.createUpstreamGtu(perceivingGtu, object, distance);
121     }
122 
123 }