1 package org.opentrafficsim.road.network.control.rampmetering;
2
3 import java.util.Iterator;
4 import java.util.LinkedHashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.djunits.value.vdouble.scalar.Duration;
9 import org.djunits.value.vdouble.scalar.Time;
10 import org.djutils.exceptions.Try;
11 import org.opentrafficsim.core.compatibility.Compatible;
12 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
13 import org.opentrafficsim.core.gtu.RelativePosition;
14 import org.opentrafficsim.core.network.NetworkException;
15 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
16 import org.opentrafficsim.road.network.lane.CrossSectionElement;
17 import org.opentrafficsim.road.network.lane.object.sensor.AbstractSensor;
18 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
19 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightColor;
20
21 import nl.tudelft.simulation.dsol.SimRuntimeException;
22 import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEventInterface;
23
24
25
26
27
28
29
30
31
32
33
34
35 public class CycleTimeLightController implements RampMeteringLightController
36 {
37
38
39 private static final Duration MIN_RED_TIME = Duration.instantiateSI(2.0);
40
41
42 private boolean enabled = false;
43
44
45 private Map<TrafficLight, Time> greenStarts = new LinkedHashMap<>();
46
47
48 private Duration cTime;
49
50
51 private final OTSSimulatorInterface simulator;
52
53
54 private final List<TrafficLight> trafficLights;
55
56
57 private Map<TrafficLight, SimEventInterface<Duration>> redEvents = new LinkedHashMap<>();
58
59
60 private Map<TrafficLight, SimEventInterface<Duration>> greenEvents = new LinkedHashMap<>();
61
62
63
64
65
66
67 public CycleTimeLightController(final OTSSimulatorInterface simulator, final List<TrafficLight> trafficLights,
68 final Compatible compatible)
69 {
70 this.simulator = simulator;
71 this.trafficLights = trafficLights;
72 for (TrafficLight trafficLight : trafficLights)
73 {
74 Try.execute(() -> new RampMeteringSensor(trafficLight, simulator, compatible),
75 "Unexpected exception while creating a detector with a ramp metering traffic light.");
76 this.greenStarts.put(trafficLight, Time.instantiateSI(Double.NEGATIVE_INFINITY));
77 }
78 }
79
80
81 @Override
82 public void disable()
83 {
84 Iterator<TrafficLight> it = this.redEvents.keySet().iterator();
85 while (it.hasNext())
86 {
87 TrafficLight trafficLight = it.next();
88 this.simulator.cancelEvent(this.redEvents.get(trafficLight));
89 it.remove();
90 }
91 it = this.greenEvents.keySet().iterator();
92 while (it.hasNext())
93 {
94 TrafficLight trafficLight = it.next();
95 this.simulator.cancelEvent(this.greenEvents.get(trafficLight));
96 it.remove();
97 }
98 this.enabled = false;
99 for (TrafficLight trafficLight : this.trafficLights)
100 {
101 trafficLight.setTrafficLightColor(TrafficLightColor.GREEN);
102 }
103 }
104
105
106
107
108
109 @Override
110 public void enable(final Duration cycleTime)
111 {
112 this.simulator.getLogger().always().info("Traffic light uses " + cycleTime);
113 this.cTime = cycleTime;
114 if (!this.enabled)
115 {
116 this.enabled = true;
117 for (TrafficLight trafficLight : this.trafficLights)
118 {
119 setGreen(trafficLight);
120 }
121 }
122 }
123
124
125
126
127
128 protected void setRed(final TrafficLight trafficLight)
129 {
130 this.redEvents.remove(trafficLight);
131 this.simulator.getLogger().always().info("Traffic light set to RED");
132 trafficLight.setTrafficLightColor(TrafficLightColor.RED);
133 }
134
135
136
137
138
139 protected void setGreen(final TrafficLight trafficLight)
140 {
141 this.greenEvents.remove(trafficLight);
142 this.greenStarts.put(trafficLight, this.simulator.getSimulatorAbsTime());
143 this.simulator.getLogger().always().info("Traffic light set to GREEN");
144 trafficLight.setTrafficLightColor(TrafficLightColor.GREEN);
145 }
146
147
148 private class RampMeteringSensor extends AbstractSensor
149 {
150
151
152 private static final long serialVersionUID = 20190618L;
153
154
155 private final TrafficLight trafficLight;
156
157
158
159
160
161
162
163 RampMeteringSensor(final TrafficLight trafficLight, final OTSSimulatorInterface simulator,
164 final Compatible detectedGTUTypes) throws NetworkException
165 {
166 super(trafficLight.getId() + "_sensor", trafficLight.getLane(), trafficLight.getLongitudinalPosition(),
167 RelativePosition.FRONT, simulator, detectedGTUTypes);
168 this.trafficLight = trafficLight;
169 }
170
171
172 @SuppressWarnings("synthetic-access")
173 @Override
174 protected void triggerResponse(final LaneBasedGTU gtu)
175 {
176 if (CycleTimeLightController.this.enabled && this.trafficLight.getTrafficLightColor().isGreen())
177 {
178 try
179 {
180
181 Time minRedTime = CycleTimeLightController.this.simulator.getSimulatorAbsTime().plus(MIN_RED_TIME);
182 Time cycleRedTime = CycleTimeLightController.this.greenStarts.get(this.trafficLight)
183 .plus(CycleTimeLightController.this.cTime);
184 Time green;
185 if (minRedTime.ge(cycleRedTime))
186 {
187 getSimulator().getLogger().always().info("Traffic light set to RED");
188 this.trafficLight.setTrafficLightColor(TrafficLightColor.RED);
189 green = minRedTime;
190 }
191 else
192 {
193 getSimulator().getLogger().always().info("Traffic light set to YELLOW (RED over 'MIN_RED_TIME')");
194 this.trafficLight.setTrafficLightColor(TrafficLightColor.YELLOW);
195 CycleTimeLightController.this.redEvents.put(this.trafficLight,
196 CycleTimeLightController.this.simulator.scheduleEventRel(MIN_RED_TIME, this,
197 CycleTimeLightController.this, "setRed", new Object[] {this.trafficLight}));
198 green = cycleRedTime;
199 }
200 CycleTimeLightController.this.greenEvents.put(this.trafficLight,
201 CycleTimeLightController.this.simulator.scheduleEventAbsTime(green, this,
202 CycleTimeLightController.this, "setGreen", new Object[] {this.trafficLight}));
203 }
204 catch (SimRuntimeException exception)
205 {
206 throw new RuntimeException(exception);
207 }
208 }
209 }
210
211
212 @Override
213 public AbstractSensor clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator)
214 throws NetworkException
215 {
216 return null;
217 }
218
219 }
220
221 }