first commit

This commit is contained in:
Your Name
2022-10-20 20:29:11 +08:00
commit 4d531f8044
3238 changed files with 1387862 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
# Add each system test category.
foreach( system_test_category
FDM
Instrumentation
Navaids
Main
)
add_subdirectory(${system_test_category})
endforeach( system_test_category )
set(TESTSUITE_SOURCES
${TESTSUITE_SOURCES}
PARENT_SCOPE
)
set(TESTSUITE_HEADERS
${TESTSUITE_HEADERS}
PARENT_SCOPE
)

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/testGlobals.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, "test");
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, "testMesh");
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, "test");
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

@@ -0,0 +1,12 @@
set(TESTSUITE_SOURCES
${TESTSUITE_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
#${CMAKE_CURRENT_SOURCE_DIR}/testgps.cxx
PARENT_SCOPE
)
set(TESTSUITE_HEADERS
${TESTSUITE_HEADERS}
#${CMAKE_CURRENT_SOURCE_DIR}/testgps.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 "testgps.hxx"
// Set up the unit tests.
//CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(GPSTests, "System tests");

View File

@@ -0,0 +1,351 @@
#include <fstream>
#include <simgear/misc/sg_path.hxx>
#include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/structure/exception.hxx>
#include <Main/fg_init.hxx>
#include <Main/fg_props.hxx>
#include <Instrumentation/gps.hxx>
#include <Autopilot/route_mgr.hxx>
#include <Environment/environment_mgr.hxx>
#include <Navaids/airways.hxx>
#include <Navaids/waypoint.hxx>
#include <Navaids/procedure.hxx>
#include "test_suite/helpers/globals.hxx"
#include "test_suite/helpers/NavDataCache.hxx"
#include "testgps.hxx"
using std::string;
using namespace flightgear;
char *homedir = ::getenv( "HOME" );
char *hostname = ::getenv( "HOSTNAME" );
bool free_hostname = false;
void testSetPosition(const SGGeod& aPos)
{
fgSetDouble("/position/longitude-deg", aPos.getLongitudeDeg());
fgSetDouble("/position/latitude-deg", aPos.getLatitudeDeg());
fgSetDouble("/position/altitude-ft", aPos.getElevationFt());
}
void printScratch(SGPropertyNode* scratch)
{
if (!scratch->getBoolValue("valid", false)) {
SG_LOG(SG_GENERAL, SG_ALERT, "Scratch is invalid.");
return;
}
SG_LOG(SG_GENERAL, SG_ALERT, "Scratch:" <<
scratch->getStringValue("ident") << "/" << scratch->getStringValue("name"));
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << scratch->getDoubleValue("longitude-deg")
<< " " << scratch->getDoubleValue("latitude-deg") << " @ " << scratch->getDoubleValue("altitude-ft"));
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << scratch->getDoubleValue("true-bearing-deg") <<
" (" << scratch->getDoubleValue("mag-bearing-deg") << " magnetic) " << scratch->getDoubleValue("distance-nm"));
if (scratch->hasChild("result-index")) {
SG_LOG(SG_GENERAL, SG_ALERT, "\tresult-index:" << scratch->getIntValue("result-index"));
}
if (scratch->hasChild("route-index")) {
SG_LOG(SG_GENERAL, SG_ALERT, "\troute-index:" << scratch->getIntValue("route-index"));
}
}
void printRoute(const WayptVec& aRoute)
{
SG_LOG(SG_GENERAL, SG_INFO, "route size=" << aRoute.size());
for (unsigned int r=0; r<aRoute.size();++r) {
Waypt* w = aRoute[r];
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << r << ": " << w->ident() << " "
<< w->owner()->ident());
}
}
void createDummyRoute(FGRouteMgr* rm)
{
SGPropertyNode* rmInput = fgGetNode("/autopilot/route-manager/input", true);
rmInput->setStringValue("UW");
rmInput->setStringValue("TLA/347/13");
rmInput->setStringValue("TLA");
rmInput->setStringValue("HAVEN");
rmInput->setStringValue("NEW/305/29");
rmInput->setStringValue("NEW");
rmInput->setStringValue("OTR");
}
void GPSTests::setUp()
{
fgtest::initTestGlobals("GPS");
fgtest::initNavDataCache();
}
void GPSTests::tearDown()
{
fgtest::shutdownTestGlobals();
}
void GPSTests::testGPS()
{
fgSetDouble("/environment/magnetic-variation-deg", 0.0);
Airway::load();
SG_LOG(SG_GENERAL, SG_ALERT, "hello world!");
const FGAirport* egph = fgFindAirportID("EGPH");
SG_LOG(SG_GENERAL, SG_ALERT, "egph: cart location:" << egph->cart());
FGAirport::AirportFilter af;
FGPositionedList l = FGPositioned::findClosestN(egph->geod(), 20, 2000.0, &af);
for (unsigned int i=0; i<l.size(); ++i) {
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << l[i]->ident() << "/" << l[i]->name());
}
//l = FGPositioned::findWithinRange(egph->geod(), 500.0, &af);
//for (unsigned int i=0; i<l.size(); ++i) {
// SG_LOG(SG_GENERAL, SG_ALERT, "\t" << l[i]->ident() << "/" << l[i]->name());
//}
FGRouteMgr* rm = new FGRouteMgr;
globals->add_subsystem( "route-manager", rm );
// FGEnvironmentMgr* envMgr = new FGEnvironmentMgr;
// globals->add_subsystem("environment", envMgr);
// envMgr->init();
fgSetBool("/sim/realism/simple-gps", true);
// _realismSimpleGps
SGPropertyNode* nd = fgGetNode("/instrumentation/gps", true);
GPS* gps = new GPS(nd);
globals->add_subsystem("gps", gps);
const FGAirport* egph = fgFindAirportID("EGPH");
testSetPosition(egph->geod());
// startup the route manager
rm->init();
nd->setBoolValue("serviceable", true);
fgSetBool("/systems/electrical/outputs/gps", true);
gps->init();
SGPropertyNode* scratch = nd->getChild("scratch", 0, true);
SGPropertyNode* wp = nd->getChild("wp", 0, true);
SGPropertyNode* wp1 = wp->getChild("wp", 1, true);
// update a few times
gps->update(0.05);
gps->update(0.05);
gps->update(0.05);
scratch->setStringValue("query", "TL");
scratch->setStringValue("type", "Vor");
scratch->setBoolValue("exact", false);
nd->setStringValue("command", "search");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
// alphanumeric sort, partial matching
nd->setDoubleValue("config/min-runway-length-ft", 5000.0);
scratch->setBoolValue("exact", false);
scratch->setBoolValue("order-by-distance", false);
scratch->setStringValue("query", "KS");
scratch->setStringValue("type", "apt");
nd->setStringValue("command", "search");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
// alphanumeric sort, explicit matching
scratch->setBoolValue("exact", true);
scratch->setBoolValue("order-by-distance", true);
scratch->setStringValue("type", "vor");
scratch->setStringValue("query", "DCS");
nd->setStringValue("command", "search");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
// search on totally missing
scratch->setBoolValue("exact", true);
scratch->setBoolValue("order-by-distance", true);
scratch->setStringValue("query", "FOFOFOFOF");
nd->setStringValue("command", "search");
printScratch(scratch);
// nearest
scratch->setStringValue("type", "apt");
scratch->setIntValue("max-results", 10);
nd->setStringValue("command", "nearest");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
// direct to
nd->setStringValue("command", "direct");
SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
<< wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
<< " " << wp1->getDoubleValue("latitude-deg"));
// OBS mode
scratch->setStringValue("query", "UW");
scratch->setBoolValue("order-by-distance", true);
nd->setStringValue("command", "search");
printScratch(scratch);
nd->setStringValue("command", "obs");
SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
<< wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
<< " " << wp1->getDoubleValue("latitude-deg"));
// load route waypoints
createDummyRoute(rm);
scratch->setIntValue("route-index", 5);
nd->setStringValue("command", "load-route-wpt");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
nd->setStringValue("command", "next");
printScratch(scratch);
scratch->setIntValue("route-index", 2);
nd->setStringValue("command", "load-route-wpt");
nd->setStringValue("command", "direct");
SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
<< wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
<< " " << wp1->getDoubleValue("latitude-deg"));
// route editing
SGGeod pos = egph->geod();
scratch->setStringValue("ident", "FOOBAR");
scratch->setDoubleValue("longitude-deg", pos.getLongitudeDeg());
scratch->setDoubleValue("latitude-deg", pos.getLatitudeDeg());
nd->setStringValue("command", "define-user-wpt");
printScratch(scratch);
// airways
FGPositioned::TypeFilter vorFilt(FGPositioned::VOR);
FGPositionedRef tla = FGPositioned::findClosestWithIdent("TLA", pos, &vorFilt);
FGPositionedRef big = FGPositioned::findClosestWithIdent("BIG", pos, &vorFilt);
FGPositionedRef pol = FGPositioned::findClosestWithIdent("POL", pos, &vorFilt);
const FGAirport* eddm = fgFindAirportID("EDDM");
FGPositionedRef mun = FGPositioned::findClosestWithIdent("MUN",
eddm->geod(), &vorFilt);
const FGAirport* ksfo = fgFindAirportID("KSFO");
FGPositionedRef sfo = FGPositioned::findClosestWithIdent("SFO",
ksfo->geod(), &vorFilt);
WayptRef awy1 = new NavaidWaypoint(tla, NULL);
WayptRef awy2 = new NavaidWaypoint(big, NULL);
WayptRef awy3 = new NavaidWaypoint(pol, NULL);
WayptRef awy4 = new NavaidWaypoint(mun, NULL);
WayptRef awy5 = new NavaidWaypoint(sfo, NULL);
WayptRef awy6 = new NavaidWaypoint(
(FGPositioned*) fgFindAirportID("KJFK"), NULL);
SGPath p("/Users/jmt/Desktop/airways.kml");
sg_ofstream f;
f.open(p, fstream::out | fstream::trunc);
// pre-amble
f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
"<Document>\n";
WayptVec route;
Airway::highLevel()->route(awy1, awy3, route);
Route::dumpRouteToLineString("egph-egcc", route, f);
Airway::lowLevel()->route(awy1, awy2, route);
Route::dumpRouteToLineString("egph-big", route, f);
Airway::lowLevel()->route(awy2, awy4, route);
Route::dumpRouteToLineString("big-mun", route, f);
Airway::highLevel()->route(awy4, awy5, route);
Route::dumpRouteToLineString("mun-sfo", route, f);
Airway::lowLevel()->route(awy5, awy6, route);
Route::dumpRouteToLineString("sfo-jfk", route, f);
// post-amble
f << "</Document>\n"
"</kml>" << endl;
f.close();
// procedures
SGPath op("/Users/jmt/Desktop/procedures.kml");
f.open(op, fstream::out | fstream::trunc);
FGAirport* eham = (FGAirport*) fgFindAirportID("EHAM");
FGPositioned::TypeFilter fixFilt(FGPositioned::FIX);
WayptVec approach;
FGPositionedRef redfa = FGPositioned::findClosestWithIdent("REDFA",
eham->geod(), &fixFilt);
bool ok = eham->buildApproach(new NavaidWaypoint(redfa, NULL),
eham->getRunwayByIdent("18R"), approach);
if (!ok ) {
SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
}
FGAirport* egll = (FGAirport*) fgFindAirportID("EGLL");
WayptVec approach2;
ok = egll->buildApproach(new NavaidWaypoint(big, NULL),
egll->getRunwayByIdent("27R"), approach2);
if (!ok ) {
SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
}
// pre-amble
f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
"<Document>\n";
Route::dumpRouteToLineString("REDFA 18R", approach, f);
Route::dumpRouteToLineString("EGLL 27R", approach2, f);
// post-amble
f << "</Document>\n"
"</kml>" << endl;
f.close();
}

View File

@@ -0,0 +1,48 @@
/*
* 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_GPS_SYSTEM_TESTS_HXX
#define _FG_GPS_SYSTEM_TESTS_HXX
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestFixture.h>
// The system tests.
class GPSTests : public CppUnit::TestFixture
{
// Set up the test suite.
CPPUNIT_TEST_SUITE(GPSTests);
CPPUNIT_TEST(testGPS);
CPPUNIT_TEST_SUITE_END();
public:
// Set up function for each test.
void setUp();
// Clean up after each test.
void tearDown();
// The tests.
void testGPS();
};
#endif // _FG_GPS_SYSTEM_TESTS_HXX

View File

@@ -0,0 +1,12 @@
set(TESTSUITE_SOURCES
${TESTSUITE_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
${CMAKE_CURRENT_SOURCE_DIR}/testOptions.cxx
PARENT_SCOPE
)
set(TESTSUITE_HEADERS
${TESTSUITE_HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/testOptions.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 "testOptions.hxx"
// Set up the unit tests.
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(OptionsTests, "System tests");

View File

@@ -0,0 +1,171 @@
// Written by James Turner, started 2017.
//
// Copyright (C) 2017 James Turner
//
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "testOptions.hxx"
#include "config.h"
#include <chrono>
#include <thread>
#include "test_suite/FGTestApi/NavDataCache.hxx"
#include "test_suite/FGTestApi/scene_graph.hxx"
#include "test_suite/FGTestApi/testGlobals.hxx"
#include <simgear/package/Root.hxx>
#include <simgear/props/props_io.hxx>
#include "Main/fg_props.hxx"
#include "Main/globals.hxx"
#include "Main/options.hxx"
#include <Main/fg_init.hxx>
using namespace std::string_literals;
using namespace flightgear;
using namespace simgear::pkg;
void OptionsTests::setUp()
{
FGTestApi::setUp::initTestGlobals("options");
FGTestApi::setUp::initNavDataCache();
Options::reset();
fgLoadProps("defaults.xml", globals->get_props());
}
void OptionsTests::tearDown()
{
FGTestApi::tearDown::shutdownTestGlobals();
}
void OptionsTests::testLoadDefaultAircraft()
{
const auto customFGAircraftPath = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "customAircraftDir";
{
Options* opts = Options::sharedInstance();
opts->setShouldLoadDefaultConfig(false);
const string fgAircraftArg = "--fg-aircraft=" + customFGAircraftPath.utf8Str();
const char* args[] = {"dummypath", fgAircraftArg.c_str()};
opts->init(2, (char**)args, SGPath());
opts->processOptions();
}
fgInitAircraftPaths(false);
fgInitAircraft(false, false);
CPPUNIT_ASSERT_EQUAL("c172p"s, string{fgGetString("/sim/aircraft")});
CPPUNIT_ASSERT_EQUAL("c172p"s, string{fgGetString("/sim/aircraft-id")});
//CPPUNIT_ASSERT_EQUAL(adPath.utf8Str(), string{fgGetString("/sim/aircraft-dir")});
}
void OptionsTests::testOptionAircraftWithAircraftDir()
{
const auto adPath = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "customAircraftDir" / "overrideUfo";
{
Options* opts = Options::sharedInstance();
opts->setShouldLoadDefaultConfig(false);
const string aircraftDirArg = "--aircraft-dir=" + adPath.utf8Str();
const char* args[] = {"dummypath", "--aircraft=ufo", aircraftDirArg.c_str()};
opts->init(3, (char**)args, SGPath());
opts->processOptions();
}
fgInitAircraftPaths(false);
fgInitAircraft(false, false);
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft")});
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft-id")});
CPPUNIT_ASSERT_EQUAL(adPath.utf8Str(), string{fgGetString("/sim/aircraft-dir")});
}
void OptionsTests::testOptionAircraftWithFGAircraft()
{
const auto customFGAircraftPath = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "customAircraftDir";
{
Options* opts = Options::sharedInstance();
opts->setShouldLoadDefaultConfig(false);
const string fgAircraftArg = "--fg-aircraft=" + customFGAircraftPath.utf8Str();
const char* args[] = {"dummypath", "--aircraft=ufo", fgAircraftArg.c_str()};
opts->init(3, (char**)args, SGPath());
opts->processOptions();
}
fgInitAircraftPaths(false);
fgInitAircraft(false, false);
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft")});
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft-id")});
const auto correctDir = (customFGAircraftPath / "overrideUfo").utf8Str();
CPPUNIT_ASSERT_EQUAL(correctDir, string{fgGetString("/sim/aircraft-dir")});
}
void OptionsTests::testOptionAircraftUnqualified()
{
const auto packageAircraftDir = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "dummy_package_root";
SGSharedPtr<Root> pkgRoot(new Root(packageAircraftDir, FLIGHTGEAR_VERSION));
globals->setPackageRoot(pkgRoot);
{
Options* opts = Options::sharedInstance();
opts->setShouldLoadDefaultConfig(false);
const char* args[] = {"dummypath", "--aircraft=bob"};
opts->init(2, (char**)args, SGPath());
opts->processOptions();
}
fgInitAircraftPaths(false);
fgInitAircraft(false, false);
CPPUNIT_ASSERT_EQUAL("bob"s, string{fgGetString("/sim/aircraft")});
CPPUNIT_ASSERT_EQUAL("org.fg.test.catalog1.bob"s, string{fgGetString("/sim/aircraft-id")});
const auto correctDir = (packageAircraftDir / "org.fg.test.catalog1" / "Aircraft" / "bobCraft").utf8Str();
CPPUNIT_ASSERT_EQUAL(correctDir, string{fgGetString("/sim/aircraft-dir")});
}
void OptionsTests::testOptionAircraftFullyQualified()
{
const auto packageAircraftDir = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "dummy_package_root";
SGSharedPtr<Root> pkgRoot(new Root(packageAircraftDir, FLIGHTGEAR_VERSION));
globals->setPackageRoot(pkgRoot);
{
Options* opts = Options::sharedInstance();
opts->setShouldLoadDefaultConfig(false);
const char* args[] = {"dummypath", "--aircraft=org.fg.test.catalog1.bob"};
opts->init(2, (char**)args, SGPath());
opts->processOptions();
}
fgInitAircraftPaths(false);
fgInitAircraft(false, false);
CPPUNIT_ASSERT_EQUAL("bob"s, string{fgGetString("/sim/aircraft")});
CPPUNIT_ASSERT_EQUAL("org.fg.test.catalog1.bob"s, string{fgGetString("/sim/aircraft-id")});
const auto correctDir = (packageAircraftDir / "org.fg.test.catalog1" / "Aircraft" / "bobCraft").utf8Str();
CPPUNIT_ASSERT_EQUAL(correctDir, string{fgGetString("/sim/aircraft-dir")});
}

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/>.
*/
#pragma once
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
// The system tests.
class OptionsTests : public CppUnit::TestFixture
{
// Set up the test suite.
CPPUNIT_TEST_SUITE(OptionsTests);
CPPUNIT_TEST(testLoadDefaultAircraft);
CPPUNIT_TEST(testOptionAircraftWithAircraftDir);
CPPUNIT_TEST(testOptionAircraftUnqualified);
CPPUNIT_TEST(testOptionAircraftFullyQualified);
CPPUNIT_TEST(testOptionAircraftWithFGAircraft);
CPPUNIT_TEST_SUITE_END();
public:
// Set up function for each test.
void setUp();
// Clean up after each test.
void tearDown();
// The tests.
void testOptionAircraftWithAircraftDir();
void testOptionAircraftUnqualified();
void testOptionAircraftFullyQualified();
void testOptionAircraftWithFGAircraft();
void testLoadDefaultAircraft();
};

View File

@@ -0,0 +1,12 @@
set(TESTSUITE_SOURCES
${TESTSUITE_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
#${CMAKE_CURRENT_SOURCE_DIR}/testnavs.cxx
PARENT_SCOPE
)
set(TESTSUITE_HEADERS
${TESTSUITE_HEADERS}
#${CMAKE_CURRENT_SOURCE_DIR}/testnavs.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 "testnavs.hxx"
// Set up the unit tests.
//CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(NavaidsTests, "System tests");

View File

@@ -0,0 +1,107 @@
// Written by James Turner, started 2009.
//
// Copyright (C) 2009 Curtis L. Olson
//
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <iostream>
#include <simgear/misc/sg_path.hxx>
#include <Navaids/fixlist.hxx>
//#include "ilslist.hxx"
#include <Navaids/navlist.hxx>
//#include "mkrbeacons.hxx"
#include "test_suite/dataStore.hxx"
#include "testnavs.hxx"
void NavaidsTests::testNavs()
{
double heading, dist;
DataStore &data = DataStore::get();
FGNavList *current_navlist = new FGNavList;
SGPath p_nav = data.getFGRoot() / "/Navaids/default.nav";
current_navlist->init( p_nav );
FGNavRecord *n;
if ( (n = current_navlist->findByFreq( -93.2 * SG_DEGREES_TO_RADIANS,
45.14 * SG_DEGREES_TO_RADIANS,
3000, 117.30)) != NULL )
{
std::cout << "Found a vor station in range" << std::endl;
std::cout << " id = " << n->get_ident() << std::endl;
} else {
std::cout << "not picking up vor. :-(" << std::endl;
}
FGNavRecord *dcs;
if ( (dcs = current_navlist->findByIdent( "DCS",
-3.3 * SG_DEGREES_TO_RADIANS,
55.9 * SG_DEGREES_TO_RADIANS))
!= NULL ) {
std::cout << "Found DCS by ident" << std::endl;
if (dcs->get_freq() != 11520)
std::cout << "Frequency for DCS VOR is wrong (should be 115.20), it's "
<< dcs->get_freq() << std::endl;
} else {
std::cout << "couldn't locate DCS (Dean-Cross) VOR" << std::endl;
}
// we have to init the marker beacon storage before we parse the ILS file
FGMarkerBeacons *current_beacons = new FGMarkerBeacons;
current_beacons->init();
FGILSList *current_ilslist = new FGILSList;
SGPath p_ils = data.getFGRoot() / "/Navaids/default.ils";
current_ilslist->init( p_ils );
FGILS *i = current_ilslist->findByFreq( -93.1 * SG_DEGREES_TO_RADIANS,
45.24 * SG_DEGREES_TO_RADIANS,
3000, 110.30);
if ( i != NULL ) {
std::cout << "Found an ils station in range" << std::endl;
std::cout << " apt = " << i->get_aptcode() << std::endl;
std::cout << " rwy = " << i->get_rwyno() << std::endl;
} else {
std::cout << "not picking up ils. :-(" << std::endl;
}
FGFixList *current_fixlist = new FGFixList;
SGPath p_fix = data.getFGRoot() / "/Navaids/default.fix";
current_fixlist->init( p_fix );
FGFix fix;
// attempting to get the position relative to the OTR VOR; heading
// should be 108 degrees, distance 74nm (according to my SimCharts
// v1.5)
if ( current_fixlist->query_and_offset( "DOGGA",
-0.103 * SG_DEGREES_TO_RADIANS,
53.698 * SG_DEGREES_TO_RADIANS,
3000, &fix, &heading, &dist) )
{
std::cout << "Found a matching fix" << std::endl;
std::cout << " id = " << fix.get_ident() << std::endl;
std::cout << " heading = " << heading << " dist = " << dist * SG_METER_TO_NM
<< std::endl;
} else {
CPPUNIT_FAIL("did not find fix. :-(");
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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_NAVAIDS_SYSTEM_TESTS_HXX
#define _FG_NAVAIDS_SYSTEM_TESTS_HXX
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestFixture.h>
// The system tests.
class NavaidsTests : public CppUnit::TestFixture
{
// Set up the test suite.
CPPUNIT_TEST_SUITE(NavaidsTests);
CPPUNIT_TEST(testNavs);
CPPUNIT_TEST_SUITE_END();
public:
// Set up function for each test.
void setUp() {}
// Clean up after each test.
void tearDown() {}
// The tests.
void testNavs();
};
#endif // _FG_NAVAIDS_SYSTEM_TESTS_HXX