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