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