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