1
0
Fork 0

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.
This commit is contained in:
James Turner 2022-11-24 08:59:37 +00:00
parent 82dbef0c12
commit 73463a3a98
5 changed files with 71 additions and 52 deletions

View file

@ -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 <config.h>
#endif
#include <simgear/math/sg_random.hxx>
#include <simgear/math/sg_geodesy.hxx>
@ -33,6 +31,7 @@
#include <Main/util.hxx>
#include <Environment/gravity.hxx>
#include <Environment/atmosphere.hxx>
#include <Main/fg_props.hxx>
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)

View file

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

View file

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

View file

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

View file

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