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