1 package org.opentrafficsim.demo.carFollowing;
2
3 import java.awt.geom.Rectangle2D;
4 import java.io.IOException;
5 import java.net.URL;
6 import java.rmi.RemoteException;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.LinkedHashSet;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13
14 import javax.naming.NamingException;
15 import javax.swing.JComponent;
16 import javax.swing.JPanel;
17 import javax.swing.JScrollPane;
18 import javax.swing.SwingUtilities;
19
20 import org.djunits.unit.LengthUnit;
21 import org.djunits.unit.SpeedUnit;
22 import org.djunits.unit.TimeUnit;
23 import org.djunits.unit.UNITS;
24 import org.djunits.value.vdouble.scalar.Duration;
25 import org.djunits.value.vdouble.scalar.Length;
26 import org.djunits.value.vdouble.scalar.Speed;
27 import org.djunits.value.vdouble.scalar.Time;
28 import org.opentrafficsim.base.modelproperties.Property;
29 import org.opentrafficsim.base.modelproperties.PropertyException;
30 import org.opentrafficsim.base.modelproperties.SelectionProperty;
31 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
32 import org.opentrafficsim.core.dsol.OTSModelInterface;
33 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
34 import org.opentrafficsim.core.geometry.OTSGeometryException;
35 import org.opentrafficsim.core.geometry.OTSPoint3D;
36 import org.opentrafficsim.core.gtu.GTUDirectionality;
37 import org.opentrafficsim.core.gtu.GTUException;
38 import org.opentrafficsim.core.gtu.GTUType;
39 import org.opentrafficsim.core.gtu.animation.GTUColorer;
40 import org.opentrafficsim.core.network.LongitudinalDirectionality;
41 import org.opentrafficsim.core.network.NetworkException;
42 import org.opentrafficsim.core.network.OTSNetwork;
43 import org.opentrafficsim.core.network.OTSNode;
44 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
45 import org.opentrafficsim.demo.PropertiesParser;
46 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
47 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
48 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
49 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
50 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
51 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
52 import org.opentrafficsim.road.network.factory.LaneFactory;
53 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
54 import org.opentrafficsim.road.network.lane.Lane;
55 import org.opentrafficsim.road.network.lane.LaneType;
56 import org.opentrafficsim.road.network.lane.object.sensor.Sensor;
57 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
58 import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
59 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
60 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightColor;
61 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
62 import org.opentrafficsim.simulationengine.OTSSimulationException;
63 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
64
65 import nl.tudelft.simulation.dsol.SimRuntimeException;
66 import nl.tudelft.simulation.dsol.gui.swing.HTMLPanel;
67 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
68 import nl.tudelft.simulation.jstats.distributions.DistTriangular;
69 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
70 import nl.tudelft.simulation.jstats.streams.StreamInterface;
71
72
73
74
75
76
77
78
79
80
81
82 public class CrossingTrafficLights extends AbstractWrappableAnimation implements UNITS
83 {
84
85 private static final long serialVersionUID = 1L;
86
87
88 private CrossingTrafficLightstModel model;
89
90
91 protected static final Duration TGREEN = new Duration(39.0, TimeUnit.SI);
92
93
94 protected static final Duration TYELLOW = new Duration(6.0, TimeUnit.SI);
95
96
97 protected static final Duration TRED = new Duration(45.0, TimeUnit.SI);
98
99
100
101
102
103 public CrossingTrafficLights() throws PropertyException
104 {
105 this.properties.add(new SelectionProperty("LaneChanging", "Lane changing",
106 "<html>The lane change strategies vary in politeness.<br>"
107 + "Two types are implemented:<ul><li>Egoistic (looks only at personal gain).</li>"
108 + "<li>Altruistic (assigns effect on new and current follower the same weight as "
109 + "the personal gain).</html>",
110 new String[] { "Egoistic", "Altruistic" }, 0, false, 500));
111 this.properties.add(new SelectionProperty("TacticalPlanner", "Tactical planner",
112 "<html>The tactical planner determines if a lane change is desired and possible.</html>",
113 new String[] { "IDM", "MOBIL/IDM", "DIRECTED/IDM", "LMRS", "Toledo" }, 0, false, 600));
114 }
115
116
117 @Override
118 public final void stopTimersThreads()
119 {
120 super.stopTimersThreads();
121 this.model = null;
122 }
123
124
125
126
127
128
129 public static void main(final String[] args) throws SimRuntimeException
130 {
131 SwingUtilities.invokeLater(new Runnable()
132 {
133 @SuppressWarnings("synthetic-access")
134 @Override
135 public void run()
136 {
137 try
138 {
139 CrossingTrafficLights crossingTrafficLights = new CrossingTrafficLights();
140 List<Property<?>> localProperties = crossingTrafficLights.getProperties();
141 crossingTrafficLights.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND),
142 new Duration(3600.0, SECOND), localProperties, null, true);
143
144 crossingTrafficLights.panel.getTabbedPane().addTab("info", crossingTrafficLights.makeInfoPane());
145 }
146 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
147 {
148 exception.printStackTrace();
149 }
150 }
151 });
152 }
153
154
155 @Override
156 protected final Rectangle2D.Double makeAnimationRectangle()
157 {
158 return new Rectangle2D.Double(-600, -600, 1200, 1200);
159 }
160
161
162 @Override
163 protected final OTSModelInterface makeModel(final GTUColorer colorer)
164 {
165 this.model = new CrossingTrafficLightstModel(this.savedUserModifiedProperties, colorer);
166 return this.model;
167 }
168
169
170
171
172 protected final JComponent makeInfoPane()
173 {
174
175 String helpSource = "/" + CrossingTrafficLightstModel.class.getPackage().getName().replace('.', '/') + "/IDMPlus.html";
176 URL page = CrossingTrafficLightstModel.class.getResource(helpSource);
177 if (page != null)
178 {
179 try
180 {
181 HTMLPanel htmlPanel = new HTMLPanel(page);
182 return new JScrollPane(htmlPanel);
183 }
184 catch (IOException exception)
185 {
186 exception.printStackTrace();
187 }
188 }
189 return new JPanel();
190 }
191
192
193 @Override
194 protected final JPanel makeCharts(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
195 {
196 return null;
197 }
198
199
200 @Override
201 public final String shortName()
202 {
203 return "Crossing with Traffic Lights";
204 }
205
206
207 @Override
208 public final String description()
209 {
210 return "<html><h1>Simulation of a crossing with traffic lights</h1>"
211 + "Simulation of four double lane roads with a crossing in the middle.</html>";
212 }
213
214 }
215
216
217
218
219
220
221
222
223
224
225
226 class CrossingTrafficLightstModel implements OTSModelInterface, UNITS
227 {
228
229 private static final long serialVersionUID = 20140815L;
230
231
232 private OTSDEVSSimulatorInterface simulator;
233
234
235 private final OTSNetwork network = new OTSNetwork("network");
236
237
238 private StreamInterface stream = new MersenneTwister(555);
239
240
241 private ContinuousDistDoubleScalar.Rel<Duration, TimeUnit> headwayDistribution =
242 new ContinuousDistDoubleScalar.Rel<>(new DistTriangular(this.stream, 7, 9, 15), TimeUnit.SECOND);
243
244
245 private ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedDistribution =
246 new ContinuousDistDoubleScalar.Rel<>(new DistTriangular(this.stream, 50, 60, 70), SpeedUnit.KM_PER_HOUR);
247
248
249 private int carsCreated = 0;
250
251
252 private GTUType gtuType = new GTUType("Car");
253
254
255 private GTUFollowingModelOld carFollowingModel;
256
257
258 private LaneChangeModel laneChangeModel;
259
260
261 private List<Property<?>> properties = null;
262
263
264 private final GTUColorer gtuColorer;
265
266
267 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactory;
268
269
270 private Speed speedLimit = new Speed(80, KM_PER_HOUR);
271
272
273
274
275
276 CrossingTrafficLightstModel(final List<Property<?>> properties, final GTUColorer gtuColorer)
277 {
278 this.properties = properties;
279 this.gtuColorer = gtuColorer;
280 }
281
282
283 @Override
284 public final void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
285 throws SimRuntimeException, RemoteException
286 {
287 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
288 try
289 {
290 OTSNode[][] nodes = new OTSNode[4][4];
291 nodes[0][0] = new OTSNode(this.network, "sn1", new OTSPoint3D(10, -500));
292 nodes[0][1] = new OTSNode(this.network, "sn2", new OTSPoint3D(10, -20));
293 nodes[0][2] = new OTSNode(this.network, "sn3", new OTSPoint3D(10, +20));
294 nodes[0][3] = new OTSNode(this.network, "sn4", new OTSPoint3D(10, +5000));
295
296 nodes[1][0] = new OTSNode(this.network, "we1", new OTSPoint3D(-500, -10));
297 nodes[1][1] = new OTSNode(this.network, "we2", new OTSPoint3D(-20, -10));
298 nodes[1][2] = new OTSNode(this.network, "we3", new OTSPoint3D(+20, -10));
299 nodes[1][3] = new OTSNode(this.network, "we4", new OTSPoint3D(+5000, -10));
300
301 nodes[2][0] = new OTSNode(this.network, "ns1", new OTSPoint3D(-10, +500));
302 nodes[2][1] = new OTSNode(this.network, "ns2", new OTSPoint3D(-10, +20));
303 nodes[2][2] = new OTSNode(this.network, "ns3", new OTSPoint3D(-10, -20));
304 nodes[2][3] = new OTSNode(this.network, "ns4", new OTSPoint3D(-10, -5000));
305
306 nodes[3][0] = new OTSNode(this.network, "ew1", new OTSPoint3D(+500, 10));
307 nodes[3][1] = new OTSNode(this.network, "ew2", new OTSPoint3D(+20, 10));
308 nodes[3][2] = new OTSNode(this.network, "ew3", new OTSPoint3D(-20, 10));
309 nodes[3][3] = new OTSNode(this.network, "ew4", new OTSPoint3D(-5000, 10));
310
311 Set<GTUType> compatibility = new HashSet<>();
312 compatibility.add(this.gtuType);
313 LaneType laneType = new LaneType("CarLane", compatibility);
314
315 Map<Lane, SimpleTrafficLight> trafficLights = new HashMap<>();
316
317 for (int i = 0; i < 4; i++)
318 {
319 for (int j = 0; j < 3; j++)
320 {
321 Lane[] lanes = LaneFactory.makeMultiLane(this.network,
322 "Lane_" + nodes[i][j].getId() + "-" + nodes[i][j + 1].getId(), nodes[i][j], nodes[i][j + 1], null,
323 2, laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
324 if (j == 0)
325 {
326 for (Lane lane : lanes)
327 {
328 this.simulator.scheduleEventRel(this.headwayDistribution.draw(), this, this, "generateCar",
329 new Object[] { lane });
330 SimpleTrafficLight tl = new SimpleTrafficLight(lane.getId() + "_TL", lane,
331 new Length(lane.getLength().minus(new Length(10.0, LengthUnit.METER))), this.simulator);
332 lane.addLaneBasedObject(tl);
333 trafficLights.put(lane, tl);
334 if (i == 0 || i == 2)
335 {
336 this.simulator.scheduleEventRel(Duration.ZERO, this, this, "changeTL",
337 new Object[] { tl });
338 }
339 else
340 {
341 this.simulator.scheduleEventRel(CrossingTrafficLights.TRED, this, this, "changeTL",
342 new Object[] { tl });
343 }
344 }
345 }
346 if (j == 2)
347 {
348 for (Lane lane : lanes)
349 {
350 Sensor sensor = new SinkSensor(lane, new Length(500.0, METER), this.simulator);
351 }
352 }
353 }
354 }
355
356 this.carFollowingModel = PropertiesParser.parseGTUFollowingModelOld(this.properties, "Car");
357 this.laneChangeModel = PropertiesParser.parseLaneChangeModel(this.properties);
358 this.strategicalPlannerFactory =
359 PropertiesParser.parseStrategicalPlannerFactory(this.properties, this.carFollowingModel, this.laneChangeModel);
360 }
361 catch (SimRuntimeException | NamingException | NetworkException | OTSGeometryException | PropertyException
362 | GTUException exception)
363 {
364 exception.printStackTrace();
365 }
366 }
367
368
369
370
371
372
373 protected final void changeTL(final TrafficLight tl) throws SimRuntimeException
374 {
375 if (tl.getTrafficLightColor().isRed())
376 {
377 tl.setTrafficLightColor(TrafficLightColor.GREEN);
378 this.simulator.scheduleEventRel(CrossingTrafficLights.TGREEN, this, this, "changeTL", new Object[] { tl });
379 }
380 else if (tl.getTrafficLightColor().isGreen())
381 {
382 tl.setTrafficLightColor(TrafficLightColor.YELLOW);
383 this.simulator.scheduleEventRel(CrossingTrafficLights.TYELLOW, this, this, "changeTL", new Object[] { tl });
384 }
385 else if (tl.getTrafficLightColor().isYellow())
386 {
387 tl.setTrafficLightColor(TrafficLightColor.RED);
388 this.simulator.scheduleEventRel(CrossingTrafficLights.TRED, this, this, "changeTL", new Object[] { tl });
389 }
390 }
391
392
393
394
395
396 protected final void generateCar(final Lane lane)
397 {
398 Length initialPosition = new Length(10, METER);
399 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
400 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
401 try
402 {
403 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
404 Length vehicleLength = new Length(4, METER);
405 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, vehicleLength,
406 new Length(1.8, METER), this.speedDistribution.draw(), this.simulator, this.network);
407 LaneBasedStrategicalPlanner strategicalPlanner = this.strategicalPlannerFactory.create(gtu);
408 gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class,
409 this.gtuColorer);
410 this.simulator.scheduleEventRel(this.headwayDistribution.draw(), this, this, "generateCar", new Object[] { lane });
411 }
412 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
413 {
414 exception.printStackTrace();
415 }
416 }
417
418
419 @Override
420 public final SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
421 {
422 return this.simulator;
423 }
424 }