1 package org.opentrafficsim.graphs;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
5
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import org.djunits.unit.SpeedUnit;
14 import org.djunits.unit.UNITS;
15 import org.djunits.value.vdouble.scalar.Acceleration;
16 import org.djunits.value.vdouble.scalar.Duration;
17 import org.djunits.value.vdouble.scalar.Length;
18 import org.djunits.value.vdouble.scalar.Speed;
19 import org.djunits.value.vdouble.scalar.Time;
20 import org.jfree.data.DomainOrder;
21 import org.junit.Test;
22 import org.opentrafficsim.core.dsol.OTSDEVSSimulator;
23 import org.opentrafficsim.core.geometry.OTSPoint3D;
24 import org.opentrafficsim.core.gtu.GTUException;
25 import org.opentrafficsim.core.gtu.GTUType;
26 import org.opentrafficsim.core.network.LongitudinalDirectionality;
27 import org.opentrafficsim.core.network.OTSNetwork;
28 import org.opentrafficsim.core.network.OTSNode;
29 import org.opentrafficsim.road.car.CarTest;
30 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
31 import org.opentrafficsim.road.gtu.lane.tactical.following.FixedAccelerationModel;
32 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
33 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
34 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
35 import org.opentrafficsim.road.network.factory.LaneFactory;
36 import org.opentrafficsim.road.network.lane.Lane;
37 import org.opentrafficsim.road.network.lane.LaneType;
38
39 /**
40 * <p>
41 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
42 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
43 * <p>
44 * $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, @version $Revision: 1401 $, by $Author: averbraeck $,
45 * initial version Aug 22, 2014 <br>
46 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
47 */
48 public class TrajectoryPlotTest implements UNITS
49 {
50 /** Sample interval for the TrajectoryPlot. */
51 Duration sampleInterval = new Duration(0.25, SECOND);
52
53 /**
54 * Test the TrajectoryPlot.
55 * @throws Exception which should not happen, but will be treated as an error by the JUnit framework if it does
56 */
57 @Test
58 public final void trajectoryTest() throws Exception
59 {
60 OTSDEVSSimulator simulator = CarTest.makeSimulator();
61 GTUType gtuType = CAR;
62 Set<GTUType> gtuTypes = new HashSet<GTUType>();
63 gtuTypes.add(gtuType);
64 LaneType laneType = new LaneType("CarLane", gtuTypes);
65 OTSNetwork network = new OTSNetwork("trajectory plot test network");
66 OTSNode node1 = new OTSNode(network, "node 1", new OTSPoint3D(100, 100, 0));
67 OTSNode node2 = new OTSNode(network, "node 2", new OTSPoint3D(1100, 100, 0));
68 OTSNode node3 = new OTSNode(network, "node 3", new OTSPoint3D(10100, 100, 0));
69 List<Lane> trajectory = new ArrayList<Lane>();
70 Speed speedLimit = new Speed(50, SpeedUnit.KM_PER_HOUR);
71 Lane lane1 = LaneFactory.makeMultiLane(network, "12", node1, node2, null, 1, 0, 0, laneType, speedLimit, simulator,
72 LongitudinalDirectionality.DIR_PLUS)[0];
73 trajectory.add(lane1);
74 Lane lane2 = LaneFactory.makeMultiLane(network, "23", node2, node3, null, 1, 0, 0, laneType, speedLimit, simulator,
75 LongitudinalDirectionality.DIR_PLUS)[0];
76 trajectory.add(lane2);
77 TrajectoryPlot tp = new TrajectoryPlot("TestTrajectory", this.sampleInterval, trajectory, simulator);
78 assertEquals("Number of trajectories should initially be 0", 0, tp.getSeriesCount());
79 for (int i = -10; i <= 10; i++)
80 {
81 assertEquals("SeriesKey(" + i + ") should return " + i, i, tp.getSeriesKey(i));
82 }
83 assertEquals("Domain order should be ASCENDING", DomainOrder.ASCENDING, tp.getDomainOrder());
84 // Create a car running 50 km.h
85 Length initialPosition = new Length(200, METER);
86 Speed initialSpeed = new Speed(50, KM_PER_HOUR);
87 Length length = new Length(5.0, METER);
88 Length width = new Length(2.0, METER);
89 Map<Lane, Length> initialLongitudinalPositions = new HashMap<>();
90 initialLongitudinalPositions.put(lane1, initialPosition);
91 // We want to start the car simulation at t=100s; therefore we have to advance the simulator up to that time.
92 simulator.runUpTo(new Time(100, SECOND));
93 Speed maxSpeed = new Speed(120, KM_PER_HOUR);
94 GTUFollowingModelOld gtuFollowingModel =
95 new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(10, SECOND));
96 LaneChangeModel laneChangeModel = new Egoistic();
97 /*-
98 LaneBasedIndividualGTU car =
99 CarTest.makeReferenceCar("12345", gtuType, lane1, initialPosition, initialSpeed, simulator, gtuFollowingModel,
100 laneChangeModel, network);
101 // Make the car accelerate with constant acceleration of 0.05 m/s/s for 400 seconds
102 Duration duration = new Duration(400, SECOND);
103
104 Time endTime = simulator.getSimulatorTime().getTime().plus(duration);
105 car.setState(new GTUFollowingModelResult(new Acceleration(0.05, METER_PER_SECOND_2), endTime));
106 // System.out.println("Car end position " + car.getPosition(car.getNextEvaluationTime()));
107 tp.addData(car);
108 assertEquals("Number of trajectories should now be 1", 1, tp.getSeriesCount());
109 verifyTrajectory(car, 0, tp);
110 simulateUntil(new Time(150, SECOND), simulator);
111 Car secondCar =
112 new Car(2, carType, null, initialLongitudinalPositions, initialSpeed, length, width, maxSpeed, simulator);
113 // Make the second car accelerate with constant acceleration of 0.03 m/s/s for 500 seconds
114 secondCar.setState(new GTUFollowingModelResult(new Acceleration(0.03, METER_PER_SECOND_2), endTime));
115 // System.out.println("Second car end position " + car.getPosition(secondCar.getNextEvaluationTime()));
116 tp.addData(secondCar);
117 assertEquals("Number of trajectories should now be 2", 2, tp.getSeriesCount());
118 verifyTrajectory(car, 0, tp); // first car trajectory should not change by adding the second
119 verifyTrajectory(secondCar, 1, tp);
120 // Check the updateHint method in the PointerHandler
121 // First get the panel that stores the result of updateHint (this is ugly)
122 JLabel hintPanel = null;
123 ChartPanel chartPanel = null;
124 for (Component c0 : tp.getComponents())
125 {
126 for (Component c1 : ((Container) c0).getComponents())
127 {
128 if (c1 instanceof Container)
129 {
130 for (Component c2 : ((Container) c1).getComponents())
131 {
132 // System.out.println("c2 is " + c2);
133 if (c2 instanceof Container)
134 {
135 for (Component c3 : ((Container) c2).getComponents())
136 {
137 // System.out.println("c3 is " + c3);
138 if (c3 instanceof JLabel)
139 {
140 if (null == hintPanel)
141 {
142 hintPanel = (JLabel) c3;
143 }
144 else
145 {
146 fail("There should be only one JPanel in a ContourPlot");
147 }
148 }
149 if (c3 instanceof ChartPanel)
150 {
151 if (null == chartPanel)
152 {
153 chartPanel = (ChartPanel) c3;
154 }
155 else
156 {
157 fail("There should be only one ChartPanel in a ContourPlot");
158 }
159 }
160 }
161 }
162 }
163 }
164 }
165 }
166 if (null == hintPanel)
167 {
168 fail("Could not find a JLabel in ContourPlot");
169 }
170 if (null == chartPanel)
171 {
172 fail("Could not find a ChartPanel in ContourPlot");
173 }
174 assertEquals("Initially the text should be a single space", " ", hintPanel.getText());
175 PointerHandler ph = null;
176 for (MouseListener ml : chartPanel.getMouseListeners())
177 {
178 if (ml instanceof PointerHandler)
179 {
180 if (null == ph)
181 {
182 ph = (PointerHandler) ml;
183 }
184 else
185 {
186 fail("There should be only one PointerHandler on the chartPanel");
187 }
188 }
189 }
190 if (null == ph)
191 {
192 fail("Could not find the PointerHandler for the chartPanel");
193 }
194 ph.updateHint(1, 2);
195 // System.out.println("Hint text is now " + hintPanel.getText());
196 assertFalse("Hint should not be a single space", " ".equals(hintPanel.getText()));
197 ph.updateHint(Double.NaN, Double.NaN);
198 assertEquals("The text should again be a single space", " ", hintPanel.getText());
199 */
200 }
201
202 /**
203 * Verify that a sampled trajectory matches the actual trajectory.
204 * @param car Car; the car whose trajectory was sampled
205 * @param series Integer; the series in the TrajectoryPlot that should correspond to the car
206 * @param tp TrajectoryPlot; the TrajectoryPlot that contains the samples
207 * @throws GTUException when car is not on lane anymore
208 */
209 private void verifyTrajectory(final LaneBasedIndividualGTU car, final int series, final TrajectoryPlot tp)
210 throws GTUException
211 {
212 // XXX we take the first (and only) lane on which the vehicle is registered.
213 Lane lane = car.positions(car.getFront()).keySet().iterator().next();
214 Time initialTime = car.getOperationalPlan().getStartTime();
215 Duration duration = car.getOperationalPlan().getTotalDuration();
216 int expectedNumberOfSamples = (int) (duration.getSI() / this.sampleInterval.getSI());
217 assertEquals("Number of samples in trajectory should be ", expectedNumberOfSamples, tp.getItemCount(series));
218 // Check that the stored trajectory accurately matches the trajectory of the car at all sampling times
219 for (int sample = 0; sample < expectedNumberOfSamples; sample++)
220 {
221 Duration deltaTime = new Duration(this.sampleInterval.getSI() * sample, SECOND);
222 Time sampleTime = initialTime.plus(deltaTime);
223 double sampledTime = tp.getXValue(series, sample);
224 assertEquals("Sample should have been taken at " + sampleTime, sampleTime.getSI(), sampledTime, 0.0001);
225 sampledTime = tp.getX(series, sample).doubleValue();
226 assertEquals("Sample should have been taken at " + sampleTime, sampleTime.getSI(), sampledTime, 0.0001);
227 Length actualPosition = car.position(lane, car.getFront(), sampleTime);
228 double sampledPosition = tp.getYValue(series, sample);
229 assertEquals("Sample position should have been " + actualPosition, actualPosition.getSI(), sampledPosition, 0.0001);
230 sampledPosition = tp.getY(series, sample).doubleValue();
231 assertEquals("Sample position should have been " + actualPosition, actualPosition.getSI(), sampledPosition, 0.0001);
232 }
233 }
234
235 }