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