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