1 package org.opentrafficsim.draw.graphs;
2
3 import static org.junit.jupiter.api.Assertions.assertEquals;
4 import static org.junit.jupiter.api.Assertions.assertNull;
5 import static org.junit.jupiter.api.Assertions.assertTrue;
6 import static org.junit.jupiter.api.Assertions.fail;
7
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.List;
11 import java.util.Set;
12
13 import javax.naming.NamingException;
14 import javax.swing.JOptionPane;
15
16 import org.djunits.unit.TimeUnit;
17 import org.djunits.unit.util.UNITS;
18 import org.djunits.value.vdouble.scalar.Direction;
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.djutils.draw.point.Point2d;
24 import org.djutils.immutablecollections.ImmutableArrayList;
25 import org.jfree.data.DomainOrder;
26 import org.junit.jupiter.api.Test;
27 import org.mockito.ArgumentMatchers;
28 import org.mockito.Mockito;
29 import org.mockito.invocation.InvocationOnMock;
30 import org.mockito.stubbing.Answer;
31 import org.opentrafficsim.animation.GraphLaneUtil;
32 import org.opentrafficsim.core.definitions.DefaultsNl;
33 import org.opentrafficsim.core.dsol.OtsReplication;
34 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
35 import org.opentrafficsim.core.gtu.GtuException;
36 import org.opentrafficsim.core.gtu.GtuType;
37 import org.opentrafficsim.core.network.NetworkException;
38 import org.opentrafficsim.core.network.Node;
39 import org.opentrafficsim.core.perception.HistoryManagerDevs;
40 import org.opentrafficsim.draw.graphs.GraphPath.Section;
41 import org.opentrafficsim.kpi.interfaces.LaneData;
42 import org.opentrafficsim.kpi.sampling.SamplerData;
43 import org.opentrafficsim.road.definitions.DefaultsRoadNl;
44 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
45 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.Lmrs;
46 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LmrsFactory;
47 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LmrsFactory.Setting;
48 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
49 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlanner;
50 import org.opentrafficsim.road.network.RoadNetwork;
51 import org.opentrafficsim.road.network.factory.LaneFactory;
52 import org.opentrafficsim.road.network.lane.Lane;
53 import org.opentrafficsim.road.network.lane.LanePosition;
54 import org.opentrafficsim.road.network.lane.LaneType;
55 import org.opentrafficsim.road.network.sampling.LaneDataRoad;
56 import org.opentrafficsim.road.network.sampling.RoadSampler;
57
58 import nl.tudelft.simulation.dsol.SimRuntimeException;
59 import nl.tudelft.simulation.dsol.formalisms.eventscheduling.Executable;
60 import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEvent;
61 import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEventInterface;
62
63 /**
64 * Test the non-GUI part of the ContourPlot class.
65 * <p>
66 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
67 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
68 * </p>
69 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
70 */
71 public final class ContourPlotTest implements UNITS
72 {
73
74 /** Mocked GraphPath. */
75 @SuppressWarnings("unchecked")
76 private GraphPath<LaneData<?>> mockedPath = Mockito.mock(GraphPath.class);
77
78 /** Section 0. */
79 @SuppressWarnings("unchecked")
80 private Section<LaneData<?>> section0 = Mockito.mock(Section.class);
81
82 /** Section 1. */
83 @SuppressWarnings("unchecked")
84 private Section<LaneData<?>> section1 = Mockito.mock(Section.class);
85
86 /** Lane 2. */
87 private LaneData<?> mockedLane0 = Mockito.mock(LaneData.class);
88
89 /** Lane 1. */
90 private LaneData<?> mockedLane1 = Mockito.mock(LaneData.class);
91
92 /** Sampler data. */
93 private SamplerData<?> mockedSamplerData = Mockito.mock(SamplerData.class);
94
95 /** Simulator. */
96 private OtsSimulatorInterface mockedSimulator = Mockito.mock(OtsSimulatorInterface.class);
97
98 /** Scheduler. */
99 private PlotScheduler mockedScheduler = Mockito.mock(PlotScheduler.class);
100
101 /** Last scheduled event. */
102 private SimEventInterface<Duration> lastScheduledEvent = null;
103
104 /** */
105 private ContourPlotTest()
106 {
107 // do not instantiate test class
108 }
109
110 /**
111 * Create a network and a path for the tests.
112 * @param simulator the simulator
113 * @param network the network
114 * @return the dummy path
115 * @throws Exception when something goes wrong (should not happen)
116 */
117 private GraphPath<LaneDataRoad> dummyPath(final OtsSimulatorInterface simulator, final RoadNetwork network) throws Exception
118 {
119 LaneType laneType = DefaultsRoadNl.TWO_WAY_LANE;
120 Node b = new Node(network, "B", new Point2d(12345, 0), Direction.ZERO);
121 ArrayList<Lane> result = new ArrayList<Lane>();
122 Lane[] lanes = LaneFactory.makeMultiLane(network, "AtoB", new Node(network, "A", new Point2d(1234, 0), Direction.ZERO),
123 b, null, 1, laneType, new Speed(100, KM_PER_HOUR), simulator, DefaultsNl.VEHICLE);
124 result.add(lanes[0]);
125 // Make a continuation lane to prevent errors when the operational plan exceeds the available remaining length
126 lanes = LaneFactory.makeMultiLane(network, "BtoC", b, new Node(network, "C", new Point2d(99999, 0), Direction.ZERO),
127 null, 1, laneType, new Speed(100, KM_PER_HOUR), null, DefaultsNl.VEHICLE);
128 return GraphLaneUtil.createPath("AtoB", lanes[0]);
129 }
130
131 /**
132 * Code common to all contour plot tests.
133 * @throws SimRuntimeException if that happens uncaught; this test has failed
134 * @throws NamingException on error
135 */
136 public void setUp() throws SimRuntimeException, NamingException
137 {
138 Mockito.when(this.mockedPath.getTotalLength()).thenReturn(Length.valueOf("2000m"));
139 Mockito.when(this.mockedPath.getNumberOfSeries()).thenReturn(2);
140 Mockito.when(this.mockedPath.get(0)).thenReturn(this.section0);
141 Mockito.when(this.mockedPath.get(1)).thenReturn(this.section1);
142 Mockito.when(this.mockedPath.getStartDistance(this.section0)).thenReturn(Length.ZERO);
143 Mockito.when(this.mockedPath.getStartDistance(this.section1)).thenReturn(Length.valueOf("1234m"));
144 Mockito.when(this.mockedPath.getSpeedLimit()).thenReturn(Speed.valueOf("100 km/h"));
145 List<Section<LaneData<?>>> sectionList = new ArrayList<>();
146 sectionList.add(this.section0);
147 sectionList.add(this.section1);
148 Mockito.when(this.mockedLane0.getLength()).thenReturn(Length.valueOf("1234m"));
149 Mockito.when(this.mockedLane1.getLength()).thenReturn(Length.valueOf("766m"));
150 Set<LaneData<?>> set0 = new HashSet<>();
151 set0.add(this.mockedLane0);
152 Mockito.when(this.section0.iterator()).thenReturn(set0.iterator());
153 Set<LaneData<?>> set1 = new HashSet<>();
154 set1.add(this.mockedLane1);
155 Mockito.when(this.section0.iterator()).thenReturn(set0.iterator());
156 Mockito.when(this.section1.iterator()).thenReturn(set1.iterator());
157 Mockito.when(this.mockedPath.getSections()).thenReturn(new ImmutableArrayList<>(sectionList));
158 Mockito.when(this.section0.length()).thenReturn(Length.valueOf("2000m"));
159 Mockito.when(this.section1.length()).thenReturn(Length.valueOf("766m"));
160 Mockito.when(this.mockedSimulator.scheduleEventAbs(ArgumentMatchers.any(Duration.class),
161 ArgumentMatchers.any(Executable.class))).thenAnswer(new Answer<SimEventInterface<Duration>>()
162 {
163 @Override
164 public SimEventInterface<Duration> answer(final InvocationOnMock invocation) throws Throwable
165 {
166 ContourPlotTest.this.lastScheduledEvent = new SimEvent<Duration>(
167 ((Time) invocation.getArgument(0)).minus(Time.ZERO), invocation.getArgument(2), "update", null);
168 return ContourPlotTest.this.lastScheduledEvent;
169 }
170 });
171 Mockito.when(this.mockedSimulator.getSimulatorTime()).thenReturn(Duration.ZERO);
172 OtsReplication replication = new OtsReplication("test", Time.ZERO, Duration.ZERO, Duration.ofSI(3600.0),
173 HistoryManagerDevs.noHistory(this.mockedSimulator));
174 Mockito.when(this.mockedSimulator.getReplication()).thenReturn(replication);
175 Mockito.when(this.mockedScheduler.getTime()).thenReturn(Duration.ZERO);
176 }
177
178 /**
179 * Test the ContourPlotAcceleration.
180 * @throws Exception when something goes wrong (should not happen)
181 */
182 @Test
183 public void accelerationContourTest() throws Exception
184 {
185 setUp();
186 ContourDataSource dataPool = new ContourDataSource(this.mockedSamplerData, this.mockedPath);
187 ContourPlotAcceleration acp = new ContourPlotAcceleration("acceleration", this.mockedScheduler, dataPool);
188 assertEquals("acceleration", acp.getSeriesKey(0), "SeriesKey should be \"acceleration\"");
189 standardContourTests(this.mockedSimulator, acp, this.mockedPath, Double.NaN, 0);
190 }
191
192 /**
193 * Test the ContourPlotDensity.
194 * @throws Exception when something goes wrong (should not happen)
195 */
196 @Test
197 public void densityContourTest() throws Exception
198 {
199 setUp();
200 OtsSimulatorInterface simulator = this.mockedSimulator;
201 RoadNetwork network = new RoadNetwork("density contour test network", simulator);
202 GraphPath<LaneDataRoad> path = dummyPath(simulator, network);
203 RoadSampler sampler = new RoadSampler(network);
204 ContourDataSource dataPool = new ContourDataSource(sampler.getSamplerData(), path);
205 ContourPlotDensity dcp = new ContourPlotDensity("density", this.mockedScheduler, dataPool);
206 assertTrue(null != dcp, "newly created DensityContourPlot should not be null");
207 assertEquals("density", dcp.getSeriesKey(0), "SeriesKey should be \"density\"");
208 standardContourTests(simulator, dcp, path, Double.NaN, Double.NaN);
209 }
210
211 /**
212 * Test the ContourPlotFlow.
213 * @throws Exception when something goes wrong (should not happen)
214 */
215 @Test
216 public void flowContourTest() throws Exception
217 {
218 setUp();
219 OtsSimulatorInterface simulator = this.mockedSimulator;
220 RoadNetwork network = new RoadNetwork("flow contour test network", simulator);
221 GraphPath<LaneDataRoad> path = dummyPath(simulator, network);
222 RoadSampler sampler = new RoadSampler(network);
223 ContourDataSource dataPool = new ContourDataSource(sampler.getSamplerData(), path);
224 ContourPlotFlow fcp = new ContourPlotFlow("flow", this.mockedScheduler, dataPool);
225 assertTrue(null != fcp, "newly created DensityContourPlot should not be null");
226 assertEquals("flow", fcp.getSeriesKey(0), "SeriesKey should be \"flow\"");
227 standardContourTests(simulator, fcp, path, Double.NaN, Double.NaN);
228 }
229
230 /**
231 * Test the SpeedContourPlot.
232 * @throws Exception when something goes wrong (should not happen)
233 */
234 @Test
235 public void speedContourTest() throws Exception
236 {
237 setUp();
238 OtsSimulatorInterface simulator = this.mockedSimulator;
239 RoadNetwork network = new RoadNetwork("flow contour test network", simulator);
240 GraphPath<LaneDataRoad> path = dummyPath(simulator, network);
241 RoadSampler sampler = new RoadSampler(network);
242 ContourDataSource dataPool = new ContourDataSource(sampler.getSamplerData(), path);
243 ContourPlotSpeed scp = new ContourPlotSpeed("speed", this.mockedScheduler, dataPool);
244 assertTrue(null != scp, "newly created DensityContourPlot should not be null");
245 assertEquals("speed", scp.getSeriesKey(0), "SeriesKey should be \"speed\"");
246 standardContourTests(simulator, scp, path, Double.NaN, 50);
247 }
248
249 /**
250 * Debugging method.
251 * @param cp a contour plot
252 * @param fromX lower bound of the x coordinate to print (inclusive)
253 * @param toX upper bound of the x coordinate to print (inclusive)
254 * @param fromY lower bound of the y coordinate to print (inclusive)
255 * @param toY upper bound of the y coordinate to print (inclusive)
256 */
257 static void printMatrix(final AbstractContourPlot<?> cp, final int fromX, final int toX, final int fromY, final int toY)
258 {
259 System.out.println("Contour plot data:");
260 int maxItem = cp.getItemCount(0);
261 for (int y = fromY; y <= toY; y++)
262 {
263 System.out.print(String.format("y=%3d ", y));
264 for (int x = fromX; x <= toX; x++)
265 {
266 // Find the item with the requested x and y
267 int item;
268 for (item = 0; item < maxItem; item++)
269 {
270 if (cp.getXValue(0, item) == x && cp.getYValue(0, item) == y)
271 {
272 break;
273 }
274 }
275 if (item < maxItem)
276 {
277 System.out.print(String.format("%10.6f", cp.getZValue(0, item)));
278 }
279 else
280 {
281 System.out.print(" -------- ");
282 }
283 }
284 System.out.println("");
285 }
286 System.out.print("");
287 }
288
289 /**
290 * Test various properties of a ContourPlot that has no observed data added.
291 * @param simulator the simulator
292 * @param cp the ContourPlot to test
293 * @param path the path
294 * @param expectedZValue the value that getZ and getZValue should return for a valid item when no car has passed
295 * @param expectedZValueWithTraffic the value that getZ and getZValue should return a valid item where a car has traveled at
296 * constant speed of 50 km/h. Supply Double.NaN if the value varies but differs from the value expected when no
297 * car has passed
298 * @throws Exception when something goes wrong (should not happen)
299 */
300 public static void standardContourTests(final OtsSimulatorInterface simulator, final AbstractContourPlot<?> cp,
301 final GraphPath<?> path, final double expectedZValue, final double expectedZValueWithTraffic) throws Exception
302 {
303 assertEquals(1, cp.getSeriesCount(), "seriesCount should be 1");
304 assertEquals(DomainOrder.ASCENDING, cp.getDomainOrder(), "domainOrder should be ASCENDING");
305 assertEquals(0, cp.indexOf(0), "indexOf always returns 0");
306 assertEquals(0, cp.indexOf("abc"), "indexOf always returns 0");
307 assertNull(cp.getGroup(), "getGroup always returns null");
308 int xBins = cp.getDataPool().timeAxis.getBinCount();
309 int yBins = cp.getDataPool().spaceAxis.getBinCount();
310 int expectedXBins = (int) Math.ceil(((AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND).getSI())
311 / ContourDataSource.DEFAULT_TIME_GRANULARITIES[ContourDataSource.DEFAULT_TIME_GRANULARITY_INDEX]
312 + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0));
313 assertEquals(expectedXBins, xBins, "Initial xBins should be " + expectedXBins);
314 int expectedYBins = (int) Math.ceil(path.getTotalLength().getSI()
315 / ContourDataSource.DEFAULT_SPACE_GRANULARITIES[ContourDataSource.DEFAULT_SPACE_GRANULARITY_INDEX]
316 + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0));
317 assertEquals(expectedYBins, yBins, "yBins should be " + expectedYBins);
318 int bins = cp.getItemCount(0);
319 assertEquals(xBins * yBins, bins, "Total bin count is product of xBins * yBins");
320 String initialUpperTimeBoundString = AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.toString();
321 // Vary the time granularity
322 for (double timeGranularity : ContourDataSource.DEFAULT_TIME_GRANULARITIES)
323 {
324 cp.setTimeGranularity(timeGranularity);
325 // Vary the distance granularity
326 for (double distanceGranularity : ContourDataSource.DEFAULT_SPACE_GRANULARITIES)
327 {
328 cp.setSpaceGranularity(distanceGranularity);
329 cp.notifyPlotChange();
330 expectedXBins = (int) Math.ceil((AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.getSI()) / timeGranularity)
331 + (cp.getDataPool().timeAxis.isInterpolate() ? 1 : 0);
332 xBins = cp.getDataPool().timeAxis.getBinCount();
333 assertEquals(expectedXBins, xBins, "Modified xBins should be " + expectedXBins);
334 expectedYBins = (int) Math.ceil(path.get(0).length().getSI() / distanceGranularity)
335 + (cp.getDataPool().spaceAxis.isInterpolate() ? 1 : 0);
336 yBins = cp.getDataPool().spaceAxis.getBinCount();
337 // System.out.println(cp.getDataPool().spaceAxis);
338 // System.out.println("path.get(0) is " + path.get(0));
339 // System.out.println("path.get(0).getLength() is " + path.get(0).getLength());
340 assertEquals(expectedYBins, yBins, "Modified yBins should be " + expectedYBins);
341 bins = cp.getItemCount(0);
342 assertEquals(xBins * yBins, bins, "Total bin count is product of xBins * yBins");
343 for (int item = 0; item < bins; item++)
344 {
345 double x = cp.getXValue(0, item);
346 // System.out.println("x for item " + item + " is " + x);
347 assertTrue(x >= -timeGranularity / 2, "X should be >= -granularity / 2");
348 assertTrue(x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.getSI(),
349 "X should be <= " + initialUpperTimeBoundString);
350 Number alternateX = cp.getX(0, item);
351 assertEquals(x, alternateX.doubleValue(), 0.000001,
352 "getXValue and getX should return things that have the same value");
353 double y = cp.getYValue(0, item);
354 Number alternateY = cp.getY(0, item);
355 assertEquals(y, alternateY.doubleValue(), 0.000001,
356 "getYValue and getY should return things that have the same value");
357 double z = cp.getZValue(0, item);
358 if (Double.isNaN(expectedZValue))
359 {
360 assertTrue(Double.isNaN(z), "Z value should be NaN");
361 }
362 else
363 {
364 assertEquals(expectedZValue, z, 0.0001, "Z value should be " + expectedZValue);
365 }
366 Number alternateZ = cp.getZ(0, item);
367 if (Double.isNaN(expectedZValue))
368 {
369 assertTrue(Double.isNaN(alternateZ.doubleValue()), "Alternate Z value should be NaN");
370 }
371 else
372 {
373 assertEquals(expectedZValue, alternateZ.doubleValue(), 0.0000,
374 "Alternate Z value should be " + expectedZValue);
375 }
376 }
377 try
378 {
379 cp.getXValue(0, -1);
380 fail("Should have thrown an Exception");
381 }
382 catch (RuntimeException e)
383 {
384 // Ignore expected exception
385 }
386 // try
387 // {
388 // cp.getXValue(0, bins);
389 // fail("Should have thrown an Exception");
390 // }
391 // catch (RuntimeException e)
392 // {
393 // // Ignore expected exception
394 // }
395 // try
396 // {
397 // cp.yAxisBin(-1);
398 // fail("Should have thrown an Exception");
399 // }
400 // catch (RuntimeException e)
401 // {
402 // // Ignore expected exception
403 // }
404 // try
405 // {
406 // cp.yAxisBin(bins);
407 // fail("Should have thrown an Exception");
408 // }
409 // catch (RuntimeException e)
410 // {
411 // // Ignore expected exception
412 // }
413 }
414 }
415 // Make the time granularity a bit more reasonable
416 final double useTimeGranularity = 30; // [s]
417 cp.setTimeGranularity(useTimeGranularity);
418 final double useDistanceGranularity =
419 ContourDataSource.DEFAULT_SPACE_GRANULARITIES[ContourDataSource.DEFAULT_SPACE_GRANULARITIES.length - 1];
420 cp.setSpaceGranularity(useDistanceGranularity);
421 cp.notifyPlotChange();
422 bins = cp.getItemCount(0);
423 Time initialTime = new Time(0, TimeUnit.BASE_SECOND);
424 Length initialPosition = new Length(100, METER);
425 Speed initialSpeed = new Speed(50, KM_PER_HOUR);
426 // Create a car running 50 km.h
427 // SequentialFixedAccelerationModel gtuFollowingModel =
428 // new SequentialFixedAccelerationModel(simulator, new Acceleration(2.0, AccelerationUnit.METER_PER_SECOND_2));
429 // // Make the car run at constant speed for one minute
430 // gtuFollowingModel
431 // .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(60, SECOND)));
432 // // Make the car run at constant speed for another minute
433 // gtuFollowingModel
434 // .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(600, SECOND)));
435 // // Make the car run at constant speed for five more minutes
436 // gtuFollowingModel
437 // .addStep(new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(300, SECOND)));
438 // LaneChangeModel laneChangeModel = new Egoistic();
439
440 // Check that the initial data in the graph contains no trace of any car.
441 for (int item = 0; item < bins; item++)
442 {
443 double x = cp.getXValue(0, item);
444 // System.out.println("x is " + x);
445 // System.out.println("time granularity is " + cp.getTimeGranularity());
446 assertTrue(x >= -cp.getTimeGranularity() / 2, "X should be >= -timeGranularity / 2");
447 assertTrue(x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.si, "X should be <= " + initialUpperTimeBoundString);
448 Number alternateX = cp.getX(0, item);
449 assertEquals(x, alternateX.doubleValue(), 0.000001,
450 "getXValue and getX should return things that have the same value");
451 double y = cp.getYValue(0, item);
452 Number alternateY = cp.getY(0, item);
453 assertEquals(y, alternateY.doubleValue(), 0.000001,
454 "getYValue and getY should return things that have the same value");
455 double z = cp.getZValue(0, item);
456 if (Double.isNaN(expectedZValue))
457 {
458 assertTrue(Double.isNaN(z), "Z value should be NaN (got " + z + ")");
459 }
460 else
461 {
462 assertEquals(expectedZValue, z, 0.0001, "Z value should be " + expectedZValue);
463 }
464 Number alternateZ = cp.getZ(0, item);
465 if (Double.isNaN(expectedZValue))
466 {
467 assertTrue(Double.isNaN(alternateZ.doubleValue()), "Alternate Z value should be NaN");
468 }
469 else
470 {
471 assertEquals(expectedZValue, alternateZ.doubleValue(), 0.0000, "Alternate Z value should be " + expectedZValue);
472 }
473 }
474
475 // LaneBasedIndividualGTU car =
476 // makeReferenceCar("0", gtuType, ((CrossSectionLink) network.getLink("AtoB")).getLanes().get(0), initialPosition,
477 // initialSpeed, simulator, null, laneChangeModel, network);
478 // car.getParameters().setParameter(ParameterTypes.LOOKAHEAD, new Length(10, LengthUnit.KILOMETER));
479 //
480 // // System.out.println("Running simulator from " + simulator.getSimulatorTime() + " to "
481 // // + gtuFollowingModel.timeAfterCompletionOfStep(0));
482 // double stopTime = gtuFollowingModel.timeAfterCompletionOfStep(0).si;
483 // simulator.runUpToAndIncluding(new Time(stopTime, TimeUnit.BASE_SECOND));
484 // while (simulator.isStartingOrRunning())
485 // {
486 // try
487 // {
488 // Thread.sleep(10);
489 // }
490 // catch (InterruptedException ie)
491 // {
492 // ie = null; // ignore
493 // }
494 // }
495 // // System.out.println("Simulator is now at " + simulator.getSimulatorTime());
496 // // System.out.println("Car at start time " + car.getOperationalPlan().getStartTime() + " is at "
497 // // + car.getPosition(car.getOperationalPlan().getStartTime()));
498 // // System.out.println("At time " + simulator.getSimulator().getSimulatorTime() + " car is at " + car);
499 // for (int item = 0; item < bins; item++)
500 // {
501 // double x = cp.getXValue(0, item);
502 // assertTrue("X should be >= 0", x >= 0);
503 // assertTrue("X should be <= " + initialUpperTimeBoundString, x <= AbstractPlot.DEFAULT_INITIAL_UPPER_TIME_BOUND.si);
504 // Number alternateX = cp.getX(0, item);
505 // assertEquals("getXValue and getX should return things that have the same value", x, alternateX.doubleValue(),
506 // 0.000001);
507 // double y = cp.getYValue(0, item);
508 // Number alternateY = cp.getY(0, item);
509 // assertEquals("getYValue and getY should return things that have the same value", y, alternateY.doubleValue(),
510 // 0.000001);
511 // double z = cp.getZValue(0, item);
512 // // figure out if the car has traveled through this cell
513 // // if (x >= 180)
514 // // System.out.println(String.format("t=%.3f, x=%.3f z=%f, exp=%.3f, carLastEval=%s, carNextEval=%s", x, y, z,
515 // // expectedZValue, car.getOperationalPlan().getStartTime().getSI(), car.getOperationalPlan().getEndTime()
516 // // .getSI()));
517 // boolean hit = false;
518 // if (x + useTimeGranularity >= 0// car.getOperationalPlan().getStartTime().getSI()
519 // && x < 60)// car.getOperationalPlan().getEndTime().getSI())
520 // {
521 // // the car MAY have contributed to this cell
522 // Time cellStartTime =
523 // new Time(Math.max(car.getOperationalPlan().getStartTime().getSI(), x), TimeUnit.BASE_SECOND);
524 // Time cellEndTime = new Time(Math.min(car.getOperationalPlan().getEndTime().getSI(), x + useTimeGranularity),
525 // TimeUnit.BASE_SECOND);
526 // // System.out.println("cellStartTime=" + cellStartTime + ", cellEndTime=" + cellEndTime);
527 // // The next if statement is the problem
528 // // if (cellStartTime.lt(cellEndTime)
529 // // && car.position(lane, car.getRear(), cellStartTime).getSI() <= y + useDistanceGranularity
530 // // && car.position(lane, car.getRear(), cellEndTime).getSI() >= y)
531 // double xAtCellStartTime = initialPosition.si + initialSpeed.si * cellStartTime.si;
532 // double xAtCellEndTime = initialPosition.si + initialSpeed.si * cellEndTime.si;
533 // if (xAtCellStartTime < y + useDistanceGranularity && xAtCellEndTime >= y)
534 // {
535 // hit = true;
536 // }
537 // }
538 // // System.out.println(String.format(
539 // // "hit=%s, t=%.3f, x=%.3f z=%f, exp=%.3f, carLastEval=%s, carNextEval=%s, simulatortime=%s", hit, x, y, z,
540 // // expectedZValue, car.getOperationalPlan().getStartTime().getSI(), car.getOperationalPlan().getEndTime()
541 // // .getSI(), car.getSimulator().getSimulatorTime()));
542 // Number alternateZ = cp.getZ(0, item);
543 // if (hit)
544 // {
545 // if (!Double.isNaN(expectedZValueWithTraffic))
546 // {
547 // if (Double.isNaN(z))
548 // {
549 // printMatrix(cp, 0, 10, 0, 10);
550 // System.out.println("Oops - z is NaN, expected z value with traffic is " + expectedZValueWithTraffic);
551 // }
552 // assertEquals("Z value should be " + expectedZValueWithTraffic, expectedZValueWithTraffic, z, 0.0001);
553 // assertEquals("Z value should be " + expectedZValueWithTraffic, expectedZValueWithTraffic,
554 // alternateZ.doubleValue(), 0.0001);
555 // }
556 // else
557 // {
558 // if (Double.isNaN(expectedZValue))
559 // { // FIXME looks wrong / PK
560 // assertFalse("Z value should not be NaN", Double.isNaN(z));
561 // }
562 // }
563 // }
564 // else
565 // {
566 // if (Double.isNaN(expectedZValue))
567 // {
568 // // if (!Double.isNaN(z))
569 // // {
570 // // System.out.println("Oops");
571 // // Time cellStartTime = new Time(x, SECOND);
572 // // Time cellEndTime =
573 // // new Time(Math.min(car.getOperationalPlan().getEndTime().getSI(), x + useTimeGranularity),
574 // // SECOND);
575 // // double xAtCellStartTime = initialPosition.si + initialSpeed.si * cellStartTime.si;
576 // // double xAtCellEndTime = initialPosition.si + initialSpeed.si * cellEndTime.si;
577 // // System.out.println("cellStartTime=" + cellStartTime + " cellEndTime=" + cellEndTime
578 // // + " xAtCellStartTime=" + xAtCellStartTime + " xAtCellEndTime=" + xAtCellEndTime);
579 // // double cellX = cp.getXValue(0, item);
580 // // double cellY = cp.getYValue(0, item);
581 // // double cellZ = cp.getZValue(0, item);
582 // // System.out.println("cellX=" + cellX + " cellY=" + cellY + " cellZ=" + cellZ + " timeGranularity="
583 // // + useTimeGranularity + " distanceGranularity=" + useDistanceGranularity);
584 // // cp.getZValue(0, item);
585 // // }
586 // assertTrue("Z value should be NaN", Double.isNaN(z));
587 // }
588 // else
589 // {
590 // assertEquals("Z value should be " + expectedZValue, expectedZValue, z, 0.0001);
591 // }
592 // if (Double.isNaN(expectedZValue))
593 // {
594 // assertTrue("Alternate Z value should be NaN", Double.isNaN(alternateZ.doubleValue()));
595 // }
596 // else
597 // {
598 // assertEquals("Alternate Z value should be " + expectedZValue, expectedZValue, alternateZ.doubleValue(),
599 // 0.0000);
600 // }
601 // }
602 // }
603 // // System.out.println("Running simulator from " + simulator.getSimulatorTime() + " to "
604 // // + gtuFollowingModel.timeAfterCompletionOfStep(1));
605 // stopTime = gtuFollowingModel.timeAfterCompletionOfStep(1).si;
606 // simulator.runUpToAndIncluding(new Time(stopTime, TimeUnit.BASE_SECOND));
607 // while (simulator.isStartingOrRunning())
608 // {
609 // try
610 // {
611 // Thread.sleep(10);
612 // }
613 // catch (InterruptedException ie)
614 // {
615 // ie = null; // ignore
616 // }
617 // }
618 // // System.out.println("Simulator is now at " + simulator.getSimulatorTime());
619 // // Check that the time range has expanded
620 // xBins = cp.getDataPool().timeAxis.getBinCount();
621 // bins = cp.getItemCount(0);
622 // double observedHighestTime = Double.MIN_VALUE;
623 // for (int bin = 0; bin < bins; bin++)
624 // {
625 // double xValue = cp.getXValue(0, bin);
626 // if (xValue > observedHighestTime)
627 // {
628 // observedHighestTime = xValue;
629 // }
630 // }
631 // double expectedHighestTime =
632 // Math.floor((car.getSimulator().getSimulatorTime().si - 0.001) / useTimeGranularity) * useTimeGranularity;
633 // assertEquals("Time range should run up to " + expectedHighestTime, expectedHighestTime, observedHighestTime, 0.0001);
634 // Check the updateHint method in the PointerHandler
635 // First get the panel that stores the result of updateHint (this is ugly)
636 // JLabel hintPanel = null;
637 // ChartPanel chartPanel = null;
638 // for (Component c0 : cp.getComponents())
639 // {
640 // for (Component c1 : ((Container) c0).getComponents())
641 // {
642 // if (c1 instanceof Container)
643 // {
644 // for (Component c2 : ((Container) c1).getComponents())
645 // {
646 // // System.out.println("c2 is " + c2);
647 // if (c2 instanceof Container)
648 // {
649 // for (Component c3 : ((Container) c2).getComponents())
650 // {
651 // // System.out.println("c3 is " + c3);
652 // if (c3 instanceof JLabel)
653 // {
654 // if (null == hintPanel)
655 // {
656 // hintPanel = (JLabel) c3;
657 // }
658 // else
659 // {
660 // fail("There should be only one JPanel in a ContourPlot");
661 // }
662 // }
663 // if (c3 instanceof ChartPanel)
664 // {
665 // if (null == chartPanel)
666 // {
667 // chartPanel = (ChartPanel) c3;
668 // }
669 // else
670 // {
671 // fail("There should be only one ChartPanel in a ContourPlot");
672 // }
673 // }
674 // }
675 // }
676 // }
677 // }
678 // }
679 // }
680 // if (null == hintPanel)
681 // {
682 // fail("Could not find a JLabel in ContourPlot");
683 // }
684 // if (null == chartPanel)
685 // {
686 // fail("Could not find a ChartPanel in ContourPlot");
687 // }
688 // assertEquals("Initially the text should be a single space", " ", hintPanel.getText());
689 // PointerHandler ph = null;
690 // for (MouseListener ml : chartPanel.getMouseListeners())
691 // {
692 // if (ml instanceof PointerHandler)
693 // {
694 // if (null == ph)
695 // {
696 // ph = (PointerHandler) ml;
697 // }
698 // else
699 // {
700 // fail("There should be only one PointerHandler on the chartPanel");
701 // }
702 // }
703 // }
704 // if (null == ph)
705 // {
706 // fail("Could not find the PointerHandler for the chartPanel");
707 // }
708 // ph.updateHint(1, 2);
709 // // System.out.println("Hint text is now " + hintPanel.getText());
710 // assertFalse("Hint should not be a single space", " ".equals(hintPanel.getText()));
711 // ph.updateHint(Double.NaN, Double.NaN);
712 // assertEquals("The text should again be a single space", " ", hintPanel.getText());
713 }
714
715 /**
716 * Create a new Car.
717 * @param id the name (number) of the Car
718 * @param gtuType the type of the new car
719 * @param lane the lane on which the new Car is positioned
720 * @param initialPosition the initial longitudinal position of the new Car
721 * @param initialSpeed the initial speed
722 * @param simulator the simulator that controls the new Car (and supplies the initial value for getLastEvalutionTime())
723 * @param gtuFollowingModel the GTU following model
724 * @param laneChangeModel the lane change model
725 * @param network the network
726 * @return the new Car
727 * @throws NamingException on network error when making the animation
728 * @throws NetworkException when the GTU cannot be placed on the given lane.
729 * @throws SimRuntimeException when the move method cannot be scheduled.
730 * @throws GtuException when construction of the GTU fails (probably due to an invalid parameter)
731 */
732 private static LaneBasedGtu makeReferenceCar(final String id, final GtuType gtuType, final Lane lane,
733 final Length initialPosition, final Speed initialSpeed, final OtsSimulatorInterface simulator,
734 final RoadNetwork network) throws NamingException, NetworkException, SimRuntimeException, GtuException
735 {
736 // TODO: simulator argument can be remove, but this method is currently only used in code that is commented out
737 Length length = new Length(5.0, METER);
738 Length width = new Length(2.0, METER);
739 Speed maxSpeed = new Speed(120, KM_PER_HOUR);
740 LaneBasedGtu gtu = new LaneBasedGtu(id, gtuType, length, width, maxSpeed, length.times(0.5), network);
741 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(new LmrsFactory<>(Lmrs::new)
742 .set(Setting.CAR_FOLLOWING_MODEL, (h, v) -> new FixedCarFollowing().get()).create(gtu), gtu);
743 gtu.init(strategicalPlanner, new LanePosition(lane, initialPosition).getLocation(), initialSpeed);
744
745 return gtu;
746 }
747
748 /**
749 * Run the DensityContourPlot stand-alone for profiling.
750 * @param args the command line arguments (not used)
751 * @throws Exception when something goes wrong (should not happen)
752 */
753 public static void main(final String[] args) throws Exception
754 {
755 ContourPlotTest cpt = new ContourPlotTest();
756 System.out.println("Click the OK button");
757 JOptionPane.showMessageDialog(null, "ContourPlot", "Start experiment", JOptionPane.INFORMATION_MESSAGE);
758 System.out.println("Running ...");
759 cpt.densityContourTest();
760 System.out.println("Finished");
761 }
762
763 }