Removed FGEnvironmentMgr as a special case in globals, initialization,
etc. Improved the weather system to interpolate between different elevations and deal with boundary-layer conditions. The configuration properties are now different (see $FG_ROOT/preferences.xml).
This commit is contained in:
parent
6f3456a734
commit
e588cbadd8
12 changed files with 444 additions and 120 deletions
|
@ -540,7 +540,8 @@ void FGApproach::get_active_runway() {
|
||||||
FGPhysicalProperty stationweather = WeatherDatabase->get(position);
|
FGPhysicalProperty stationweather = WeatherDatabase->get(position);
|
||||||
#else
|
#else
|
||||||
FGEnvironment stationweather =
|
FGEnvironment stationweather =
|
||||||
globals->get_environment_mgr()->getEnvironment(lat, lon, elev);
|
((FGEnvironmentMgr *)globals->get_subsystem("environment"))
|
||||||
|
->getEnvironment(lat, lon, elev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
|
|
|
@ -113,7 +113,8 @@ void FGATIS::UpdateTransmission() {
|
||||||
FGPhysicalProperty stationweather = WeatherDatabase->get(position);
|
FGPhysicalProperty stationweather = WeatherDatabase->get(position);
|
||||||
#else
|
#else
|
||||||
FGEnvironment stationweather =
|
FGEnvironment stationweather =
|
||||||
globals->get_environment_mgr()->getEnvironment(lat, lon, elev);
|
((FGEnvironmentMgr *)globals->get_subsystem("environment"))
|
||||||
|
->getEnvironment(lat, lon, elev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
transmission = "";
|
transmission = "";
|
||||||
|
|
|
@ -41,10 +41,79 @@
|
||||||
#include "environment.hxx"
|
#include "environment.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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; they were then converted to deltas from the sea-level
|
||||||
|
// defaults (approx. 15degC, 29.92inHG, and 0.00237slugs/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 factor (degK), pressure factor (inHG)
|
||||||
|
static double atmosphere_data[][3] = {
|
||||||
|
{ 0.00, 1.00, 1.000 },
|
||||||
|
{ 2952.76, 0.98, 0.898 },
|
||||||
|
{ 5905.51, 0.96, 0.804 },
|
||||||
|
{ 8858.27, 0.94, 0.719 },
|
||||||
|
{ 11811.02, 0.92, 0.641 },
|
||||||
|
{ 14763.78, 0.90, 0.570 },
|
||||||
|
{ 17716.54, 0.88, 0.506 },
|
||||||
|
{ 20669.29, 0.86, 0.447 },
|
||||||
|
{ 23622.05, 0.84, 0.394 },
|
||||||
|
{ 26574.80, 0.82, 0.347 },
|
||||||
|
{ 29527.56, 0.80, 0.304 },
|
||||||
|
{ 32480.31, 0.78, 0.266 },
|
||||||
|
{ 35433.07, 0.76, 0.231 },
|
||||||
|
{ 38385.83, 0.75, 0.201 },
|
||||||
|
{ 41338.58, 0.75, 0.174 },
|
||||||
|
{ 44291.34, 0.75, 0.151 },
|
||||||
|
{ 47244.09, 0.75, 0.131 },
|
||||||
|
{ 50196.85, 0.75, 0.114 },
|
||||||
|
{ 53149.61, 0.75, 0.099 },
|
||||||
|
{ 56102.36, 0.75, 0.086 },
|
||||||
|
{ 59055.12, 0.75, 0.075 },
|
||||||
|
{ 62007.87, 0.75, 0.065 },
|
||||||
|
{ -1, -1, -1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static SGInterpTable * _temperature_degc_table = 0;
|
||||||
|
static SGInterpTable * _pressure_inhg_table = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_setup_tables ()
|
||||||
|
{
|
||||||
|
if (_temperature_degc_table != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_temperature_degc_table = new SGInterpTable;
|
||||||
|
_pressure_inhg_table = new SGInterpTable;
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGEnvironment.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FGEnvironment::FGEnvironment()
|
FGEnvironment::FGEnvironment()
|
||||||
: _temperature_degc_table(new SGInterpTable),
|
: elevation_ft(0),
|
||||||
_pressure_inhg_table(new SGInterpTable),
|
|
||||||
elevation_ft(0),
|
|
||||||
visibility_m(32000),
|
visibility_m(32000),
|
||||||
temperature_sea_level_degc(15),
|
temperature_sea_level_degc(15),
|
||||||
temperature_degc(15),
|
temperature_degc(15),
|
||||||
|
@ -56,32 +125,85 @@ FGEnvironment::FGEnvironment()
|
||||||
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),
|
||||||
|
turbulence_norm(0)
|
||||||
{
|
{
|
||||||
_setup_tables();
|
_setup_tables();
|
||||||
}
|
}
|
||||||
|
|
||||||
FGEnvironment::FGEnvironment (const FGEnvironment &env)
|
FGEnvironment::FGEnvironment (const FGEnvironment &env)
|
||||||
: _temperature_degc_table(new SGInterpTable),
|
|
||||||
_pressure_inhg_table(new SGInterpTable),
|
|
||||||
elevation_ft(env.elevation_ft),
|
|
||||||
visibility_m(env.visibility_m),
|
|
||||||
temperature_sea_level_degc(env.temperature_sea_level_degc),
|
|
||||||
dewpoint_sea_level_degc(env.dewpoint_sea_level_degc),
|
|
||||||
pressure_sea_level_inhg(env.pressure_sea_level_inhg),
|
|
||||||
wind_from_heading_deg(env.wind_from_heading_deg),
|
|
||||||
wind_speed_kt(env.wind_speed_kt),
|
|
||||||
wind_from_north_fps(env.wind_from_north_fps),
|
|
||||||
wind_from_east_fps(env.wind_from_east_fps),
|
|
||||||
wind_from_down_fps(env.wind_from_down_fps)
|
|
||||||
{
|
{
|
||||||
_setup_tables();
|
FGEnvironment();
|
||||||
|
copy(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
FGEnvironment::~FGEnvironment()
|
FGEnvironment::~FGEnvironment()
|
||||||
{
|
{
|
||||||
delete _temperature_degc_table;
|
}
|
||||||
delete _pressure_inhg_table;
|
|
||||||
|
void
|
||||||
|
FGEnvironment::copy (const FGEnvironment &env)
|
||||||
|
{
|
||||||
|
elevation_ft = env.elevation_ft;
|
||||||
|
visibility_m = env.visibility_m;
|
||||||
|
temperature_sea_level_degc = env.temperature_sea_level_degc;
|
||||||
|
dewpoint_sea_level_degc = env.dewpoint_sea_level_degc;
|
||||||
|
pressure_sea_level_inhg = env.pressure_sea_level_inhg;
|
||||||
|
wind_from_heading_deg = env.wind_from_heading_deg;
|
||||||
|
wind_speed_kt = env.wind_speed_kt;
|
||||||
|
wind_from_north_fps = env.wind_from_north_fps;
|
||||||
|
wind_from_east_fps = env.wind_from_east_fps;
|
||||||
|
wind_from_down_fps = env.wind_from_down_fps;
|
||||||
|
turbulence_norm = env.turbulence_norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
maybe_copy_value (FGEnvironment * env, const SGPropertyNode * node,
|
||||||
|
const char * name, void (FGEnvironment::*setter)(double))
|
||||||
|
{
|
||||||
|
const SGPropertyNode * child = node->getChild(name);
|
||||||
|
// fragile: depends on not being typed
|
||||||
|
// as a number
|
||||||
|
if (child != 0 && child->getStringValue()[0] != '\0') {
|
||||||
|
(env->*setter)(child->getDoubleValue());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGEnvironment::read (const SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
maybe_copy_value(this, node, "visibility-m",
|
||||||
|
&FGEnvironment::set_visibility_m);
|
||||||
|
|
||||||
|
if (!maybe_copy_value(this, node, "temperature-sea-level-degc",
|
||||||
|
&FGEnvironment::set_temperature_sea_level_degc))
|
||||||
|
maybe_copy_value(this, node, "temperature-degc",
|
||||||
|
&FGEnvironment::set_temperature_degc);
|
||||||
|
|
||||||
|
if (!maybe_copy_value(this, node, "dewpoint-sea-level-degc",
|
||||||
|
&FGEnvironment::set_dewpoint_sea_level_degc))
|
||||||
|
maybe_copy_value(this, node, "dewpoint-degc",
|
||||||
|
&FGEnvironment::set_dewpoint_degc);
|
||||||
|
|
||||||
|
if (!maybe_copy_value(this, node, "pressure-sea-level-inhg",
|
||||||
|
&FGEnvironment::set_pressure_sea_level_inhg))
|
||||||
|
maybe_copy_value(this, node, "pressure-inhg",
|
||||||
|
&FGEnvironment::set_pressure_inhg);
|
||||||
|
|
||||||
|
maybe_copy_value(this, node, "wind-from-heading-deg",
|
||||||
|
&FGEnvironment::set_wind_from_heading_deg);
|
||||||
|
|
||||||
|
maybe_copy_value(this, node, "wind-speed-kt",
|
||||||
|
&FGEnvironment::set_wind_speed_kt);
|
||||||
|
|
||||||
|
maybe_copy_value(this, node, "elevation-ft",
|
||||||
|
&FGEnvironment::set_elevation_ft);
|
||||||
|
|
||||||
|
maybe_copy_value(this, node, "turbulence-norm",
|
||||||
|
&FGEnvironment::set_turbulence_norm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,6 +285,12 @@ FGEnvironment::get_wind_from_down_fps () const
|
||||||
return wind_from_down_fps;
|
return wind_from_down_fps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
FGEnvironment::get_turbulence_norm () const
|
||||||
|
{
|
||||||
|
return turbulence_norm;
|
||||||
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
FGEnvironment::get_elevation_ft () const
|
FGEnvironment::get_elevation_ft () const
|
||||||
{
|
{
|
||||||
|
@ -262,6 +390,12 @@ FGEnvironment::set_wind_from_down_fps (double d)
|
||||||
_recalc_hdgspd();
|
_recalc_hdgspd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGEnvironment::set_turbulence_norm (double t)
|
||||||
|
{
|
||||||
|
turbulence_norm = t;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGEnvironment::set_elevation_ft (double e)
|
FGEnvironment::set_elevation_ft (double e)
|
||||||
{
|
{
|
||||||
|
@ -272,59 +406,6 @@ FGEnvironment::set_elevation_ft (double e)
|
||||||
_recalc_density();
|
_recalc_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; they were then converted to deltas from the sea-level
|
|
||||||
// defaults (approx. 15degC, 29.92inHG, and 0.00237slugs/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 factor (degK), pressure factor (inHG)
|
|
||||||
static double atmosphere_data[][3] = {
|
|
||||||
{ 0.00, 1.00, 1.000 },
|
|
||||||
{ 2952.76, 0.98, 0.898 },
|
|
||||||
{ 5905.51, 0.96, 0.804 },
|
|
||||||
{ 8858.27, 0.94, 0.719 },
|
|
||||||
{ 11811.02, 0.92, 0.641 },
|
|
||||||
{ 14763.78, 0.90, 0.570 },
|
|
||||||
{ 17716.54, 0.88, 0.506 },
|
|
||||||
{ 20669.29, 0.86, 0.447 },
|
|
||||||
{ 23622.05, 0.84, 0.394 },
|
|
||||||
{ 26574.80, 0.82, 0.347 },
|
|
||||||
{ 29527.56, 0.80, 0.304 },
|
|
||||||
{ 32480.31, 0.78, 0.266 },
|
|
||||||
{ 35433.07, 0.76, 0.231 },
|
|
||||||
{ 38385.83, 0.75, 0.201 },
|
|
||||||
{ 41338.58, 0.75, 0.174 },
|
|
||||||
{ 44291.34, 0.75, 0.151 },
|
|
||||||
{ 47244.09, 0.75, 0.131 },
|
|
||||||
{ 50196.85, 0.75, 0.114 },
|
|
||||||
{ 53149.61, 0.75, 0.099 },
|
|
||||||
{ 56102.36, 0.75, 0.086 },
|
|
||||||
{ 59055.12, 0.75, 0.075 },
|
|
||||||
{ 62007.87, 0.75, 0.065 },
|
|
||||||
{ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGEnvironment::_recalc_hdgspd ()
|
FGEnvironment::_recalc_hdgspd ()
|
||||||
{
|
{
|
||||||
|
@ -438,4 +519,76 @@ FGEnvironment::_recalc_density ()
|
||||||
density_slugft3 = pressure_psf / (virtual_temperature_degr * 1718);
|
density_slugft3 = pressure_psf / (virtual_temperature_degr * 1718);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static inline double
|
||||||
|
do_interp (double a, double b, double fraction)
|
||||||
|
{
|
||||||
|
double retval = (a + ((b - a) * fraction));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double
|
||||||
|
do_interp_deg (double a, double b, double fraction)
|
||||||
|
{
|
||||||
|
a = fmod(a, 360);
|
||||||
|
b = fmod(b, 360);
|
||||||
|
if (fabs(b-a) > 180) {
|
||||||
|
if (a < b)
|
||||||
|
a += 360;
|
||||||
|
else
|
||||||
|
b += 360;
|
||||||
|
}
|
||||||
|
return fmod(do_interp(a, b, fraction), 360);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
interpolate (const FGEnvironment * env1, const FGEnvironment * env2,
|
||||||
|
double fraction, FGEnvironment * result)
|
||||||
|
{
|
||||||
|
result->set_visibility_m
|
||||||
|
(do_interp(env1->get_visibility_m(),
|
||||||
|
env2->get_visibility_m(),
|
||||||
|
fraction));
|
||||||
|
|
||||||
|
result->set_temperature_sea_level_degc
|
||||||
|
(do_interp(env1->get_temperature_sea_level_degc(),
|
||||||
|
env2->get_temperature_sea_level_degc(),
|
||||||
|
fraction));
|
||||||
|
|
||||||
|
result->set_dewpoint_sea_level_degc
|
||||||
|
(do_interp(env1->get_dewpoint_sea_level_degc(),
|
||||||
|
env2->get_dewpoint_sea_level_degc(),
|
||||||
|
fraction));
|
||||||
|
|
||||||
|
result->set_pressure_sea_level_inhg
|
||||||
|
(do_interp(env1->get_pressure_sea_level_inhg(),
|
||||||
|
env2->get_pressure_sea_level_inhg(),
|
||||||
|
fraction));
|
||||||
|
|
||||||
|
result->set_wind_from_heading_deg
|
||||||
|
(do_interp_deg(env1->get_wind_from_heading_deg(),
|
||||||
|
env2->get_wind_from_heading_deg(),
|
||||||
|
fraction));
|
||||||
|
|
||||||
|
result->set_wind_speed_kt
|
||||||
|
(do_interp(env1->get_wind_speed_kt(),
|
||||||
|
env2->get_wind_speed_kt(),
|
||||||
|
fraction));
|
||||||
|
|
||||||
|
result->set_elevation_ft
|
||||||
|
(do_interp(env1->get_elevation_ft(),
|
||||||
|
env2->get_elevation_ft(),
|
||||||
|
fraction));
|
||||||
|
|
||||||
|
result->set_turbulence_norm
|
||||||
|
(do_interp(env1->get_turbulence_norm(),
|
||||||
|
env2->get_turbulence_norm(),
|
||||||
|
fraction));
|
||||||
|
}
|
||||||
|
|
||||||
// end of environment.cxx
|
// end of environment.cxx
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class SGInterpTable;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model the natural environment.
|
* Model the natural environment.
|
||||||
|
@ -54,6 +52,10 @@ public:
|
||||||
FGEnvironment (const FGEnvironment &environment);
|
FGEnvironment (const FGEnvironment &environment);
|
||||||
virtual ~FGEnvironment();
|
virtual ~FGEnvironment();
|
||||||
|
|
||||||
|
virtual void copy (const FGEnvironment &environment);
|
||||||
|
|
||||||
|
virtual void read (const SGPropertyNode * node);
|
||||||
|
|
||||||
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;
|
||||||
|
@ -70,6 +72,8 @@ public:
|
||||||
virtual double get_wind_from_east_fps () const;
|
virtual double get_wind_from_east_fps () const;
|
||||||
virtual double get_wind_from_down_fps () const;
|
virtual double get_wind_from_down_fps () const;
|
||||||
|
|
||||||
|
virtual double get_turbulence_norm () 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);
|
||||||
|
@ -85,17 +89,13 @@ public:
|
||||||
virtual void set_wind_from_east_fps (double e);
|
virtual void set_wind_from_east_fps (double e);
|
||||||
virtual void set_wind_from_down_fps (double d);
|
virtual void set_wind_from_down_fps (double d);
|
||||||
|
|
||||||
protected:
|
virtual void set_turbulence_norm (double t);
|
||||||
|
|
||||||
friend class FGEnvironmentMgr;
|
|
||||||
|
|
||||||
virtual double get_elevation_ft () const;
|
virtual double get_elevation_ft () const;
|
||||||
virtual void set_elevation_ft (double elevation_ft);
|
virtual void set_elevation_ft (double elevation_ft);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void _setup_tables ();
|
|
||||||
|
|
||||||
void _recalc_hdgspd ();
|
void _recalc_hdgspd ();
|
||||||
void _recalc_ne ();
|
void _recalc_ne ();
|
||||||
|
|
||||||
|
@ -107,9 +107,6 @@ private:
|
||||||
void _recalc_alt_pressure ();
|
void _recalc_alt_pressure ();
|
||||||
void _recalc_density ();
|
void _recalc_density ();
|
||||||
|
|
||||||
SGInterpTable * _temperature_degc_table;
|
|
||||||
SGInterpTable * _pressure_inhg_table;
|
|
||||||
|
|
||||||
double elevation_ft;
|
double elevation_ft;
|
||||||
|
|
||||||
double visibility_m;
|
double visibility_m;
|
||||||
|
@ -123,6 +120,8 @@ private:
|
||||||
double pressure_inhg;
|
double pressure_inhg;
|
||||||
double density_slugft3;
|
double density_slugft3;
|
||||||
|
|
||||||
|
double turbulence_norm;
|
||||||
|
|
||||||
double wind_from_heading_deg;
|
double wind_from_heading_deg;
|
||||||
double wind_speed_kt;
|
double wind_speed_kt;
|
||||||
|
|
||||||
|
@ -132,4 +131,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void interpolate (const FGEnvironment * env1, const FGEnvironment * env2,
|
||||||
|
double fraction, FGEnvironment * result);
|
||||||
|
|
||||||
#endif // _ENVIRONMENT_HXX
|
#endif // _ENVIRONMENT_HXX
|
||||||
|
|
|
@ -156,4 +156,143 @@ FGUserDefEnvironmentCtrl::update (double dt)
|
||||||
_environment->set_wind_speed_kt(_current_wind_speed_kt);
|
_environment->set_wind_speed_kt(_current_wind_speed_kt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGInterpolateEnvironmentCtrl.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FGInterpolateEnvironmentCtrl::FGInterpolateEnvironmentCtrl ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGInterpolateEnvironmentCtrl::~FGInterpolateEnvironmentCtrl ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _boundary_table.size(); i++)
|
||||||
|
delete _boundary_table[i];
|
||||||
|
for (int i = 0; i < _aloft_table.size(); i++)
|
||||||
|
delete _aloft_table[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FGInterpolateEnvironmentCtrl::init ()
|
||||||
|
{
|
||||||
|
read_table(fgGetNode("/environment/config/boundary", true),
|
||||||
|
_boundary_table);
|
||||||
|
read_table(fgGetNode("/environment/config/aloft", true),
|
||||||
|
_aloft_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGInterpolateEnvironmentCtrl::reinit ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _boundary_table.size(); i++)
|
||||||
|
delete _boundary_table[i];
|
||||||
|
for (int i = 0; i < _aloft_table.size(); i++)
|
||||||
|
delete _aloft_table[i];
|
||||||
|
_boundary_table.clear();
|
||||||
|
_aloft_table.clear();
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGInterpolateEnvironmentCtrl::read_table (const SGPropertyNode * node,
|
||||||
|
vector<bucket *> &table)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < node->nChildren(); i++) {
|
||||||
|
const SGPropertyNode * child = node->getChild(i);
|
||||||
|
if (!strcmp(child->getName(), "entry") &&
|
||||||
|
child->getStringValue("elevation-ft", "")[0] != '\0') {
|
||||||
|
bucket * b = new bucket;
|
||||||
|
if (i > 0)
|
||||||
|
b->environment.copy(table[i-1]->environment);
|
||||||
|
b->environment.read(child);
|
||||||
|
b->altitude_ft = b->environment.get_elevation_ft();
|
||||||
|
table.push_back(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort(table.begin(), table.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGInterpolateEnvironmentCtrl::update (double delta_time_sec)
|
||||||
|
{
|
||||||
|
// FIXME
|
||||||
|
double altitude_ft = fgGetDouble("/position/altitude-ft");
|
||||||
|
double altitude_agl_ft = fgGetDouble("/position/altitude-agl-ft");
|
||||||
|
double boundary_transition =
|
||||||
|
fgGetDouble("/environment/config/boundary-transition-ft", 500);
|
||||||
|
|
||||||
|
double ground_elevation_ft = altitude_ft - altitude_agl_ft;
|
||||||
|
|
||||||
|
int length = _boundary_table.size();
|
||||||
|
|
||||||
|
if (length > 0) {
|
||||||
|
// boundary table
|
||||||
|
double boundary_limit = _boundary_table[length-1]->altitude_ft;
|
||||||
|
if (boundary_limit >= altitude_agl_ft) {
|
||||||
|
do_interpolate(_boundary_table, altitude_agl_ft,
|
||||||
|
_environment);
|
||||||
|
return;
|
||||||
|
} else if ((boundary_limit + boundary_transition) >= altitude_agl_ft) {
|
||||||
|
// both tables
|
||||||
|
do_interpolate(_boundary_table, altitude_agl_ft, &env1);
|
||||||
|
do_interpolate(_aloft_table, altitude_ft, &env2);
|
||||||
|
double fraction =
|
||||||
|
(altitude_agl_ft - boundary_limit) / boundary_transition;
|
||||||
|
interpolate(&env1, &env2, fraction, _environment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// aloft table
|
||||||
|
do_interpolate(_aloft_table, altitude_ft, _environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGInterpolateEnvironmentCtrl::do_interpolate (vector<bucket *> &table,
|
||||||
|
double altitude_ft,
|
||||||
|
FGEnvironment * environment)
|
||||||
|
{
|
||||||
|
int length = table.size();
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Boundary conditions
|
||||||
|
if ((length == 1) || (table[0]->altitude_ft >= altitude_ft)) {
|
||||||
|
environment->copy(table[0]->environment);
|
||||||
|
return;
|
||||||
|
} else if (table[length-1]->altitude_ft <= altitude_ft) {
|
||||||
|
environment->copy(table[length-1]->environment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the interpolation table
|
||||||
|
for (int i = 0; i < length - 1; i++) {
|
||||||
|
if ((i == length - 1) || (table[i]->altitude_ft <= altitude_ft)) {
|
||||||
|
FGEnvironment * env1 = &(table[i]->environment);
|
||||||
|
FGEnvironment * env2 = &(table[i+1]->environment);
|
||||||
|
double fraction;
|
||||||
|
if (table[i]->altitude_ft == table[i+1]->altitude_ft)
|
||||||
|
fraction = 1.0;
|
||||||
|
else
|
||||||
|
fraction =
|
||||||
|
((altitude_ft - table[i]->altitude_ft) /
|
||||||
|
(table[i+1]->altitude_ft - table[i]->altitude_ft));
|
||||||
|
interpolate(env1, env2, fraction, environment);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGInterpolateEnvironmentCtrl::bucket::operator< (const bucket &b) const
|
||||||
|
{
|
||||||
|
return (altitude_ft < b.altitude_ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// end of environment_ctrl.cxx
|
// end of environment_ctrl.cxx
|
||||||
|
|
|
@ -31,8 +31,14 @@
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
SG_USING_STD(vector);
|
||||||
|
|
||||||
class SGPropertyNode;
|
class SGPropertyNode;
|
||||||
|
|
||||||
|
#include <Main/fgfs.hxx>
|
||||||
|
|
||||||
#include "environment.hxx"
|
#include "environment.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +46,7 @@ class SGPropertyNode;
|
||||||
/**
|
/**
|
||||||
* Interface to control environment information for a specific location.
|
* Interface to control environment information for a specific location.
|
||||||
*/
|
*/
|
||||||
class FGEnvironmentCtrl
|
class FGEnvironmentCtrl : public FGSubsystem
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -61,9 +67,6 @@ public:
|
||||||
virtual double getLatitudeDeg () const { return _lat_deg; }
|
virtual double getLatitudeDeg () const { return _lat_deg; }
|
||||||
virtual double getElevationFt () const { return _elev_ft; }
|
virtual double getElevationFt () const { return _elev_ft; }
|
||||||
|
|
||||||
virtual void init () = 0;
|
|
||||||
virtual void update (double dt) = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
FGEnvironment * _environment;
|
FGEnvironment * _environment;
|
||||||
|
@ -97,4 +100,38 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interplation controller using user-supplied parameters.
|
||||||
|
*/
|
||||||
|
class FGInterpolateEnvironmentCtrl : public FGEnvironmentCtrl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FGInterpolateEnvironmentCtrl ();
|
||||||
|
virtual ~FGInterpolateEnvironmentCtrl ();
|
||||||
|
|
||||||
|
virtual void init ();
|
||||||
|
virtual void reinit ();
|
||||||
|
virtual void update (double delta_time_sec);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct bucket {
|
||||||
|
double altitude_ft;
|
||||||
|
FGEnvironment environment;
|
||||||
|
bool operator< (const bucket &b) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void read_table (const SGPropertyNode * node, vector<bucket *> &table);
|
||||||
|
void do_interpolate (vector<bucket *> &table, double altitude_ft,
|
||||||
|
FGEnvironment * environment);
|
||||||
|
|
||||||
|
FGEnvironment env1, env2; // temporaries
|
||||||
|
|
||||||
|
vector<bucket *> _boundary_table;
|
||||||
|
vector<bucket *> _aloft_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // _ENVIRONMENT_CTRL_HXX
|
#endif // _ENVIRONMENT_CTRL_HXX
|
||||||
|
|
|
@ -35,8 +35,10 @@ extern SGSky *thesky; // FIXME: from main.cxx
|
||||||
|
|
||||||
FGEnvironmentMgr::FGEnvironmentMgr ()
|
FGEnvironmentMgr::FGEnvironmentMgr ()
|
||||||
: _environment(new FGEnvironment),
|
: _environment(new FGEnvironment),
|
||||||
_controller(new FGUserDefEnvironmentCtrl)
|
_controller(new FGInterpolateEnvironmentCtrl)
|
||||||
{
|
{
|
||||||
|
_controller->setEnvironment(_environment);
|
||||||
|
set_subsystem("controller", _controller, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
FGEnvironmentMgr::~FGEnvironmentMgr ()
|
FGEnvironmentMgr::~FGEnvironmentMgr ()
|
||||||
|
@ -49,8 +51,15 @@ void
|
||||||
FGEnvironmentMgr::init ()
|
FGEnvironmentMgr::init ()
|
||||||
{
|
{
|
||||||
SG_LOG( SG_GENERAL, SG_INFO, "Initializing environment subsystem");
|
SG_LOG( SG_GENERAL, SG_INFO, "Initializing environment subsystem");
|
||||||
_controller->setEnvironment(_environment);
|
FGSubsystemGroup::init();
|
||||||
_controller->init();
|
_update_fdm();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGEnvironmentMgr::reinit ()
|
||||||
|
{
|
||||||
|
SG_LOG( SG_GENERAL, SG_INFO, "Reinitializing environment subsystem");
|
||||||
|
FGSubsystemGroup::reinit();
|
||||||
_update_fdm();
|
_update_fdm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +106,10 @@ FGEnvironmentMgr::bind ()
|
||||||
&FGEnvironment::get_wind_from_down_fps,
|
&FGEnvironment::get_wind_from_down_fps,
|
||||||
&FGEnvironment::set_wind_from_down_fps);
|
&FGEnvironment::set_wind_from_down_fps);
|
||||||
fgSetArchivable("/environment/wind-from-down-fps");
|
fgSetArchivable("/environment/wind-from-down-fps");
|
||||||
|
fgTie("/environment/turbulence-norm", _environment,
|
||||||
|
&FGEnvironment::get_turbulence_norm,
|
||||||
|
&FGEnvironment::set_turbulence_norm);
|
||||||
|
fgSetArchivable("/environment/turbulence-norm");
|
||||||
|
|
||||||
for (int i = 0; i < MAX_CLOUD_LAYERS; i++) {
|
for (int i = 0; i < MAX_CLOUD_LAYERS; i++) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
@ -160,7 +173,8 @@ FGEnvironmentMgr::unbind ()
|
||||||
void
|
void
|
||||||
FGEnvironmentMgr::update (double dt)
|
FGEnvironmentMgr::update (double dt)
|
||||||
{
|
{
|
||||||
_controller->update(dt);
|
FGSubsystemGroup::update(dt);
|
||||||
|
|
||||||
// FIXME: the FDMs should update themselves
|
// FIXME: the FDMs should update themselves
|
||||||
current_aircraft.fdm_state
|
current_aircraft.fdm_state
|
||||||
->set_Velocities_Local_Airmass(_environment->get_wind_from_north_fps(),
|
->set_Velocities_Local_Airmass(_environment->get_wind_from_north_fps(),
|
||||||
|
|
|
@ -40,7 +40,7 @@ class FGEnvironmentCtrl;
|
||||||
/**
|
/**
|
||||||
* Manage environment information.
|
* Manage environment information.
|
||||||
*/
|
*/
|
||||||
class FGEnvironmentMgr : public FGSubsystem
|
class FGEnvironmentMgr : public FGSubsystemGroup
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -53,6 +53,7 @@ public:
|
||||||
virtual ~FGEnvironmentMgr ();
|
virtual ~FGEnvironmentMgr ();
|
||||||
|
|
||||||
virtual void init ();
|
virtual void init ();
|
||||||
|
virtual void reinit ();
|
||||||
virtual void bind ();
|
virtual void bind ();
|
||||||
virtual void unbind ();
|
virtual void unbind ();
|
||||||
virtual void update (double dt);
|
virtual void update (double dt);
|
||||||
|
|
|
@ -1477,8 +1477,7 @@ bool fgInitSubsystems() {
|
||||||
global_events.Register( "weather update", &fgUpdateWeatherDatabase,
|
global_events.Register( "weather update", &fgUpdateWeatherDatabase,
|
||||||
30000);
|
30000);
|
||||||
#else
|
#else
|
||||||
globals->get_environment_mgr()->init();
|
globals->add_subsystem("environment", new FGEnvironmentMgr);
|
||||||
globals->get_environment_mgr()->bind();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FG_USE_CLOUDS_3D
|
#ifdef FG_USE_CLOUDS_3D
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
#include <simgear/misc/commands.hxx>
|
#include <simgear/misc/commands.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
|
||||||
#include <Environment/environment_mgr.hxx>
|
|
||||||
|
|
||||||
#include "globals.hxx"
|
#include "globals.hxx"
|
||||||
#include "viewmgr.hxx"
|
#include "viewmgr.hxx"
|
||||||
|
|
||||||
|
@ -59,7 +57,6 @@ FGGlobals::FGGlobals() :
|
||||||
route( NULL ),
|
route( NULL ),
|
||||||
current_panel( NULL ),
|
current_panel( NULL ),
|
||||||
soundmgr( NULL ),
|
soundmgr( NULL ),
|
||||||
environment_mgr( NULL ),
|
|
||||||
ATC_mgr( NULL ),
|
ATC_mgr( NULL ),
|
||||||
ATC_display( NULL ),
|
ATC_display( NULL ),
|
||||||
AI_mgr( NULL ),
|
AI_mgr( NULL ),
|
||||||
|
|
|
@ -65,8 +65,6 @@ class FGATCDisplay;
|
||||||
class FGAircraftModel;
|
class FGAircraftModel;
|
||||||
class FGAutopilot;
|
class FGAutopilot;
|
||||||
class FGControls;
|
class FGControls;
|
||||||
class FGEnvironment;
|
|
||||||
class FGEnvironmentMgr;
|
|
||||||
class FGIO;
|
class FGIO;
|
||||||
class FGModelMgr;
|
class FGModelMgr;
|
||||||
class FGScenery;
|
class FGScenery;
|
||||||
|
@ -136,9 +134,6 @@ private:
|
||||||
// sound manager
|
// sound manager
|
||||||
SGSoundMgr *soundmgr;
|
SGSoundMgr *soundmgr;
|
||||||
|
|
||||||
// environment information
|
|
||||||
FGEnvironmentMgr * environment_mgr;
|
|
||||||
|
|
||||||
// ATC manager
|
// ATC manager
|
||||||
FGATCMgr *ATC_mgr;
|
FGATCMgr *ATC_mgr;
|
||||||
|
|
||||||
|
@ -245,13 +240,6 @@ public:
|
||||||
inline SGRoute *get_route() const { return route; }
|
inline SGRoute *get_route() const { return route; }
|
||||||
inline void set_route( SGRoute *r ) { route = r; }
|
inline void set_route( SGRoute *r ) { route = r; }
|
||||||
|
|
||||||
inline FGEnvironmentMgr * get_environment_mgr() {
|
|
||||||
return environment_mgr;
|
|
||||||
}
|
|
||||||
inline void set_environment_mgr(FGEnvironmentMgr * mgr) {
|
|
||||||
environment_mgr = mgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FGATCMgr *get_ATC_mgr() const { return ATC_mgr; }
|
inline FGATCMgr *get_ATC_mgr() const { return ATC_mgr; }
|
||||||
inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; }
|
inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; }
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@ SG_USING_STD(endl);
|
||||||
#include <simgear/ephemeris/ephemeris.hxx>
|
#include <simgear/ephemeris/ephemeris.hxx>
|
||||||
#include <simgear/route/route.hxx>
|
#include <simgear/route/route.hxx>
|
||||||
|
|
||||||
|
#include <Environment/environment_mgr.hxx>
|
||||||
|
|
||||||
#ifdef SG_MATH_EXCEPTION_CLASH
|
#ifdef SG_MATH_EXCEPTION_CLASH
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -183,8 +185,6 @@ static double delta_time_sec = 0;
|
||||||
|
|
||||||
#ifdef FG_WEATHERCM
|
#ifdef FG_WEATHERCM
|
||||||
# include <WeatherCM/FGLocalWeatherDatabase.h>
|
# include <WeatherCM/FGLocalWeatherDatabase.h>
|
||||||
#else
|
|
||||||
# include <Environment/environment_mgr.hxx>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -952,10 +952,6 @@ void fgUpdateTimeDepCalcs() {
|
||||||
cur_fdm_state->bind();
|
cur_fdm_state->bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FG_WEATHERCM
|
|
||||||
globals->get_environment_mgr()->update(delta_time_sec);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// conceptually, the following block could be done for each fdm
|
// conceptually, the following block could be done for each fdm
|
||||||
// instance ...
|
// instance ...
|
||||||
if ( !cur_fdm_state->get_inited() ) {
|
if ( !cur_fdm_state->get_inited() ) {
|
||||||
|
@ -1582,10 +1578,6 @@ static bool fgMainInit( int argc, char **argv ) {
|
||||||
|
|
||||||
globals = new FGGlobals;
|
globals = new FGGlobals;
|
||||||
|
|
||||||
#ifndef FG_WEATHERCM
|
|
||||||
globals->set_environment_mgr(new FGEnvironmentMgr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// seed the random number generater
|
// seed the random number generater
|
||||||
sg_srandom_time();
|
sg_srandom_time();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue