1   package org.opentrafficsim.road.network.lane.conflict;
2   
3   import org.djunits.value.vdouble.scalar.Length;
4   import org.djutils.exceptions.Throw;
5   import org.djutils.immutablecollections.ImmutableMap;
6   import org.opentrafficsim.core.gtu.GTUDirectionality;
7   import org.opentrafficsim.core.gtu.GTUException;
8   import org.opentrafficsim.core.gtu.GTUType;
9   import org.opentrafficsim.core.gtu.RelativePosition;
10  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
11  import org.opentrafficsim.road.network.lane.CrossSectionLink.Priority;
12  import org.opentrafficsim.road.network.lane.Lane;
13  
14  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  public class BusStopConflictRule implements ConflictRule
28  {
29  
30      
31      private final SimulatorInterface.TimeDoubleUnit simulator;
32  
33      
34  
35  
36  
37      public BusStopConflictRule(final SimulatorInterface.TimeDoubleUnit simulator)
38      {
39          this.simulator = simulator;
40      }
41  
42      
43      @Override
44      public ConflictPriority determinePriority(final Conflict conflict)
45      {
46  
47          
48          boolean requestingFromBusStop;
49          Conflict busConflict;
50          
51          if (conflict.getLane().getParentLink().getPriority().equals(Priority.BUS_STOP))
52          {
53              Throw.when(conflict.getOtherConflict().getLane().getParentLink().getPriority().equals(Priority.BUS_STOP),
54                      IllegalArgumentException.class,
55                      "BusStopConflictRule does not support a conflict between two links with priority BUS_STOP.");
56              requestingFromBusStop = true;
57              busConflict = conflict;
58          }
59          else
60          {
61              requestingFromBusStop = false;
62              busConflict = conflict.getOtherConflict();
63          }
64  
65          
66          
67          Lane lane = busConflict.getLane();
68          GTUDirectionality dir =
69                  busConflict.getDirection().isForward() ? GTUDirectionality.DIR_PLUS : GTUDirectionality.DIR_MINUS;
70          Length pos = busConflict.getLongitudinalPosition();
71          LaneBasedGTU gtu = null;
72          try
73          {
74              while (gtu == null && lane != null)
75              {
76                  gtu = lane.getGtuBehind(pos, dir, RelativePosition.FRONT, this.simulator.getSimulatorTime());
77                  if (gtu == null)
78                  {
79                      ImmutableMap<Lane, GTUDirectionality> map =
80                              lane.upstreamLanes(dir, lane.getNetwork().getGtuType(GTUType.DEFAULTS.BUS));
81                      if (map.size() == 1)
82                      {
83                          lane = map.keySet().iterator().next();
84                          
85                          if (lane.getParentLink().getPriority().isBusStop())
86                          {
87                              dir = map.get(lane);
88                              pos = dir.isPlus() ? lane.getLength() : Length.ZERO;
89                          }
90                          else
91                          {
92                              lane = null;
93                          }
94                      }
95                      else
96                      {
97                          lane = null;
98                      }
99                  }
100             }
101         }
102         catch (GTUException exception)
103         {
104             throw new RuntimeException("Error while looking for GTU upstream of merge at bus stop.", exception);
105         }
106         boolean busHasPriority =
107                 gtu != null && gtu.getGTUType().isOfType(GTUType.DEFAULTS.BUS) && gtu.getTurnIndicatorStatus().isLeft();
108 
109         
110         
111         return busHasPriority == requestingFromBusStop ? ConflictPriority.PRIORITY : ConflictPriority.YIELD;
112 
113     }
114 
115     
116     @Override
117     public final ConflictRule clone(final SimulatorInterface.TimeDoubleUnit newSimulator)
118     {
119         return new BusStopConflictRule(newSimulator);
120     }
121 
122     
123     @Override
124     public final String toString()
125     {
126         return "BusStopConflictRule";
127     }
128 
129 }