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