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