1
0
Fork 0

Sync. with JSBSim (CVS) again

This commit is contained in:
ehofman 2009-09-05 12:22:54 +00:00 committed by Tim Moore
parent d9d725f28d
commit f220feb684
7 changed files with 460 additions and 39 deletions

View file

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

View file

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

View file

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

View 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;
}
}
}
}

View 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

View file

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

View file

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