diff --git a/tests/blackmisc/CMakeLists.txt b/tests/blackmisc/CMakeLists.txt index 511c0943d..335d4e776 100644 --- a/tests/blackmisc/CMakeLists.txt +++ b/tests/blackmisc/CMakeLists.txt @@ -93,6 +93,12 @@ add_swift_test( LINK_LIBRARIES misc tests_test Qt::Core ) +add_swift_test( + NAME misc_simulation_interpolatorpbh + SOURCES simulation/testinterpolatorpbh/testinterpolatorpbh.cpp + LINK_LIBRARIES misc tests_test Qt::Core +) + add_swift_test( NAME misc_simulation_xplane SOURCES simulation/testxplane/testxplane.cpp diff --git a/tests/blackmisc/simulation/testinterpolatorlinear/testinterpolatorlinear.cpp b/tests/blackmisc/simulation/testinterpolatorlinear/testinterpolatorlinear.cpp index 5c09a078f..f5cba3538 100644 --- a/tests/blackmisc/simulation/testinterpolatorlinear/testinterpolatorlinear.cpp +++ b/tests/blackmisc/simulation/testinterpolatorlinear/testinterpolatorlinear.cpp @@ -52,9 +52,6 @@ namespace BlackMiscTest //! Basic unit tests for interpolator void basicInterpolatorTests(); - //! Interpolator PBH - void pbhInterpolatorTest(); - private: //! Test situation for testing static BlackMisc::Aviation::CAircraftSituation getTestSituation(const BlackMisc::Aviation::CCallsign &callsign, int number, qint64 ts, qint64 deltaT, qint64 offset); @@ -175,176 +172,6 @@ namespace BlackMiscTest << "for" << fetchedParts << "fetched parts"; } - void CTestInterpolatorLinear::pbhInterpolatorTest() - { - const CCallsign cs("SWIFT"); - CAircraftSituation s1 = getTestSituation(cs, 0, 0, 0, 0); - CAircraftSituation s2 = getTestSituation(cs, 5000, 0, 0, 0); - const CHeading heading1(0, CHeading::True, CAngleUnit::deg()); - const CHeading heading2(120, CHeading::True, CAngleUnit::deg()); - s1.setHeading(heading1); - s2.setHeading(heading2); - CInterpolatorPbh pbh(s1, s2); - - const int steps = 10; - const double tfStep = 1.0 / steps; - - double lastDeg = 0; - - for (int i = 0; i < steps; i++) - { - double timeFraction = tfStep * i; - pbh.setTimeFraction(timeFraction); - const CHeading heading = pbh.getHeading(); - const double h = heading.value(CAngleUnit::deg()); - if (i < 1) - { - lastDeg = h; - continue; - } - QVERIFY2(h > lastDeg, "Expect increasing heading"); - lastDeg = h; - } - - // move from -90 -> 30 over 0 - const CHeading heading3(270, CHeading::True, CAngleUnit::deg()); - const CHeading heading4(30, CHeading::True, CAngleUnit::deg()); - s1.setHeading(heading3); - s2.setHeading(heading4); - pbh.setSituations(s1, s2); - - for (int i = 0; i < steps; i++) - { - double timeFraction = tfStep * i; - pbh.setTimeFraction(timeFraction); - const CHeading heading = pbh.getHeading(); - const double h = heading.value(CAngleUnit::deg()); - if (i < 1) - { - lastDeg = h; - continue; - } - QVERIFY2(h > lastDeg, "Expect increasing heading"); - lastDeg = h; - } - - // move from -90 -> 170 over 180 - const CHeading heading5(270, CHeading::True, CAngleUnit::deg()); - const CHeading heading6(170, CHeading::True, CAngleUnit::deg()); - s1.setHeading(heading5); - s2.setHeading(heading6); - pbh.setSituations(s1, s2); - - for (int i = 0; i < steps; i++) - { - double timeFraction = tfStep * i; - pbh.setTimeFraction(timeFraction); - const CHeading heading = pbh.getHeading(); - const double h = CAngle::normalizeDegrees360(heading.value(CAngleUnit::deg())); - if (i < 1) - { - lastDeg = h; - continue; - } - QVERIFY2(h < lastDeg, "Expect increasing heading"); - lastDeg = h; - } - - // bank from 270 -> 30 over 0 - s1.setHeading(heading5); - s2.setHeading(heading5); - const CAngle bank1(270, CAngleUnit::deg()); - const CAngle bank2(30, CAngleUnit::deg()); - s1.setBank(bank1); - s2.setBank(bank2); - pbh.setSituations(s1, s2); - - for (int i = 0; i < steps; i++) - { - double timeFraction = tfStep * i; - pbh.setTimeFraction(timeFraction); - const CAngle bank = pbh.getBank(); - const double b = bank.value(CAngleUnit::deg()); - if (i < 1) - { - lastDeg = b; - continue; - } - QVERIFY2(b > lastDeg, "Expect increasing bank"); - lastDeg = b; - } - - // bank from 170 -> 190 (-170) over 180 - CAngle bank3(170, CAngleUnit::deg()); - CAngle bank4(190, CAngleUnit::deg()); - s1.setBank(bank3); - s2.setBank(bank4); - pbh.setSituations(s1, s2); - - for (int i = 0; i < steps; i++) - { - double timeFraction = tfStep * i; - pbh.setTimeFraction(timeFraction); - const CAngle bank = pbh.getBank(); - const double b = CAngle::normalizeDegrees360(bank.value(CAngleUnit::deg())); - if (i < 1) - { - lastDeg = b; - continue; - } - QVERIFY2(b > lastDeg, "Expect increasing bank"); - lastDeg = b; - } - - // pitch from 30 -> -30 over 0 - s1.setHeading(heading5); - s2.setHeading(heading5); - const CAngle pitch1(30, CAngleUnit::deg()); - const CAngle pitch2(-30, CAngleUnit::deg()); - s1.setPitch(pitch1); - s2.setPitch(pitch2); - pbh.setSituations(s1, s2); - - for (int i = 0; i < steps; i++) - { - double timeFraction = tfStep * i; - pbh.setTimeFraction(timeFraction); - const CAngle pitch = pbh.getPitch(); - const double p = pitch.value(CAngleUnit::deg()); - if (i < 1) - { - lastDeg = p; - continue; - } - QVERIFY2(p < lastDeg, "Expect decreasing pitch"); - lastDeg = p; - } - - // pitch from -30 -> 30 over 0 - s1.setHeading(heading5); - s2.setHeading(heading5); - const CAngle pitch3(-30, CAngleUnit::deg()); - const CAngle pitch4(30, CAngleUnit::deg()); - s1.setPitch(pitch3); - s2.setPitch(pitch4); - pbh.setSituations(s1, s2); - - for (int i = 0; i < steps; i++) - { - double timeFraction = tfStep * i; - pbh.setTimeFraction(timeFraction); - const CAngle pitch = pbh.getPitch(); - const double p = pitch.value(CAngleUnit::deg()); - if (i < 1) - { - lastDeg = p; - continue; - } - QVERIFY2(p > lastDeg, "Expect increasing pitch"); - lastDeg = p; - } - } - CAircraftSituation CTestInterpolatorLinear::getTestSituation(const CCallsign &callsign, int number, qint64 ts, qint64 deltaT, qint64 offset) { const CAltitude alt(number, CAltitude::MeanSeaLevel, CLengthUnit::m()); diff --git a/tests/blackmisc/simulation/testinterpolatorpbh/testinterpolatorpbh.cpp b/tests/blackmisc/simulation/testinterpolatorpbh/testinterpolatorpbh.cpp new file mode 100644 index 000000000..243ac1568 --- /dev/null +++ b/tests/blackmisc/simulation/testinterpolatorpbh/testinterpolatorpbh.cpp @@ -0,0 +1,267 @@ +// SPDX-FileCopyrightText: Copyright (C) swift Project Community / Contributors +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1 + +//! \cond PRIVATE_TESTS +//! \file +//! \ingroup testblackmisc + +#include "blackmisc/aviation/aircraftsituation.h" +#include "blackmisc/aviation/heading.h" +#include "blackmisc/simulation/interpolatorpbh.h" +#include "blackmisc/math/mathutils.h" +#include "test.h" + +#include + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Geo; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Math; +using namespace BlackMisc::Simulation; + +namespace BlackMiscTest +{ + //! InterpolatorPBH tests + //! As the PBH interpolator works with time-fractions, the situations are time-independent + class CTestInterpolatorPbh : public QObject + { + Q_OBJECT + + private slots: + //! Test interpolate heading from 0 to 120 degrees + static void pbhInterpolatorTestHeading0To120(); + + //! Test interpolate heading from -90 to 30 degrees (over 0) + static void pbhInterpolatorTestHeadingM90To30(); + + //! Test interpolate heading from -90 to 170 degrees (over 180) + static void pbhInterpolatorTestHeadingM90To170(); + + //! Test interpolate bank from 270 to 30 degrees (over 0) + static void pbhInterpolatorTestBank270To30(); + + //! Test interpolate bank from 170 to 190 degrees (over 180) + static void pbhInterpolatorTestBank170To190(); + + //! Test interpolate pitch from 30 to -30 degrees (over 0) + static void pbhInterpolatorTestPitch30ToM30(); + + //! Test interpolate pitch from -30 to 30 degrees (over 0) + static void pbhInterpolatorTestPitchM30To30(); + + private: + static constexpr const int m_steps = 10; //!< Time steps to check + static constexpr const double m_tfStep = 1.0 / m_steps; //!< Time fraction between steps + }; + + void CTestInterpolatorPbh::pbhInterpolatorTestHeading0To120() + { + CAircraftSituation s1({}, CHeading(0, CHeading::True, CAngleUnit::deg())); + CAircraftSituation s2({}, CHeading(120, CHeading::True, CAngleUnit::deg())); + CInterpolatorPbh pbh(s1, s2); + + double lastDeg = 0; + + for (int i = 0; i <= m_steps; i++) + { + pbh.setTimeFraction(m_tfStep * i); + const double h = pbh.getHeading().value(CAngleUnit::deg()); + + if (i == 0) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(h, 0.0), "Expect initial heading"); + } + else if (i == m_steps) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(h, 120.0), "Expect final heading"); + } + else + { + QVERIFY2(h > lastDeg, "Expect increasing heading"); + } + lastDeg = h; + } + } + + void CTestInterpolatorPbh::pbhInterpolatorTestHeadingM90To30() + { + CAircraftSituation s1({}, CHeading(270, CHeading::True, CAngleUnit::deg())); // -90 + CAircraftSituation s2({}, CHeading(30, CHeading::True, CAngleUnit::deg())); + CInterpolatorPbh pbh(s1, s2); + + double lastDeg = 0; + + for (int i = 0; i <= m_steps; i++) + { + pbh.setTimeFraction(m_tfStep * i); + const double h = pbh.getHeading().value(CAngleUnit::deg()); + + if (i == 0) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(h, -90.0), "Expect initial heading"); + } + else if (i == m_steps) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(h, 30.0), "Expect final heading"); + } + else + { + QVERIFY2(h > lastDeg, "Expect increasing heading"); + } + lastDeg = h; + } + } + + void CTestInterpolatorPbh::pbhInterpolatorTestHeadingM90To170() + { + CAircraftSituation s1({}, CHeading(270, CHeading::True, CAngleUnit::deg())); // -90 + CAircraftSituation s2({}, CHeading(170, CHeading::True, CAngleUnit::deg())); + CInterpolatorPbh pbh(s1, s2); + + double lastDeg = 0; + + for (int i = 0; i <= m_steps; i++) + { + pbh.setTimeFraction(m_tfStep * i); + const double h = CAngle::normalizeDegrees360(pbh.getHeading().value(CAngleUnit::deg())); + + if (i == 0) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(h, 270.0), "Expect initial heading"); + } + else if (i == m_steps) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(h, 170.0), "Expect final heading"); + } + else + { + QVERIFY2(h < lastDeg, "Expect decreasing heading"); + } + lastDeg = h; + } + } + + void CTestInterpolatorPbh::pbhInterpolatorTestBank270To30() + { + CAircraftSituation s1({}, CHeading {}, {}, CAngle(270, CAngleUnit::deg())); + CAircraftSituation s2({}, CHeading {}, {}, CAngle(30, CAngleUnit::deg())); + CInterpolatorPbh pbh(s1, s2); + + double lastDeg = 0; + + for (int i = 0; i <= m_steps; i++) + { + pbh.setTimeFraction(m_tfStep * i); + const double b = pbh.getBank().value(CAngleUnit::deg()); + + if (i == 0) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(b, -90.0), "Expect initial bank"); // -90 as not normalized + } + else if (i == m_steps) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(b, 30.0), "Expect final bank"); + } + else + { + QVERIFY2(b > lastDeg, "Expect increasing bank"); + } + lastDeg = b; + } + } + + void CTestInterpolatorPbh::pbhInterpolatorTestBank170To190() + { + CAircraftSituation s1({}, CHeading {}, {}, CAngle(170, CAngleUnit::deg())); + CAircraftSituation s2({}, CHeading {}, {}, CAngle(190, CAngleUnit::deg())); + CInterpolatorPbh pbh(s1, s2); + + double lastDeg = 0; + + for (int i = 0; i <= m_steps; i++) + { + pbh.setTimeFraction(m_tfStep * i); + const double b = CAngle::normalizeDegrees360(pbh.getBank().value(CAngleUnit::deg())); + + if (i == 0) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(b, 170.0), "Expect initial bank"); + } + else if (i == m_steps) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(b, 190.0), "Expect final bank"); + } + else + { + QVERIFY2(b > lastDeg, "Expect increasing bank"); + } + lastDeg = b; + } + } + + void CTestInterpolatorPbh::pbhInterpolatorTestPitch30ToM30() + { + CAircraftSituation s1({}, {}, CAngle(30, CAngleUnit::deg())); + CAircraftSituation s2({}, {}, CAngle(-30, CAngleUnit::deg())); + CInterpolatorPbh pbh(s1, s2); + + double lastDeg = 0; + + for (int i = 0; i <= m_steps; i++) + { + pbh.setTimeFraction(m_tfStep * i); + const double p = pbh.getPitch().value(CAngleUnit::deg()); + + if (i == 0) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(p, 30.0), "Expect initial pitch"); + } + else if (i == m_steps) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(p, -30.0), "Expect final pitch"); + } + else + { + QVERIFY2(p < lastDeg, "Expect decreasing pitch"); + } + lastDeg = p; + } + } + + void CTestInterpolatorPbh::pbhInterpolatorTestPitchM30To30() + { + CAircraftSituation s1({}, {}, CAngle(-30, CAngleUnit::deg())); + CAircraftSituation s2({}, {}, CAngle(30, CAngleUnit::deg())); + CInterpolatorPbh pbh(s1, s2); + + double lastDeg = 0; + + for (int i = 0; i <= m_steps; i++) + { + pbh.setTimeFraction(m_tfStep * i); + const double p = pbh.getPitch().value(CAngleUnit::deg()); + + if (i == 0) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(p, -30.0), "Expect initial pitch"); + } + else if (i == m_steps) + { + QVERIFY2(CMathUtils::epsilonEqualLimits(p, 30.0), "Expect final pitch"); + } + else + { + QVERIFY2(p > lastDeg, "Expect increasing pitch"); + } + lastDeg = p; + } + } +} + +//! main +BLACKTEST_MAIN(BlackMiscTest::CTestInterpolatorPbh); + +#include "testinterpolatorpbh.moc" + +//! \endcond