From 73463a3a9879d134d6d662b7270d3b258653d738 Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 24 Nov 2022 08:59:37 +0000 Subject: [PATCH] Atmosphere: add ISA Mach conversion helpers This is being added for use in FlightPlans, but replace equivalent code in AIBallistic which showed up. As part of this, simplify AIbase. --- src/AIModel/AIBallistic.cxx | 9 +++++--- src/AIModel/AIBase.cxx | 41 ---------------------------------- src/AIModel/AIBase.hxx | 8 ------- src/Environment/atmosphere.cxx | 41 ++++++++++++++++++++++++++++++++++ src/Environment/atmosphere.hxx | 24 ++++++++++++++++++++ 5 files changed, 71 insertions(+), 52 deletions(-) diff --git a/src/AIModel/AIBallistic.cxx b/src/AIModel/AIBallistic.cxx index 24e15262c..b45f0ea6b 100644 --- a/src/AIModel/AIBallistic.cxx +++ b/src/AIModel/AIBallistic.cxx @@ -19,9 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -#ifdef HAVE_CONFIG_H -# include -#endif +#include #include #include @@ -33,6 +31,7 @@ #include
#include +#include #include
using namespace simgear; @@ -695,6 +694,10 @@ void FGAIBallistic::Run(double dt) { // for a conventional shell/bullet (no boat-tail). double Cdm; + const double Mach = FGAtmo::machFromKnotsAtAltitudeFt(speed, altitude_ft); + const double rhoKgM3 = FGAtmo::densityAtAltitudeFt(altitude_ft); + const double rho = rhoKgM3 / SG_SLUGFT3_TO_KGPM3; + if (Mach < 0.7) Cdm = 0.0125 * Mach + _cd; else if (Mach < 1.2) diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index e4142d90b..4afa62a51 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -193,12 +193,6 @@ FGAIBase::FGAIBase(object_type ot, bool enableHot) : replay_time(fgGetNode("sim/ serviceable = false; - rho = 1; - T = 280; - p = 1e5; - a = 340; - Mach = 0; - // explicitly disable HOT for (most) AI models if (!enableHot) aip.getSceneGraph()->setNodeMask(~SG_NODEMASK_TERRAIN_BIT); @@ -309,9 +303,6 @@ void FGAIBase::update(double dt) { if (_otype == object_type::otStatic) return; - if (_otype == object_type::otBallistic) - CalculateMach(); - ft_per_deg_lat = 366468.96 - 3717.12 * cos(pos.getLatitudeRad()); ft_per_deg_lon = 365228.16 * cos(pos.getLatitudeRad()); @@ -1193,38 +1184,6 @@ int FGAIBase::_getFallbackModelIndex() const { return _fallback_model_index; } -void FGAIBase::CalculateMach() { - // Calculate rho at altitude, using standard atmosphere - // For the temperature T and the pressure p, - double altitude = altitude_ft; - - if (altitude < 36152) { // curve fits for the troposphere - T = 59 - 0.00356 * altitude; - p = 2116 * pow( ((T + 459.7) / 518.6) , 5.256); - } else if ( 36152 < altitude && altitude < 82345 ) { // lower stratosphere - T = -70; - p = 473.1 * pow( e , 1.73 - (0.000048 * altitude) ); - } else { // upper stratosphere - T = -205.05 + (0.00164 * altitude); - p = 51.97 * pow( ((T + 459.7) / 389.98) , -11.388); - } - - rho = p / (1718 * (T + 459.7)); - - // calculate the speed of sound at altitude - // a = sqrt ( g * R * (T + 459.7)) - // where: - // a = speed of sound [ft/s] - // g = specific heat ratio, which is usually equal to 1.4 - // R = specific gas constant, which equals 1716 ft-lb/slug/R - a = sqrt ( 1.4 * 1716 * (T + 459.7)); - - // calculate Mach number - Mach = speed/a; - - // cout << "Speed(ft/s) "<< speed <<" Altitude(ft) "<< altitude << " Mach " << Mach << endl; -} - int FGAIBase::_newAIModelID() { static int id = 0; diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx index 13af98939..18c808c11 100644 --- a/src/AIModel/AIBase.hxx +++ b/src/AIModel/AIBase.hxx @@ -292,7 +292,6 @@ protected: ModelSearchOrder _searchOrder = ModelSearchOrder::DATA_ONLY; void Transform(); - void CalculateMach(); double UpdateRadar(FGAIManager* manager); void removeModel(); @@ -377,13 +376,6 @@ public: const char* _getSubmodel() const; int _getFallbackModelIndex() const; - // These are used in the Mach number calculations - double rho; - double T; // temperature, degs farenheit - double p; // pressure lbs/sq ft - double a; // speed of sound at altitude (ft/s) - double Mach; // Mach number - static const double e; static const double lbs_to_slugs; diff --git a/src/Environment/atmosphere.cxx b/src/Environment/atmosphere.cxx index 0c0b044df..4d37308a6 100644 --- a/src/Environment/atmosphere.cxx +++ b/src/Environment/atmosphere.cxx @@ -151,6 +151,47 @@ double FGAtmo::a_vs_p(const double press, const double qnh) { return T0 * ( pow(qnh/P0,nn) - pow(press/P0,nn) ) / lam0; } + +double FGAtmo::ISATemperatureKAtAltitudeFt(const double alt, const double Tsl) +{ + double pressure, temp; + std::tie(pressure, temp) = PT_vs_hpt(alt * SG_FEET_TO_METER, atmodel::ISA::P0, Tsl); + return temp; +} + +double FGAtmo::CSMetersPerSecondAtAltitudeFt(const double alt, const double Tsl) +{ + const double oatK = ISATemperatureKAtAltitudeFt(alt, Tsl); + // calculate the speed of sound at altitude + const double g = 1.4; // specific heat ratio of air + const double R = 287.053; // specific gas constant (J/kgK) + return sqrt (g * R * oatK); +} + +double FGAtmo::densityAtAltitudeFt(const double alt, const double Tsl) +{ + double pressure, temp; + std::tie(pressure, temp) = PT_vs_hpt(alt * SG_FEET_TO_METER, atmodel::ISA::P0, Tsl); + const double R = 287.053; // specific gas constant (J/kgK) + return pressure / (temp * R); +} + +double FGAtmo::machFromKnotsAtAltitudeFt(const double knots, + const double altFt, + const double Tsl) +{ + const auto cs = CSMetersPerSecondAtAltitudeFt(altFt, Tsl); + return (knots * SG_KT_TO_MPS) / cs; +} + +double FGAtmo::knotsFromMachAtAltitudeFt(const double mach, + const double altFt, + const double Tsl) +{ + const auto cs = CSMetersPerSecondAtAltitudeFt(altFt, Tsl); + return mach * cs * SG_MPS_TO_KT; +} + // force retabulation void FGAtmoCache::tabulate() { using namespace atmodel; diff --git a/src/Environment/atmosphere.hxx b/src/Environment/atmosphere.hxx index 8c21186bb..0e88216df 100644 --- a/src/Environment/atmosphere.hxx +++ b/src/Environment/atmosphere.hxx @@ -117,6 +117,30 @@ public: * or millibars */ static double fieldPressure(const double field_elev, const double qnh); + + /** + Compute the outisde temperature at an altitude, according to the standard atmosphere + model. Optionally allow offseting the temperature at seal level, but default to the ISA standard + for that value as well + */ + static double ISATemperatureKAtAltitudeFt(const double alt, + const double Tsl = atmodel::ISA::T0); + + /** + Compute the speed of sound at an altitude + */ + static double CSMetersPerSecondAtAltitudeFt(const double alt, + const double Tsl = atmodel::ISA::T0); + + static double densityAtAltitudeFt(const double alt, const double Tsl = atmodel::ISA::T0); + + static double machFromKnotsAtAltitudeFt(const double knots, + const double altFt, + const double Tsl = atmodel::ISA::T0); + + static double knotsFromMachAtAltitudeFt(const double mach, + const double altFt, + const double Tsl = atmodel::ISA::T0); };