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