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