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