Sync. with JSBSim (CVS) again
This commit is contained in:
parent
d9d725f28d
commit
f220feb684
7 changed files with 460 additions and 39 deletions
|
@ -349,9 +349,9 @@ protected:
|
||||||
static int phase = 0;
|
static int phase = 0;
|
||||||
double X;
|
double X;
|
||||||
|
|
||||||
V1 = V2 = S = X = 0.0;
|
|
||||||
|
|
||||||
if (phase == 0) {
|
if (phase == 0) {
|
||||||
|
V1 = V2 = S = X = 0.0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
double U1 = (double)rand() / RAND_MAX;
|
double U1 = (double)rand() / RAND_MAX;
|
||||||
double U2 = (double)rand() / RAND_MAX;
|
double U2 = (double)rand() / RAND_MAX;
|
||||||
|
|
|
@ -82,8 +82,8 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
|
||||||
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
|
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
|
||||||
// SetTurbType( ttCulp );
|
// SetTurbType( ttCulp );
|
||||||
SetTurbType( ttNone );
|
SetTurbType( ttNone );
|
||||||
TurbGain = 0.0;
|
TurbGain = 1.0;
|
||||||
TurbRate = 1.7;
|
TurbRate = 10.0;
|
||||||
Rhythmicity = 0.1;
|
Rhythmicity = 0.1;
|
||||||
spike = target_time = strength = 0.0;
|
spike = target_time = strength = 0.0;
|
||||||
wind_from_clockwise = 0.0;
|
wind_from_clockwise = 0.0;
|
||||||
|
@ -375,9 +375,11 @@ void FGAtmosphere::SetWindPsi(double dir)
|
||||||
|
|
||||||
void FGAtmosphere::Turbulence(void)
|
void FGAtmosphere::Turbulence(void)
|
||||||
{
|
{
|
||||||
|
double DeltaT = rate*State->Getdt();
|
||||||
|
|
||||||
switch (turbType) {
|
switch (turbType) {
|
||||||
case ttStandard: {
|
case ttStandard: {
|
||||||
TurbGain = TurbGain * TurbGain * 100.0;
|
// TurbGain = TurbGain * TurbGain * 100.0; // what is this!?
|
||||||
|
|
||||||
vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
|
vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
|
||||||
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
|
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
|
||||||
|
@ -388,8 +390,8 @@ void FGAtmosphere::Turbulence(void)
|
||||||
// away from the peaks
|
// away from the peaks
|
||||||
MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
|
MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
|
||||||
(1 + fabs(Magnitude)));
|
(1 + fabs(Magnitude)));
|
||||||
MagnitudeAccel += MagnitudedAccelDt*rate*TurbRate*State->Getdt();
|
MagnitudeAccel += MagnitudedAccelDt*TurbRate*DeltaT;
|
||||||
Magnitude += MagnitudeAccel*rate*State->Getdt();
|
Magnitude += MagnitudeAccel*DeltaT;
|
||||||
Magnitude = fabs(Magnitude);
|
Magnitude = fabs(Magnitude);
|
||||||
|
|
||||||
vDirectiondAccelDt.Normalize();
|
vDirectiondAccelDt.Normalize();
|
||||||
|
@ -398,9 +400,9 @@ void FGAtmosphere::Turbulence(void)
|
||||||
vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX));
|
vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX));
|
||||||
vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY));
|
vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY));
|
||||||
|
|
||||||
vDirectionAccel += vDirectiondAccelDt*rate*TurbRate*State->Getdt();
|
vDirectionAccel += vDirectiondAccelDt*TurbRate*DeltaT;
|
||||||
vDirectionAccel.Normalize();
|
vDirectionAccel.Normalize();
|
||||||
vDirection += vDirectionAccel*rate*State->Getdt();
|
vDirection += vDirectionAccel*DeltaT;
|
||||||
|
|
||||||
vDirection.Normalize();
|
vDirection.Normalize();
|
||||||
|
|
||||||
|
@ -449,42 +451,37 @@ void FGAtmosphere::Turbulence(void)
|
||||||
}
|
}
|
||||||
case ttBerndt: { // This is very experimental and incomplete at the moment.
|
case ttBerndt: { // This is very experimental and incomplete at the moment.
|
||||||
|
|
||||||
TurbGain = TurbGain * TurbGain * 100.0;
|
vDirectiondAccelDt(eX) = GaussianRandomNumber();
|
||||||
|
vDirectiondAccelDt(eY) = GaussianRandomNumber();
|
||||||
vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
|
vDirectiondAccelDt(eZ) = GaussianRandomNumber();
|
||||||
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
|
|
||||||
vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
|
|
||||||
|
|
||||||
|
MagnitudedAccelDt = GaussianRandomNumber();
|
||||||
MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
|
MagnitudeAccel += MagnitudedAccelDt * DeltaT;
|
||||||
MagnitudeAccel += MagnitudedAccelDt*rate*State->Getdt();
|
Magnitude += MagnitudeAccel * DeltaT;
|
||||||
Magnitude += MagnitudeAccel*rate*State->Getdt();
|
|
||||||
|
|
||||||
vDirectiondAccelDt.Normalize();
|
vDirectiondAccelDt.Normalize();
|
||||||
vDirectionAccel += vDirectiondAccelDt*rate*State->Getdt();
|
vDirectionAccel += TurbRate * vDirectiondAccelDt * DeltaT;
|
||||||
vDirectionAccel.Normalize();
|
vDirectionAccel.Normalize();
|
||||||
vDirection += vDirectionAccel*rate*State->Getdt();
|
vDirection += vDirectionAccel*DeltaT;
|
||||||
|
|
||||||
// Diminish z-vector within two wingspans
|
// Diminish z-vector within two wingspans of the ground
|
||||||
// of the ground
|
|
||||||
double HOverBMAC = Auxiliary->GetHOverBMAC();
|
double HOverBMAC = Auxiliary->GetHOverBMAC();
|
||||||
if (HOverBMAC < 2.0)
|
if (HOverBMAC < 2.0) vDirection(eZ) *= HOverBMAC / 2.0;
|
||||||
vDirection(eZ) *= HOverBMAC / 2.0;
|
|
||||||
|
|
||||||
vDirection.Normalize();
|
vDirection.Normalize();
|
||||||
|
|
||||||
vTurbulenceNED = TurbGain*Magnitude * vDirection;
|
vTurbulenceNED = TurbGain*Magnitude * vDirection;
|
||||||
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
|
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
|
||||||
|
|
||||||
vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
|
vBodyTurbGrad = Propagate->GetTl2b() * vTurbulenceGrad;
|
||||||
vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
|
vTurbPQR(eP) = vBodyTurbGrad(eY) / Aircraft->GetWingSpan();
|
||||||
if (Aircraft->GetHTailArm() > 0)
|
if (Aircraft->GetHTailArm() > 0)
|
||||||
vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
|
vTurbPQR(eQ) = vBodyTurbGrad(eZ) / Aircraft->GetHTailArm();
|
||||||
else
|
else
|
||||||
vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
|
vTurbPQR(eQ) = vBodyTurbGrad(eZ) / 10.0;
|
||||||
|
|
||||||
if (Aircraft->GetVTailArm() > 0)
|
if (Aircraft->GetVTailArm() > 0)
|
||||||
vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
|
vTurbPQR(eR) = vBodyTurbGrad(eX) / Aircraft->GetVTailArm();
|
||||||
else
|
else
|
||||||
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
|
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
|
||||||
|
|
||||||
|
@ -571,7 +568,9 @@ void FGAtmosphere::bind(void)
|
||||||
{
|
{
|
||||||
typedef double (FGAtmosphere::*PMF)(int) const;
|
typedef double (FGAtmosphere::*PMF)(int) const;
|
||||||
typedef double (FGAtmosphere::*PMFv)(void) const;
|
typedef double (FGAtmosphere::*PMFv)(void) const;
|
||||||
|
typedef int (FGAtmosphere::*PMFt)(void) const;
|
||||||
typedef void (FGAtmosphere::*PMFd)(int,double);
|
typedef void (FGAtmosphere::*PMFd)(int,double);
|
||||||
|
typedef void (FGAtmosphere::*PMFi)(int);
|
||||||
PropertyManager->Tie("atmosphere/T-R", this, (PMFv)&FGAtmosphere::GetTemperature);
|
PropertyManager->Tie("atmosphere/T-R", this, (PMFv)&FGAtmosphere::GetTemperature);
|
||||||
PropertyManager->Tie("atmosphere/rho-slugs_ft3", this, (PMFv)&FGAtmosphere::GetDensity);
|
PropertyManager->Tie("atmosphere/rho-slugs_ft3", this, (PMFv)&FGAtmosphere::GetDensity);
|
||||||
PropertyManager->Tie("atmosphere/P-psf", this, (PMFv)&FGAtmosphere::GetPressure);
|
PropertyManager->Tie("atmosphere/P-psf", this, (PMFv)&FGAtmosphere::GetPressure);
|
||||||
|
@ -608,9 +607,17 @@ void FGAtmosphere::bind(void)
|
||||||
PropertyManager->Tie("atmosphere/gust-down-fps", this, eDown, (PMF)&FGAtmosphere::GetGustNED,
|
PropertyManager->Tie("atmosphere/gust-down-fps", this, eDown, (PMF)&FGAtmosphere::GetGustNED,
|
||||||
(PMFd)&FGAtmosphere::SetGustNED);
|
(PMFd)&FGAtmosphere::SetGustNED);
|
||||||
|
|
||||||
|
PropertyManager->Tie("atmosphere/turb-north-fps", this, eNorth, (PMF)&FGAtmosphere::GetTurbNED,
|
||||||
|
(PMFd)&FGAtmosphere::SetTurbNED);
|
||||||
|
PropertyManager->Tie("atmosphere/turb-east-fps", this, eEast, (PMF)&FGAtmosphere::GetTurbNED,
|
||||||
|
(PMFd)&FGAtmosphere::SetTurbNED);
|
||||||
|
PropertyManager->Tie("atmosphere/turb-down-fps", this, eDown, (PMF)&FGAtmosphere::GetTurbNED,
|
||||||
|
(PMFd)&FGAtmosphere::SetTurbNED);
|
||||||
|
|
||||||
PropertyManager->Tie("atmosphere/p-turb-rad_sec", this,1, (PMF)&FGAtmosphere::GetTurbPQR);
|
PropertyManager->Tie("atmosphere/p-turb-rad_sec", this,1, (PMF)&FGAtmosphere::GetTurbPQR);
|
||||||
PropertyManager->Tie("atmosphere/q-turb-rad_sec", this,2, (PMF)&FGAtmosphere::GetTurbPQR);
|
PropertyManager->Tie("atmosphere/q-turb-rad_sec", this,2, (PMF)&FGAtmosphere::GetTurbPQR);
|
||||||
PropertyManager->Tie("atmosphere/r-turb-rad_sec", this,3, (PMF)&FGAtmosphere::GetTurbPQR);
|
PropertyManager->Tie("atmosphere/r-turb-rad_sec", this,3, (PMF)&FGAtmosphere::GetTurbPQR);
|
||||||
|
PropertyManager->Tie("atmosphere/turb-type", this, (PMFt)&FGAtmosphere::GetTurbType, (PMFi)&FGAtmosphere::SetTurbType);
|
||||||
PropertyManager->Tie("atmosphere/turb-rate", this, &FGAtmosphere::GetTurbRate, &FGAtmosphere::SetTurbRate);
|
PropertyManager->Tie("atmosphere/turb-rate", this, &FGAtmosphere::GetTurbRate, &FGAtmosphere::SetTurbRate);
|
||||||
PropertyManager->Tie("atmosphere/turb-gain", this, &FGAtmosphere::GetTurbGain, &FGAtmosphere::SetTurbGain);
|
PropertyManager->Tie("atmosphere/turb-gain", this, &FGAtmosphere::GetTurbGain, &FGAtmosphere::SetTurbGain);
|
||||||
PropertyManager->Tie("atmosphere/turb-rhythmicity", this, &FGAtmosphere::GetRhythmicity,
|
PropertyManager->Tie("atmosphere/turb-rhythmicity", this, &FGAtmosphere::GetRhythmicity,
|
||||||
|
|
|
@ -83,7 +83,7 @@ public:
|
||||||
@return false if no error */
|
@return false if no error */
|
||||||
bool Run(void);
|
bool Run(void);
|
||||||
bool InitModel(void);
|
bool InitModel(void);
|
||||||
enum tType {ttStandard, ttBerndt, ttCulp, ttNone} turbType;
|
enum tType {ttNone, ttStandard, ttBerndt, ttCulp} turbType;
|
||||||
|
|
||||||
/// Returns the temperature in degrees Rankine.
|
/// Returns the temperature in degrees Rankine.
|
||||||
double GetTemperature(void) const {return *temperature;}
|
double GetTemperature(void) const {return *temperature;}
|
||||||
|
@ -194,16 +194,22 @@ public:
|
||||||
/// Sets a gust component in NED frame.
|
/// Sets a gust component in NED frame.
|
||||||
void SetGustNED(int idx, double gust) { vGustNED(idx)=gust;}
|
void SetGustNED(int idx, double gust) { vGustNED(idx)=gust;}
|
||||||
|
|
||||||
|
/// Sets a turbulence component in NED frame.
|
||||||
|
void SetTurbNED(int idx, double turb) { vTurbulenceNED(idx)=turb;}
|
||||||
|
|
||||||
/// Sets the gust components in NED frame.
|
/// Sets the gust components in NED frame.
|
||||||
void SetGustNED(double gN, double gE, double gD) { vGustNED(eNorth)=gN; vGustNED(eEast)=gE; vGustNED(eDown)=gD;}
|
void SetGustNED(double gN, double gE, double gD) { vGustNED(eNorth)=gN; vGustNED(eEast)=gE; vGustNED(eDown)=gD;}
|
||||||
|
|
||||||
/// Retrieves a gust component in NED frame.
|
/// Retrieves a gust component in NED frame.
|
||||||
double GetGustNED(int idx) const {return vGustNED(idx);}
|
double GetGustNED(int idx) const {return vGustNED(idx);}
|
||||||
|
|
||||||
|
/// Retrieves a turbulence component in NED frame.
|
||||||
|
double GetTurbNED(int idx) const {return vTurbulenceNED(idx);}
|
||||||
|
|
||||||
/// Retrieves the gust components in NED frame.
|
/// Retrieves the gust components in NED frame.
|
||||||
FGColumnVector3& GetGustNED(void) {return vGustNED;}
|
FGColumnVector3& GetGustNED(void) {return vGustNED;}
|
||||||
|
|
||||||
/** Turbulence models available: ttStandard, ttBerndt, ttCulp, ttNone */
|
/** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp */
|
||||||
void SetTurbType(tType tt) {turbType = tt;}
|
void SetTurbType(tType tt) {turbType = tt;}
|
||||||
tType GetTurbType() const {return turbType;}
|
tType GetTurbType() const {return turbType;}
|
||||||
|
|
||||||
|
|
254
src/FDM/JSBSim/models/flight_control/FGMagnetometer.cpp
Executable file
254
src/FDM/JSBSim/models/flight_control/FGMagnetometer.cpp
Executable file
|
@ -0,0 +1,254 @@
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
Module: FGMagnetometer.cpp
|
||||||
|
Author: Matthew Chave
|
||||||
|
Date started: August 2009
|
||||||
|
|
||||||
|
------------- Copyright (C) 2009 -------------
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser 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 Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Further information about the GNU Lesser General Public License can also be found on
|
||||||
|
the world wide web at http://www.gnu.org.
|
||||||
|
|
||||||
|
FUNCTIONAL DESCRIPTION
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
HISTORY
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
COMMENTS, REFERENCES, and NOTES
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
INCLUDES
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
#include "FGMagnetometer.h"
|
||||||
|
#include "simgear/magvar/coremag.hxx"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
namespace JSBSim {
|
||||||
|
|
||||||
|
static const char *IdSrc = "$Id$";
|
||||||
|
static const char *IdHdr = ID_MAGNETOMETER;
|
||||||
|
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
CLASS IMPLEMENTATION
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
|
||||||
|
FGMagnetometer::FGMagnetometer(FGFCS* fcs, Element* element) : FGSensor(fcs, element),\
|
||||||
|
counter(0),
|
||||||
|
INERTIAL_UPDATE_RATE(1000)
|
||||||
|
{
|
||||||
|
Propagate = fcs->GetExec()->GetPropagate();
|
||||||
|
MassBalance = fcs->GetExec()->GetMassBalance();
|
||||||
|
Inertial = fcs->GetExec()->GetInertial();
|
||||||
|
|
||||||
|
Element* location_element = element->FindElement("location");
|
||||||
|
if (location_element) vLocation = location_element->FindElementTripletConvertTo("IN");
|
||||||
|
else {cerr << "No location given for magnetometer. " << endl; exit(-1);}
|
||||||
|
|
||||||
|
vRadius = MassBalance->StructuralToBody(vLocation);
|
||||||
|
|
||||||
|
Element* orient_element = element->FindElement("orientation");
|
||||||
|
if (orient_element) vOrient = orient_element->FindElementTripletConvertTo("RAD");
|
||||||
|
else {cerr << "No orientation given for magnetometer. " << endl;}
|
||||||
|
|
||||||
|
Element* axis_element = element->FindElement("axis");
|
||||||
|
if (axis_element) {
|
||||||
|
string sAxis = element->FindElementValue("axis");
|
||||||
|
if (sAxis == "X" || sAxis == "x") {
|
||||||
|
axis = 1;
|
||||||
|
} else if (sAxis == "Y" || sAxis == "y") {
|
||||||
|
axis = 2;
|
||||||
|
} else if (sAxis == "Z" || sAxis == "z") {
|
||||||
|
axis = 3;
|
||||||
|
} else {
|
||||||
|
cerr << " Incorrect/no axis specified for magnetometer; assuming X axis" << endl;
|
||||||
|
axis = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculateTransformMatrix();
|
||||||
|
|
||||||
|
//assuming date wont significantly change over a flight to affect mag field
|
||||||
|
//would be better to get the date from the sim if its simulated...
|
||||||
|
time_t rawtime;
|
||||||
|
time( &rawtime );
|
||||||
|
tm * ptm = gmtime ( &rawtime );
|
||||||
|
|
||||||
|
int year = ptm->tm_year;
|
||||||
|
if(year>100)
|
||||||
|
{
|
||||||
|
year-= 100;
|
||||||
|
}
|
||||||
|
//the months here are zero based TODO find out if the function expects 1s based
|
||||||
|
date = (yymmdd_to_julian_days(ptm->tm_year,ptm->tm_mon,ptm->tm_mday));//Julian 1950-2049 yy,mm,dd
|
||||||
|
updateInertialMag();
|
||||||
|
|
||||||
|
Debug(0);
|
||||||
|
}
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
FGMagnetometer::~FGMagnetometer()
|
||||||
|
{
|
||||||
|
Debug(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
void FGMagnetometer::updateInertialMag(void)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
if(counter > INERTIAL_UPDATE_RATE)//dont need to update every iteration
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
usedLat = (Propagate->GetGeodLatitudeRad());//radians, N and E lat and long are positive, S and W negative
|
||||||
|
usedLon = (Propagate->GetLongitude());//radians
|
||||||
|
usedAlt = (Propagate->GetGeodeticAltitude()*fttom*0.001);//km
|
||||||
|
|
||||||
|
//this should be done whenever the position changes significantly (in nTesla)
|
||||||
|
double magvar = calc_magvar( usedLat,
|
||||||
|
usedLon,
|
||||||
|
usedAlt,
|
||||||
|
date,
|
||||||
|
field );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
bool FGMagnetometer::Run(void )
|
||||||
|
{
|
||||||
|
// There is no input assumed. This is a dedicated acceleration sensor.
|
||||||
|
|
||||||
|
vRadius = MassBalance->StructuralToBody(vLocation);
|
||||||
|
|
||||||
|
|
||||||
|
updateInertialMag();
|
||||||
|
//Inertial magnetic field rotated to the body frame
|
||||||
|
vMag = Propagate->GetTl2b() * FGColumnVector3(field[3], field[4], field[5]);
|
||||||
|
|
||||||
|
//allow for sensor orientation
|
||||||
|
vMag = mT * vMag;
|
||||||
|
|
||||||
|
Input = vMag(axis);
|
||||||
|
|
||||||
|
Output = Input; // perfect magnetometer
|
||||||
|
|
||||||
|
// Degrade signal as specified
|
||||||
|
|
||||||
|
if (fail_stuck) {
|
||||||
|
Output = PreviousOutput;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lag != 0.0) Lag(); // models magnetometer lag
|
||||||
|
if (noise_variance != 0.0) Noise(); // models noise
|
||||||
|
if (drift_rate != 0.0) Drift(); // models drift over time
|
||||||
|
if (bias != 0.0) Bias(); // models a finite bias
|
||||||
|
if (gain != 0.0) Gain(); // models a gain
|
||||||
|
|
||||||
|
if (fail_low) Output = -HUGE_VAL;
|
||||||
|
if (fail_high) Output = HUGE_VAL;
|
||||||
|
|
||||||
|
if (bits != 0) Quantize(); // models quantization degradation
|
||||||
|
// if (delay != 0.0) Delay(); // models system signal transport latencies
|
||||||
|
|
||||||
|
Clip(); // Is it right to clip an magnetometer?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
void FGMagnetometer::CalculateTransformMatrix(void)
|
||||||
|
{
|
||||||
|
double cp,sp,cr,sr,cy,sy;
|
||||||
|
|
||||||
|
cp=cos(vOrient(ePitch)); sp=sin(vOrient(ePitch));
|
||||||
|
cr=cos(vOrient(eRoll)); sr=sin(vOrient(eRoll));
|
||||||
|
cy=cos(vOrient(eYaw)); sy=sin(vOrient(eYaw));
|
||||||
|
|
||||||
|
|
||||||
|
mT(1,1) = cp*cy;
|
||||||
|
mT(1,2) = cp*sy;
|
||||||
|
mT(1,3) = -sp;
|
||||||
|
|
||||||
|
mT(2,1) = sr*sp*cy - cr*sy;
|
||||||
|
mT(2,2) = sr*sp*sy + cr*cy;
|
||||||
|
mT(2,3) = sr*cp;
|
||||||
|
|
||||||
|
mT(3,1) = cr*sp*cy + sr*sy;
|
||||||
|
mT(3,2) = cr*sp*sy - sr*cy;
|
||||||
|
mT(3,3) = cr*cp;
|
||||||
|
|
||||||
|
|
||||||
|
// This transform is different than for FGForce, where we want a native nozzle
|
||||||
|
// force in body frame. Here we calculate the body frame accel and want it in
|
||||||
|
// the transformed magnetometer frame. So, the next line is commented out.
|
||||||
|
// mT = mT.Inverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
// The bitmasked value choices are as follows:
|
||||||
|
// unset: In this case (the default) JSBSim would only print
|
||||||
|
// out the normally expected messages, essentially echoing
|
||||||
|
// the config files as they are read. If the environment
|
||||||
|
// variable is not set, debug_lvl is set to 1 internally
|
||||||
|
// 0: This requests JSBSim not to output any messages
|
||||||
|
// whatsoever.
|
||||||
|
// 1: This value explicity requests the normal JSBSim
|
||||||
|
// startup messages
|
||||||
|
// 2: This value asks for a message to be printed out when
|
||||||
|
// a class is instantiated
|
||||||
|
// 4: When this value is set, a message is displayed when a
|
||||||
|
// FGModel object executes its Run() method
|
||||||
|
// 8: When this value is set, various runtime state variables
|
||||||
|
// are printed out periodically
|
||||||
|
// 16: When set various parameters are sanity checked and
|
||||||
|
// a message is printed out when they go out of bounds
|
||||||
|
|
||||||
|
void FGMagnetometer::Debug(int from)
|
||||||
|
{
|
||||||
|
string ax[4] = {"none", "X", "Y", "Z"};
|
||||||
|
|
||||||
|
if (debug_lvl <= 0) return;
|
||||||
|
|
||||||
|
if (debug_lvl & 1) { // Standard console startup message output
|
||||||
|
if (from == 0) { // Constructor
|
||||||
|
cout << " Axis: " << ax[axis] << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
|
||||||
|
if (from == 0) cout << "Instantiated: FGMagnetometer" << endl;
|
||||||
|
if (from == 1) cout << "Destroyed: FGMagnetometer" << endl;
|
||||||
|
}
|
||||||
|
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
|
||||||
|
}
|
||||||
|
if (debug_lvl & 8 ) { // Runtime state variables
|
||||||
|
}
|
||||||
|
if (debug_lvl & 16) { // Sanity checking
|
||||||
|
}
|
||||||
|
if (debug_lvl & 64) {
|
||||||
|
if (from == 0) { // Constructor
|
||||||
|
cout << IdSrc << endl;
|
||||||
|
cout << IdHdr << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
152
src/FDM/JSBSim/models/flight_control/FGMagnetometer.h
Executable file
152
src/FDM/JSBSim/models/flight_control/FGMagnetometer.h
Executable file
|
@ -0,0 +1,152 @@
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
Header: FGMagnetometer.h
|
||||||
|
Author: Matthew Chave
|
||||||
|
Date started: August 2009
|
||||||
|
|
||||||
|
------------- Copyright (C) 2009 -------------
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser 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 Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Further information about the GNU Lesser General Public License can also be found on
|
||||||
|
the world wide web at http://www.gnu.org.
|
||||||
|
|
||||||
|
HISTORY
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
SENTRY
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
#ifndef FGMAGNETOMETER_H
|
||||||
|
#define FGMAGNETOMETER_H
|
||||||
|
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
INCLUDES
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
#include "FGSensor.h"
|
||||||
|
#include <input_output/FGXMLElement.h>
|
||||||
|
#include "models/FGPropagate.h"
|
||||||
|
#include "models/FGMassBalance.h"
|
||||||
|
#include "models/FGInertial.h"
|
||||||
|
#include "math/FGColumnVector3.h"
|
||||||
|
#include "math/FGMatrix33.h"
|
||||||
|
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
DEFINITIONS
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
#define ID_MAGNETOMETER "$Id$"
|
||||||
|
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
FORWARD DECLARATIONS
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
namespace JSBSim {
|
||||||
|
|
||||||
|
class FGFCS;
|
||||||
|
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
CLASS DOCUMENTATION
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
/** Encapsulates a magnetometer component for the flight control system.
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
|
||||||
|
@code
|
||||||
|
<magnetometer name="name">
|
||||||
|
<input> property </input>
|
||||||
|
<lag> number </lag>
|
||||||
|
<noise variation="PERCENT|ABSOLUTE"> number </noise>
|
||||||
|
<quantization name="name">
|
||||||
|
<bits> number </bits>
|
||||||
|
<min> number </min>
|
||||||
|
<max> number </max>
|
||||||
|
</quantization>
|
||||||
|
<drift_rate> number </drift_rate>
|
||||||
|
<bias> number </bias>
|
||||||
|
<gain> number </gain>
|
||||||
|
</magnetometer>
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
@code
|
||||||
|
<magnetometer name="aero/magnetometer/qbar">
|
||||||
|
<input> aero/qbar </input>
|
||||||
|
<lag> 0.5 </lag>
|
||||||
|
<noise variation="PERCENT"> 2 </noise>
|
||||||
|
<quantization name="aero/magnetometer/quantized/qbar">
|
||||||
|
<bits> 12 </bits>
|
||||||
|
<min> 0 </min>
|
||||||
|
<max> 400 </max>
|
||||||
|
</quantization>
|
||||||
|
<bias> 0.5 </bias>
|
||||||
|
<gain> 0.5 </gain>
|
||||||
|
</magnetometer>
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
The only required element in the magnetometer definition is the input element. In that
|
||||||
|
case, no degradation would be modeled, and the output would simply be the input.
|
||||||
|
|
||||||
|
For noise, if the type is PERCENT, then the value supplied is understood to be a
|
||||||
|
percentage variance. That is, if the number given is 0.05, the the variance is
|
||||||
|
understood to be +/-0.05 percent maximum variance. So, the actual value for the magnetometer
|
||||||
|
will be *anywhere* from 0.95 to 1.05 of the actual "perfect" value at any time -
|
||||||
|
even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the delta
|
||||||
|
time.
|
||||||
|
|
||||||
|
@author Jon S. Berndt
|
||||||
|
@version $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
CLASS DECLARATION
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
|
class FGMagnetometer : public FGSensor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FGMagnetometer(FGFCS* fcs, Element* element);
|
||||||
|
~FGMagnetometer();
|
||||||
|
|
||||||
|
bool Run (void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FGPropagate* Propagate;
|
||||||
|
FGMassBalance* MassBalance;
|
||||||
|
FGInertial* Inertial;
|
||||||
|
FGColumnVector3 vLocation;
|
||||||
|
FGColumnVector3 vOrient;
|
||||||
|
FGColumnVector3 vRadius;
|
||||||
|
FGColumnVector3 vMag;
|
||||||
|
FGMatrix33 mT;
|
||||||
|
void CalculateTransformMatrix(void);
|
||||||
|
void updateInertialMag(void);
|
||||||
|
int axis;
|
||||||
|
double field[6];
|
||||||
|
double usedLat;
|
||||||
|
double usedLon;
|
||||||
|
double usedAlt;
|
||||||
|
unsigned long int date;
|
||||||
|
int counter;
|
||||||
|
int INERTIAL_UPDATE_RATE;
|
||||||
|
|
||||||
|
void Debug(int from);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,12 +1,14 @@
|
||||||
noinst_LIBRARIES = libFlightControl.a
|
noinst_LIBRARIES = libFlightControl.a
|
||||||
|
|
||||||
libFlightControl_a_SOURCES = FGPID.cpp FGDeadBand.cpp FGFCSComponent.cpp \
|
libFlightControl_a_SOURCES = \
|
||||||
FGFilter.cpp FGGain.cpp FGGradient.cpp FGKinemat.cpp \
|
FGPID.cpp FGDeadBand.cpp FGFCSComponent.cpp \
|
||||||
FGSummer.cpp FGSwitch.cpp FGFCSFunction.cpp FGSensor.cpp \
|
FGFilter.cpp FGGain.cpp FGGradient.cpp FGKinemat.cpp \
|
||||||
FGActuator.cpp FGAccelerometer.cpp FGGyro.cpp
|
FGSummer.cpp FGSwitch.cpp FGFCSFunction.cpp FGSensor.cpp \
|
||||||
|
FGActuator.cpp FGAccelerometer.cpp FGGyro.cpp FGMagnetometer.cpp
|
||||||
|
|
||||||
noinst_HEADERS = FGPID.h FGDeadBand.h FGFCSComponent.h FGFilter.h \
|
noinst_HEADERS = \
|
||||||
FGGain.h FGGradient.h FGKinemat.h FGSummer.h FGSwitch.h FGFCSFunction.h \
|
FGPID.h FGDeadBand.h FGFCSComponent.h FGFilter.h \
|
||||||
FGSensor.h FGActuator.h FGAccelerometer.h FGGyro.h
|
FGGain.h FGGradient.h FGKinemat.h FGSummer.h FGSwitch.h FGFCSFunction.h\
|
||||||
|
FGSensor.h FGActuator.h FGAccelerometer.h FGGyro.h FGMagnetometer.h
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
|
INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
|
||||||
|
|
|
@ -185,7 +185,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
|
||||||
Bore = el->FindElementValueAsNumberConvertTo("bore","IN");
|
Bore = el->FindElementValueAsNumberConvertTo("bore","IN");
|
||||||
if (el->FindElement("stroke"))
|
if (el->FindElement("stroke"))
|
||||||
Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN");
|
Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN");
|
||||||
if (el->FindElement("stroke"))
|
if (el->FindElement("cylinders"))
|
||||||
Cylinders = el->FindElementValueAsNumber("cylinders");
|
Cylinders = el->FindElementValueAsNumber("cylinders");
|
||||||
if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
|
if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
|
||||||
BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds");
|
BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds");
|
||||||
|
|
Loading…
Reference in a new issue