-/*******************************************************************************
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGAtmosphere.cpp
Author: Jon Berndt
11/24/98 JSB Created
07/23/99 TP Added implementation of 1959 Standard Atmosphere
Moved calculation of Mach number to FGTranslation
-********************************************************************************
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
-********************************************************************************
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1] Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0
-********************************************************************************
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
-*******************************************************************************/
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGAtmosphere.h"
#include "FGState.h"
#include "FGPosition.h"
#include "FGAuxiliary.h"
#include "FGOutput.h"
-#include "FGDefs.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
-/*******************************************************************************
-************************************ CODE **************************************
-*******************************************************************************/
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_ATMOSPHERE;
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex),vWindUVW(3),vWindNED(3)
+
+FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
{
- Name = "FGAtmosphere";
- h = 0;
- Calculate(h);
- SLtemperature = temperature;
- SLpressure = pressure;
- SLdensity = density;
- SLsoundspeed = sqrt(SHRATIO*Reng*temperature);
- useExternal=false;
- vWindUVW(1)=0;vWindUVW(2)=0;vWindUVW(3)=0;
- vWindNED(1)=0;vWindNED(2)=0;vWindNED(3)=0;
+ Name = "FGAtmosphere";
+ lastIndex=0;
+ h = 0;
+ htab[0]=0;
+ htab[1]=36089.239;
+ htab[2]=65616.798;
+ htab[3]=104986.878;
+ htab[4]=154199.475;
+ htab[5]=170603.675;
+ htab[6]=200131.234;
+ htab[7]=259186.352; //ft.
+
+ MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
+ turbType = ttNone;
+// turbType = ttBerndt; // temporarily disable turbulence until fully tested
+ TurbGain = 100.0;
+
+ Debug(0);
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGAtmosphere::~FGAtmosphere()
{
+ Debug(1);
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGAtmosphere::Run(void)
+bool FGAtmosphere::InitModel(void)
{
- //cout << "In FGAtmosphere::Run(void)" << endl;
- if (!FGModel::Run()) { // if false then execute this Run()
- //do temp, pressure, and density first
- if (!useExternal) {
- //cout << "Atmosphere: Using internal model, altitude= ";
- h = Position->Geth();
-
- Calculate(h);
- } else {
- density = exDensity;
- pressure = exPressure;
- temperature = exTemperature;
- //switch sign of wind components so that they are
- //in aircraft reference frame. The classic example is
- //takeoff or landing where you always want to fly
- //into the wind. Suppose that an aircraft is
- //taking off into the wind on the runway heading
- //of pure north. Into the wind means the wind is
- //flowing to the south (or negative) direction,
- //and we know that headwinds increase the relative
- //velocity, so to make a positive delta U from the
- //southerly wind the sign must be switched.
- vWindNED *= -1;
- vWindUVW = State->GetTl2b()*vWindNED;
- }
- soundspeed = sqrt(SHRATIO*Reng*temperature);
- //cout << "Atmosphere: soundspeed: " << soundspeed << endl;
- State->Seta(soundspeed);
-
-
- } else { // skip Run() execution this time
- }
- return false;
+ FGModel::InitModel();
+
+ Calculate(h);
+ SLtemperature = temperature;
+ SLpressure = pressure;
+ SLdensity = density;
+ SLsoundspeed = sqrt(SHRatio*Reng*temperature);
+ rSLtemperature = 1.0/temperature;
+ rSLpressure = 1.0/pressure;
+ rSLdensity = 1.0/density;
+ rSLsoundspeed = 1.0/SLsoundspeed;
+ useExternal=false;
+
+ return true;
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGAtmosphere::Calculate(float altitude)
+bool FGAtmosphere::Run(void)
{
- //see reference [1]
-
- float slope,reftemp,refpress,refdens;
- int i=0;
- float htab[]={0,36089,82020,154198,173882,259183,295272,344484}; //ft.
- // cout << "Atmosphere: h=" << altitude << " rho= " << density << endl;
- if (altitude <= htab[0]) {
- altitude=0;
- } else if (altitude >= htab[7]){
- i = 7;
- altitude = htab[7];
+ if (!FGModel::Run()) { // if false then execute this Run()
+ //do temp, pressure, and density first
+ if (!useExternal) {
+ h = Position->Geth();
+ Calculate(h);
} else {
- while (htab[i+1] < altitude) {
- i++;
- }
+ density = exDensity;
+ pressure = exPressure;
+ temperature = exTemperature;
}
- switch(i) {
- case 0: // sea level
- slope = -0.0035662; // R/ft.
- reftemp = 518.688; // R
- refpress = 2116.17; // psf
- refdens = 0.0023765; // slugs/cubic ft.
- break;
- case 1: // 36089 ft.
- slope = 0;
- reftemp = 389.988;
- refpress = 474.1;
- refdens = 0.0007078;
- break;
- case 2: // 82020 ft.
- slope = 0.00164594;
- reftemp = 389.988;
- refpress = 52.7838;
- refdens = 7.8849E-5;
- break;
- case 3: // 154198 ft.
- slope = 0;
- reftemp = 508.788;
- refpress = 2.62274;
- refdens = 3.01379E-6;
- break;
- case 4: // 173882 ft.
- slope = -0.00246891;
- reftemp = 508.788;
- refpress = 1.28428;
- refdens = 1.47035e-06;
- break;
- case 5: // 259183 ft.
- slope = 0;
- reftemp = 298.188;
- refpress = 0.0222008;
- refdens = 4.33396e-08;
- break;
- case 6: // 295272 ft.
- slope = 0.00219459;
- reftemp = 298.188;
- refpress = 0.00215742;
- refdens = 4.21368e-09;
- break;
- case 7: // 344484 ft.
- slope = 0;
- reftemp = 406.188;
- refpress = 0.000153755;
- refdens = 2.20384e-10;
- break;
+ if (turbType != ttNone) {
+ Turbulence();
+ vWindNED += vTurbulence;
}
+ if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) );
- if (slope == 0) {
- temperature = reftemp;
- pressure = refpress*exp(-GRAVITY/(reftemp*Reng)*(altitude-htab[i]));
- density = refdens*exp(-GRAVITY/(reftemp*Reng)*(altitude-htab[i]));
- } else {
- temperature = reftemp+slope*(altitude-htab[i]);
- pressure = refpress*pow(temperature/reftemp,-GRAVITY/(slope*Reng));
- density = refdens*pow(temperature/reftemp,-(GRAVITY/(slope*Reng)+1));
- }
+ if (psiw < 0) psiw += 2*M_PI;
- //cout << "Atmosphere: h=" << altitude << " rho= " << density << endl;
+ soundspeed = sqrt(SHRatio*Reng*temperature);
+ State->Seta(soundspeed);
+
+ Debug(2);
+
+ } else { // skip Run() execution this time
+ }
+
+ return false;
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// See reference 1
+void FGAtmosphere::Calculate(double altitude)
+{
+ double slope, reftemp, refpress;
+ int i = 0;
+
+ i = lastIndex;
+ if (altitude < htab[lastIndex]) {
+ if (altitude <= 0) {
+ i = 0;
+ altitude=0;
+ } else {
+ i = lastIndex-1;
+ while (htab[i] > altitude) i--;
+ }
+ } else if (altitude > htab[lastIndex+1]){
+ if (altitude >= htab[7]){
+ i = 7;
+ altitude = htab[7];
+ } else {
+ i = lastIndex+1;
+ while(htab[i+1] < altitude) i++;
+ }
+ }
+
+ switch(i) {
+ case 1: // 36089 ft.
+ slope = 0;
+ reftemp = 389.97;
+ refpress = 472.452;
+ //refdens = 0.000706032;
+ break;
+ case 2: // 65616 ft.
+ slope = 0.00054864;
+ reftemp = 389.97;
+ refpress = 114.636;
+ //refdens = 0.000171306;
+ break;
+ case 3: // 104986 ft.
+ slope = 0.00153619;
+ reftemp = 411.57;
+ refpress = 8.36364;
+ //refdens = 1.18422e-05;
+ break;
+ case 4: // 154199 ft.
+ slope = 0;
+ reftemp = 487.17;
+ refpress = 0.334882;
+ //refdens = 4.00585e-7;
+ break;
+ case 5: // 170603 ft.
+ slope = -0.00109728;
+ reftemp = 487.17;
+ refpress = 0.683084;
+ //refdens = 8.17102e-7;
+ break;
+ case 6: // 200131 ft.
+ slope = -0.00219456;
+ reftemp = 454.17;
+ refpress = 0.00684986;
+ //refdens = 8.77702e-9;
+ break;
+ case 7: // 259186 ft.
+ slope = 0;
+ reftemp = 325.17;
+ refpress = 0.000122276;
+ //refdens = 2.19541e-10;
+ break;
+ case 0:
+ default: // sea level
+ slope = -0.00356616; // R/ft.
+ reftemp = 518.67; // R
+ refpress = 2116.22; // psf
+ //refdens = 0.00237767; // slugs/cubic ft.
+ break;
+
+ }
+
+ if (slope == 0) {
+ temperature = reftemp;
+ pressure = refpress*exp(-Inertial->SLgravity()/(reftemp*Reng)*(altitude-htab[i]));
+ //density = refdens*exp(-Inertial->SLgravity()/(reftemp*Reng)*(altitude-htab[i]));
+ density = pressure/(Reng*temperature);
+ } else {
+ temperature = reftemp+slope*(altitude-htab[i]);
+ pressure = refpress*pow(temperature/reftemp,-Inertial->SLgravity()/(slope*Reng));
+ //density = refdens*pow(temperature/reftemp,-(Inertial->SLgravity()/(slope*Reng)+1));
+ density = pressure/(Reng*temperature);
+ }
+ lastIndex=i;
+ //cout << "Atmosphere: h=" << altitude << " rho= " << density << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAtmosphere::Turbulence(void)
+{
+ switch (turbType) {
+ case ttBerndt:
+ vDirectiondAccelDt(eX) = 1 - 2.0*(((double)(rand()))/RAND_MAX);
+ vDirectiondAccelDt(eY) = 1 - 2.0*(((double)(rand()))/RAND_MAX);
+ vDirectiondAccelDt(eZ) = 1 - 2.0*(((double)(rand()))/RAND_MAX);
+
+ MagnitudedAccelDt = 1 - 2.0*(((double)(rand()))/RAND_MAX);
+ MagnitudeAccel += MagnitudedAccelDt*rate*State->Getdt();
+ Magnitude += MagnitudeAccel*rate*State->Getdt();
+
+ vDirectiondAccelDt.Normalize();
+ vDirectionAccel += vDirectiondAccelDt*rate*State->Getdt();
+ vDirectionAccel.Normalize();
+ vDirection += vDirectionAccel*rate*State->Getdt();
+ vDirection.Normalize();
+
+ vTurbulence = TurbGain*Magnitude * vDirection;
+ vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
+
+ vBodyTurbGrad = State->GetTl2b()*vTurbulenceGrad;
+ vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
+ if (Aircraft->GetHTailArm() != 0.0)
+ vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
+ else
+ vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
+
+ if (Aircraft->GetVTailArm())
+ vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
+ else
+ vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
+
+ break;
+ default:
+ break;
+ }
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// 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 FGAtmosphere::Debug(int from)
+{
+ if (debug_lvl <= 0) return;
+
+ if (debug_lvl & 1) { // Standard console startup message output
+ if (from == 0) { // Constructor
+ }
+ }
+ if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+ if (from == 0) cout << "Instantiated: FGAtmosphere" << endl;
+ if (from == 1) cout << "Destroyed: FGAtmosphere" << 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 & 32) { // Turbulence
+ if (frame == 0 && from == 2) {
+ cout << "vTurbulence(X), vTurbulence(Y), vTurbulence(Z), "
+ << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), "
+ << "vDirection(X), vDirection(Y), vDirection(Z), "
+ << "Magnitude, "
+ << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl;
+ } else if (from == 2) {
+ cout << vTurbulence << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl;
+ }
+ }
+ if (debug_lvl & 64) {
+ if (from == 0) { // Constructor
+ cout << IdSrc << endl;
+ cout << IdHdr << endl;
+ }
+ }
+}