1 package org.opentrafficsim.graphs;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertTrue;
6 import static org.junit.Assert.fail;
7
8 import java.awt.Component;
9 import java.awt.Container;
10 import java.awt.event.ActionEvent;
11 import java.awt.event.MouseListener;
12 import java.util.HashSet;
13 import java.util.LinkedHashSet;
14 import java.util.Set;
15
16 import javax.swing.JLabel;
17
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.jfree.chart.ChartPanel;
25 import org.junit.Test;
26 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
27 import org.opentrafficsim.core.dsol.OTSModelInterface;
28 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
29 import org.opentrafficsim.core.gtu.GTUDirectionality;
30 import org.opentrafficsim.core.gtu.GTUType;
31 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
32 import org.opentrafficsim.core.network.OTSNetwork;
33 import org.opentrafficsim.road.DefaultTestParameters;
34 import org.opentrafficsim.road.car.CarTest;
35 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
36 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlanner;
37 import org.opentrafficsim.road.gtu.lane.tactical.following.FixedAccelerationModel;
38 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
39 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
40 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
41 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
42 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
43 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
44 import org.opentrafficsim.road.network.lane.Lane;
45 import org.opentrafficsim.road.network.lane.LaneType;
46 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
47 import org.opentrafficsim.simulationengine.SimpleSimulator;
48
49 import nl.tudelft.simulation.dsol.SimRuntimeException;
50 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
51
52
53
54
55
56
57
58
59
60
61 public class FundamentalDiagramPlotTest implements OTSModelInterface, UNITS
62 {
63
64 private static final long serialVersionUID = 20150226L;
65
66
67 private OTSNetwork network = new OTSNetwork("network");
68
69
70 private OTSDEVSSimulatorInterface simulator;
71
72
73
74
75
76 @SuppressWarnings("static-method")
77
78 public final void fundamentalDiagramTest() throws Exception
79 {
80 this.simulator =
81 new SimpleSimulator(new Time(0, SECOND), new Duration(0, SECOND), new Duration(1800, SECOND), this);
82
83 Duration aggregationTime = new Duration(30, SECOND);
84 Length position = new Length(123, METER);
85 Length carPosition = new Length(122.5, METER);
86 GTUType gtuType = new GTUType("Car");
87 Set<GTUType> compatibility = new HashSet<GTUType>();
88 compatibility.add(gtuType);
89 LaneType laneType = new LaneType("CarLane", compatibility);
90 Lane lane = CarTest.makeLane(this.network, laneType);
91 FundamentalDiagram fd = new FundamentalDiagram("Fundamental Diagram", aggregationTime, lane, position, this.simulator);
92 assertEquals("SeriesCount should match numberOfLanes", 1, fd.getSeriesCount());
93 assertEquals("Position should match the supplied position", position.getSI(), fd.getPosition().getSI(), 0.0001);
94 try
95 {
96 fd.getXValue(-1, 0);
97 fail("Bad series should have thrown an Error");
98 }
99 catch (Error e)
100 {
101
102 }
103 try
104 {
105 fd.getXValue(1, 0);
106 fail("Bad series should have thrown an Error");
107 }
108 catch (Error e)
109 {
110
111 }
112 double value = fd.getXValue(0, 0);
113 assertTrue("No data should result in NaN", java.lang.Double.isNaN(value));
114 value = fd.getX(0, 0).doubleValue();
115 assertTrue("No data should result in NaN", java.lang.Double.isNaN(value));
116 value = fd.getYValue(0, 0);
117 assertTrue("No data should result in NaN", java.lang.Double.isNaN(value));
118 value = fd.getY(0, 0).doubleValue();
119 assertTrue("No data should result in NaN", java.lang.Double.isNaN(value));
120 ActionEvent setXToSpeed = new ActionEvent(fd, 0, "Speed/Speed");
121 ActionEvent resetAxis = new ActionEvent(fd, 0, "Flow/Density");
122 Speed speed = new Speed(100, KM_PER_HOUR);
123 Time time = new Time(123, SECOND);
124 Length length = new Length(5.0, METER);
125 Length width = new Length(2.0, METER);
126 Speed maxSpeed = new Speed(120, KM_PER_HOUR);
127 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>(1);
128 initialLongitudinalPositions.add(new DirectedLanePosition(lane, carPosition, GTUDirectionality.DIR_PLUS));
129
130
131 new SinkSensor(lane, new Length(lane.getLength().getSI() - 100, METER), simulator);
132
133 simulator.runUpTo(time);
134 while (simulator.isRunning())
135 {
136 try
137 {
138 Thread.sleep(1);
139 }
140 catch (InterruptedException ie)
141 {
142 ie = null;
143 }
144 }
145 int bucket = (int) Math.floor(time.getSI() / aggregationTime.getSI());
146 LaneChangeModel laneChangeModel = new Egoistic();
147 GTUFollowingModelOld gtuFollowingModel =
148 new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(1000, SECOND));
149
150 BehavioralCharacteristics behavioralCharacteristics = DefaultTestParameters.create();
151 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("1", gtuType, length, width, maxSpeed, simulator, this.network);
152 LaneBasedStrategicalPlanner strategicalPlanner =
153 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics, new LaneBasedCFLCTacticalPlanner(
154 gtuFollowingModel, laneChangeModel, gtu), gtu);
155 gtu.init(strategicalPlanner, initialLongitudinalPositions, speed);
156 simulator.runUpTo(new Time(124, SECOND));
157 while (simulator.isRunning())
158 {
159 try
160 {
161 Thread.sleep(1);
162 }
163 catch (InterruptedException ie)
164 {
165 ie = null;
166 }
167 }
168 for (int sample = 0; sample < 10; sample++)
169 {
170 boolean shouldHaveData = sample == bucket;
171 value = fd.getXValue(0, sample);
172
173 if (shouldHaveData)
174 {
175 double expectedDensity = 3600 / aggregationTime.getSI() / speed.getSI();
176
177
178 }
179 else
180 {
181 assertTrue("Data should be NaN", java.lang.Double.isNaN(value));
182 }
183 value = fd.getX(0, sample).doubleValue();
184 if (shouldHaveData)
185 {
186 double expectedDensity = 3600 / aggregationTime.getSI() / speed.getSI();
187 assertEquals("Density should be " + expectedDensity, expectedDensity, value, 0.00001);
188 }
189 else
190 {
191 assertTrue("Data should be NaN", java.lang.Double.isNaN(value));
192 }
193 shouldHaveData = sample <= bucket;
194 value = fd.getYValue(0, sample);
195 if (shouldHaveData)
196 {
197 double expectedFlow = sample == bucket ? 3600 / aggregationTime.getSI() : 0;
198 assertEquals("Flow should be " + expectedFlow, expectedFlow, value, 0.00001);
199 }
200 else
201 {
202 assertTrue("Data should be NaN", java.lang.Double.isNaN(value));
203 }
204 value = fd.getY(0, sample).doubleValue();
205 if (shouldHaveData)
206 {
207 double expectedFlow = sample == bucket ? 3600 / aggregationTime.getSI() : 0;
208 assertEquals("Flow should be " + expectedFlow, expectedFlow, value, 0.00001);
209 }
210 else
211 {
212 assertTrue("Data should be NaN", java.lang.Double.isNaN(value));
213 }
214 fd.actionPerformed(setXToSpeed);
215 value = fd.getYValue(0, sample);
216 if (shouldHaveData)
217 {
218 double expectedSpeed = sample == bucket ? speed.getInUnit() : 0;
219 assertEquals("Speed should be " + expectedSpeed, expectedSpeed, value, 0.00001);
220 }
221 else
222 {
223 assertTrue("Data should be NaN", java.lang.Double.isNaN(value));
224 }
225 value = fd.getY(0, sample).doubleValue();
226 if (shouldHaveData)
227 {
228 double expectedSpeed = sample == bucket ? speed.getInUnit() : 0;
229 assertEquals("Speed should be " + expectedSpeed, expectedSpeed, value, 0.00001);
230 }
231 else
232 {
233 assertTrue("Data should be NaN", java.lang.Double.isNaN(value));
234 }
235 fd.actionPerformed(resetAxis);
236 }
237
238 speed = new Speed(10, KM_PER_HOUR);
239 behavioralCharacteristics = DefaultTestParameters.create();
240 LaneBasedIndividualGTU gtuX =
241 new LaneBasedIndividualGTU("1234", gtuType, length, width, maxSpeed, simulator, this.network);
242 strategicalPlanner =
243 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics, new LaneBasedCFLCTacticalPlanner(
244 gtuFollowingModel, laneChangeModel, gtuX), gtuX);
245 gtuX.init(strategicalPlanner, initialLongitudinalPositions, speed);
246 simulator.runUpTo(new Time(125, SECOND));
247 while (simulator.isRunning())
248 {
249 try
250 {
251 Thread.sleep(1);
252 }
253 catch (InterruptedException ie)
254 {
255 ie = null;
256 }
257 }
258 fd.actionPerformed(setXToSpeed);
259 value = fd.getYValue(0, bucket);
260 double expected = 2d / (1d / 100 + 1d / 10);
261
262 assertEquals("Harmonic mean of 10 and 100 is " + expected, expected, value, 0.0001);
263
264 try
265 {
266 fd.actionPerformed(new ActionEvent(fd, 0, "bla"));
267 fail("Bad ActionEvent should have thrown an Error");
268 }
269 catch (Error e)
270 {
271
272 }
273 try
274 {
275 fd.actionPerformed(new ActionEvent(fd, 0, "Speed/bla"));
276 fail("Bad ActionEvent should have thrown an Error");
277 }
278 catch (Error e)
279 {
280
281 }
282 try
283 {
284 fd.actionPerformed(new ActionEvent(fd, 0, "Flow/bla"));
285 fail("Bad ActionEvent should have thrown an Error");
286 }
287 catch (Error e)
288 {
289
290 }
291 try
292 {
293 fd.actionPerformed(new ActionEvent(fd, 0, "Density/bla"));
294 fail("Bad ActionEvent should have thrown an Error");
295 }
296 catch (Error e)
297 {
298
299 }
300 try
301 {
302 fd.actionPerformed(new ActionEvent(fd, 0, "bla/Speed"));
303 fail("Bad ActionEvent should have thrown an Error");
304 }
305 catch (Error e)
306 {
307
308 }
309 try
310 {
311 fd.actionPerformed(new ActionEvent(fd, 0, "bla/Flow"));
312 fail("Bad ActionEvent should have thrown an Error");
313 }
314 catch (Error e)
315 {
316
317 }
318 try
319 {
320 fd.actionPerformed(new ActionEvent(fd, 0, "bla/Density"));
321 fail("Bad ActionEvent should have thrown an Error");
322 }
323 catch (Error e)
324 {
325
326 }
327 }
328
329
330
331
332
333 @SuppressWarnings("static-method")
334 @Test
335 public final void testHints() throws Exception
336 {
337 this.simulator =
338 new SimpleSimulator(new Time(0, SECOND), new Duration(0, SECOND), new Duration(1800, SECOND), this);
339
340 Duration aggregationTime = new Duration(30, SECOND);
341 Length position = new Length(123, METER);
342 Set<GTUType> compatibility = new HashSet<GTUType>();
343 compatibility.add(GTUType.ALL);
344 LaneType laneType = new LaneType("CarLane", compatibility);
345 FundamentalDiagram fd =
346 new FundamentalDiagram("Fundamental Diagram", aggregationTime, CarTest.makeLane(this.network, laneType),
347 position, this.simulator);
348
349 JLabel hintPanel = null;
350 ChartPanel chartPanel = null;
351 for (Component c0 : fd.getComponents())
352 {
353 for (Component c1 : ((Container) c0).getComponents())
354 {
355 if (c1 instanceof Container)
356 {
357 for (Component c2 : ((Container) c1).getComponents())
358 {
359
360 if (c2 instanceof Container)
361 {
362 for (Component c3 : ((Container) c2).getComponents())
363 {
364
365 if (c3 instanceof JLabel)
366 {
367 if (null == hintPanel)
368 {
369 hintPanel = (JLabel) c3;
370 }
371 else
372 {
373 fail("There should be only one JPanel in a FundamentalDiagram");
374 }
375 }
376 if (c3 instanceof ChartPanel)
377 {
378 if (null == chartPanel)
379 {
380 chartPanel = (ChartPanel) c3;
381 }
382 else
383 {
384 fail("There should be only one ChartPanel in a FundamentalDiagram");
385 }
386 }
387 }
388 }
389 }
390 }
391 }
392 }
393 if (null == hintPanel)
394 {
395 fail("Could not find a JLabel in FundamentalDiagram");
396 }
397 if (null == chartPanel)
398 {
399 fail("Could not find a ChartPanel in FundamentalDiagram");
400 }
401 assertEquals("Initially the text should be a single space", " ", hintPanel.getText());
402 PointerHandler ph = null;
403 for (MouseListener ml : chartPanel.getMouseListeners())
404 {
405 if (ml instanceof PointerHandler)
406 {
407 if (null == ph)
408 {
409 ph = (PointerHandler) ml;
410 }
411 else
412 {
413 fail("There should be only one PointerHandler on the chartPanel");
414 }
415 }
416 }
417 if (null == ph)
418 {
419 fail("Could not find the PointerHandler for the chartPanel");
420 }
421 ph.updateHint(1, 2);
422
423 assertFalse("Hint should not be a single space", " ".equals(hintPanel.getText()));
424 ph.updateHint(java.lang.Double.NaN, java.lang.Double.NaN);
425 assertEquals("The text should again be a single space", " ", hintPanel.getText());
426 }
427
428
429 @Override
430 public void constructModel(SimulatorInterface<Time, Duration, OTSSimTimeDouble> arg0)
431 throws SimRuntimeException
432 {
433
434 }
435
436
437 @Override
438 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator()
439
440 {
441 return this.simulator;
442 }
443
444 }