1 package org.opentrafficsim.demo.carFollowing;
2
3 import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
4
5 import java.awt.Frame;
6 import java.rmi.RemoteException;
7 import java.util.ArrayList;
8 import java.util.HashSet;
9 import java.util.LinkedHashSet;
10 import java.util.List;
11 import java.util.Random;
12 import java.util.Set;
13
14 import javax.naming.NamingException;
15 import javax.swing.SwingUtilities;
16
17 import org.djunits.unit.TimeUnit;
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.ProbabilityDistributionProperty;
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.graphs.FundamentalDiagram;
43 import org.opentrafficsim.road.animation.AnimationToggles;
44 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
45 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
46 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingTacticalPlanner;
47 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
48 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
49 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
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.changing.OvertakingConditions;
58 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
59 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
60 import org.opentrafficsim.simulationengine.OTSSimulationException;
61 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
62
63 import nl.tudelft.simulation.dsol.SimRuntimeException;
64 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
65 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
66
67
68
69
70
71
72
73
74
75
76
77 public class FundamentalDiagrams extends AbstractWrappableAnimation implements UNITS
78 {
79
80 private static final long serialVersionUID = 1L;
81
82
83 private FundamentalDiagramPlotsModel model;
84
85
86 public FundamentalDiagrams()
87 {
88 try
89 {
90 this.properties.add(new SelectionProperty("CarFollowingModel", "Car following model",
91 "<html>The car following model determines "
92 + "the acceleration that a vehicle will make taking into account nearby vehicles, "
93 + "infrastructural restrictions (e.g. speed limit, curvature of the road) "
94 + "capabilities of the vehicle and personality of the driver.</html>",
95 new String[] { "IDM", "IDM+" }, 1, false, 500));
96 this.properties.add(new ProbabilityDistributionProperty("TrafficComposition", "Traffic composition",
97 "<html>Mix of passenger cars and trucks</html>", new String[] { "passenger car", "truck" },
98 new Double[] { 0.8, 0.2 }, false, 10));
99 }
100 catch (PropertyException exception)
101 {
102 exception.printStackTrace();
103 }
104 }
105
106
107 @Override
108 public final void stopTimersThreads()
109 {
110 super.stopTimersThreads();
111 this.model = null;
112 }
113
114
115
116
117
118
119 public static void main(final String[] args) throws SimRuntimeException
120 {
121
122 SwingUtilities.invokeLater(new Runnable()
123 {
124 @Override
125 public void run()
126 {
127 try
128 {
129 FundamentalDiagrams fundamentalDiagrams = new FundamentalDiagrams();
130 fundamentalDiagrams.buildAnimator(Time.ZERO, Duration.ZERO,
131 new Duration(3600.0, SECOND), fundamentalDiagrams.getProperties(), null, true);
132 }
133 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
134 {
135 exception.printStackTrace();
136 }
137 }
138 });
139 }
140
141
142 @Override
143 protected final OTSModelInterface makeModel(final GTUColorer colorer)
144 {
145 this.model = new FundamentalDiagramPlotsModel(this.savedUserModifiedProperties, colorer);
146 return this.model;
147 }
148
149
150 @Override
151 protected final void addAnimationToggles()
152 {
153 AnimationToggles.setTextAnimationTogglesStandard(this);
154 }
155
156
157 @Override
158 protected final void addTabs(final SimpleSimulatorInterface simulator) throws OTSSimulationException
159 {
160 final int panelsPerRow = 3;
161 TablePanel charts = new TablePanel(4, panelsPerRow);
162 for (int plotNumber = 0; plotNumber < 10; plotNumber++)
163 {
164 Length detectorLocation = new Length(400 + 500 * plotNumber, METER);
165 FundamentalDiagram fd;
166 try
167 {
168 fd = new FundamentalDiagram("Fundamental Diagram at " + detectorLocation.getSI() + "m", new Duration(1, MINUTE),
169 this.model.getLane(), detectorLocation, simulator);
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 addTab(getTabCount(), "statistics", 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
217 class FundamentalDiagramPlotsModel implements OTSModelInterface, UNITS
218 {
219
220 private static final long serialVersionUID = 20140820L;
221
222
223 private OTSDEVSSimulatorInterface simulator;
224
225
226 private OTSNetwork network = new OTSNetwork("network");
227
228
229 private Duration headway;
230
231
232 private int carsCreated = 0;
233
234
235 private GTUType gtuType = CAR;
236
237
238 private GTUFollowingModelOld carFollowingModelCars;
239
240
241 private GTUFollowingModelOld carFollowingModelTrucks;
242
243
244 private double carProbability;
245
246
247 private LaneBasedIndividualGTU block = null;
248
249
250 private Length minimumDistance = new Length(0, METER);
251
252
253 private Length maximumDistance = new Length(5000, METER);
254
255
256 private Lane lane;
257
258
259 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
260
261
262 private List<FundamentalDiagram> fundamentalDiagrams = new ArrayList<>();
263
264
265 private List<Property<?>> fundamentalDiagramProperties = null;
266
267
268 private Random randomGenerator = new Random(12345);
269
270
271 private final GTUColorer gtuColorer;
272
273
274
275
276
277 FundamentalDiagramPlotsModel(final List<Property<?>> properties, final GTUColorer gtuColorer)
278 {
279 this.fundamentalDiagramProperties = properties;
280 this.gtuColorer = gtuColorer;
281 }
282
283
284 @Override
285 public final void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
286 throws SimRuntimeException, RemoteException
287 {
288 try
289 {
290 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
291 OTSNode from = new OTSNode(this.network, "From", new OTSPoint3D(getMinimumDistance().getSI(), 0, 0));
292 OTSNode to = new OTSNode(this.network, "To", new OTSPoint3D(getMaximumDistance().getSI(), 0, 0));
293 OTSNode end = new OTSNode(this.network, "End", new OTSPoint3D(getMaximumDistance().getSI() + 50.0, 0, 0));
294 Set<GTUType> compatibility = new HashSet<>();
295 compatibility.add(this.gtuType);
296 LaneType laneType = new LaneType("CarLane", compatibility);
297 this.lane = LaneFactory.makeLane(this.network, "Lane", from, to, null, laneType, this.speedLimit,
298 this.simulator, LongitudinalDirectionality.DIR_PLUS);
299 CrossSectionLink endLink = LaneFactory.makeLink(this.network, "endLink", to, end, null,
300 LongitudinalDirectionality.DIR_PLUS, simulator);
301
302 Lane sinkLane = new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
303 this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0), laneType,
304 LongitudinalDirectionality.DIR_PLUS, this.speedLimit, new OvertakingConditions.None());
305 new SinkSensor(sinkLane, new Length(10.0, METER), this.simulator);
306 }
307 catch (NamingException | NetworkException | OTSGeometryException exception)
308 {
309 exception.printStackTrace();
310 }
311
312
313
314 for (Property<?> p : this.fundamentalDiagramProperties)
315 {
316 if (p instanceof SelectionProperty)
317 {
318 SelectionProperty sp = (SelectionProperty) p;
319 if ("CarFollowingModel".equals(sp.getKey()))
320 {
321 String modelName = sp.getValue();
322 if (modelName.equals("IDM"))
323 {
324 this.carFollowingModelCars = new IDMOld(new Acceleration(1, METER_PER_SECOND_2),
325 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND),
326 1d);
327 this.carFollowingModelTrucks = new IDMOld(new Acceleration(0.5, METER_PER_SECOND_2),
328 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND),
329 1d);
330 }
331 else if (modelName.equals("IDM+"))
332 {
333 this.carFollowingModelCars = new IDMPlusOld(new Acceleration(1, METER_PER_SECOND_2),
334 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND),
335 1d);
336 this.carFollowingModelTrucks = new IDMPlusOld(new Acceleration(0.5, METER_PER_SECOND_2),
337 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND),
338 1d);
339 }
340 else
341 {
342 throw new Error("Car following model " + modelName + " not implemented");
343 }
344 }
345 else
346 {
347 throw new Error("Unhandled SelectionProperty " + p.getKey());
348 }
349 }
350 else if (p instanceof ProbabilityDistributionProperty)
351 {
352 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) p;
353 String modelName = p.getKey();
354 if (modelName.equals("TrafficComposition"))
355 {
356 this.carProbability = pdp.getValue()[0];
357 }
358 else
359 {
360 throw new Error("Unhandled ProbabilityDistributionProperty " + p.getKey());
361 }
362 }
363 else
364 {
365 throw new Error("Unhandled property: " + p);
366 }
367 }
368
369
370 this.headway = new Duration(3600.0 / 1500.0, SECOND);
371
372 try
373 {
374
375 this.simulator.scheduleEventAbs(Time.ZERO, this, this, "generateCar", null);
376
377 this.simulator.scheduleEventAbs(new Time(300, TimeUnit.BASE_SECOND), this, this, "createBlock", null);
378
379 this.simulator.scheduleEventAbs(new Time(420, TimeUnit.BASE_SECOND), this, this, "removeBlock", null);
380
381 for (int t = 1; t <= 1800; t++)
382 {
383 this.simulator.scheduleEventAbs(new Time(t - 0.001, TimeUnit.BASE_SECOND), this, this, "drawGraphs", null);
384 }
385 }
386 catch (SimRuntimeException exception)
387 {
388 exception.printStackTrace();
389 }
390 }
391
392
393
394
395
396 protected final void createBlock() throws RemoteException
397 {
398 Length initialPosition = new Length(4000, METER);
399 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
400 try
401 {
402 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition, GTUDirectionality.DIR_PLUS));
403 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
404
405
406
407 this.block = new LaneBasedIndividualGTU("999999", this.gtuType, new Length(4, METER), new Length(1.8, METER),
408 Speed.ZERO, this.simulator, this.network);
409 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
410 new LaneBasedGTUFollowingTacticalPlanner(this.carFollowingModelCars, this.block), this.block);
411 this.block.initWithAnimation(strategicalPlanner, initialPositions, Speed.ZERO,
412 DefaultCarAnimation.class, this.gtuColorer);
413 }
414 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
415 {
416 exception.printStackTrace();
417 }
418 }
419
420
421
422
423 protected final void removeBlock()
424 {
425 this.block.destroy();
426 this.block = null;
427 }
428
429
430
431
432 protected final void generateCar()
433 {
434 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
435 Length initialPosition = new Length(0, METER);
436 Speed initialSpeed = new Speed(100, KM_PER_HOUR);
437 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
438 try
439 {
440 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition, GTUDirectionality.DIR_PLUS));
441 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
442 GTUFollowingModelOld gtuFollowingModel =
443 generateTruck ? this.carFollowingModelTrucks : this.carFollowingModelCars;
444 if (null == gtuFollowingModel)
445 {
446 throw new Error("gtuFollowingModel is null");
447 }
448 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
449
450
451
452 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, vehicleLength,
453 new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, this.network);
454 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
455 new LaneBasedGTUFollowingTacticalPlanner(gtuFollowingModel, gtu), gtu);
456 gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class,
457 this.gtuColorer);
458
459 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
460 }
461 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
462 {
463 exception.printStackTrace();
464 }
465 }
466
467
468
469
470 protected final void drawGraphs()
471 {
472
473 for (FundamentalDiagram fd : this.fundamentalDiagrams)
474 {
475 fd.reGraph();
476 }
477 }
478
479
480 @Override
481 public final SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
482 {
483 return this.simulator;
484 }
485
486
487 @Override
488 public OTSNetwork getNetwork()
489 {
490 return this.network;
491 }
492
493
494
495
496 public final List<FundamentalDiagram> getFundamentalDiagrams()
497 {
498 return this.fundamentalDiagrams;
499 }
500
501
502
503
504 public final Length getMinimumDistance()
505 {
506 return this.minimumDistance;
507 }
508
509
510
511
512 public final Length getMaximumDistance()
513 {
514 return this.maximumDistance;
515 }
516
517
518
519
520 public Lane getLane()
521 {
522 return this.lane;
523 }
524 }
525
526
527 @Override
528 public final String toString()
529 {
530 return "FundamentalDiagrams [model=" + this.model + "]";
531 }
532 }