1
0
Fork 0

TestSuite: Migration of the AeroMesh tests into the CppUnit infrastructure.

This commit is contained in:
Edward d'Auvergne 2018-06-06 22:40:47 +02:00
parent 7aa034bc80
commit acb3307a1a
17 changed files with 403 additions and 264 deletions

View file

@ -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) {

View file

@ -28,17 +28,9 @@
#include <simgear/math/SGGeod.hxx>
#include <simgear/math/SGGeoc.hxx>
#include <simgear/math/SGQuat.hxx>
#ifdef FG_TESTLIB
#include <map>
#include <simgear/props/props.hxx>
#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)

View file

@ -24,14 +24,16 @@
#ifndef _FG_AIWAKEGROUP_HXX
#define _FG_AIWAKEGROUP_HXX
#include <simgear/props/propsfwd.hxx>
#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) {}

View file

@ -32,11 +32,7 @@
#include "AircraftMesh.hxx"
#include <FDM/flight.hxx>
#include "AIWakeGroup.hxx"
#ifndef FG_TESTLIB
#include "AIModel/AIAircraft.hxx"
#else
#include "fakeAIAircraft.hxx"
#endif
extern "C" {
#include "../LaRCsim/ls_matrix.h"
}

View file

@ -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<SGVec3d> collPt, midPt;
SGQuatd Te2b;
SGVec3d moment;

View file

@ -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<AeroElement_ptr> elements;

View file

@ -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)

View file

@ -1,2 +1,47 @@
#include "PrivateAccessorFDM.hxx"
#include <FDM/AIWake/AIWakeGroup.hxx>
#include <FDM/AIWake/AircraftMesh.hxx>
#include <FDM/AIWake/WakeMesh.hxx>
// 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<SGVec3d>
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_AircraftMesh_collPt(AircraftMesh* instance) const
{
return instance->collPt;
}
const std::vector<SGVec3d>
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<AeroElement_ptr>
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;
}

View file

@ -1,6 +1,21 @@
#ifndef _FG_PRIVATE_ACCESSOR_FDM_HXX
#define _FG_PRIVATE_ACCESSOR_FDM_HXX
#include <map>
#include <vector>
#include <simgear/math/SGMath.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
// Forward declarations for src/FDM/AIWake.
class AIWakeData;
class AIWakeGroup;
class AircraftMesh;
class WakeMesh;
class AeroElement;
typedef SGSharedPtr<AeroElement> 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<SGVec3d> read_FDM_AIWake_AircraftMesh_collPt(AircraftMesh* instance) const;
const std::vector<SGVec3d> read_FDM_AIWake_AircraftMesh_midPt(AircraftMesh* instance) const;
// Access variables from src/FDM/AIWake/WakeMesh.hxx.
const std::vector<AeroElement_ptr> 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.

View file

@ -1,5 +1,6 @@
# Add each system test category.
foreach( system_test_category
FDM
)
add_subdirectory(${system_test_category})

View file

@ -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
)

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "testAeroMesh.hxx"
// Set up the unit tests.
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AeroMeshTests, "System tests");

View file

@ -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 <vector>
#include <map>
#include <iostream>
#include <simgear/constants.h>
#include <simgear/misc/test_macros.hxx>
#include <simgear/math/SGVec3.hxx>
#include <simgear/math/SGGeod.hxx>
#include <simgear/math/SGQuat.hxx>
#include <simgear/math/SGGeoc.hxx>
#include <simgear/props/props.hxx>
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIManager.hxx>
#include <AIModel/performancedata.hxx>
#include <AIModel/performancedb.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"
#include <Main/globals.hxx>
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<PerformanceDB>(SGSubsystemMgr::POST_FDM);
globals->get_subsystem<PerformanceDB>()->bind();
globals->get_subsystem<PerformanceDB>()->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);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef _FG_AERO_MESH_SYSTEM_TESTS_HXX
#define _FG_AERO_MESH_SYSTEM_TESTS_HXX
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestFixture.h>
// 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

View file

@ -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)

View file

@ -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

View file

@ -1,170 +0,0 @@
#include <vector>
#include <map>
#include <iostream>
#include <simgear/constants.h>
#include <simgear/misc/test_macros.hxx>
#include <simgear/math/SGVec3.hxx>
#include <simgear/math/SGGeod.hxx>
#include <simgear/math/SGQuat.hxx>
#include <simgear/math/SGGeoc.hxx>
#include <simgear/props/props.hxx>
#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();
}