View Javadoc
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.dsol.OTSSimulatorInterface;
7   import org.opentrafficsim.core.gtu.GTUDirectionality;
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-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
19   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
20   * <p>
21   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 27 jan. 2017 <br>
22   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
23   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
24   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
25   */
26  public class BusStopConflictRule implements ConflictRule
27  {
28  
29      /** Simulator. */
30      private final OTSSimulatorInterface simulator;
31  
32      /**
33       * Constructor.
34       * @param simulator OTSSimulatorInterface; simulator
35       */
36      public BusStopConflictRule(final OTSSimulatorInterface simulator)
37      {
38          this.simulator = simulator;
39      }
40  
41      /** {@inheritDoc} */
42      @Override
43      public ConflictPriority determinePriority(final Conflict conflict)
44      {
45  
46          // determine if we request from bus stop, or not
47          boolean requestingFromBusStop;
48          Conflict busConflict;
49          // conflict builder enforces that only one of the two links has priority BUS_STOP
50          if (conflict.getLane().getParentLink().getPriority().equals(Priority.BUS_STOP))
51          {
52              Throw.when(conflict.getOtherConflict().getLane().getParentLink().getPriority().equals(Priority.BUS_STOP),
53                      IllegalArgumentException.class,
54                      "BusStopConflictRule does not support a conflict between two links with priority BUS_STOP.");
55              requestingFromBusStop = true;
56              busConflict = conflict;
57          }
58          else
59          {
60              requestingFromBusStop = false;
61              busConflict = conflict.getOtherConflict();
62          }
63  
64          // find bus and determine if it has priority
65          // conflict forces that LongitudinalDirection is DIR_PLUS or DIR_MINUS
66          Lane lane = busConflict.getLane();
67          GTUDirectionality dir =
68                  busConflict.getDirection().isForward() ? GTUDirectionality.DIR_PLUS : GTUDirectionality.DIR_MINUS;
69          Length pos = busConflict.getLongitudinalPosition();
70          LaneBasedGTU gtu = null;
71          try
72          {
73              while (gtu == null && lane != null)
74              {
75                  gtu = lane.getGtuBehind(pos, dir, RelativePosition.FRONT, this.simulator.getSimulatorAbsTime());
76                  if (gtu == null)
77                  {
78                      ImmutableMap<Lane, GTUDirectionality> map =
79                              lane.upstreamLanes(dir, lane.getNetwork().getGtuType(GTUType.DEFAULTS.BUS));
80                      if (map.size() == 1)
81                      {
82                          lane = map.keySet().iterator().next();
83                          // only on bus stop
84                          if (lane.getParentLink().getPriority().isBusStop())
85                          {
86                              dir = map.get(lane);
87                              pos = dir.isPlus() ? lane.getLength() : Length.ZERO;
88                          }
89                          else
90                          {
91                              lane = null;
92                          }
93                      }
94                      else
95                      {
96                          lane = null;
97                      }
98                  }
99              }
100         }
101         catch (GTUException exception)
102         {
103             throw new RuntimeException("Error while looking for GTU upstream of merge at bus stop.", exception);
104         }
105         boolean busHasPriority =
106                 gtu != null && gtu.getGTUType().isOfType(GTUType.DEFAULTS.BUS) && gtu.getTurnIndicatorStatus().isLeft();
107 
108         // if bus has priority and bus is asking, PRIORITY
109         // if bus has no priority and bus is not asking (i.e. car is asking), PRIORITY
110         return busHasPriority == requestingFromBusStop ? ConflictPriority.PRIORITY : ConflictPriority.YIELD;
111 
112     }
113 
114     /** {@inheritDoc} */
115     @Override
116     public final ConflictRule clone(final OTSSimulatorInterface newSimulator)
117     {
118         return new BusStopConflictRule(newSimulator);
119     }
120 
121     /** {@inheritDoc} */
122     @Override
123     public final String toString()
124     {
125         return "BusStopConflictRule";
126     }
127 
128 }