1 package org.opentrafficsim.demo.carFollowing;
2
3 import java.awt.Frame;
4 import java.awt.geom.Rectangle2D;
5 import java.rmi.RemoteException;
6 import java.util.ArrayList;
7 import java.util.LinkedHashSet;
8 import java.util.Random;
9 import java.util.Set;
10
11 import javax.naming.NamingException;
12 import javax.swing.JPanel;
13 import javax.swing.SwingUtilities;
14
15 import nl.tudelft.simulation.dsol.SimRuntimeException;
16 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
17 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
18
19 import org.djunits.unit.TimeUnit;
20 import org.djunits.unit.UNITS;
21 import org.djunits.value.vdouble.scalar.Acceleration;
22 import org.djunits.value.vdouble.scalar.DoubleScalar;
23 import org.djunits.value.vdouble.scalar.Length;
24 import org.djunits.value.vdouble.scalar.Speed;
25 import org.djunits.value.vdouble.scalar.Time;
26 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
27 import org.opentrafficsim.core.dsol.OTSModelInterface;
28 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
29 import org.opentrafficsim.core.geometry.OTSGeometryException;
30 import org.opentrafficsim.core.geometry.OTSPoint3D;
31 import org.opentrafficsim.core.gtu.GTUDirectionality;
32 import org.opentrafficsim.core.gtu.GTUException;
33 import org.opentrafficsim.core.gtu.GTUType;
34 import org.opentrafficsim.core.gtu.animation.GTUColorer;
35 import org.opentrafficsim.core.network.LongitudinalDirectionality;
36 import org.opentrafficsim.core.network.NetworkException;
37 import org.opentrafficsim.core.network.OTSNetwork;
38 import org.opentrafficsim.core.network.OTSNode;
39 import org.opentrafficsim.graphs.FundamentalDiagram;
40 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
41 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
42 import org.opentrafficsim.road.gtu.lane.driver.LaneBasedBehavioralCharacteristics;
43 import org.opentrafficsim.road.gtu.lane.perception.LanePerceptionFull;
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.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
49 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
50 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
51 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
52 import org.opentrafficsim.road.network.factory.LaneFactory;
53 import org.opentrafficsim.road.network.lane.CrossSectionLink;
54 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
55 import org.opentrafficsim.road.network.lane.Lane;
56 import org.opentrafficsim.road.network.lane.LaneType;
57 import org.opentrafficsim.road.network.lane.Sensor;
58 import org.opentrafficsim.road.network.lane.SinkSensor;
59 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
60 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
61 import org.opentrafficsim.simulationengine.OTSSimulationException;
62 import org.opentrafficsim.simulationengine.properties.AbstractProperty;
63 import org.opentrafficsim.simulationengine.properties.ProbabilityDistributionProperty;
64 import org.opentrafficsim.simulationengine.properties.PropertyException;
65 import org.opentrafficsim.simulationengine.properties.SelectionProperty;
66
67
68
69
70
71
72
73
74
75
76
77 public class FundamentalDiagrams extends AbstractWrappableAnimation implements UNITS
78 {
79
80 private FundamentalDiagramPlotsModel model;
81
82
83 public FundamentalDiagrams()
84 {
85 try
86 {
87 this.properties.add(new SelectionProperty("Car following model",
88 "<html>The car following model determines "
89 + "the acceleration that a vehicle will make taking into account nearby vehicles, "
90 + "infrastructural restrictions (e.g. speed limit, curvature of the road) "
91 + "capabilities of the vehicle and personality of the driver.</html>", new String[]{"IDM", "IDM+"},
92 1, false, 500));
93 this.properties.add(new ProbabilityDistributionProperty("Traffic composition",
94 "<html>Mix of passenger cars and trucks</html>", new String[]{"passenger car", "truck"}, new Double[]{
95 0.8, 0.2}, false, 10));
96 }
97 catch (PropertyException exception)
98 {
99 exception.printStackTrace();
100 }
101 }
102
103
104 @Override
105 public final void stopTimersThreads()
106 {
107 super.stopTimersThreads();
108 this.model = null;
109 }
110
111
112
113
114
115
116 public static void main(final String[] args) throws SimRuntimeException
117 {
118
119 SwingUtilities.invokeLater(new Runnable()
120 {
121 @Override
122 public void run()
123 {
124 try
125 {
126 FundamentalDiagrams fundamentalDiagrams = new FundamentalDiagrams();
127 fundamentalDiagrams.buildAnimator(new Time.Abs(0.0, SECOND), new Time.Rel(0.0, SECOND),
128 new Time.Rel(3600.0, SECOND), fundamentalDiagrams.getProperties(), null, true);
129 }
130 catch (SimRuntimeException | NamingException | OTSSimulationException exception)
131 {
132 exception.printStackTrace();
133 }
134 }
135 });
136 }
137
138
139 @Override
140 protected final OTSModelInterface makeModel(final GTUColorer colorer)
141 {
142 this.model = new FundamentalDiagramPlotsModel(this.savedUserModifiedProperties, colorer);
143 return this.model;
144 }
145
146
147 @Override
148 protected final Rectangle2D.Double makeAnimationRectangle()
149 {
150 return new Rectangle2D.Double(0, -100, 5000, 200);
151 }
152
153
154 @Override
155 protected final JPanel makeCharts() throws OTSSimulationException
156 {
157 final int panelsPerRow = 3;
158 TablePanel charts = new TablePanel(4, panelsPerRow);
159 for (int plotNumber = 0; plotNumber < 10; plotNumber++)
160 {
161 Length.Rel detectorLocation = new Length.Rel(400 + 500 * plotNumber, METER);
162 FundamentalDiagram fd;
163 try
164 {
165 fd =
166 new FundamentalDiagram("Fundamental Diagram at " + detectorLocation.getSI() + "m", new Time.Rel(1,
167 MINUTE), this.model.getLane(), detectorLocation);
168 fd.setTitle("Density Contour Graph");
169 fd.setExtendedState(Frame.MAXIMIZED_BOTH);
170 this.model.getFundamentalDiagrams().add(fd);
171 charts.setCell(fd.getContentPane(), plotNumber / panelsPerRow, plotNumber % panelsPerRow);
172 }
173 catch (NetworkException exception)
174 {
175 exception.printStackTrace();
176 }
177 }
178 return charts;
179 }
180
181
182 @Override
183 public final String shortName()
184 {
185 return "Fundamental Diagrams";
186 }
187
188
189 @Override
190 public final String description()
191 {
192 return "<html><h1>Fundamental Diagram Plots</H1>"
193 + "Simulation of a single lane road of 5 km length. Vechicles are generated at a constant rate of "
194 + "1500 veh/hour. At time 300s a blockade is inserted at position 4km; this blockade is removed at time "
195 + "500s. This blockade simulates a bridge opening.<br>"
196 + "The blockade causes a traffic jam that slowly dissolves after the blockade is removed.<br>"
197 + "Output is a set of Diagrams that plot observed density, flow and speed plots against each other.</html>";
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 class FundamentalDiagramPlotsModel implements OTSModelInterface, UNITS
215 {
216
217 private static final long serialVersionUID = 20140820L;
218
219
220 private OTSDEVSSimulatorInterface simulator;
221
222
223 private OTSNetwork network = new OTSNetwork("network");
224
225
226 private Time.Rel headway;
227
228
229 private int carsCreated = 0;
230
231
232 private GTUType gtuType = GTUType.makeGTUType("Car");
233
234
235 private GTUFollowingModelOld carFollowingModelCars;
236
237
238 private GTUFollowingModelOld carFollowingModelTrucks;
239
240
241 private double carProbability;
242
243
244 private AbstractLaneChangeModel laneChangeModel = new Egoistic();
245
246
247 private LaneBasedIndividualGTU block = null;
248
249
250 private Length.Rel minimumDistance = new Length.Rel(0, METER);
251
252
253 private Length.Rel maximumDistance = new Length.Rel(5000, METER);
254
255
256 private Lane lane;
257
258
259 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
260
261
262 private ArrayList<FundamentalDiagram> fundamentalDiagrams = new ArrayList<FundamentalDiagram>();
263
264
265 private ArrayList<AbstractProperty<?>> properties = null;
266
267
268 private Random randomGenerator = new Random(12345);
269
270
271 private final GTUColorer gtuColorer;
272
273
274
275
276
277 public FundamentalDiagramPlotsModel(final ArrayList<AbstractProperty<?>> properties, final GTUColorer gtuColorer)
278 {
279 this.properties = properties;
280 this.gtuColorer = gtuColorer;
281 }
282
283
284 @Override
285 public final
286 void
287 constructModel(
288 final SimulatorInterface<DoubleScalar.Abs<TimeUnit>, DoubleScalar.Rel<TimeUnit>, OTSSimTimeDouble> theSimulator)
289 throws SimRuntimeException, RemoteException
290 {
291 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
292 OTSNode from = new OTSNode("From", new OTSPoint3D(getMinimumDistance().getSI(), 0, 0));
293 OTSNode to = new OTSNode("To", new OTSPoint3D(getMaximumDistance().getSI(), 0, 0));
294 OTSNode end = new OTSNode("End", new OTSPoint3D(getMaximumDistance().getSI() + 50.0, 0, 0));
295 LaneType laneType = new LaneType("CarLane");
296 laneType.addCompatibility(this.gtuType);
297 try
298 {
299 this.lane =
300 LaneFactory.makeLane("Lane", from, to, null, laneType, this.speedLimit, this.simulator,
301 LongitudinalDirectionality.DIR_PLUS);
302 CrossSectionLink endLink =
303 LaneFactory.makeLink("endLink", to, end, null, LongitudinalDirectionality.DIR_PLUS);
304
305 Lane sinkLane =
306 new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
307 this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0),
308 laneType, LongitudinalDirectionality.DIR_PLUS, this.speedLimit, new OvertakingConditions.None());
309 Sensor sensor = new SinkSensor(sinkLane, new Length.Rel(10.0, METER), this.simulator);
310 sinkLane.addSensor(sensor, GTUType.ALL);
311 }
312 catch (NamingException | NetworkException | OTSGeometryException exception)
313 {
314 exception.printStackTrace();
315 }
316
317
318
319 for (AbstractProperty<?> p : this.properties)
320 {
321 if (p instanceof SelectionProperty)
322 {
323 SelectionProperty sp = (SelectionProperty) p;
324 if ("Car following model".equals(sp.getShortName()))
325 {
326 String modelName = sp.getValue();
327 if (modelName.equals("IDM"))
328 {
329 this.carFollowingModelCars =
330 new IDMOld(new Acceleration(1, METER_PER_SECOND_2), new Acceleration(1.5,
331 METER_PER_SECOND_2), new Length.Rel(2, METER), new Time.Rel(1, SECOND), 1d);
332 this.carFollowingModelTrucks =
333 new IDMOld(new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.5,
334 METER_PER_SECOND_2), new Length.Rel(2, METER), new Time.Rel(1, SECOND), 1d);
335 }
336 else if (modelName.equals("IDM+"))
337 {
338 this.carFollowingModelCars =
339 new IDMPlusOld(new Acceleration(1, METER_PER_SECOND_2), new Acceleration(1.5,
340 METER_PER_SECOND_2), new Length.Rel(2, METER), new Time.Rel(1, SECOND), 1d);
341 this.carFollowingModelTrucks =
342 new IDMPlusOld(new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.5,
343 METER_PER_SECOND_2), new Length.Rel(2, METER), new Time.Rel(1, SECOND), 1d);
344 }
345 else
346 {
347 throw new Error("Car following model " + modelName + " not implemented");
348 }
349 }
350 else
351 {
352 throw new Error("Unhandled SelectionProperty " + p.getShortName());
353 }
354 }
355 else if (p instanceof ProbabilityDistributionProperty)
356 {
357 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) p;
358 String modelName = p.getShortName();
359 if (modelName.equals("Traffic composition"))
360 {
361 this.carProbability = pdp.getValue()[0];
362 }
363 else
364 {
365 throw new Error("Unhandled ProbabilityDistributionProperty " + p.getShortName());
366 }
367 }
368 else
369 {
370 throw new Error("Unhandled property: " + p);
371 }
372 }
373
374
375 this.headway = new Time.Rel(3600.0 / 1500.0, SECOND);
376
377 try
378 {
379
380 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(0.0, SECOND), this, this, "generateCar",
381 null);
382
383 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(300, SECOND), this, this, "createBlock",
384 null);
385
386 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(420, SECOND), this, this, "removeBlock",
387 null);
388
389 for (int t = 1; t <= 1800; t++)
390 {
391 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(t - 0.001, SECOND), this, this,
392 "drawGraphs", null);
393 }
394 }
395 catch (SimRuntimeException exception)
396 {
397 exception.printStackTrace();
398 }
399 }
400
401
402
403
404
405 protected final void createBlock() throws RemoteException
406 {
407 Length.Rel initialPosition = new Length.Rel(4000, METER);
408 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
409 try
410 {
411 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition,
412 GTUDirectionality.DIR_PLUS));
413 LaneBasedBehavioralCharacteristics drivingCharacteristics =
414 new LaneBasedBehavioralCharacteristics(this.carFollowingModelCars, this.laneChangeModel);
415 LaneBasedStrategicalPlanner strategicalPlanner =
416 new LaneBasedStrategicalRoutePlanner(drivingCharacteristics,
417 new LaneBasedGTUFollowingTacticalPlanner());
418 this.block =
419 new LaneBasedIndividualGTU("999999", this.gtuType, initialPositions, new Speed(0.0, KM_PER_HOUR),
420 new Length.Rel(4, METER), new Length.Rel(1.8, METER), new Speed(0.0, KM_PER_HOUR),
421 this.simulator, strategicalPlanner, new LanePerceptionFull(), DefaultCarAnimation.class,
422 this.gtuColorer, this.network);
423 }
424 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
425 {
426 exception.printStackTrace();
427 }
428 }
429
430
431
432
433 protected final void removeBlock()
434 {
435 this.block.destroy();
436 this.block = null;
437 }
438
439
440
441
442 protected final void generateCar()
443 {
444 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
445 Length.Rel initialPosition = new Length.Rel(0, METER);
446 Speed initialSpeed = new Speed(100, KM_PER_HOUR);
447 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
448 try
449 {
450 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition,
451 GTUDirectionality.DIR_PLUS));
452 Length.Rel vehicleLength = new Length.Rel(generateTruck ? 15 : 4, METER);
453 GTUFollowingModelOld gtuFollowingModel =
454 generateTruck ? this.carFollowingModelTrucks : this.carFollowingModelCars;
455 if (null == gtuFollowingModel)
456 {
457 throw new Error("gtuFollowingModel is null");
458 }
459 LaneBasedBehavioralCharacteristics drivingCharacteristics =
460 new LaneBasedBehavioralCharacteristics(gtuFollowingModel, this.laneChangeModel);
461 LaneBasedStrategicalPlanner strategicalPlanner =
462 new LaneBasedStrategicalRoutePlanner(drivingCharacteristics,
463 new LaneBasedGTUFollowingTacticalPlanner());
464 new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, initialPositions, initialSpeed,
465 vehicleLength, new Length.Rel(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator,
466 strategicalPlanner, new LanePerceptionFull(), DefaultCarAnimation.class, this.gtuColorer,
467 this.network);
468
469 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
470 }
471 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
472 {
473 exception.printStackTrace();
474 }
475 }
476
477
478
479
480 protected final void drawGraphs()
481 {
482
483 for (FundamentalDiagram fd : this.fundamentalDiagrams)
484 {
485 fd.reGraph();
486 }
487 }
488
489
490 @Override
491 public final SimulatorInterface<DoubleScalar.Abs<TimeUnit>, DoubleScalar.Rel<TimeUnit>, OTSSimTimeDouble>
492 getSimulator() throws RemoteException
493 {
494 return null;
495 }
496
497
498
499
500 public final ArrayList<FundamentalDiagram> getFundamentalDiagrams()
501 {
502 return this.fundamentalDiagrams;
503 }
504
505
506
507
508 public final Length.Rel getMinimumDistance()
509 {
510 return this.minimumDistance;
511 }
512
513
514
515
516 public final Length.Rel getMaximumDistance()
517 {
518 return this.maximumDistance;
519 }
520
521
522
523
524 public Lane getLane()
525 {
526 return this.lane;
527 }
528 }
529 }