swift
testinterpolatorlinear.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
7 
8 #include <QCoreApplication>
9 #include <QDebug>
10 #include <QElapsedTimer>
11 #include <QEventLoop>
12 #include <QScopedPointer>
13 #include <QTest>
14 #include <QTime>
15 #include <QtDebug>
16 
17 #include "test.h"
18 
24 #include "misc/aviation/altitude.h"
25 #include "misc/aviation/callsign.h"
26 #include "misc/aviation/heading.h"
28 #include "misc/geo/latitude.h"
29 #include "misc/geo/longitude.h"
31 #include "misc/pq/angle.h"
32 #include "misc/pq/length.h"
34 #include "misc/pq/speed.h"
35 #include "misc/pq/units.h"
39 
40 using namespace swift::misc;
41 using namespace swift::misc::aviation;
42 using namespace swift::misc::geo;
43 using namespace swift::misc::physical_quantities;
44 using namespace swift::misc::simulation;
45 
46 namespace MiscTest
47 {
50  {
51  Q_OBJECT
52 
53  private slots:
55  void basicInterpolatorTests();
56 
57  private:
60  getTestSituation(const swift::misc::aviation::CCallsign &callsign, int number, qint64 ts, qint64 deltaT,
61  qint64 offset);
62 
64  static swift::misc::aviation::CAircraftParts getTestParts(int number, qint64 ts, qint64 deltaT);
65  };
66 
67  void CTestInterpolatorLinear::basicInterpolatorTests()
68  {
69  const CCallsign cs("SWIFT");
71  CInterpolatorLinear interpolator(cs, nullptr, nullptr, &provider);
72  interpolator.markAsUnitTest();
73 
74  // fixed time so everything can be debugged
75  const qint64 ts = 1425000000000; // QDateTime::currentMSecsSinceEpoch();
76  const qint64 deltaT = 5000; // ms
77  const qint64 offset = 5000; // ms
78  for (int i = IRemoteAircraftProvider::MaxSituationsPerCallsign - 1; i >= 0; i--)
79  {
80  const CAircraftSituation s(getTestSituation(cs, i, ts, deltaT, offset));
81 
82  // check height above ground
83  CLength hag = (s.getAltitude() - s.getGroundElevation());
84  QVERIFY2(s.getHeightAboveGround() == hag, "Wrong elevation");
85  provider.insertNewSituation(s);
86  }
87 
88  constexpr int partsCount = 10;
89  for (int i = partsCount - 1; i >= 0; i--)
90  {
91  const CAircraftParts p(getTestParts(i, ts, deltaT));
92  provider.insertNewAircraftParts(cs, p, false);
93  }
94 
95  // make sure signals are processed, if the interpolator depends on those signals
97 
98  // interpolation functional check
100  double latOld = 360.0;
101  double lngOld = 360.0;
102 
103  qint64 from = ts - 2 * deltaT + offset;
104  qint64 to = ts; // ts + offset is last value, but we have to consider offset
105  qint64 step = deltaT / 20;
106  for (qint64 currentTime = from; currentTime < to; currentTime += step)
107  {
108  // This will use time range
109  // from: ts - 2 * deltaT + offset
110  // to: ts + offset
111 
112  const CInterpolationResult result = interpolator.getInterpolation(currentTime, setup, 0);
113  const CAircraftSituation currentSituation(result);
114  QVERIFY2(result.getInterpolationStatus().isInterpolated(), "Value was not interpolated");
115  const double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5);
116  const double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5);
117  QVERIFY2(latDeg < latOld && lngDeg < lngOld, QStringLiteral("Values shall decrease: %1/%2 %3/%4")
118  .arg(latDeg)
119  .arg(latOld)
120  .arg(lngDeg)
121  .arg(lngOld)
122  .toLatin1());
123  QVERIFY2(latDeg >= 0 && latDeg <= IRemoteAircraftProvider::MaxSituationsPerCallsign,
124  "Values shall be in range");
125  latOld = latDeg;
126  lngOld = lngDeg;
127  }
128 
129  QElapsedTimer timer;
130  timer.start();
131  int interpolationNo = 0;
132  const qint64 startTimeMsSinceEpoch = ts - 2 * deltaT;
133 
134  // Pseudo performance test:
135  // Those make not completely sense, as the performance depends on the implementation of
136  // the dummy provider, which is different from the real provider
137  // With one callsign in the lists (of dummy provider) it is somehow expected to be roughly the same performance
138 
139  interpolator.resetLastInterpolation();
140  interpolator.markAsUnitTest();
141  for (int loops = 0; loops < 20; loops++)
142  {
143  from = startTimeMsSinceEpoch + offset;
144  to = ts; // ts + offset is last value, but we have to consider offset
145  step = deltaT / 20;
146 
147  for (qint64 currentTime = from; currentTime < to; currentTime += step)
148  {
149  // This will use range
150  // from: ts - 2* deltaT + offset
151  // to: ts + offset
152  const CInterpolationResult result = interpolator.getInterpolation(currentTime, setup, 0);
153  const CAircraftSituation currentSituation(result);
154  QVERIFY2(result.getInterpolationStatus().isInterpolated(), "Not interpolated");
155  QVERIFY2(!currentSituation.getCallsign().isEmpty(), "Empty callsign");
156  QVERIFY2(currentSituation.getCallsign() == cs, "Wrong callsign");
157  const double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5);
158  const double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5);
159  Q_UNUSED(latDeg);
160  Q_UNUSED(lngDeg);
161  interpolationNo++;
162  }
163  }
164 
165  // check on time just to learn if interpolation suddenly gets very slow
166  // this is a risky test as in some situations the values can be exceeded
167  int timeMs = timer.elapsed();
168  QVERIFY2(timeMs < interpolationNo * 1.5, "Interpolation > 1.5ms");
169  qDebug() << timeMs << "ms"
170  << "for" << interpolationNo << "interpolations";
171 
172  int fetchedParts = 0;
173  timer.start();
174  for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250)
175  {
176  const CInterpolationResult result = interpolator.getInterpolation(currentTime, setup, 0);
177  fetchedParts++;
178  QVERIFY2(result.getPartsStatus().isSupportingParts(), "Parts not supported");
179  }
180  timeMs = timer.elapsed();
181  qDebug() << timeMs << "ms"
182  << "for" << fetchedParts << "fetched parts";
183  }
184 
185  CAircraftSituation CTestInterpolatorLinear::getTestSituation(const CCallsign &callsign, int number, qint64 ts,
186  qint64 deltaT, qint64 offset)
187  {
188  const CAltitude alt(number, CAltitude::MeanSeaLevel, CLengthUnit::m());
189  const CLatitude lat(number, CAngleUnit::deg());
190  const CLongitude lng(180.0 + number, CAngleUnit::deg());
191  const CHeading heading(number * 10, CHeading::True, CAngleUnit::deg());
192  const CAngle bank(number, CAngleUnit::deg());
193  const CAngle pitch(number, CAngleUnit::deg());
194  const CSpeed gs(number * 10, CSpeedUnit::km_h());
195  const CAltitude gndElev({ 0, CLengthUnit::m() }, CAltitude::MeanSeaLevel);
196  const CCoordinateGeodetic c(lat, lng, alt);
197  CAircraftSituation s(callsign, c, heading, pitch, bank, gs);
198  s.setGroundElevation(gndElev, CAircraftSituation::Test);
199  s.setMSecsSinceEpoch(ts - deltaT * number); // values in past
200  s.setTimeOffsetMs(offset);
201  return s;
202  }
203 
204  CAircraftParts CTestInterpolatorLinear::getTestParts(int number, qint64 ts, qint64 deltaT)
205  {
206  CAircraftLights l(true, false, true, false, true, false);
207  CAircraftEngineList e({ CAircraftEngine(1, true), CAircraftEngine(2, false), CAircraftEngine(3, true) });
208  CAircraftParts p(l, true, 20, true, e, false);
209  p.setMSecsSinceEpoch(ts - deltaT * number); // values in past
210  return p;
211  }
212 } // namespace MiscTest
213 
215 SWIFTTEST_MAIN(MiscTest::CTestInterpolatorLinear);
216 
217 #include "testinterpolatorlinear.moc"
218 
Interpolator classes basic tests.
Value object encapsulating information of aircraft's parts.
Definition: aircraftparts.h:26
Value object encapsulating information of an aircraft's situation.
Value object encapsulating information of a callsign.
Definition: callsign.h:30
Physical unit length (length)
Definition: length.h:18
Value object for interpolator and rendering per callsign.
const CInterpolationStatus & getInterpolationStatus() const
Get status.
bool isInterpolated() const
Did interpolation succeed?
Linear interpolator, calculation inbetween positions.
void insertNewSituation(const aviation::CAircraftSituation &situation)
For testing, add new situation and fire signals.
void insertNewAircraftParts(const aviation::CCallsign &callsign, const aviation::CAircraftParts &parts, bool removeOutdatedParts)
For testing, add new situation and fire signals.
Free functions in swift::misc.
void processEvents(QEventLoop::ProcessEventsFlags flags)
qint64 elapsed() const const
QVERIFY2(condition, message)