View Javadoc
1   package org.opentrafficsim.road.network.lane.object.trafficlight;
2   
3   import java.util.LinkedHashMap;
4   import java.util.LinkedHashSet;
5   import java.util.Map;
6   import java.util.NavigableSet;
7   import java.util.Set;
8   import java.util.SortedMap;
9   import java.util.TreeMap;
10  
11  import org.djunits.value.vdouble.scalar.Duration;
12  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
13  
14  import nl.tudelft.simulation.dsol.SimRuntimeException;
15  
16  /**
17   * A traffic light controller with fixed durations. Red, yellow and green times of each phase can be set, as well as the time
18   * between phases.
19   * <p>
20   * Copyright (c) 2013-2022 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/docs/current/license.html">OpenTrafficSim License</a>.
22   * </p>
23   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
24   * initial version Oct 4, 2016 <br>
25   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
26   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
27   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
28   */
29  public class TrafficLightControllerFixedDuration implements TrafficLightController
30  {
31      /** the controller id. */
32      private final String id;
33  
34      /** the simulator. */
35      private final OTSSimulatorInterface simulator;
36  
37      /** the phases with a number identifying them to create a sorted map. */
38      private final SortedMap<Integer, Set<TrafficLight>> phases = new TreeMap<>();
39  
40      /** the fixed yellow duration per phase. */
41      private final Map<Integer, Duration> yellowDurations = new LinkedHashMap<>();
42  
43      /** the fixed green duration per phase. */
44      private final Map<Integer, Duration> greenDurations = new LinkedHashMap<>();
45  
46      /** the current phase. */
47      private int currentPhase;
48  
49      /** the current light in the current phase. */
50      private TrafficLightColor currentColor = TrafficLightColor.RED;
51  
52      /** fixed clearance duration between phases. */
53      private Duration clearanceDuration = Duration.ZERO;
54  
55      /**
56       * Create a fixed time controller.
57       * @param id String; the controller id
58       * @param simulator OTSSimulatorInterface; the simulator
59       * @throws TrafficLightException when scheduling of thhe start event fails
60       */
61      public TrafficLightControllerFixedDuration(final String id, final OTSSimulatorInterface simulator)
62              throws TrafficLightException
63      {
64          this.id = id;
65          this.simulator = simulator;
66          try
67          {
68              this.simulator.scheduleEventNow(this, this, "changePhase", null);
69          }
70          catch (SimRuntimeException exception)
71          {
72              throw new TrafficLightException(exception);
73          }
74      }
75  
76      /**
77       * Change the phase and/or color of the traffic lights.
78       * @throws TrafficLightException when scheduling of thhe start event fails
79       */
80      protected final void changePhase() throws TrafficLightException
81      {
82          try
83          {
84              if (this.currentColor.isGreen())
85              {
86                  for (TrafficLight trafficLight : this.phases.get(this.currentPhase))
87                  {
88                      trafficLight.setTrafficLightColor(TrafficLightColor.YELLOW);
89                  }
90                  this.currentColor = TrafficLightColor.YELLOW;
91                  this.simulator.scheduleEventRel(this.yellowDurations.get(this.currentPhase), this, this, "changePhase", null);
92                  return;
93              }
94              else if (this.currentColor.isYellow())
95              {
96                  for (TrafficLight trafficLight : this.phases.get(this.currentPhase))
97                  {
98                      trafficLight.setTrafficLightColor(TrafficLightColor.RED);
99                  }
100                 this.currentColor = TrafficLightColor.RED;
101             }
102 
103             if (this.currentColor.isRed())
104             {
105                 Integer nextPhase = ((NavigableSet<Integer>) this.phases.keySet()).higher(this.currentPhase);
106                 if (nextPhase == null)
107                 {
108                     nextPhase = this.phases.firstKey();
109                 }
110                 this.currentPhase = nextPhase;
111                 this.currentColor = TrafficLightColor.GREEN;
112                 this.simulator.scheduleEventRel(this.greenDurations.get(this.currentPhase), this, this, "changePhase", null);
113             }
114         }
115         catch (SimRuntimeException exception)
116         {
117             throw new TrafficLightException(exception);
118         }
119     }
120 
121     /** {@inheritDoc} */
122     @Override
123     public final int getNumberOfPhases()
124     {
125         return this.phases.size();
126     }
127 
128     /** {@inheritDoc} */
129     @Override
130     public final int getCurrentPhase()
131     {
132         return this.currentPhase;
133     }
134 
135     /** {@inheritDoc} */
136     @Override
137     public final Duration getClearanceDurationToNextPhase()
138     {
139         return this.clearanceDuration;
140     }
141 
142     /**
143      * Add a new phase.
144      * @param phaseId int; the id of the phase to be added.
145      * @param yellowDuration Duration; the yellow time
146      * @param greenDuration Duration; the green time
147      * @throws TrafficLightException when the phase already existed
148      */
149     public final void addPhase(final int phaseId, final Duration yellowDuration, final Duration greenDuration)
150             throws TrafficLightException
151     {
152         if (this.phases.containsKey(phaseId))
153         {
154             throw new TrafficLightException("Phase " + phaseId + " for traffic light " + this.id + " was already defined");
155         }
156         this.phases.put(phaseId, new LinkedHashSet<TrafficLight>());
157         this.yellowDurations.put(phaseId, yellowDuration);
158         this.greenDurations.put(phaseId, greenDuration);
159     }
160 
161     /** {@inheritDoc} */
162     @Override
163     public final void addTrafficLightToPhase(final int phaseId, final TrafficLight trafficLight) throws TrafficLightException
164     {
165         if (!this.phases.containsKey(phaseId))
166         {
167             throw new TrafficLightException("Phase " + phaseId + " for traffic light " + this.id + " was not defined");
168         }
169         this.phases.get(phaseId).add(trafficLight);
170         trafficLight.setTrafficLightColor(TrafficLightColor.RED);
171     }
172 
173     /** {@inheritDoc} */
174     @Override
175     public final String getId()
176     {
177         return this.id;
178     }
179 
180     /**
181      * @param clearanceDuration Duration; set clearanceDuration
182      */
183     public final void setClearanceDuration(final Duration clearanceDuration)
184     {
185         this.clearanceDuration = clearanceDuration;
186     }
187 
188     /** {@inheritDoc} */
189     @Override
190     @SuppressWarnings("checkstyle:designforextension")
191     public String toString()
192     {
193         return "TrafficLightControllerFixedDuration [id=" + this.id + ", phases=" + this.phases + ", yellowDurations="
194                 + this.yellowDurations + ", greenDurations=" + this.greenDurations + ", currentPhase=" + this.currentPhase
195                 + ", currentColor=" + this.currentColor + ", clearanceDuration=" + this.clearanceDuration + "]";
196     }
197 
198 }