diff --git a/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.cpp b/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.cpp index f5c4b1e16..fbe5e862f 100644 --- a/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.cpp +++ b/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.cpp @@ -79,5 +79,12 @@ namespace BlackMisc emit addedRemoteAircraftSituation(situation); } + void CRemoteAircraftProviderDummy::clear() + { + m_situations.clear(); + m_parts.clear(); + m_aircraft.clear(); + } + } // namespace } // namespace diff --git a/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.h b/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.h index 9f6826b49..826e468e2 100644 --- a/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.h +++ b/src/blackmisc/simulation/simdirectaccessremoteaircraftdummy.h @@ -65,6 +65,9 @@ namespace BlackMisc //! For testing, add new situation and fire signals void insertNewSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + // clear all data + void clear(); + signals: //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftSituation void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); diff --git a/tests/blackcore/testinterpolator.cpp b/tests/blackcore/testinterpolator.cpp index e356b9442..56dbba227 100644 --- a/tests/blackcore/testinterpolator.cpp +++ b/tests/blackcore/testinterpolator.cpp @@ -26,26 +26,15 @@ namespace BlackCoreTest QScopedPointer provider(new CRemoteAircraftProviderDummy()); CInterpolatorLinear interpolator(provider.data()); - const CCallsign cs("SWIFT"); const qint64 ts = QDateTime::currentMSecsSinceEpoch(); const qint64 deltaT = 5000; // ms + CCallsign cs("SWIFT"); for (int i = 0; i < IInterpolator::MaxSituationsPerCallsign; i++) { - CAltitude a(i, CAltitude::MeanSeaLevel, CLengthUnit::m()); - CLatitude lat(i, CAngleUnit::deg()); - CLongitude lng(180.0 + i, CAngleUnit::deg()); - CLength height(0, CLengthUnit::m()); - CHeading heading(i * 10, CHeading::True, CAngleUnit::deg()); - CAngle bank(i, CAngleUnit::deg()); - CAngle pitch(i, CAngleUnit::deg()); - CSpeed gs(i * 10, CSpeedUnit::km_h()); - CCoordinateGeodetic c(lat, lng, height); - CAircraftSituation s(c, a, heading, pitch, bank, gs); - s.setMSecsSinceEpoch(ts - deltaT * i); // values in past - s.setCallsign(cs); + CAircraftSituation s(getTestSituation(cs, i, ts, deltaT)); // check height above ground - CLength hag = (a - height); + CLength hag = (s.getAltitude() - s.geodeticHeight()); QVERIFY2(s.getHeightAboveGround() == hag, "Wrong elevation"); provider->insertNewSituation(s); } @@ -57,7 +46,7 @@ namespace BlackCoreTest QVERIFY2(interpolator.getSituationsForCallsign(cs).size() == IInterpolator::MaxSituationsPerCallsign, "Missing situations"); // interpolation - bool ok = false; + IInterpolator::InterpolationStatus status; double latOld = 360.0; double lngOld = 360.0; for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250) @@ -65,10 +54,11 @@ namespace BlackCoreTest // This will use range // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs // to: ts - IInterpolator::TimeOffsetMs - CAircraftSituation currentSituation(interpolator.getCurrentInterpolatedSituation - (interpolator.getSituationsByCallsign(), cs, currentTime, &ok) + CAircraftSituation currentSituation(interpolator.getInterpolatedSituation + (cs, currentTime, status) ); - QVERIFY2(ok, "OK was false"); + QVERIFY2(status.interpolationSucceeded, "Interpolation was not succesful"); + QVERIFY2(status.changedPosition, "Interpolation did not changed"); double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5); double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5); QVERIFY2(latDeg < latOld && lngDeg < lngOld, "Values shall decrease"); @@ -88,10 +78,10 @@ namespace BlackCoreTest // This will use range // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs // to: ts - IInterpolator::TimeOffsetMs - CAircraftSituation currentSituation(interpolator.getCurrentInterpolatedSituation - (interpolator.getSituationsByCallsign(), cs, currentTime, &ok) + CAircraftSituation currentSituation(interpolator.getInterpolatedSituation + (cs, currentTime, status) ); - QVERIFY2(ok, "OK was false"); + QVERIFY2(status.allTrue(), "Failed interpolation"); QVERIFY2(currentSituation.getCallsign() == cs, "Wrong callsign"); double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5); double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5); @@ -102,20 +92,101 @@ namespace BlackCoreTest } int timeMs = timer.elapsed(); QVERIFY2(timeMs < interpolationNo, "Interpolation > 1ms"); + qDebug() << timeMs << "ms" << "for" << interpolationNo; - interpolator.syncRequestSituationsCalculationsForAllCallsigns(1, startTimeMsSinceEpoch); - CAircraftSituationList interpolationsSync(interpolator.getRequest(1)); - QVERIFY(interpolationsSync.size() == 1); - QVERIFY(interpolationsSync.containsCallsign(cs)); + CAircraftSituationList interpolations(interpolator.getInterpolatedSituations(startTimeMsSinceEpoch)); + QVERIFY(interpolations.size() == 1); + QVERIFY(interpolations.containsCallsign(cs)); - interpolator.asyncRequestSituationsCalculationsForAllCallsigns(2, startTimeMsSinceEpoch); - QCoreApplication::processEvents(QEventLoop::AllEvents, 1000); - CAircraftSituationList interpolationsAsync(interpolator.getRequest(1)); - QVERIFY(interpolationsAsync.size() == 1); - QVERIFY(interpolationsAsync.containsCallsign(cs)); + // + // Single interpolation vs. all interpolations at once + // - QVERIFY2(interpolationsAsync.front() == interpolationsSync.front(), "Calculated values should be equal"); + // Create data in provider + provider->clear(); + interpolator.clear(); + QVERIFY(interpolator.getSituationsByCallsign().size() == 0); + const int callsignsInProvider = 20; + for (int callsignNo = 0; callsignNo < callsignsInProvider; callsignNo++) + { + cs = CCallsign("SWIFT" + QString::number(callsignNo)); + int i = 0; + for (int t = 0; t < IInterpolator::MaxSituationsPerCallsign; t++) + { + qint64 currentTime = ts - t * deltaT; + CAircraftSituation s(getTestSituation(cs, i++, currentTime, 0)); + provider->insertNewSituation(s); + } + } + QList csKeys = interpolator.getSituationsByCallsign().keys(); + CCallsignList callsigns(csKeys); + QVERIFY(callsigns.size() == callsignsInProvider); + QVERIFY(interpolator.getSituationsForCallsign("SWIFT0").size() == IInterpolator::MaxSituationsPerCallsign); + + // interpolation for time, then for each callsign + int doneInterpolations = 0; + timer.start(); + for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250) + { + // This will use range + // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs + // to: ts - IInterpolator::TimeOffsetMs + + for (const CCallsign &cs : callsigns) + { + CAircraftSituation currentSituation(interpolator.getInterpolatedSituation + (cs, currentTime, status) + ); + QVERIFY2(status.interpolationSucceeded, "Interpolation was not succesful"); + QVERIFY2(status.changedPosition, "Interpolation did not changed"); + double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5); + double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5); + Q_UNUSED(latDeg); + Q_UNUSED(lngDeg); + doneInterpolations++; + } + } + timeMs = timer.elapsed(); + qDebug() << "Per callsign" << doneInterpolations << "interpolations in" << timeMs << "ms"; + + doneInterpolations = 0; + timer.start(); + for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250) + { + // This will use range + // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs + // to: ts - IInterpolator::TimeOffsetMs + + CAircraftSituationList currentSituations(interpolator.getInterpolatedSituations(currentTime)); + QVERIFY2(currentSituations.size() == callsignsInProvider, "Interpolation was not succesful"); + for (const CAircraftSituation ¤tSituation : currentSituations) + { + double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5); + double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5); + doneInterpolations++; + Q_UNUSED(latDeg); + Q_UNUSED(lngDeg); + } + } + timeMs = timer.elapsed(); + qDebug() << "All callsigns" << doneInterpolations << "interpolations in" << timeMs << "ms"; + } + + CAircraftSituation CTestInterpolator::getTestSituation(const CCallsign &callsign, int number, qint64 ts, qint64 deltaT) + { + CAltitude a(number, CAltitude::MeanSeaLevel, CLengthUnit::m()); + CLatitude lat(number, CAngleUnit::deg()); + CLongitude lng(180.0 + number, CAngleUnit::deg()); + CLength height(0, CLengthUnit::m()); + CHeading heading(number * 10, CHeading::True, CAngleUnit::deg()); + CAngle bank(number, CAngleUnit::deg()); + CAngle pitch(number, CAngleUnit::deg()); + CSpeed gs(number * 10, CSpeedUnit::km_h()); + CCoordinateGeodetic c(lat, lng, height); + CAircraftSituation s(callsign, c, a, heading, pitch, bank, gs); + s.setMSecsSinceEpoch(ts - deltaT * number); // values in past + return s; } } // namespace diff --git a/tests/blackcore/testinterpolator.h b/tests/blackcore/testinterpolator.h index 9ad3295f0..1a186a174 100644 --- a/tests/blackcore/testinterpolator.h +++ b/tests/blackcore/testinterpolator.h @@ -12,6 +12,7 @@ #ifndef BLACKCORETEST_TESTAVIATIONBASE_H #define BLACKCORETEST_TESTAVIATIONBASE_H +#include "blackmisc/avaircraftsituation.h" #include namespace BlackCoreTest @@ -29,6 +30,10 @@ namespace BlackCoreTest private slots: //! Basic unit tests for interpolator void linearInterpolator(); + + private: + //! Test situation for testing + static BlackMisc::Aviation::CAircraftSituation getTestSituation(const BlackMisc::Aviation::CCallsign &callsign, int number, qint64 ts, qint64 deltaT); }; } // namespace diff --git a/tests/blackmisc/testcontainers.cpp b/tests/blackmisc/testcontainers.cpp index 07c378b3d..d1ca1c2f1 100644 --- a/tests/blackmisc/testcontainers.cpp +++ b/tests/blackmisc/testcontainers.cpp @@ -266,7 +266,7 @@ namespace BlackMiscTest CAircraftSituation s; s.setCallsign("CS" + QString::number(i)); s.setMSecsSinceEpoch(cTs); - situations.insertTimestampObject(s, maxElements); + situations.push_frontMaxElements(s, maxElements); if (i > maxElements - 1) { QVERIFY2(situations.size() == maxElements, "Situations must only contain max.elements");