1
0
Fork 0

Finished off the atmosphere model (Troposphere and lower

Stratosphere).  The atmospheric properties are as follow:

/environment/temperature-sea-level-degc
/environment/temperature-degc
/environment/pressure-sea-level-inhg
/environment/pressure-inhg
/environment/density-sea-level-slugft3
/environment/density-slugft3

Setting either the sea-level or altitude value automatically sets the
other value appropriate, except for temperature at altitude above the
Troposphere (where there's no reliable way to back-calculate it).  The
atmosphere model appears in the atmosphere_data array in
environment.cxx, and can easily be extended into the upper
stratosphere and beyond.

These are not yet tied into the FDMs or steam module.
This commit is contained in:
david 2002-05-15 03:00:41 +00:00
parent abdb5abb6a
commit 8a5cdbdbc6
3 changed files with 167 additions and 40 deletions

View file

@ -35,38 +35,52 @@
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/interpolater.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include "environment.hxx" #include "environment.hxx"
FGEnvironment::FGEnvironment() FGEnvironment::FGEnvironment()
: visibility_m(32000), : _temperature_degc_table(new SGInterpTable),
_pressure_inhg_table(new SGInterpTable),
_density_slugft3_table(new SGInterpTable),
visibility_m(32000),
temperature_sea_level_degc(20), temperature_sea_level_degc(20),
pressure_sea_level_inhg(28), pressure_sea_level_inhg(28),
density_sea_level_slugft3(0.0024),
wind_from_heading_deg(0), wind_from_heading_deg(0),
wind_speed_kt(0), wind_speed_kt(0),
wind_from_north_fps(0), wind_from_north_fps(0),
wind_from_east_fps(0), wind_from_east_fps(0),
wind_from_down_fps(0) wind_from_down_fps(0)
{ {
_setup_tables();
} }
FGEnvironment::FGEnvironment (const FGEnvironment &env) FGEnvironment::FGEnvironment (const FGEnvironment &env)
: elevation_ft(env.elevation_ft), : _temperature_degc_table(new SGInterpTable),
_pressure_inhg_table(new SGInterpTable),
_density_slugft3_table(new SGInterpTable),
elevation_ft(env.elevation_ft),
visibility_m(env.visibility_m), visibility_m(env.visibility_m),
temperature_sea_level_degc(env.temperature_sea_level_degc), temperature_sea_level_degc(env.temperature_sea_level_degc),
pressure_sea_level_inhg(env.pressure_sea_level_inhg), pressure_sea_level_inhg(env.pressure_sea_level_inhg),
density_sea_level_slugft3(env.density_sea_level_slugft3),
wind_from_heading_deg(env.wind_from_heading_deg), wind_from_heading_deg(env.wind_from_heading_deg),
wind_speed_kt(env.wind_speed_kt), wind_speed_kt(env.wind_speed_kt),
wind_from_north_fps(env.wind_from_north_fps), wind_from_north_fps(env.wind_from_north_fps),
wind_from_east_fps(env.wind_from_east_fps), wind_from_east_fps(env.wind_from_east_fps),
wind_from_down_fps(env.wind_from_down_fps) wind_from_down_fps(env.wind_from_down_fps)
{ {
_setup_tables();
} }
FGEnvironment::~FGEnvironment() FGEnvironment::~FGEnvironment()
{ {
delete _temperature_degc_table;
delete _pressure_inhg_table;
delete _density_slugft3_table;
} }
@ -100,6 +114,18 @@ FGEnvironment::get_pressure_inhg () const
return pressure_inhg; return pressure_inhg;
} }
double
FGEnvironment::get_density_sea_level_slugft3 () const
{
return density_sea_level_slugft3;
}
double
FGEnvironment::get_density_slugft3 () const
{
return density_slugft3;
}
double double
FGEnvironment::get_wind_from_heading_deg () const FGEnvironment::get_wind_from_heading_deg () const
{ {
@ -136,8 +162,6 @@ FGEnvironment::get_elevation_ft () const
return elevation_ft; return elevation_ft;
} }
void void
FGEnvironment::set_visibility_m (double v) FGEnvironment::set_visibility_m (double v)
{ {
@ -148,28 +172,42 @@ void
FGEnvironment::set_temperature_sea_level_degc (double t) FGEnvironment::set_temperature_sea_level_degc (double t)
{ {
temperature_sea_level_degc = t; temperature_sea_level_degc = t;
_recalc_alt_temp(); _recalc_alt_temperature();
} }
void void
FGEnvironment::set_temperature_degc (double t) FGEnvironment::set_temperature_degc (double t)
{ {
temperature_degc = t; temperature_degc = t;
_recalc_sl_temp(); _recalc_sl_temperature();
} }
void void
FGEnvironment::set_pressure_sea_level_inhg (double p) FGEnvironment::set_pressure_sea_level_inhg (double p)
{ {
pressure_sea_level_inhg = p; pressure_sea_level_inhg = p;
_recalc_alt_press(); _recalc_alt_pressure();
} }
void void
FGEnvironment::set_pressure_inhg (double p) FGEnvironment::set_pressure_inhg (double p)
{ {
pressure_inhg = p; pressure_inhg = p;
_recalc_sl_press(); _recalc_sl_pressure();
}
void
FGEnvironment::set_density_sea_level_slugft3 (double d)
{
density_sea_level_slugft3 = d;
_recalc_alt_density();
}
void
FGEnvironment::set_density_slugft3 (double d)
{
density_slugft3 = d;
_recalc_sl_density();
} }
void void
@ -211,8 +249,63 @@ void
FGEnvironment::set_elevation_ft (double e) FGEnvironment::set_elevation_ft (double e)
{ {
elevation_ft = e; elevation_ft = e;
_recalc_alt_temp(); _recalc_alt_temperature();
_recalc_alt_press(); _recalc_alt_pressure();
_recalc_alt_density();
}
// Atmosphere model.
// Copied from YASim Atmosphere.cxx, with m converted to ft, degK
// converted to degC, Pa converted to inHG, and kg/m^3 converted to
// slug/ft^3.
// Original comment from YASim:
// Copied from McCormick, who got it from "The ARDC Model Atmosphere"
// Note that there's an error in the text in the first entry,
// McCormick lists 299.16/101325/1.22500, but those don't agree with
// R=287. I chose to correct the temperature to 288.20, since 79F is
// pretty hot for a "standard" atmosphere.
// Elevation (ft), temperature (degC), pressure (inHG), density (slug/ft^3)
static double atmosphere_data[][4] = {
0, 0.00, 0.000, 0.000000,
2952, -5.89, -3.058, -0.000198,
5905, -11.74, -5.856, -0.000384,
8858, -17.58, -8.413, -0.000556,
11811, -23.43, -10.745, -0.000717,
14763, -29.27, -12.867, -0.000867,
17716, -35.11, -14.794, -0.001006,
20669, -40.95, -16.541, -0.001136,
23622, -46.79, -18.120, -0.001255,
26574, -52.62, -19.544, -0.001366,
29527, -58.46, -20.826, -0.001467,
32480, -64.29, -21.976, -0.001561,
35433, -70.12, -23.005, -0.001647,
38385, -71.54, -23.916, -0.001739,
41338, -71.54, -24.708, -0.001822,
44291, -71.54, -25.395, -0.001894,
47244, -71.54, -25.991, -0.001957,
50196, -71.54, -26.509, -0.002012,
53149, -71.54, -26.959, -0.002059,
56102, -71.54, -27.349, -0.002100,
59055, -71.54, -27.687, -0.002136,
62007, -71.54, -27.981, -0.002167,
-1, -1, -1, -1
};
void
FGEnvironment::_setup_tables ()
{
for (int i = 0; atmosphere_data[i][0] != -1; i++) {
_temperature_degc_table->addEntry(atmosphere_data[i][0],
atmosphere_data[i][1]);
_pressure_inhg_table->addEntry(atmosphere_data[i][0],
atmosphere_data[i][2]);
_density_slugft3_table->addEntry(atmosphere_data[i][0],
atmosphere_data[i][3]);
}
} }
void void
@ -251,47 +344,50 @@ FGEnvironment::_recalc_ne ()
} }
void void
FGEnvironment::_recalc_sl_temp () FGEnvironment::_recalc_sl_temperature ()
{ {
// Earth atmosphere model from if (elevation_ft < 38000) {
// http://www.grc.nasa.gov/WWW/K-12/airplane/atmos.html
// Stratospheric temperatures are not really reversible, so use 15degC.
if (elevation_ft < 36152) // Troposphere
temperature_sea_level_degc = temperature_sea_level_degc =
temperature_degc + (.00649 * SG_FEET_TO_METER * elevation_ft); temperature_degc - _temperature_degc_table->interpolate(elevation_ft);
}
// If we're in the stratosphere, leave sea-level temp alone // If we're in the stratosphere, leave sea-level temp alone
} }
void void
FGEnvironment::_recalc_alt_temp () FGEnvironment::_recalc_alt_temperature ()
{ {
// Earth atmosphere model from
// http://www.grc.nasa.gov/WWW/K-12/airplane/atmos.html
if (elevation_ft < 36152) // Troposphere
temperature_degc = temperature_degc =
temperature_sea_level_degc - (.00649 * SG_FEET_TO_METER * elevation_ft); temperature_sea_level_degc +
else if (elevation_ft < 82345) // Lower Stratosphere _temperature_degc_table->interpolate(elevation_ft);
temperature_degc = -56.46;
else
temperature_degc = -131.21 + (.00299 * SG_FEET_TO_METER * elevation_ft);
} }
void void
FGEnvironment::_recalc_sl_press () FGEnvironment::_recalc_sl_pressure ()
{ {
// FIXME: calculate properly pressure_sea_level_inhg =
pressure_sea_level_inhg = pressure_inhg; pressure_inhg - _pressure_inhg_table->interpolate(elevation_ft);
} }
void void
FGEnvironment::_recalc_alt_press () FGEnvironment::_recalc_alt_pressure ()
{ {
// FIXME: calculate properly pressure_inhg =
pressure_inhg = pressure_sea_level_inhg; pressure_sea_level_inhg + _pressure_inhg_table->interpolate(elevation_ft);
}
void
FGEnvironment::_recalc_sl_density ()
{
density_sea_level_slugft3 =
density_slugft3 - _density_slugft3_table->interpolate(elevation_ft);
}
void
FGEnvironment::_recalc_alt_density ()
{
density_slugft3 =
density_sea_level_slugft3 +
_density_slugft3_table->interpolate(elevation_ft);
} }
// end of environment.cxx // end of environment.cxx

View file

@ -34,6 +34,8 @@
# include <math.h> # include <math.h>
#endif #endif
class SGInterpTable;
/** /**
* Model the natural environment. * Model the natural environment.
@ -53,10 +55,14 @@ public:
virtual ~FGEnvironment(); virtual ~FGEnvironment();
virtual double get_visibility_m () const; virtual double get_visibility_m () const;
virtual double get_temperature_sea_level_degc () const; virtual double get_temperature_sea_level_degc () const;
virtual double get_temperature_degc () const; virtual double get_temperature_degc () const;
virtual double get_pressure_sea_level_inhg () const; virtual double get_pressure_sea_level_inhg () const;
virtual double get_pressure_inhg () const; virtual double get_pressure_inhg () const;
virtual double get_density_sea_level_slugft3 () const;
virtual double get_density_slugft3 () const;
virtual double get_wind_from_heading_deg () const; virtual double get_wind_from_heading_deg () const;
virtual double get_wind_speed_kt () const; virtual double get_wind_speed_kt () const;
virtual double get_wind_from_north_fps () const; virtual double get_wind_from_north_fps () const;
@ -64,10 +70,14 @@ public:
virtual double get_wind_from_down_fps () const; virtual double get_wind_from_down_fps () const;
virtual void set_visibility_m (double v); virtual void set_visibility_m (double v);
virtual void set_temperature_sea_level_degc (double t); virtual void set_temperature_sea_level_degc (double t);
virtual void set_temperature_degc (double t); virtual void set_temperature_degc (double t);
virtual void set_pressure_sea_level_inhg (double p); virtual void set_pressure_sea_level_inhg (double p);
virtual void set_pressure_inhg (double p); virtual void set_pressure_inhg (double p);
virtual void set_density_sea_level_slugft3 (double d);
virtual void set_density_slugft3 (double d);
virtual void set_wind_from_heading_deg (double h); virtual void set_wind_from_heading_deg (double h);
virtual void set_wind_speed_kt (double s); virtual void set_wind_speed_kt (double s);
virtual void set_wind_from_north_fps (double n); virtual void set_wind_from_north_fps (double n);
@ -83,20 +93,33 @@ protected:
private: private:
void _setup_tables ();
void _recalc_hdgspd (); void _recalc_hdgspd ();
void _recalc_ne (); void _recalc_ne ();
void _recalc_sl_temp ();
void _recalc_alt_temp (); void _recalc_sl_temperature ();
void _recalc_sl_press (); void _recalc_alt_temperature ();
void _recalc_alt_press (); void _recalc_sl_pressure ();
void _recalc_alt_pressure ();
void _recalc_sl_density ();
void _recalc_alt_density ();
SGInterpTable * _temperature_degc_table;
SGInterpTable * _pressure_inhg_table;
SGInterpTable * _density_slugft3_table;
double elevation_ft; double elevation_ft;
double visibility_m; double visibility_m;
// Atmosphere
double temperature_sea_level_degc; double temperature_sea_level_degc;
double temperature_degc; double temperature_degc;
double pressure_sea_level_inhg; double pressure_sea_level_inhg;
double pressure_inhg; double pressure_inhg;
double density_sea_level_slugft3;
double density_slugft3;
double wind_from_heading_deg; double wind_from_heading_deg;
double wind_speed_kt; double wind_speed_kt;

View file

@ -72,6 +72,14 @@ FGEnvironmentMgr::bind ()
&FGEnvironment::get_pressure_inhg, &FGEnvironment::get_pressure_inhg,
&FGEnvironment::set_pressure_inhg); &FGEnvironment::set_pressure_inhg);
fgSetArchivable("/environment/pressure-inhg"); fgSetArchivable("/environment/pressure-inhg");
fgTie("/environment/density-sea-level-slugft3", _environment,
&FGEnvironment::get_density_sea_level_slugft3,
&FGEnvironment::set_density_sea_level_slugft3);
fgSetArchivable("/environment/density-sea-level-slugft3");
fgTie("/environment/density-slugft3", _environment,
&FGEnvironment::get_density_slugft3,
&FGEnvironment::set_density_slugft3);
fgSetArchivable("/environment/density-inhg");
fgTie("/environment/wind-from-heading-deg", _environment, fgTie("/environment/wind-from-heading-deg", _environment,
&FGEnvironment::get_wind_from_heading_deg, &FGEnvironment::get_wind_from_heading_deg,
&FGEnvironment::set_wind_from_heading_deg); &FGEnvironment::set_wind_from_heading_deg);