static int phase = 0;
double X;
- V1 = V2 = S = X = 0.0;
-
if (phase == 0) {
+ V1 = V2 = S = X = 0.0;
+
do {
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
// SetTurbType( ttCulp );
SetTurbType( ttNone );
- TurbGain = 0.0;
- TurbRate = 1.7;
+ TurbGain = 1.0;
+ TurbRate = 10.0;
Rhythmicity = 0.1;
spike = target_time = strength = 0.0;
wind_from_clockwise = 0.0;
void FGAtmosphere::Turbulence(void)
{
+ double DeltaT = rate*State->Getdt();
+
switch (turbType) {
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(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
// away from the peaks
MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
(1 + fabs(Magnitude)));
- MagnitudeAccel += MagnitudedAccelDt*rate*TurbRate*State->Getdt();
- Magnitude += MagnitudeAccel*rate*State->Getdt();
+ MagnitudeAccel += MagnitudedAccelDt*TurbRate*DeltaT;
+ Magnitude += MagnitudeAccel*DeltaT;
Magnitude = fabs(Magnitude);
vDirectiondAccelDt.Normalize();
vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX));
vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY));
- vDirectionAccel += vDirectiondAccelDt*rate*TurbRate*State->Getdt();
+ vDirectionAccel += vDirectiondAccelDt*TurbRate*DeltaT;
vDirectionAccel.Normalize();
- vDirection += vDirectionAccel*rate*State->Getdt();
+ vDirection += vDirectionAccel*DeltaT;
vDirection.Normalize();
}
case ttBerndt: { // This is very experimental and incomplete at the moment.
- TurbGain = TurbGain * TurbGain * 100.0;
-
- vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
- vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
- vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
+ vDirectiondAccelDt(eX) = GaussianRandomNumber();
+ vDirectiondAccelDt(eY) = GaussianRandomNumber();
+ vDirectiondAccelDt(eZ) = GaussianRandomNumber();
-
- MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
- MagnitudeAccel += MagnitudedAccelDt*rate*State->Getdt();
- Magnitude += MagnitudeAccel*rate*State->Getdt();
+ MagnitudedAccelDt = GaussianRandomNumber();
+ MagnitudeAccel += MagnitudedAccelDt * DeltaT;
+ Magnitude += MagnitudeAccel * DeltaT;
vDirectiondAccelDt.Normalize();
- vDirectionAccel += vDirectiondAccelDt*rate*State->Getdt();
+ vDirectionAccel += TurbRate * vDirectiondAccelDt * DeltaT;
vDirectionAccel.Normalize();
- vDirection += vDirectionAccel*rate*State->Getdt();
+ vDirection += vDirectionAccel*DeltaT;
- // Diminish z-vector within two wingspans
- // of the ground
+ // Diminish z-vector within two wingspans of the ground
double HOverBMAC = Auxiliary->GetHOverBMAC();
- if (HOverBMAC < 2.0)
- vDirection(eZ) *= HOverBMAC / 2.0;
+ if (HOverBMAC < 2.0) vDirection(eZ) *= HOverBMAC / 2.0;
vDirection.Normalize();
vTurbulenceNED = TurbGain*Magnitude * vDirection;
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
- vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
- vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
+ vBodyTurbGrad = Propagate->GetTl2b() * vTurbulenceGrad;
+ vTurbPQR(eP) = vBodyTurbGrad(eY) / Aircraft->GetWingSpan();
if (Aircraft->GetHTailArm() > 0)
- vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
+ vTurbPQR(eQ) = vBodyTurbGrad(eZ) / Aircraft->GetHTailArm();
else
- vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
+ vTurbPQR(eQ) = vBodyTurbGrad(eZ) / 10.0;
if (Aircraft->GetVTailArm() > 0)
- vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
+ vTurbPQR(eR) = vBodyTurbGrad(eX) / Aircraft->GetVTailArm();
else
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
{
typedef double (FGAtmosphere::*PMF)(int) const;
typedef double (FGAtmosphere::*PMFv)(void) const;
+ typedef int (FGAtmosphere::*PMFt)(void) const;
typedef void (FGAtmosphere::*PMFd)(int,double);
+ typedef void (FGAtmosphere::*PMFi)(int);
PropertyManager->Tie("atmosphere/T-R", this, (PMFv)&FGAtmosphere::GetTemperature);
PropertyManager->Tie("atmosphere/rho-slugs_ft3", this, (PMFv)&FGAtmosphere::GetDensity);
PropertyManager->Tie("atmosphere/P-psf", this, (PMFv)&FGAtmosphere::GetPressure);
PropertyManager->Tie("atmosphere/gust-down-fps", this, eDown, (PMF)&FGAtmosphere::GetGustNED,
(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/q-turb-rad_sec", this,2, (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-gain", this, &FGAtmosphere::GetTurbGain, &FGAtmosphere::SetTurbGain);
PropertyManager->Tie("atmosphere/turb-rhythmicity", this, &FGAtmosphere::GetRhythmicity,
@return false if no error */
bool Run(void);
bool InitModel(void);
- enum tType {ttStandard, ttBerndt, ttCulp, ttNone} turbType;
+ enum tType {ttNone, ttStandard, ttBerndt, ttCulp} turbType;
/// Returns the temperature in degrees Rankine.
double GetTemperature(void) const {return *temperature;}
/// Sets a gust component in NED frame.
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.
void SetGustNED(double gN, double gE, double gD) { vGustNED(eNorth)=gN; vGustNED(eEast)=gE; vGustNED(eDown)=gD;}
/// Retrieves a gust component in NED frame.
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.
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;}
tType GetTurbType() const {return turbType;}
--- /dev/null
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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;
+ }
+ }
+}
+}
--- /dev/null
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
noinst_LIBRARIES = libFlightControl.a
-libFlightControl_a_SOURCES = FGPID.cpp FGDeadBand.cpp FGFCSComponent.cpp \
- FGFilter.cpp FGGain.cpp FGGradient.cpp FGKinemat.cpp \
- FGSummer.cpp FGSwitch.cpp FGFCSFunction.cpp FGSensor.cpp \
- FGActuator.cpp FGAccelerometer.cpp FGGyro.cpp
+libFlightControl_a_SOURCES = \
+ FGPID.cpp FGDeadBand.cpp FGFCSComponent.cpp \
+ FGFilter.cpp FGGain.cpp FGGradient.cpp FGKinemat.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 \
- FGGain.h FGGradient.h FGKinemat.h FGSummer.h FGSwitch.h FGFCSFunction.h \
- FGSensor.h FGActuator.h FGAccelerometer.h FGGyro.h
+noinst_HEADERS = \
+ FGPID.h FGDeadBand.h FGFCSComponent.h FGFilter.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
Bore = el->FindElementValueAsNumberConvertTo("bore","IN");
if (el->FindElement("stroke"))
Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN");
- if (el->FindElement("stroke"))
+ if (el->FindElement("cylinders"))
Cylinders = el->FindElementValueAsNumber("cylinders");
if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds");