From acb3307a1a72e98b6a13893cd1285c08b9ba845a Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Wed, 6 Jun 2018 22:40:47 +0200 Subject: [PATCH] TestSuite: Migration of the AeroMesh tests into the CppUnit infrastructure. --- src/AIModel/performancedata.cxx | 11 +- src/FDM/AIWake/AIWakeGroup.cxx | 8 - src/FDM/AIWake/AIWakeGroup.hxx | 8 +- src/FDM/AIWake/AircraftMesh.cxx | 4 - src/FDM/AIWake/AircraftMesh.hxx | 5 +- src/FDM/AIWake/WakeMesh.hxx | 7 +- test_suite/CMakeLists.txt | 1 + test_suite/FGTestApi/PrivateAccessorFDM.cxx | 45 ++++ test_suite/FGTestApi/PrivateAccessorFDM.hxx | 26 +++ test_suite/system_tests/CMakeLists.txt | 1 + test_suite/system_tests/FDM/CMakeLists.txt | 12 + test_suite/system_tests/FDM/TestSuite.cxx | 24 ++ test_suite/system_tests/FDM/testAeroMesh.cxx | 222 +++++++++++++++++++ test_suite/system_tests/FDM/testAeroMesh.hxx | 52 +++++ tests/CMakeLists.txt | 13 -- tests/fakeAIAircraft.hxx | 58 ----- tests/testAeroMesh.cxx | 170 -------------- 17 files changed, 403 insertions(+), 264 deletions(-) create mode 100644 test_suite/system_tests/FDM/CMakeLists.txt create mode 100644 test_suite/system_tests/FDM/TestSuite.cxx create mode 100644 test_suite/system_tests/FDM/testAeroMesh.cxx create mode 100644 test_suite/system_tests/FDM/testAeroMesh.hxx delete mode 100644 tests/fakeAIAircraft.hxx delete mode 100644 tests/testAeroMesh.cxx diff --git a/src/AIModel/performancedata.cxx b/src/AIModel/performancedata.cxx index 351cf92d8..c2157e5d3 100644 --- a/src/AIModel/performancedata.cxx +++ b/src/AIModel/performancedata.cxx @@ -26,7 +26,10 @@ PerformanceData::PerformanceData() : _vDescent(300.0), _vApproach(170.0), _vTouchdown(150.0), - _vTaxi(15.0) + _vTaxi(15.0), + _wingSpan(100.0), + _wingChord(12.0), + _weight(90000.0) { _rollrate = 9.0; // degrees per second _maxbank = 30.0; // passenger friendly bank angle @@ -69,9 +72,9 @@ void PerformanceData::initFromProps(SGPropertyNode *db_node) _vApproach = db_node->getDoubleValue("approach-speed-kts", _vApproach); _vTouchdown = db_node->getDoubleValue("touchdown-speed-kts", _vTouchdown); _vTaxi = db_node->getDoubleValue("taxi-speed-kts", _vTaxi); - _wingSpan = db_node->getDoubleValue("geometry/wing/span-ft", 100.); - _wingChord = db_node->getDoubleValue("geometry/wing/chord-ft", 12.); - _weight = db_node->getDoubleValue("geometry/weight-lbs", 90000.); + _wingSpan = db_node->getDoubleValue("geometry/wing/span-ft", _wingSpan); + _wingChord = db_node->getDoubleValue("geometry/wing/chord-ft", _wingChord); + _weight = db_node->getDoubleValue("geometry/weight-lbs", _weight); } double PerformanceData::actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt, bool maxBrakes) { diff --git a/src/FDM/AIWake/AIWakeGroup.cxx b/src/FDM/AIWake/AIWakeGroup.cxx index c6bcf2d42..afbdcf73e 100644 --- a/src/FDM/AIWake/AIWakeGroup.cxx +++ b/src/FDM/AIWake/AIWakeGroup.cxx @@ -28,17 +28,9 @@ #include #include #include -#ifdef FG_TESTLIB -#include -#include -#include "tests/fakeAIAircraft.hxx" -Globals g; -Globals *globals = &g; -#else #include "Main/globals.hxx" #include "AIModel/performancedata.hxx" #include "AIModel/AIAircraft.hxx" -#endif #include "FDM/AIWake/AIWakeGroup.hxx" AIWakeGroup::AIWakeGroup(void) diff --git a/src/FDM/AIWake/AIWakeGroup.hxx b/src/FDM/AIWake/AIWakeGroup.hxx index e4fe934e2..66ae66544 100644 --- a/src/FDM/AIWake/AIWakeGroup.hxx +++ b/src/FDM/AIWake/AIWakeGroup.hxx @@ -24,14 +24,16 @@ #ifndef _FG_AIWAKEGROUP_HXX #define _FG_AIWAKEGROUP_HXX +#include + #include "FDM/AIWake/WakeMesh.hxx" +namespace FGTestApi { namespace PrivateAccessor { namespace FDM { class Accessor; } } } class FGAIAircraft; class AIWakeGroup { -#ifdef FG_TESTLIB -public: -#endif + friend class FGTestApi::PrivateAccessor::FDM::Accessor; + struct AIWakeData { explicit AIWakeData(WakeMesh* m = nullptr) : mesh(m) {} diff --git a/src/FDM/AIWake/AircraftMesh.cxx b/src/FDM/AIWake/AircraftMesh.cxx index f5338feab..7bc9994b5 100644 --- a/src/FDM/AIWake/AircraftMesh.cxx +++ b/src/FDM/AIWake/AircraftMesh.cxx @@ -32,11 +32,7 @@ #include "AircraftMesh.hxx" #include #include "AIWakeGroup.hxx" -#ifndef FG_TESTLIB #include "AIModel/AIAircraft.hxx" -#else -#include "fakeAIAircraft.hxx" -#endif extern "C" { #include "../LaRCsim/ls_matrix.h" } diff --git a/src/FDM/AIWake/AircraftMesh.hxx b/src/FDM/AIWake/AircraftMesh.hxx index 884b7cb32..1cbf496d8 100644 --- a/src/FDM/AIWake/AircraftMesh.hxx +++ b/src/FDM/AIWake/AircraftMesh.hxx @@ -26,6 +26,7 @@ #include "WakeMesh.hxx" +namespace FGTestApi { namespace PrivateAccessor { namespace FDM { class Accessor; } } } class FGAIAircraft; class AIWakeGroup; @@ -36,9 +37,9 @@ public: SGVec3d GetForce(const AIWakeGroup& wg, const SGVec3d& vel, double rho); const SGVec3d& GetMoment(void) const { return moment; }; -#ifndef FG_TESTLIB private: -#endif + friend class FGTestApi::PrivateAccessor::FDM::Accessor; + std::vector collPt, midPt; SGQuatd Te2b; SGVec3d moment; diff --git a/src/FDM/AIWake/WakeMesh.hxx b/src/FDM/AIWake/WakeMesh.hxx index 6605d6ae0..2c2a63708 100644 --- a/src/FDM/AIWake/WakeMesh.hxx +++ b/src/FDM/AIWake/WakeMesh.hxx @@ -25,6 +25,9 @@ #include "AeroElement.hxx" +namespace FGTestApi { namespace PrivateAccessor { namespace FDM { class Accessor; } } } + + class WakeMesh : public SGReferenced { public: WakeMesh(double _span, double _chord); @@ -32,9 +35,9 @@ public: double computeAoA(double vel, double rho, double weight); SGVec3d getInducedVelocityAt(const SGVec3d& at) const; -#ifndef FG_TESTLIB protected: -#endif + friend class FGTestApi::PrivateAccessor::FDM::Accessor; + int nelm; double span, chord; std::vector elements; diff --git a/test_suite/CMakeLists.txt b/test_suite/CMakeLists.txt index 7ef78b905..cd8cd8a4a 100644 --- a/test_suite/CMakeLists.txt +++ b/test_suite/CMakeLists.txt @@ -61,6 +61,7 @@ endif() # Set up all test suites as CTests. # System test suites. +add_test(AeroMeshSystemTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -s AeroMeshTests) # Unit test suites. add_test(AddonManagementUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u AddonManagementTests) diff --git a/test_suite/FGTestApi/PrivateAccessorFDM.cxx b/test_suite/FGTestApi/PrivateAccessorFDM.cxx index 67d92f9ec..40dd3f431 100644 --- a/test_suite/FGTestApi/PrivateAccessorFDM.cxx +++ b/test_suite/FGTestApi/PrivateAccessorFDM.cxx @@ -1,2 +1,47 @@ #include "PrivateAccessorFDM.hxx" +#include +#include +#include + + +// Access variables from src/FDM/AIWake/AIWakeGroup.hxx. +WakeMesh* +FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_AIWakeGroup_aiWakeData(AIWakeGroup* instance, int i) +{ + return instance->_aiWakeData[i].mesh; +} + + +// Access variables from src/FDM/AIWake/AircraftMesh.hxx. +const std::vector +FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_AircraftMesh_collPt(AircraftMesh* instance) const +{ + return instance->collPt; +} + +const std::vector +FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_AircraftMesh_midPt(AircraftMesh* instance) const +{ + return instance->midPt; +} + + +// Access variables from src/FDM/AIWake/WakeMesh.hxx. +const std::vector +FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_WakeMesh_elements(WakeMesh* instance) const +{ + return instance->elements; +} + +int +FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_WakeMesh_nelm(WakeMesh* instance) const +{ + return instance->nelm; +} + +double ** +FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_WakeMesh_Gamma(WakeMesh* instance) const +{ + return instance->Gamma; +} diff --git a/test_suite/FGTestApi/PrivateAccessorFDM.hxx b/test_suite/FGTestApi/PrivateAccessorFDM.hxx index 7db30b6b3..ad08b18df 100644 --- a/test_suite/FGTestApi/PrivateAccessorFDM.hxx +++ b/test_suite/FGTestApi/PrivateAccessorFDM.hxx @@ -1,6 +1,21 @@ #ifndef _FG_PRIVATE_ACCESSOR_FDM_HXX #define _FG_PRIVATE_ACCESSOR_FDM_HXX +#include +#include + +#include +#include + +// Forward declarations for src/FDM/AIWake. +class AIWakeData; +class AIWakeGroup; +class AircraftMesh; +class WakeMesh; +class AeroElement; +typedef SGSharedPtr AeroElement_ptr; + + namespace FGTestApi { namespace PrivateAccessor { namespace FDM { @@ -8,6 +23,17 @@ namespace FDM { class Accessor { public: + // Access variables from src/FDM/AIWake/AIWakeGroup.hxx. + WakeMesh* read_FDM_AIWake_AIWakeGroup_aiWakeData(AIWakeGroup* instance, int i); + + // Access variables from src/FDM/AIWake/AircraftMesh.hxx. + const std::vector read_FDM_AIWake_AircraftMesh_collPt(AircraftMesh* instance) const; + const std::vector read_FDM_AIWake_AircraftMesh_midPt(AircraftMesh* instance) const; + + // Access variables from src/FDM/AIWake/WakeMesh.hxx. + const std::vector read_FDM_AIWake_WakeMesh_elements(WakeMesh* instance) const; + int read_FDM_AIWake_WakeMesh_nelm(WakeMesh* instance) const; + double **read_FDM_AIWake_WakeMesh_Gamma(WakeMesh* instance) const; }; } // End of namespace FDM. diff --git a/test_suite/system_tests/CMakeLists.txt b/test_suite/system_tests/CMakeLists.txt index 5c143face..1c01bd88f 100644 --- a/test_suite/system_tests/CMakeLists.txt +++ b/test_suite/system_tests/CMakeLists.txt @@ -1,5 +1,6 @@ # Add each system test category. foreach( system_test_category + FDM ) add_subdirectory(${system_test_category}) diff --git a/test_suite/system_tests/FDM/CMakeLists.txt b/test_suite/system_tests/FDM/CMakeLists.txt new file mode 100644 index 000000000..4bbf525c2 --- /dev/null +++ b/test_suite/system_tests/FDM/CMakeLists.txt @@ -0,0 +1,12 @@ +set(TESTSUITE_SOURCES + ${TESTSUITE_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/testAeroMesh.cxx + PARENT_SCOPE +) + +set(TESTSUITE_HEADERS + ${TESTSUITE_HEADERS} + ${CMAKE_CURRENT_SOURCE_DIR}/testAeroMesh.hxx + PARENT_SCOPE +) diff --git a/test_suite/system_tests/FDM/TestSuite.cxx b/test_suite/system_tests/FDM/TestSuite.cxx new file mode 100644 index 000000000..611b8bb70 --- /dev/null +++ b/test_suite/system_tests/FDM/TestSuite.cxx @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 Edward d'Auvergne + * + * This file is part of the program FlightGear. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "testAeroMesh.hxx" + + +// Set up the unit tests. +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AeroMeshTests, "System tests"); diff --git a/test_suite/system_tests/FDM/testAeroMesh.cxx b/test_suite/system_tests/FDM/testAeroMesh.cxx new file mode 100644 index 000000000..e16224029 --- /dev/null +++ b/test_suite/system_tests/FDM/testAeroMesh.cxx @@ -0,0 +1,222 @@ +#include "testAeroMesh.hxx" + +#include "test_suite/FGTestApi/globals.hxx" +#include "test_suite/FGTestApi/PrivateAccessorFDM.hxx" +#include "test_suite/FGTestApi/scene_graph.hxx" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "FDM/AIWake/AircraftMesh.hxx" +#include "FDM/AIWake/AIWakeGroup.hxx" +extern "C" { +#include "src/FDM/LaRCsim/ls_matrix.h" +} + +#include "FDM/JSBSim/math/FGLocation.h" +#include "FDM/JSBSim/math/FGQuaternion.h" + +#include
+ + +using namespace std; +using namespace JSBSim; + +double rho = 2.0E-3; + + +// Set up function for each test. +void AeroMeshTests::setUp() +{ + FGTestApi::setUp::initTestGlobals("aeromesh"); + FGTestApi::setUp::initScenery(); + globals->get_props()->getNode("environment/density-slugft3", true) + ->setDoubleValue(rho); +} + + +// Clean up after each test. +void AeroMeshTests::tearDown() +{ + FGTestApi::tearDown::shutdownTestGlobals(); +} + + +void AeroMeshTests::testLiftComputation() +{ + double b = 10.0; + double c = 2.0; + AircraftMesh_ptr mesh = new AircraftMesh(b, c); + SGGeod geodPos = SGGeod::fromDeg(0.0, 0.0); + SGVec3d pos; + double vel = 100.; + double weight = 50.; + + SGGeodesy::SGGeodToCart(geodPos, pos); + mesh->setPosition(pos, SGQuatd::unit()); + + SGPropertyNode* props = globals->get_props()->getNode("ai/models", true); + props->setDoubleValue("acceleration-kts-hour", 0.0); + props->setDoubleValue("deceleration-kts-hour", 0.0); + props->setDoubleValue("climbrate-fpm", 0.0); + props->setDoubleValue("decentrate-fpm", 0.0); + props->setDoubleValue("rotate-speed-kts", 0.0); + props->setDoubleValue("takeoff-speed-kts", 0.0); + props->setDoubleValue("climb-speed-kts", 0.0); + props->setDoubleValue("cruise-speed-kts", 0.0); + props->setDoubleValue("decent-speed-kts", 0.0); + props->setDoubleValue("approach-speed-kts", 0.0); + props->setDoubleValue("touchdown-speed-kts", 0.0); + props->setDoubleValue("taxi-speed-kts", 0.0); + props->setDoubleValue("geometry/wing/span-ft", b); + props->setDoubleValue("geometry/wing/chord-ft", c); + props->setDoubleValue("geometry/weight-lbs", weight); + + globals->add_new_subsystem(SGSubsystemMgr::POST_FDM); + globals->get_subsystem()->bind(); + globals->get_subsystem()->init(); + + FGAIManager *aiManager = new FGAIManager; + FGAIAircraft *ai = new FGAIAircraft; + ai->setGeodPos(geodPos); + ai->setSpeed(vel * SG_FPS_TO_KT); + ai->setPerformance("", "jet_transport"); + ai->getPerformance()->initFromProps(props); + aiManager->attach(ai); + + AIWakeGroup wg; + wg.AddAI(ai); + + SGVec3d force = mesh->GetForce(wg, SGVec3d(vel, 0., 0.), rho); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(force[1], 0.0, 1e-9); + CPPUNIT_ASSERT_DOUBLES_EQUAL(force[2], -weight, 1e-9); + + SGVec3d moment = mesh->GetMoment(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(moment[0], 0.0, 1e-9); + CPPUNIT_ASSERT_DOUBLES_EQUAL(moment[1], -0.5*weight, 1e-9); + CPPUNIT_ASSERT_DOUBLES_EQUAL(moment[2], 0.0, 1e-9); + + auto accessor = FGTestApi::PrivateAccessor::FDM::Accessor(); + + for (int i=1; i<= accessor.read_FDM_AIWake_WakeMesh_nelm(mesh); ++i) + CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_WakeMesh_Gamma(accessor.read_FDM_AIWake_AIWakeGroup_aiWakeData(&wg, 1))[i][1], + accessor.read_FDM_AIWake_WakeMesh_Gamma(mesh)[i][1], 1e-9); +} + + +void AeroMeshTests::testFourierLiftingLine() +{ + double b = 10.0; + double c = 2.0; + double vel = 100.; + double weight = 50.; + + auto accessor = FGTestApi::PrivateAccessor::FDM::Accessor(); + + WakeMesh_ptr mesh = new WakeMesh(b, c); + int N = accessor.read_FDM_AIWake_WakeMesh_nelm(mesh); + double **mtx = nr_matrix(1, N, 1, N); + double **coef = nr_matrix(1, N, 1, 1); + + mesh->computeAoA(vel, rho, weight); + + for (int m=1; m<=N; ++m) { + double vm = M_PI*m/(N+1); + double sm = sin(vm); + coef[m][1] = c*M_PI/(2*b); + for (int n=1; n<=N; ++n) + mtx[m][n] = sin(n*vm)*(1.0+coef[m][1]*n/sm); + } + + nr_gaussj(mtx, N, coef, 1); + + double S = b*c; + double AR = b*b/S; + double lift = 0.5*rho*S*vel*vel*coef[1][1]*M_PI*AR; + double sinAlpha = weight / lift; + lift *= sinAlpha; + + cout << "y, Lift (Fourier), Lift (VLM), Corrected lift (VLM)" << endl; + + for (int i=1; i<=N; ++i) { + double y = accessor.read_FDM_AIWake_WakeMesh_elements(mesh)[i-1]->getBoundVortexMidPoint()[1]; + double theta = acos(2.0*y/b); + double gamma = 0.0; + for (int n=1; n<=N; ++n) + gamma += coef[n][1]*sin(n*theta); + + gamma *= 2.0*b*vel*sinAlpha; + + cout << y << ", " << gamma << ", " << accessor.read_FDM_AIWake_WakeMesh_Gamma(mesh)[i][1] << ", " + << accessor.read_FDM_AIWake_WakeMesh_Gamma(mesh)[i][1] / gamma - 1.0 << endl; + } + + nr_free_matrix(mtx, 1, N, 1, N); + nr_free_matrix(coef, 1, N, 1, 1); +} + + +void AeroMeshTests::testFrameTransformations() +{ + double b = 10.0; + double c = 2.0; + double yaw = 80. * SGD_DEGREES_TO_RADIANS; + double pitch = 5. * SGD_DEGREES_TO_RADIANS; + double roll = -10. * SGD_DEGREES_TO_RADIANS; + SGQuatd orient = SGQuatd::fromYawPitchRoll(yaw, pitch, roll); + SGGeod geodPos = SGGeod::fromDeg(45.0, 10.0); + SGVec3d pos; + + SGGeodesy::SGGeodToCart(geodPos, pos); + SGGeoc geoc = SGGeoc::fromCart(pos); + + FGLocation loc(geoc.getLongitudeRad(), + geoc.getLatitudeRad(), + geoc.getRadiusFt()); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(pos[0] * SG_METER_TO_FEET, loc(1), 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(pos[1] * SG_METER_TO_FEET, loc(2), 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(pos[2] * SG_METER_TO_FEET, loc(3), 1e-7); + + AircraftMesh_ptr mesh = new AircraftMesh(b, c); + mesh->setPosition(pos, orient); + + FGQuaternion qJ(roll, pitch, yaw); + FGMatrix33 Tb2l = qJ.GetTInv(); + FGColumnVector3 refPos = loc.GetTec2l() * loc; + + for (int i=0; i < 4; ++i) + CPPUNIT_ASSERT_DOUBLES_EQUAL(orient(i), qJ((i+1) % 4 + 1), 1e-9); + + auto accessor = FGTestApi::PrivateAccessor::FDM::Accessor(); + + for (int i=0; i < accessor.read_FDM_AIWake_WakeMesh_nelm(mesh); ++i) { + SGVec3d pt = accessor.read_FDM_AIWake_WakeMesh_elements(mesh)[i]->getBoundVortexMidPoint(); + FGColumnVector3 ptJ(pt[0], pt[1], pt[2]); + FGColumnVector3 p = loc.GetTl2ec() * (refPos + Tb2l * ptJ); + CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_midPt(mesh)[i][0], p(1), 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_midPt(mesh)[i][1], p(2), 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_midPt(mesh)[i][2], p(3), 1e-7); + + pt = accessor.read_FDM_AIWake_WakeMesh_elements(mesh)[i]->getCollocationPoint(); + ptJ.InitMatrix(pt[0], pt[1], pt[2]); + p = loc.GetTl2ec() * (refPos + Tb2l * ptJ); + CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_collPt(mesh)[i][0], p(1), 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_collPt(mesh)[i][1], p(2), 1e-7); + CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_collPt(mesh)[i][2], p(3), 1e-7); + } +} diff --git a/test_suite/system_tests/FDM/testAeroMesh.hxx b/test_suite/system_tests/FDM/testAeroMesh.hxx new file mode 100644 index 000000000..118c25389 --- /dev/null +++ b/test_suite/system_tests/FDM/testAeroMesh.hxx @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 Edward d'Auvergne + * + * This file is part of the program FlightGear. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef _FG_AERO_MESH_SYSTEM_TESTS_HXX +#define _FG_AERO_MESH_SYSTEM_TESTS_HXX + + +#include +#include + + +// The system tests. +class AeroMeshTests : public CppUnit::TestFixture +{ + // Set up the test suite. + CPPUNIT_TEST_SUITE(AeroMeshTests); + CPPUNIT_TEST(testFourierLiftingLine); + CPPUNIT_TEST(testFrameTransformations); + CPPUNIT_TEST(testLiftComputation); + CPPUNIT_TEST_SUITE_END(); + +public: + // Set up function for each test. + void setUp(); + + // Clean up after each test. + void tearDown(); + + // The tests. + void testFourierLiftingLine(); + void testFrameTransformations(); + void testLiftComputation(); +}; + +#endif // _FG_AERO_MESH_SYSTEM_TESTS_HXX diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 69db72820..d94d32257 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -115,16 +115,3 @@ macro(flightgear_test name sources) target_link_libraries(${name} fgtestlib) add_test(${name} ${EXECUTABLE_OUTPUT_PATH}/${name}) endmacro() - -add_executable(testAeroMesh testAeroMesh.cxx - ${CMAKE_SOURCE_DIR}/src/FDM/AIWake/AeroElement.cxx - ${CMAKE_SOURCE_DIR}/src/FDM/AIWake/AircraftMesh.cxx - ${CMAKE_SOURCE_DIR}/src/FDM/AIWake/WakeMesh.cxx - ${CMAKE_SOURCE_DIR}/src/FDM/AIWake/AIWakeGroup.cxx - ${CMAKE_SOURCE_DIR}/src/FDM/LaRCsim/ls_matrix.c - ) -set_target_properties (testAeroMesh PROPERTIES COMPILE_DEFINITIONS "FG_TESTLIB") -target_include_directories(testAeroMesh PRIVATE ${CMAKE_SOURCE_DIR}/tests - ${CMAKE_SOURCE_DIR}/src/FDM/JSBSim) -target_link_libraries(testAeroMesh SimGearCore JSBSim) -add_test(testAeroMesh ${EXECUTABLE_OUTPUT_PATH}/testAeroMesh) diff --git a/tests/fakeAIAircraft.hxx b/tests/fakeAIAircraft.hxx deleted file mode 100644 index d4d53b5d7..000000000 --- a/tests/fakeAIAircraft.hxx +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef FAKEFGAIAIRCRAFT -#define FAKEFGAIAIRCRAFT - -struct Globals { - Globals(void) { root.getNode("environment/density-slugft3", true); } - SGPropertyNode* get_props(void) { return &root; } - SGPropertyNode root; -}; - -struct PerformanceData { - double _span, _chord, _weight; - PerformanceData(double s, double c, double w) - : _span(s), _chord(c), _weight(w) {} - double wingSpan(void) const { return _span; } - double wingChord(void) const { return _chord; } - double weight(void) const { return _weight; } -}; - -class FGAIAircraft { -public: - explicit FGAIAircraft(int id) - : _id(id), _pos(SGVec3d::zeros()), _heading(0.0), _pitch(0.0), - _vel(0.0), _perf(0.0, 0.0, 0.0) {} - void setPosition(const SGVec3d& pos) { _pos = pos; } - void setOrientation(double heading, double pitch) - { - _heading = heading; - _pitch = pitch; - } - void setGeom(double s, double c, double w) - { - _perf._span = s; - _perf._chord = c; - _perf._weight = w; - } - void setVelocity(double v) { _vel = v; } - const SGVec3d& getCartPos(void) const { return _pos; } - double _getHeading(void) const { return _heading; } - double getPitch(void) const { return _pitch; } - int getID(void) const { return _id; } - PerformanceData* getPerformance(void) { return &_perf; } - std::string getAcType(void) const { return "The AC type"; } - std::string _getName(void) const { return "The AC name"; } - double getSpeed(void) const { return _vel * SG_FPS_TO_KT; } - double getVerticalSpeed(void) const { return 0.0; } - double getAltitude(void) const { return 3000.; } - double getRoll(void) const { return 0.0; } - -private: - int _id; - SGVec3d _pos; - double _heading, _pitch, _vel; - PerformanceData _perf; -}; - -extern Globals* globals; - -#endif diff --git a/tests/testAeroMesh.cxx b/tests/testAeroMesh.cxx deleted file mode 100644 index 9a445ae93..000000000 --- a/tests/testAeroMesh.cxx +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "fakeAIAircraft.hxx" -#include "FDM/AIWake/AircraftMesh.hxx" -#include "FDM/AIWake/AIWakeGroup.hxx" -extern "C" { -#include "src/FDM/LaRCsim/ls_matrix.h" -} - -#include "FDM/JSBSim/math/FGLocation.h" -#include "FDM/JSBSim/math/FGQuaternion.h" - -using namespace std; -using namespace JSBSim; - -double rho = 2.0E-3; - -void testLiftComputation() -{ - double b = 10.0; - double c = 2.0; - AircraftMesh_ptr mesh = new AircraftMesh(b, c); - SGGeod geodPos = SGGeod::fromDeg(0.0, 0.0); - SGVec3d pos; - double vel = 100.; - double weight = 50.; - - SGGeodesy::SGGeodToCart(geodPos, pos); - mesh->setPosition(pos, SGQuatd::unit()); - - FGAIAircraft ai(1); - ai.setPosition(pos); - ai.setGeom(b, c, weight); - ai.setVelocity(vel); - - AIWakeGroup wg; - wg.AddAI(&ai); - - SGVec3d force = mesh->GetForce(wg, SGVec3d(vel, 0., 0.), rho); - - SG_CHECK_EQUAL_EP(force[1], 0.0); - SG_CHECK_EQUAL_EP(force[2], -weight); - - SGVec3d moment = mesh->GetMoment(); - SG_CHECK_EQUAL_EP(moment[0], 0.0); - SG_CHECK_EQUAL_EP(moment[1], -0.5*weight); - SG_CHECK_EQUAL_EP(moment[2], 0.0); - - for (int i=1; i<= mesh->nelm; ++i) - SG_CHECK_EQUAL_EP(wg._aiWakeData[1].mesh->Gamma[i][1], - mesh->Gamma[i][1]); -} - -void testFourierLiftingLine() -{ - double b = 10.0; - double c = 2.0; - double vel = 100.; - double weight = 50.; - - WakeMesh_ptr mesh = new WakeMesh(b, c); - int N = mesh->nelm; - double **mtx = nr_matrix(1, N, 1, N); - double **coef = nr_matrix(1, N, 1, 1); - - mesh->computeAoA(vel, rho, weight); - - for (int m=1; m<=N; ++m) { - double vm = M_PI*m/(N+1); - double sm = sin(vm); - coef[m][1] = c*M_PI/(2*b); - for (int n=1; n<=N; ++n) - mtx[m][n] = sin(n*vm)*(1.0+coef[m][1]*n/sm); - } - - nr_gaussj(mtx, N, coef, 1); - - double S = b*c; - double AR = b*b/S; - double lift = 0.5*rho*S*vel*vel*coef[1][1]*M_PI*AR; - double sinAlpha = weight / lift; - lift *= sinAlpha; - - cout << "y, Lift (Fourier), Lift (VLM), Corrected lift (VLM)" << endl; - - for (int i=1; i<=N; ++i) { - double y = mesh->elements[i-1]->getBoundVortexMidPoint()[1]; - double theta = acos(2.0*y/b); - double gamma = 0.0; - for (int n=1; n<=N; ++n) - gamma += coef[n][1]*sin(n*theta); - - gamma *= 2.0*b*vel*sinAlpha; - - cout << y << ", " << gamma << ", " << mesh->Gamma[i][1] << ", " - << mesh->Gamma[i][1] / gamma - 1.0 << endl; - } - - nr_free_matrix(mtx, 1, N, 1, N); - nr_free_matrix(coef, 1, N, 1, 1); -} - -void testFrameTransformations() -{ - double b = 10.0; - double c = 2.0; - double yaw = 80. * SGD_DEGREES_TO_RADIANS; - double pitch = 5. * SGD_DEGREES_TO_RADIANS; - double roll = -10. * SGD_DEGREES_TO_RADIANS; - SGQuatd orient = SGQuatd::fromYawPitchRoll(yaw, pitch, roll); - SGGeod geodPos = SGGeod::fromDeg(45.0, 10.0); - SGVec3d pos; - - SGGeodesy::SGGeodToCart(geodPos, pos); - SGGeoc geoc = SGGeoc::fromCart(pos); - - FGLocation loc(geoc.getLongitudeRad(), - geoc.getLatitudeRad(), - geoc.getRadiusFt()); - - SG_CHECK_EQUAL_EP(pos[0] * SG_METER_TO_FEET, loc(1)); - SG_CHECK_EQUAL_EP(pos[1] * SG_METER_TO_FEET, loc(2)); - SG_CHECK_EQUAL_EP(pos[2] * SG_METER_TO_FEET, loc(3)); - - AircraftMesh_ptr mesh = new AircraftMesh(b, c); - mesh->setPosition(pos, orient); - - FGQuaternion qJ(roll, pitch, yaw); - FGMatrix33 Tb2l = qJ.GetTInv(); - FGColumnVector3 refPos = loc.GetTec2l() * loc; - - for (int i=0; i < 4; ++i) - SG_CHECK_EQUAL_EP(orient(i), qJ((i+1) % 4 + 1)); - - for (int i=0; i < mesh->nelm; ++i) { - SGVec3d pt = mesh->elements[i]->getBoundVortexMidPoint(); - FGColumnVector3 ptJ(pt[0], pt[1], pt[2]); - FGColumnVector3 p = loc.GetTl2ec() * (refPos + Tb2l * ptJ); - SG_CHECK_EQUAL_EP(mesh->midPt[i][0], p(1)); - SG_CHECK_EQUAL_EP(mesh->midPt[i][1], p(2)); - SG_CHECK_EQUAL_EP(mesh->midPt[i][2], p(3)); - - pt = mesh->elements[i]->getCollocationPoint(); - ptJ.InitMatrix(pt[0], pt[1], pt[2]); - p = loc.GetTl2ec() * (refPos + Tb2l * ptJ); - SG_CHECK_EQUAL_EP(mesh->collPt[i][0], p(1)); - SG_CHECK_EQUAL_EP(mesh->collPt[i][1], p(2)); - SG_CHECK_EQUAL_EP(mesh->collPt[i][2], p(3)); - } -} - -int main(int argc, char* argv[]) -{ - globals->get_props()->getNode("environment/density-slugft3", false) - ->setDoubleValue(rho); - - testFourierLiftingLine(); - testLiftComputation(); - testFrameTransformations(); -}