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