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.List;
10 import java.util.Random;
11 import java.util.Set;
12
13 import javax.naming.NamingException;
14 import javax.swing.JPanel;
15 import javax.swing.SwingUtilities;
16
17 import nl.tudelft.simulation.dsol.SimRuntimeException;
18 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
19 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
20
21 import org.djunits.unit.TimeUnit;
22 import org.djunits.unit.UNITS;
23 import org.djunits.value.vdouble.scalar.Acceleration;
24 import org.djunits.value.vdouble.scalar.DoubleScalar;
25 import org.djunits.value.vdouble.scalar.Duration;
26 import org.djunits.value.vdouble.scalar.Length;
27 import org.djunits.value.vdouble.scalar.Speed;
28 import org.djunits.value.vdouble.scalar.Time;
29 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
30 import org.opentrafficsim.core.dsol.OTSModelInterface;
31 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
32 import org.opentrafficsim.core.geometry.OTSGeometryException;
33 import org.opentrafficsim.core.geometry.OTSPoint3D;
34 import org.opentrafficsim.core.gtu.GTUDirectionality;
35 import org.opentrafficsim.core.gtu.GTUException;
36 import org.opentrafficsim.core.gtu.GTUType;
37 import org.opentrafficsim.core.gtu.animation.GTUColorer;
38 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
39 import org.opentrafficsim.core.network.LongitudinalDirectionality;
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.graphs.FundamentalDiagramLane;
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.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 FundamentalDiagramsLane extends AbstractWrappableAnimation implements UNITS
78 {
79
80 private static final long serialVersionUID = 1L;
81
82
83 private FundamentalDiagramLanePlotsModel model;
84
85
86 public FundamentalDiagramsLane()
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>", new String[] {"IDM", "IDM+"}, 1,
95 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"}, new Double[] {0.8,
98 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 FundamentalDiagramsLane fundamentalDiagramsLane = new FundamentalDiagramsLane();
130 fundamentalDiagramsLane.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND), new Duration(
131 3600.0, SECOND), fundamentalDiagramsLane.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 FundamentalDiagramLanePlotsModel(this.savedUserModifiedProperties, colorer);
146 return this.model;
147 }
148
149
150 @Override
151 protected final Rectangle2D.Double makeAnimationRectangle()
152 {
153 return new Rectangle2D.Double(0, -100, 5000, 200);
154 }
155
156
157 @Override
158 protected final JPanel makeCharts() throws OTSSimulationException
159 {
160 final int panelsPerRow = 3;
161 TablePanel charts = new TablePanel(3, panelsPerRow);
162 for (int plotNumber = 0; plotNumber < 9; plotNumber++)
163 {
164 FundamentalDiagramLane fd;
165 try
166 {
167 Lane lane = this.model.getLane(plotNumber);
168 int xs = (int) lane.getParentLink().getStartNode().getPoint().x;
169 int xe = (int) lane.getParentLink().getEndNode().getPoint().x;
170 fd =
171 new FundamentalDiagramLane("Fundamental Diagram for [" + xs + ", " + xe + "] m", new Duration(1.0,
172 SECOND), lane, (OTSDEVSSimulatorInterface) this.model.getSimulator());
173 fd.setTitle("Fundamental Diagram Graph");
174 fd.setExtendedState(Frame.MAXIMIZED_BOTH);
175 this.model.getFundamentalDiagrams().add(fd);
176 charts.setCell(fd.getContentPane(), plotNumber / panelsPerRow, plotNumber % panelsPerRow);
177 }
178 catch (NetworkException | RemoteException | SimRuntimeException exception)
179 {
180 exception.printStackTrace();
181 }
182 }
183 return charts;
184 }
185
186
187 @Override
188 public final String shortName()
189 {
190 return "Fundamental Diagrams";
191 }
192
193
194 @Override
195 public final String description()
196 {
197 return "<html><h1>Fundamental Diagram Plots</H1>"
198 + "Simulation of a single lane road of 5 km length. Vechicles are generated at a constant rate of "
199 + "1500 veh/hour. At time 300s a blockade is inserted at position 4km; this blockade is removed at time "
200 + "500s. This blockade simulates a bridge opening.<br>"
201 + "The blockade causes a traffic jam that slowly dissolves after the blockade is removed.<br>"
202 + "Output is a set of Diagrams that plot observed density, flow and speed plots against each other.</html>";
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 class FundamentalDiagramLanePlotsModel implements OTSModelInterface, UNITS
220 {
221
222 private static final long serialVersionUID = 20140820L;
223
224
225 private OTSNetwork network = new OTSNetwork("network");
226
227
228 private OTSDEVSSimulatorInterface simulator;
229
230
231 private Duration headway;
232
233
234 private int carsCreated = 0;
235
236
237 private GTUType gtuType = new GTUType("Car");
238
239
240 private GTUFollowingModelOld carFollowingModelCars;
241
242
243 private GTUFollowingModelOld carFollowingModelTrucks;
244
245
246 private double carProbability;
247
248
249 private LaneBasedIndividualGTU block = null;
250
251
252 private Length startX = new Length(0, METER);
253
254
255 private Length laneLength = new Length(500, METER);
256
257
258 private List<Lane> lanes = new ArrayList<>();
259
260
261 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
262
263
264 private ArrayList<FundamentalDiagramLane> fundamentalDiagramsLane = new ArrayList<>();
265
266
267 private ArrayList<AbstractProperty<?>> properties = null;
268
269
270 private Random randomGenerator = new Random(12345);
271
272
273 private final GTUColorer gtuColorer;
274
275
276
277
278
279 public FundamentalDiagramLanePlotsModel(final ArrayList<AbstractProperty<?>> properties, final GTUColorer gtuColorer)
280 {
281 this.properties = properties;
282 this.gtuColorer = gtuColorer;
283 }
284
285
286 @Override
287 public final void constructModel(
288 final SimulatorInterface<DoubleScalar.Abs<TimeUnit>, DoubleScalar.Rel<TimeUnit>, OTSSimTimeDouble> theSimulator)
289 throws SimRuntimeException, RemoteException
290 {
291 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
292 try
293 {
294 Set<GTUType> compatibility = new HashSet<>();
295 compatibility.add(this.gtuType);
296 LaneType laneType = new LaneType("CarLane", compatibility);
297 OTSNode node = new OTSNode("Node 0", new OTSPoint3D(this.startX.getSI(), 0, 0));
298 for (int laneNr = 0; laneNr < 10; laneNr++)
299 {
300 OTSNode next =
301 new OTSNode("Node " + (laneNr + 1), new OTSPoint3D(node.getPoint().x + this.laneLength.si, 0, 0));
302 Lane lane =
303 LaneFactory.makeLane("Lane", node, next, null, laneType, this.speedLimit, this.simulator,
304 LongitudinalDirectionality.DIR_PLUS);
305 this.lanes.add(lane);
306 node = next;
307 }
308
309 OTSNode end = new OTSNode("End", new OTSPoint3D(node.getPoint().x + 50.0, 0, 0));
310 CrossSectionLink endLink =
311 LaneFactory.makeLink("endLink", node, end, null, LongitudinalDirectionality.DIR_PLUS);
312 int last = this.lanes.size() - 1;
313 Lane sinkLane =
314 new Lane(endLink, "sinkLane", this.lanes.get(last).getLateralCenterPosition(1.0), this.lanes.get(last)
315 .getLateralCenterPosition(1.0), this.lanes.get(last).getWidth(1.0), this.lanes.get(last).getWidth(
316 1.0), laneType, LongitudinalDirectionality.DIR_PLUS, this.speedLimit,
317 new OvertakingConditions.None());
318 Sensor sensor = new SinkSensor(sinkLane, new Length(10.0, METER), this.simulator);
319 sinkLane.addSensor(sensor, GTUType.ALL);
320 }
321 catch (NamingException | NetworkException | OTSGeometryException exception)
322 {
323 exception.printStackTrace();
324 }
325
326 for (AbstractProperty<?> p : this.properties)
327 {
328 if (p instanceof SelectionProperty)
329 {
330 SelectionProperty sp = (SelectionProperty) p;
331 if ("CarGollowingModel".equals(sp.getKey()))
332 {
333 String modelName = sp.getValue();
334 if (modelName.equals("IDM"))
335 {
336 this.carFollowingModelCars =
337 new IDMOld(new Acceleration(1, METER_PER_SECOND_2),
338 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER),
339 new Duration(1, SECOND), 1d);
340 this.carFollowingModelTrucks =
341 new IDMOld(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 if (modelName.equals("IDM+"))
345 {
346 this.carFollowingModelCars =
347 new IDMPlusOld(new Acceleration(1, METER_PER_SECOND_2), new Acceleration(1.5,
348 METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND), 1d);
349 this.carFollowingModelTrucks =
350 new IDMPlusOld(new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.5,
351 METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND), 1d);
352 }
353 else
354 {
355 throw new Error("Car following model " + modelName + " not implemented");
356 }
357 }
358 else
359 {
360 throw new Error("Unhandled SelectionProperty " + p.getKey());
361 }
362 }
363 else if (p instanceof ProbabilityDistributionProperty)
364 {
365 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) p;
366 String modelName = p.getKey();
367 if (modelName.equals("TrafficComposition"))
368 {
369 this.carProbability = pdp.getValue()[0];
370 }
371 else
372 {
373 throw new Error("Unhandled ProbabilityDistributionProperty " + p.getKey());
374 }
375 }
376 else
377 {
378 throw new Error("Unhandled property: " + p);
379 }
380 }
381
382
383 this.headway = new Duration(3600.0 / 1500.0, SECOND);
384
385 try
386 {
387
388 this.simulator
389 .scheduleEventAbs(new DoubleScalar.Abs<>(0.0, SECOND), this, this, "generateCar", null);
390
391 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<>(1000, SECOND), this, this, "createBlock",
392 null);
393
394 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<>(1200, SECOND), this, this, "removeBlock",
395 null);
396
397 for (int t = 1; t <= this.simulator.getReplication().getTreatment().getRunLength().si / 25; t++)
398 {
399 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<>(25 * t - 0.001, SECOND), this, this,
400 "drawGraphs", null);
401 }
402 }
403 catch (SimRuntimeException exception)
404 {
405 exception.printStackTrace();
406 }
407 }
408
409
410
411
412
413 protected final void createBlock() throws RemoteException
414 {
415 Length initialPosition = new Length(200, METER);
416 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
417 try
418 {
419 initialPositions.add(new DirectedLanePosition(this.lanes.get(this.lanes.size() - 1), initialPosition,
420 GTUDirectionality.DIR_PLUS));
421 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
422 this.block =
423 new LaneBasedIndividualGTU("999999", this.gtuType, new Length(4, METER), new Length(1.8, METER),
424 new Speed(0.0, KM_PER_HOUR), this.simulator, DefaultCarAnimation.class, this.gtuColorer,
425 this.network);
426 LaneBasedStrategicalPlanner strategicalPlanner =
427 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
428 new LaneBasedGTUFollowingTacticalPlanner(this.carFollowingModelCars, this.block), this.block);
429 this.block.init(strategicalPlanner, initialPositions, new Speed(0.0, KM_PER_HOUR));
430 }
431 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
432 {
433 exception.printStackTrace();
434 }
435 }
436
437
438
439
440 protected final void removeBlock()
441 {
442 this.block.destroy();
443 this.block = null;
444 }
445
446
447
448
449 protected final void generateCar()
450 {
451 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
452 Length initialPosition = new Length(0, METER);
453 Speed initialSpeed = new Speed(100, KM_PER_HOUR);
454 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
455 try
456 {
457 initialPositions
458 .add(new DirectedLanePosition(this.lanes.get(0), initialPosition, GTUDirectionality.DIR_PLUS));
459 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
460 GTUFollowingModelOld gtuFollowingModel =
461 generateTruck ? this.carFollowingModelTrucks : this.carFollowingModelCars;
462 if (null == gtuFollowingModel)
463 {
464 throw new Error("gtuFollowingModel is null");
465 }
466 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
467
468 LaneBasedIndividualGTU gtu =
469 new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, vehicleLength,
470 new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, DefaultCarAnimation.class,
471 this.gtuColorer, this.network);
472 LaneBasedStrategicalPlanner strategicalPlanner =
473 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
474 new LaneBasedGTUFollowingTacticalPlanner(gtuFollowingModel, gtu), gtu);
475 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
476 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
477 }
478 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
479 {
480 exception.printStackTrace();
481 }
482 }
483
484
485
486
487 protected final void drawGraphs()
488 {
489
490 for (FundamentalDiagramLane fd : this.fundamentalDiagramsLane)
491 {
492 fd.reGraph();
493 }
494 }
495
496
497 @Override
498 public final SimulatorInterface<DoubleScalar.Abs<TimeUnit>, DoubleScalar.Rel<TimeUnit>, OTSSimTimeDouble>
499 getSimulator() throws RemoteException
500 {
501 return this.simulator;
502 }
503
504
505
506
507 public final ArrayList<FundamentalDiagramLane> getFundamentalDiagrams()
508 {
509 return this.fundamentalDiagramsLane;
510 }
511
512
513
514
515
516 public Lane getLane(final int laneNr)
517 {
518 return this.lanes.get(laneNr);
519 }
520 }
521 }