View Javadoc
1   package org.opentrafficsim.road.network.lane.conflict;
2   
3   import java.util.Set;
4   
5   import org.djunits.value.vdouble.scalar.Length;
6   import org.djutils.exceptions.Throw;
7   import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
8   import org.opentrafficsim.core.gtu.GtuException;
9   import org.opentrafficsim.core.gtu.GtuType;
10  import org.opentrafficsim.core.gtu.RelativePosition;
11  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
12  import org.opentrafficsim.road.network.lane.CrossSectionLink.Priority;
13  import org.opentrafficsim.road.network.lane.Lane;
14  
15  /**
16   * Conflict rule for conflicts where busses enter the lane after a stop.
17   * <p>
18   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
19   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
20   * </p>
21   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
22   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
23   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
24   */
25  public class BusStopConflictRule implements ConflictRule
26  {
27  
28      /** Simulator. */
29      private final OtsSimulatorInterface simulator;
30  
31      /** GTU type for buses. */
32      private final GtuType busType;
33  
34      /**
35       * Constructor.
36       * @param simulator simulator
37       * @param busType GTU type for buses.
38       */
39      public BusStopConflictRule(final OtsSimulatorInterface simulator, final GtuType busType)
40      {
41          this.simulator = simulator;
42          this.busType = busType;
43      }
44  
45      @Override
46      public ConflictPriority determinePriority(final Conflict conflict)
47      {
48  
49          // determine if we request from bus stop, or not
50          boolean requestingFromBusStop;
51          Conflict busConflict;
52          // conflict builder enforces that only one of the two links has priority BUS_STOP
53          if (conflict.getLane().getLink().getPriority().equals(Priority.BUS_STOP))
54          {
55              Throw.when(conflict.getOtherConflict().getLane().getLink().getPriority().equals(Priority.BUS_STOP),
56                      IllegalArgumentException.class,
57                      "BusStopConflictRule does not support a conflict between two links with priority BUS_STOP.");
58              requestingFromBusStop = true;
59              busConflict = conflict;
60          }
61          else
62          {
63              requestingFromBusStop = false;
64              busConflict = conflict.getOtherConflict();
65          }
66  
67          // find bus and determine if it has priority
68          Lane lane = busConflict.getLane();
69          Length pos = busConflict.getLongitudinalPosition();
70          LaneBasedGtu gtu = null;
71          try
72          {
73              while (gtu == null && lane != null)
74              {
75                  gtu = lane.getGtuBehind(pos, RelativePosition.FRONT, this.simulator.getSimulatorAbsTime());
76                  if (gtu == null)
77                  {
78                      Set<Lane> set = lane.prevLanes(this.busType);
79                      if (set.size() == 1)
80                      {
81                          lane = set.iterator().next();
82                          // only on bus stop
83                          if (lane.getLink().getPriority().isBusStop())
84                          {
85                              pos = lane.getLength();
86                          }
87                          else
88                          {
89                              lane = null;
90                          }
91                      }
92                      else
93                      {
94                          lane = null;
95                      }
96                  }
97              }
98          }
99          catch (GtuException exception)
100         {
101             throw new RuntimeException("Error while looking for GTU upstream of merge at bus stop.", exception);
102         }
103         boolean busHasPriority = gtu != null && gtu.getType().isOfType(this.busType) && gtu.getTurnIndicatorStatus().isLeft();
104 
105         // if bus has priority and bus is asking, PRIORITY
106         // if bus has no priority and bus is not asking (i.e. car is asking), PRIORITY
107         return busHasPriority == requestingFromBusStop ? ConflictPriority.PRIORITY : ConflictPriority.YIELD;
108 
109     }
110 
111     @Override
112     public final String toString()
113     {
114         return "BusStopConflictRule";
115     }
116 
117 }