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.TrajectoryPlot;
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 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" },
97 new Double[] { 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 void addAnimationToggles()
143 {
144 AnimationToggles.setTextAnimationTogglesStandard(this);
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 void addTabs(final 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 addTab(getTabCount(), "statistics", 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 = 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 = LaneFactory.makeLane(this.network, "Lane", from, to, null, laneType, this.speedLimit, this.simulator,
288 LongitudinalDirectionality.DIR_PLUS);
289 CrossSectionLink endLink =
290 LaneFactory.makeLink(this.network, "endLink", to, end, null, LongitudinalDirectionality.DIR_PLUS, simulator);
291
292 Lane sinkLane = new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
293 this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0), laneType,
294 LongitudinalDirectionality.DIR_PLUS, this.speedLimit, new OvertakingConditions.None());
295 new SinkSensor(sinkLane, new Length(10.0, METER), this.simulator);
296 }
297 catch (NamingException | NetworkException | OTSGeometryException exception1)
298 {
299 exception1.printStackTrace();
300 }
301
302 for (Property<?> p : this.properties)
303 {
304 if (p instanceof SelectionProperty)
305 {
306 SelectionProperty sp = (SelectionProperty) p;
307 if ("CarFollowingModel".equals(sp.getKey()))
308 {
309 String modelName = sp.getValue();
310 if (modelName.equals("IDM"))
311 {
312 this.carFollowingModelCars = new IDMOld(new Acceleration(1, METER_PER_SECOND_2),
313 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND), 1d);
314 this.carFollowingModelTrucks = new IDMOld(new Acceleration(0.5, METER_PER_SECOND_2),
315 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND), 1d);
316 }
317 else if (modelName.equals("IDM+"))
318 {
319 this.carFollowingModelCars = new IDMPlusOld(new Acceleration(1, METER_PER_SECOND_2),
320 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND), 1d);
321 this.carFollowingModelTrucks = new IDMPlusOld(new Acceleration(0.5, METER_PER_SECOND_2),
322 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2, METER), new Duration(1, SECOND), 1d);
323 }
324 else
325 {
326 throw new Error("Car following model " + modelName + " not implemented");
327 }
328 }
329 else
330 {
331 throw new Error("Unhandled SelectionProperty " + p.getKey());
332 }
333 }
334 else if (p instanceof ProbabilityDistributionProperty)
335 {
336 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) p;
337 String modelName = p.getKey();
338 if (modelName.equals("TrafficComposition"))
339 {
340 this.carProbability = pdp.getValue()[0];
341 }
342 else
343 {
344 throw new Error("Unhandled ProbabilityDistributionProperty " + p.getKey());
345 }
346 }
347 else
348 {
349 throw new Error("Unhandled property: " + p);
350 }
351 }
352
353
354 this.headway = new Duration(3600.0 / 1500.0, SECOND);
355
356 try
357 {
358
359 this.simulator.scheduleEventAbs(new Time(0.0, SECOND), this, this, "generateCar", null);
360
361 this.simulator.scheduleEventAbs(new Time(300, SECOND), this, this, "createBlock", null);
362
363 this.simulator.scheduleEventAbs(new Time(420, SECOND), this, this, "removeBlock", null);
364
365 for (int t = 1; t <= 1800; t++)
366 {
367 this.simulator.scheduleEventAbs(new Time(t - 0.001, SECOND), this, this, "drawGraph", null);
368 }
369 }
370 catch (SimRuntimeException exception)
371 {
372 exception.printStackTrace();
373 }
374 }
375
376
377
378
379
380
381
382
383
384 protected final void createBlock()
385 throws NamingException, SimRuntimeException, NetworkException, GTUException, OTSGeometryException
386 {
387 Length initialPosition = new Length(4000, METER);
388 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
389 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition, GTUDirectionality.DIR_PLUS));
390 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
391 this.block = new LaneBasedIndividualGTU("999999", this.gtuType, new Length(4, METER), new Length(1.8, METER),
392 new Speed(0.0, KM_PER_HOUR), this.simulator, this.network);
393 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
394 new LaneBasedGTUFollowingTacticalPlanner(this.carFollowingModelCars, this.block), this.block);
395 this.block.initWithAnimation(strategicalPlanner, initialPositions, new Speed(0.0, KM_PER_HOUR),
396 DefaultCarAnimation.class, this.gtuColorer);
397 }
398
399
400
401
402 protected final void removeBlock()
403 {
404 this.block.destroy();
405 this.block = null;
406 }
407
408
409
410
411 protected final void generateCar()
412 {
413 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
414 Length initialPosition = new Length(0, METER);
415 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
416 try
417 {
418 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition, GTUDirectionality.DIR_PLUS));
419 Speed initialSpeed = new Speed(100, KM_PER_HOUR);
420 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
421 GTUFollowingModelOld gtuFollowingModel = generateTruck ? this.carFollowingModelTrucks : this.carFollowingModelCars;
422 if (null == gtuFollowingModel)
423 {
424 throw new Error("gtuFollowingModel is null");
425 }
426 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
427 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, vehicleLength,
428 new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, this.network);
429 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
430 new LaneBasedGTUFollowingTacticalPlanner(gtuFollowingModel, gtu), gtu);
431 gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class,
432 this.gtuColorer);
433
434 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
435 }
436 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
437 {
438 exception.printStackTrace();
439 }
440 }
441
442
443 @Override
444 public final SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
445 {
446 return this.simulator;
447 }
448
449
450 @Override
451 public OTSNetwork getNetwork()
452 {
453 return this.network;
454 }
455
456
457
458
459 protected final void drawGraph()
460 {
461 this.trajectoryPlot.reGraph();
462 }
463
464
465
466
467 public final Length getMinimumDistance()
468 {
469 return this.minimumDistance;
470 }
471
472
473
474
475 public final Length getMaximumDistance()
476 {
477 return this.maximumDistance;
478 }
479
480
481
482
483 public final void setTrajectoryPlot(final TrajectoryPlot trajectoryPlot)
484 {
485 this.trajectoryPlot = trajectoryPlot;
486 }
487
488
489
490
491 public Lane getLane()
492 {
493 return this.lane;
494 }
495
496 }