Intercept errors in the matrix inversion routine and report the faulty aircraft in the log.
This commit is contained in:
parent
3441c5ef3a
commit
83cad5797e
6 changed files with 24 additions and 8 deletions
|
@ -47,7 +47,8 @@ void AIWakeGroup::AddAI(FGAIAircraft* ai)
|
||||||
if (_aiWakeData.find(id) == _aiWakeData.end()) {
|
if (_aiWakeData.find(id) == _aiWakeData.end()) {
|
||||||
double span = perfData->wingSpan();
|
double span = perfData->wingSpan();
|
||||||
double chord = perfData->wingChord();
|
double chord = perfData->wingChord();
|
||||||
_aiWakeData[id] = AIWakeData(new WakeMesh(span, chord));
|
_aiWakeData[id] = AIWakeData(new WakeMesh(span, chord,
|
||||||
|
std::string("AI:") + ai->_getName()));
|
||||||
|
|
||||||
SG_LOG(SG_FLIGHT, SG_DEV_ALERT,
|
SG_LOG(SG_FLIGHT, SG_DEV_ALERT,
|
||||||
"Created mesh for " << ai->_getName() << " ID: #" << id);
|
"Created mesh for " << ai->_getName() << " ID: #" << id);
|
||||||
|
|
|
@ -37,8 +37,8 @@ extern "C" {
|
||||||
#include "../LaRCsim/ls_matrix.h"
|
#include "../LaRCsim/ls_matrix.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
AircraftMesh::AircraftMesh(double _span, double _chord)
|
AircraftMesh::AircraftMesh(double _span, double _chord, const std::string& name)
|
||||||
: WakeMesh(_span, _chord)
|
: WakeMesh(_span, _chord, name)
|
||||||
{
|
{
|
||||||
collPt.resize(nelm, SGVec3d::zeros());
|
collPt.resize(nelm, SGVec3d::zeros());
|
||||||
midPt.resize(nelm, SGVec3d::zeros());
|
midPt.resize(nelm, SGVec3d::zeros());
|
||||||
|
|
|
@ -32,7 +32,7 @@ class AIWakeGroup;
|
||||||
|
|
||||||
class AircraftMesh : public WakeMesh {
|
class AircraftMesh : public WakeMesh {
|
||||||
public:
|
public:
|
||||||
AircraftMesh(double _span, double _chord);
|
AircraftMesh(double _span, double _chord, const std::string& name);
|
||||||
void setPosition(const SGVec3d& pos, const SGQuatd& orient);
|
void setPosition(const SGVec3d& pos, const SGQuatd& orient);
|
||||||
SGVec3d GetForce(const AIWakeGroup& wg, const SGVec3d& vel, double rho);
|
SGVec3d GetForce(const AIWakeGroup& wg, const SGVec3d& vel, double rho);
|
||||||
const SGVec3d& GetMoment(void) const { return moment; };
|
const SGVec3d& GetMoment(void) const { return moment; };
|
||||||
|
|
|
@ -25,13 +25,14 @@
|
||||||
|
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
#include <simgear/math/SGVec3.hxx>
|
#include <simgear/math/SGVec3.hxx>
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
#include "WakeMesh.hxx"
|
#include "WakeMesh.hxx"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "../LaRCsim/ls_matrix.h"
|
#include "../LaRCsim/ls_matrix.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
WakeMesh::WakeMesh(double _span, double _chord)
|
WakeMesh::WakeMesh(double _span, double _chord, const std::string& aircraft_name)
|
||||||
: nelm(10), span(_span), chord(_chord)
|
: nelm(10), span(_span), chord(_chord)
|
||||||
{
|
{
|
||||||
double y1 = -0.5*span;
|
double y1 = -0.5*span;
|
||||||
|
@ -59,7 +60,20 @@ WakeMesh::WakeMesh(double _span, double _chord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the inverse matrix with the Gauss-Jordan algorithm
|
// Compute the inverse matrix with the Gauss-Jordan algorithm
|
||||||
nr_gaussj(influenceMtx, nelm, 0, 0);
|
int ret = nr_gaussj(influenceMtx, nelm, nullptr, 0);
|
||||||
|
if (ret) {
|
||||||
|
// Something went wrong with the matrix inversion.
|
||||||
|
|
||||||
|
// 1. Nullify the influence matrix to disable the current aircraft wake.
|
||||||
|
for (int i=0; i < nelm; ++i) {
|
||||||
|
for (int j=0; j < nelm; ++j)
|
||||||
|
influenceMtx[i+1][j+1] = 0.0;
|
||||||
|
}
|
||||||
|
// 2. Report the issue in the log.
|
||||||
|
SG_LOG(SG_FLIGHT, SG_WARN,
|
||||||
|
"Failed to build wake mesh. " << aircraft_name << " ( span:"
|
||||||
|
<< _span << ", chord:" << _chord << ") wake will be ignored.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WakeMesh::~WakeMesh()
|
WakeMesh::~WakeMesh()
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace FGTestApi { namespace PrivateAccessor { namespace FDM { class Accessor
|
||||||
|
|
||||||
class WakeMesh : public SGReferenced {
|
class WakeMesh : public SGReferenced {
|
||||||
public:
|
public:
|
||||||
WakeMesh(double _span, double _chord);
|
WakeMesh(double _span, double _chord, const std::string& aircraft_name);
|
||||||
virtual ~WakeMesh();
|
virtual ~WakeMesh();
|
||||||
double computeAoA(double vel, double rho, double weight);
|
double computeAoA(double vel, double rho, double weight);
|
||||||
SGVec3d getInducedVelocityAt(const SGVec3d& at) const;
|
SGVec3d getInducedVelocityAt(const SGVec3d& at) const;
|
||||||
|
|
|
@ -367,7 +367,8 @@ FGJSBsim::FGJSBsim( double dt )
|
||||||
crashed = false;
|
crashed = false;
|
||||||
|
|
||||||
mesh = new AircraftMesh(fgGetDouble("/fdm/jsbsim/metrics/bw-ft"),
|
mesh = new AircraftMesh(fgGetDouble("/fdm/jsbsim/metrics/bw-ft"),
|
||||||
fgGetDouble("/fdm/jsbsim/metrics/cbarw-ft"));
|
fgGetDouble("/fdm/jsbsim/metrics/cbarw-ft"),
|
||||||
|
fdmex->GetModelName());
|
||||||
|
|
||||||
// Trim once to initialize all output parameters
|
// Trim once to initialize all output parameters
|
||||||
FGTrim *fgtrim = new FGTrim(fdmex,tFull);
|
FGTrim *fgtrim = new FGTrim(fdmex,tFull);
|
||||||
|
|
Loading…
Reference in a new issue