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