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.LinkedHashSet;
8 import java.util.List;
9 import java.util.Random;
10 import java.util.Set;
11
12 import javax.naming.NamingException;
13 import javax.swing.JPanel;
14 import javax.swing.SwingUtilities;
15
16 import nl.tudelft.simulation.dsol.SimRuntimeException;
17 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
18 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
19
20 import org.djunits.unit.TimeUnit;
21 import org.djunits.unit.UNITS;
22 import org.djunits.value.vdouble.scalar.Acceleration;
23 import org.djunits.value.vdouble.scalar.DoubleScalar;
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.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.network.LongitudinalDirectionality;
37 import org.opentrafficsim.core.network.NetworkException;
38 import org.opentrafficsim.core.network.OTSNetwork;
39 import org.opentrafficsim.core.network.OTSNode;
40 import org.opentrafficsim.graphs.TrajectoryPlot;
41 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
42 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
43 import org.opentrafficsim.road.gtu.lane.driver.LaneBasedBehavioralCharacteristics;
44 import org.opentrafficsim.road.gtu.lane.perception.LanePerceptionFull;
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.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
50 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
51 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
52 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
53 import org.opentrafficsim.road.network.factory.LaneFactory;
54 import org.opentrafficsim.road.network.lane.CrossSectionLink;
55 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
56 import org.opentrafficsim.road.network.lane.Lane;
57 import org.opentrafficsim.road.network.lane.LaneType;
58 import org.opentrafficsim.road.network.lane.Sensor;
59 import org.opentrafficsim.road.network.lane.SinkSensor;
60 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
61 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
62 import org.opentrafficsim.simulationengine.OTSSimulationException;
63 import org.opentrafficsim.simulationengine.properties.AbstractProperty;
64 import org.opentrafficsim.simulationengine.properties.ProbabilityDistributionProperty;
65 import org.opentrafficsim.simulationengine.properties.PropertyException;
66 import org.opentrafficsim.simulationengine.properties.SelectionProperty;
67
68
69
70
71
72
73
74
75
76
77
78 public class Trajectories extends AbstractWrappableAnimation implements UNITS
79 {
80
81 private TrajectoriesModel model;
82
83
84 public Trajectories()
85 {
86 try
87 {
88 this.properties.add(new SelectionProperty("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>", new String[]{"IDM", "IDM+"},
93 1, false, 10));
94 this.properties.add(new ProbabilityDistributionProperty("Traffic composition",
95 "<html>Mix of passenger cars and trucks</html>", new String[]{"passenger car", "truck"}, new Double[]{
96 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.Abs(0.0, SECOND), new Time.Rel(0.0, SECOND), new Time.Rel(
129 3600.0, SECOND), trajectories.getProperties(), null, true);
130 }
131 catch (SimRuntimeException | NamingException | OTSSimulationException 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() throws OTSSimulationException
157 {
158 TablePanel charts = new TablePanel(1, 1);
159 Time.Rel sampleInterval = new Time.Rel(0.5, SECOND);
160 List<Lane> path = new ArrayList<Lane>();
161 path.add(this.model.getLane());
162 TrajectoryPlot tp = new TrajectoryPlot("Trajectory Plot", sampleInterval, path);
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 Time.Rel headway;
219
220
221 private int carsCreated = 0;
222
223
224 private GTUType gtuType = GTUType.makeGTUType("Car");
225
226
227 private GTUFollowingModelOld carFollowingModelCars;
228
229
230 private GTUFollowingModelOld carFollowingModelTrucks;
231
232
233 private double carProbability;
234
235
236 private AbstractLaneChangeModel laneChangeModel = new Egoistic();
237
238
239 private LaneBasedIndividualGTU block = null;
240
241
242 private Length.Rel minimumDistance = new Length.Rel(0, METER);
243
244
245 private Length.Rel maximumDistance = new Length.Rel(5000, METER);
246
247
248 private Lane lane;
249
250
251 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
252
253
254 private TrajectoryPlot trajectoryPlot;
255
256
257 private ArrayList<AbstractProperty<?>> properties = null;
258
259
260 private Random randomGenerator = new Random(12345);
261
262
263 private final GTUColorer gtuColorer;
264
265
266
267
268
269 public TrajectoriesModel(final ArrayList<AbstractProperty<?>> properties, final GTUColorer gtuColorer)
270 {
271 this.properties = properties;
272 this.gtuColorer = gtuColorer;
273 }
274
275
276 @Override
277 public final
278 void
279 constructModel(
280 final SimulatorInterface<DoubleScalar.Abs<TimeUnit>, DoubleScalar.Rel<TimeUnit>, OTSSimTimeDouble> theSimulator)
281 throws SimRuntimeException, RemoteException
282 {
283 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
284 OTSNode from = new OTSNode("From", new OTSPoint3D(getMinimumDistance().getSI(), 0, 0));
285 OTSNode to = new OTSNode("To", new OTSPoint3D(getMaximumDistance().getSI(), 0, 0));
286 OTSNode end = new OTSNode("End", new OTSPoint3D(getMaximumDistance().getSI() + 50.0, 0, 0));
287 LaneType laneType = new LaneType("CarLane");
288 laneType.addCompatibility(this.gtuType);
289 try
290 {
291 this.lane =
292 LaneFactory.makeLane("Lane", from, to, null, laneType, this.speedLimit, this.simulator,
293 LongitudinalDirectionality.DIR_PLUS);
294 CrossSectionLink endLink =
295 LaneFactory.makeLink("endLink", to, end, null, LongitudinalDirectionality.DIR_PLUS);
296
297 Lane sinkLane =
298 new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
299 this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0),
300 laneType, LongitudinalDirectionality.DIR_PLUS, this.speedLimit, new OvertakingConditions.None());
301 Sensor sensor = new SinkSensor(sinkLane, new Length.Rel(10.0, METER), this.simulator);
302 sinkLane.addSensor(sensor, GTUType.ALL);
303 }
304 catch (NamingException | NetworkException | OTSGeometryException exception1)
305 {
306 exception1.printStackTrace();
307 }
308
309 for (AbstractProperty<?> p : this.properties)
310 {
311 if (p instanceof SelectionProperty)
312 {
313 SelectionProperty sp = (SelectionProperty) p;
314 if ("Car following model".equals(sp.getShortName()))
315 {
316 String modelName = sp.getValue();
317 if (modelName.equals("IDM"))
318 {
319 this.carFollowingModelCars =
320 new IDMOld(new Acceleration(1, METER_PER_SECOND_2), new Acceleration(1.5, METER_PER_SECOND_2),
321 new Length.Rel(2, METER), new Time.Rel(1, SECOND), 1d);
322 this.carFollowingModelTrucks =
323 new IDMOld(new Acceleration(0.5, METER_PER_SECOND_2),
324 new Acceleration(1.5, METER_PER_SECOND_2), new Length.Rel(2, METER), new Time.Rel(1,
325 SECOND), 1d);
326 }
327 else if (modelName.equals("IDM+"))
328 {
329 this.carFollowingModelCars =
330 new IDMPlusOld(new Acceleration(1, METER_PER_SECOND_2), new Acceleration(1.5,
331 METER_PER_SECOND_2), new Length.Rel(2, METER), new Time.Rel(1, SECOND), 1d);
332 this.carFollowingModelTrucks =
333 new IDMPlusOld(new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.5,
334 METER_PER_SECOND_2), new Length.Rel(2, METER), new Time.Rel(1, SECOND), 1d);
335 }
336 else
337 {
338 throw new Error("Car following model " + modelName + " not implemented");
339 }
340 }
341 else
342 {
343 throw new Error("Unhandled SelectionProperty " + p.getShortName());
344 }
345 }
346 else if (p instanceof ProbabilityDistributionProperty)
347 {
348 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) p;
349 String modelName = p.getShortName();
350 if (modelName.equals("Traffic composition"))
351 {
352 this.carProbability = pdp.getValue()[0];
353 }
354 else
355 {
356 throw new Error("Unhandled ProbabilityDistributionProperty " + p.getShortName());
357 }
358 }
359 else
360 {
361 throw new Error("Unhandled property: " + p);
362 }
363 }
364
365
366 this.headway = new Time.Rel(3600.0 / 1500.0, SECOND);
367
368 try
369 {
370
371 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(0.0, SECOND), this, this, "generateCar",
372 null);
373
374 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(300, SECOND), this, this, "createBlock",
375 null);
376
377 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(420, SECOND), this, this, "removeBlock",
378 null);
379
380 for (int t = 1; t <= 1800; t++)
381 {
382 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(t - 0.001, SECOND), this, this,
383 "drawGraph", null);
384 }
385 }
386 catch (SimRuntimeException exception)
387 {
388 exception.printStackTrace();
389 }
390 }
391
392
393
394
395
396
397
398
399
400 protected final void createBlock() throws NamingException, SimRuntimeException, NetworkException, GTUException,
401 OTSGeometryException
402 {
403 Length.Rel initialPosition = new Length.Rel(4000, METER);
404 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
405 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition, GTUDirectionality.DIR_PLUS));
406 LaneBasedBehavioralCharacteristics drivingCharacteristics =
407 new LaneBasedBehavioralCharacteristics(this.carFollowingModelCars, this.laneChangeModel);
408 LaneBasedStrategicalPlanner strategicalPlanner =
409 new LaneBasedStrategicalRoutePlanner(drivingCharacteristics, new LaneBasedGTUFollowingTacticalPlanner());
410 this.block =
411 new LaneBasedIndividualGTU("999999", this.gtuType, initialPositions, new Speed(0.0, KM_PER_HOUR),
412 new Length.Rel(4, METER), new Length.Rel(1.8, METER), new Speed(0.0, KM_PER_HOUR), this.simulator,
413 strategicalPlanner, new LanePerceptionFull(), DefaultCarAnimation.class, this.gtuColorer, this.network);
414 }
415
416
417
418
419 protected final void removeBlock()
420 {
421 this.block.destroy();
422 this.block = null;
423 }
424
425
426
427
428 protected final void generateCar()
429 {
430 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
431 Length.Rel initialPosition = new Length.Rel(0, METER);
432 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
433 try
434 {
435 initialPositions.add(new DirectedLanePosition(this.getLane(), initialPosition, GTUDirectionality.DIR_PLUS));
436 Speed initialSpeed = new Speed(100, KM_PER_HOUR);
437 Length.Rel vehicleLength = new Length.Rel(generateTruck ? 15 : 4, METER);
438 GTUFollowingModelOld gtuFollowingModel =
439 generateTruck ? this.carFollowingModelTrucks : this.carFollowingModelCars;
440 if (null == gtuFollowingModel)
441 {
442 throw new Error("gtuFollowingModel is null");
443 }
444 LaneBasedBehavioralCharacteristics drivingCharacteristics =
445 new LaneBasedBehavioralCharacteristics(gtuFollowingModel, this.laneChangeModel);
446 LaneBasedStrategicalPlanner strategicalPlanner =
447 new LaneBasedStrategicalRoutePlanner(drivingCharacteristics, new LaneBasedGTUFollowingTacticalPlanner());
448 new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, initialPositions, initialSpeed,
449 vehicleLength, new Length.Rel(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator,
450 strategicalPlanner, new LanePerceptionFull(), DefaultCarAnimation.class, this.gtuColorer, this.network);
451
452 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
453 }
454 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
455 {
456 exception.printStackTrace();
457 }
458 }
459
460
461 @Override
462 public final SimulatorInterface<DoubleScalar.Abs<TimeUnit>, DoubleScalar.Rel<TimeUnit>, OTSSimTimeDouble>
463 getSimulator() throws RemoteException
464 {
465 return this.simulator;
466 }
467
468
469
470
471 protected final void drawGraph()
472 {
473 this.trajectoryPlot.reGraph();
474 }
475
476
477
478
479 public final Length.Rel getMinimumDistance()
480 {
481 return this.minimumDistance;
482 }
483
484
485
486
487 public final Length.Rel getMaximumDistance()
488 {
489 return this.maximumDistance;
490 }
491
492
493
494
495 public final void setTrajectoryPlot(final TrajectoryPlot trajectoryPlot)
496 {
497 this.trajectoryPlot = trajectoryPlot;
498 }
499
500
501
502
503 public Lane getLane()
504 {
505 return this.lane;
506 }
507
508 }