1 package org.opentrafficsim.graphs; 2 3 import static org.junit.Assert.assertEquals; 4 5 import java.rmi.RemoteException; 6 7 import org.junit.Test; 8 import org.opentrafficsim.core.car.LaneBasedIndividualCar; 9 import org.opentrafficsim.core.network.NetworkException; 10 import org.opentrafficsim.core.network.lane.Lane; 11 import org.opentrafficsim.core.unit.LengthUnit; 12 import org.opentrafficsim.core.unit.TimeUnit; 13 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar; 14 15 /** 16 * <p> 17 * Copyright (c) 2013-2014 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 18 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>. 19 * <p> 20 * @version Aug 22, 2014 <br> 21 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a> 22 */ 23 public class TrajectoryPlotTest 24 { 25 /** Sample interval for the TrajectoryPlot. */ 26 DoubleScalar.Rel<TimeUnit> sampleInterval = new DoubleScalar.Rel<TimeUnit>(0.25, TimeUnit.SECOND); 27 28 /** 29 * Test the TrajectoryPlot. 30 * @throws Exception which should not happen, but will be treated as an error by the JUnit framework if it does 31 */ 32 @Test 33 public final void trajectoryTest() throws Exception 34 { 35 DoubleScalar.Rel<LengthUnit> minimumDistance = new DoubleScalar.Rel<LengthUnit>(1234, LengthUnit.METER); 36 DoubleScalar.Rel<LengthUnit> maximumDistance = new DoubleScalar.Rel<LengthUnit>(12345, LengthUnit.METER); 37 38 // TODO adapt to new path (List<Lane>) concept 39 /*- 40 TrajectoryPlot tp = new TrajectoryPlot("Trajectory", this.sampleInterval, minimumDistance, maximumDistance); 41 assertTrue("newly created DensityContourPlot should not be null", null != tp); 42 assertEquals("Number of trajectories should initially be 0", 0, tp.getSeriesCount()); 43 for (int i = -10; i <= 10; i++) 44 { 45 assertEquals("SeriesKey(" + i + ") should return " + i, i, tp.getSeriesKey(i)); 46 } 47 assertEquals("Domain order should be ASCENDING", DomainOrder.ASCENDING, tp.getDomainOrder()); 48 // Create a car running 50 km.h 49 DoubleScalar.Rel<LengthUnit> initialPosition = new DoubleScalar.Rel<LengthUnit>(2000, LengthUnit.METER); 50 DoubleScalar.Abs<SpeedUnit> initialSpeed = new DoubleScalar.Abs<SpeedUnit>(50, SpeedUnit.KM_PER_HOUR); 51 GTUType<String> carType = new GTUType<String>("Car"); 52 DoubleScalar.Rel<LengthUnit> length = new DoubleScalar.Rel<LengthUnit>(5.0, LengthUnit.METER); 53 DoubleScalar.Rel<LengthUnit> width = new DoubleScalar.Rel<LengthUnit>(2.0, LengthUnit.METER); 54 Map<Lane, DoubleScalar.Rel<LengthUnit>> initialLongitudinalPositions = new HashMap<>(); 55 Lane lane = CarTest.makeLane(); 56 initialLongitudinalPositions.put(lane, initialPosition); 57 OTSDEVSSimulator simulator = CarTest.makeSimulator(); 58 // We want to start the car simulation at t=100s; therefore we have to advance the simulator up to that time. 59 simulateUntil(new DoubleScalar.Abs<TimeUnit>(100, TimeUnit.SECOND), simulator); 60 DoubleScalar.Abs<SpeedUnit> maxSpeed = new DoubleScalar.Abs<SpeedUnit>(120, SpeedUnit.KM_PER_HOUR); 61 Car<Integer> car = 62 new Car<Integer>(12345, carType, null, initialLongitudinalPositions, initialSpeed, length, width, maxSpeed, 63 simulator); 64 // Make the car accelerate with constant acceleration of 0.05 m/s/s for 400 seconds 65 DoubleScalar.Rel<TimeUnit> duration = new DoubleScalar.Rel<TimeUnit>(400, TimeUnit.SECOND); 66 DoubleScalar.Abs<TimeUnit> endTime = DoubleScalar.plus(simulator.getSimulatorTime().get(), duration).immutable(); 67 car.setState(new GTUFollowingModelResult(new DoubleScalar.Abs<AccelerationUnit>(0.05, 68 AccelerationUnit.METER_PER_SECOND_2), endTime)); 69 // System.out.println("Car end position " + car.getPosition(car.getNextEvaluationTime())); 70 tp.addData(car); 71 assertEquals("Number of trajectories should now be 1", 1, tp.getSeriesCount()); 72 verifyTrajectory(car, 0, tp); 73 simulateUntil(new DoubleScalar.Abs<TimeUnit>(150, TimeUnit.SECOND), simulator); 74 Car<Integer> secondCar = 75 new Car<Integer>(2, carType, null, initialLongitudinalPositions, initialSpeed, length, width, maxSpeed, 76 simulator); 77 // Make the second car accelerate with constant acceleration of 0.03 m/s/s for 500 seconds 78 secondCar.setState(new GTUFollowingModelResult(new DoubleScalar.Abs<AccelerationUnit>(0.03, 79 AccelerationUnit.METER_PER_SECOND_2), endTime)); 80 // System.out.println("Second car end position " + car.getPosition(secondCar.getNextEvaluationTime())); 81 tp.addData(secondCar); 82 assertEquals("Number of trajectories should now be 2", 2, tp.getSeriesCount()); 83 verifyTrajectory(car, 0, tp); // first car trajectory should not change by adding the second 84 verifyTrajectory(secondCar, 1, tp); 85 // Check the updateHint method in the PointerHandler 86 // First get the panel that stores the result of updateHint (this is ugly) 87 JLabel hintPanel = null; 88 ChartPanel chartPanel = null; 89 for (Component c0 : tp.getComponents()) 90 { 91 for (Component c1 : ((Container) c0).getComponents()) 92 { 93 if (c1 instanceof Container) 94 { 95 for (Component c2 : ((Container) c1).getComponents()) 96 { 97 // System.out.println("c2 is " + c2); 98 if (c2 instanceof Container) 99 { 100 for (Component c3 : ((Container) c2).getComponents()) 101 { 102 // System.out.println("c3 is " + c3); 103 if (c3 instanceof JLabel) 104 { 105 if (null == hintPanel) 106 { 107 hintPanel = (JLabel) c3; 108 } 109 else 110 { 111 fail("There should be only one JPanel in a ContourPlot"); 112 } 113 } 114 if (c3 instanceof ChartPanel) 115 { 116 if (null == chartPanel) 117 { 118 chartPanel = (ChartPanel) c3; 119 } 120 else 121 { 122 fail("There should be only one ChartPanel in a ContourPlot"); 123 } 124 } 125 } 126 } 127 } 128 } 129 } 130 } 131 if (null == hintPanel) 132 { 133 fail("Could not find a JLabel in ContourPlot"); 134 } 135 if (null == chartPanel) 136 { 137 fail("Could not find a ChartPanel in ContourPlot"); 138 } 139 assertEquals("Initially the text should be a single space", " ", hintPanel.getText()); 140 PointerHandler ph = null; 141 for (MouseListener ml : chartPanel.getMouseListeners()) 142 { 143 if (ml instanceof PointerHandler) 144 { 145 if (null == ph) 146 { 147 ph = (PointerHandler) ml; 148 } 149 else 150 { 151 fail("There should be only one PointerHandler on the chartPanel"); 152 } 153 } 154 } 155 if (null == ph) 156 { 157 fail("Could not find the PointerHandler for the chartPanel"); 158 } 159 ph.updateHint(1, 2); 160 // System.out.println("Hint text is now " + hintPanel.getText()); 161 assertFalse("Hint should not be a single space", " ".equals(hintPanel.getText())); 162 ph.updateHint(Double.NaN, Double.NaN); 163 assertEquals("The text should again be a single space", " ", hintPanel.getText()); 164 */ 165 } 166 167 /** 168 * Verify that a sampled trajectory matches the actual trajectory. 169 * @param car Car; the car whose trajectory was sampled 170 * @param series Integer; the series in the TrajectoryPlot that should correspond to the car 171 * @param tp TrajectoryPlot; the TrajectoryPlot that contains the samples 172 * @throws NetworkException when car is not on lane anymore 173 * @throws RemoteException on communication failure 174 */ 175 private void verifyTrajectory(final LaneBasedIndividualCar<?> car, final int series, final TrajectoryPlot tp) throws NetworkException, 176 RemoteException 177 { 178 // XXX we take the first (and only) lane on which the vehicle is registered. 179 Lane lane = car.positions(car.getFront()).keySet().iterator().next(); 180 DoubleScalar.Abs<TimeUnit> initialTime = car.getLastEvaluationTime(); 181 DoubleScalar.Rel<TimeUnit> duration = 182 DoubleScalar.minus(car.getNextEvaluationTime(), car.getLastEvaluationTime()).immutable(); 183 int expectedNumberOfSamples = (int) (duration.getSI() / this.sampleInterval.getSI()); 184 assertEquals("Number of samples in trajectory should be ", expectedNumberOfSamples, tp.getItemCount(series)); 185 // Check that the stored trajectory accurately matches the trajectory of the car at all sampling times 186 for (int sample = 0; sample < expectedNumberOfSamples; sample++) 187 { 188 DoubleScalar.Rel<TimeUnit> deltaTime = 189 new DoubleScalar.Rel<TimeUnit>(this.sampleInterval.getSI() * sample, TimeUnit.SECOND); 190 DoubleScalar.Abs<TimeUnit> sampleTime = DoubleScalar.plus(initialTime, deltaTime).immutable(); 191 double sampledTime = tp.getXValue(series, sample); 192 assertEquals("Sample should have been taken at " + sampleTime, sampleTime.getSI(), sampledTime, 0.0001); 193 sampledTime = tp.getX(series, sample).doubleValue(); 194 assertEquals("Sample should have been taken at " + sampleTime, sampleTime.getSI(), sampledTime, 0.0001); 195 DoubleScalar.Rel<LengthUnit> actualPosition = car.position(lane, car.getFront(), sampleTime); 196 double sampledPosition = tp.getYValue(series, sample); 197 assertEquals("Sample position should have been " + actualPosition, actualPosition.getSI(), sampledPosition, 198 0.0001); 199 sampledPosition = tp.getY(series, sample).doubleValue(); 200 assertEquals("Sample position should have been " + actualPosition, actualPosition.getSI(), sampledPosition, 201 0.0001); 202 } 203 } 204 205 }