#include <simgear/constants.h>
#include <simgear/math/sg_types.hxx>
#include <simgear/misc/props.hxx>
+
+#include <Main/fg_props.hxx>
#include <Aircraft/aircraft.hxx>
+#ifdef FG_WEATHERCM
+# include <WeatherCM/FGLocalWeatherDatabase.h>
+#else
+# include <Environment/environment_mgr.hxx>
+# include <Environment/environment.hxx>
+#endif
SG_USING_NAMESPACE(std);
\f
////////////////////////////////////////////////////////////////////////
-// Declare the functions that read the variables
+// Constructor and destructor.
////////////////////////////////////////////////////////////////////////
-double FGSteam::the_STATIC_inhg = 29.92;
-double FGSteam::the_ALT_ft = 0.0; // Indicated altitude
-double FGSteam::get_ALT_ft() { _CatchUp(); return the_ALT_ft; }
-
-double FGSteam::the_ALT_datum_mb = 1013.0;
-double FGSteam::get_ALT_datum_mb() { return the_ALT_datum_mb; }
-
-void FGSteam::set_ALT_datum_mb ( double datum_mb ) {
- the_ALT_datum_mb = datum_mb;
+FGSteam::FGSteam ()
+ :
+ the_ALT_ft(0.0),
+ the_ALT_datum_mb(1013.0),
+ the_TC_rad(0.0),
+ the_TC_std(0.0),
+ the_STATIC_inhg(29.92),
+ the_VACUUM_inhg(0.0),
+ the_VSI_fps(0.0),
+ the_VSI_case(29.92),
+ the_MH_deg(0.0),
+ the_MH_degps(0.0),
+ the_MH_err(0.0),
+ the_DG_deg(0.0),
+ the_DG_degps(0.0),
+ the_DG_inhg(0.0),
+ the_DG_err(0.0),
+ _UpdateTimePending(1000000)
+{
}
-double FGSteam::get_ASI_kias() { return fgGetDouble("/velocities/airspeed"); }
-
-double FGSteam::the_VSI_case = 29.92;
-double FGSteam::the_VSI_fps = 0.0;
-double FGSteam::get_VSI_fps() { _CatchUp(); return the_VSI_fps; }
+FGSteam::~FGSteam ()
+{
+}
-double FGSteam::the_VACUUM_inhg = 0.0;
-double FGSteam::get_VACUUM_inhg() { _CatchUp(); return the_VACUUM_inhg; }
+void
+FGSteam::init ()
+{
+ _heading_deg_node = fgGetNode("/orientation/heading-deg", true);
+ _mag_var_deg_node = fgGetNode("/environment/magnetic-variation-deg", true);
+ _mag_dip_deg_node = fgGetNode("/environment/magnetic-dip-deg", true);
+ _engine_0_rpm_node = fgGetNode("/engines/engine[0]/rpm", true);
+ _pressure_inhg_node = fgGetNode("environment/pressure-inhg", true);
+}
-double FGSteam::the_MH_err = 0.0;
-double FGSteam::the_MH_deg = 0.0;
-double FGSteam::the_MH_degps = 0.0;
-double FGSteam::get_MH_deg () { _CatchUp(); return the_MH_deg; }
+void
+FGSteam::update (double dt_sec)
+{
+ _UpdateTimePending += dt_sec;
+ _CatchUp();
+}
-double FGSteam::the_DG_err = 0.0;
-double FGSteam::the_DG_deg = 0.0;
-double FGSteam::the_DG_degps = 0.0;
-double FGSteam::the_DG_inhg = 0.0;
-double FGSteam::get_DG_deg () { _CatchUp(); return the_DG_deg; }
-double FGSteam::get_DG_err () { _CatchUp(); return the_DG_err; }
+void
+FGSteam::bind ()
+{
+ fgTie("/steam/airspeed-kt", this, &FGSteam::get_ASI_kias);
+ fgSetArchivable("/steam/airspeed-kt");
+ fgTie("/steam/altitude-ft", this, &FGSteam::get_ALT_ft);
+ fgSetArchivable("/steam/altitude-ft");
+ fgTie("/steam/altimeter-datum-mb", this,
+ &FGSteam::get_ALT_datum_mb, &FGSteam::set_ALT_datum_mb,
+ false); /* don't modify the value */
+ fgSetArchivable("/steam/altimeter-datum-mb");
+ fgTie("/steam/turn-rate", this, &FGSteam::get_TC_std);
+ fgSetArchivable("/steam/turn-rate");
+ fgTie("/steam/slip-skid",this, &FGSteam::get_TC_rad);
+ fgSetArchivable("/steam/slip-skid");
+ fgTie("/steam/vertical-speed-fps", this, &FGSteam::get_VSI_fps);
+ fgSetArchivable("/steam/vertical-speed-fps");
+ fgTie("/steam/gyro-compass-deg", this, &FGSteam::get_DG_deg);
+ fgSetArchivable("/steam/gyro-compass-deg");
+ // fgTie("/steam/adf-deg", FGSteam::get_HackADF_deg);
+ // fgSetArchivable("/steam/adf-deg");
+ fgTie("/steam/gyro-compass-error-deg", this,
+ &FGSteam::get_DG_err, &FGSteam::set_DG_err,
+ false); /* don't modify the value */
+ fgSetArchivable("/steam/gyro-compass-error-deg");
+ fgTie("/steam/mag-compass-deg", this, &FGSteam::get_MH_deg);
+ fgSetArchivable("/steam/mag-compass-deg");
+}
-void FGSteam::set_DG_err ( double approx_magvar ) {
- the_DG_err = approx_magvar;
+void
+FGSteam::unbind ()
+{
+ fgUntie("/steam/airspeed-kt");
+ fgUntie("/steam/altitude-ft");
+ fgUntie("/steam/altimeter-datum-mb");
+ fgUntie("/steam/turn-rate");
+ fgUntie("/steam/slip-skid");
+ fgUntie("/steam/vertical-speed-fps");
+ fgUntie("/steam/gyro-compass-deg");
+ fgUntie("/steam/gyro-compass-error-deg");
+ fgUntie("/steam/mag-compass-deg");
}
-double FGSteam::the_TC_rad = 0.0;
-double FGSteam::the_TC_std = 0.0;
-double FGSteam::get_TC_rad () { _CatchUp(); return the_TC_rad; }
-double FGSteam::get_TC_std () { _CatchUp(); return the_TC_std; }
\f
////////////////////////////////////////////////////////////////////////
-// Recording the current time
+// Declare the functions that read the variables
////////////////////////////////////////////////////////////////////////
+double
+FGSteam::get_ALT_ft () const
+{
+ return the_ALT_ft;
+}
+
+double
+FGSteam::get_ALT_datum_mb () const
+{
+ return the_ALT_datum_mb;
+}
+
+void
+FGSteam::set_ALT_datum_mb (double datum_mb)
+{
+ the_ALT_datum_mb = datum_mb;
+}
+
+double
+FGSteam::get_ASI_kias () const
+{
+ return fgGetDouble("/velocities/airspeed-kt");
+}
+
+double
+FGSteam::get_VSI_fps () const
+{
+ return the_VSI_fps;
+}
+
+double
+FGSteam::get_VACUUM_inhg () const
+{
+ return the_VACUUM_inhg;
+}
+
+double
+FGSteam::get_MH_deg () const
+{
+ return the_MH_deg;
+}
+
+double
+FGSteam::get_DG_deg () const
+{
+ return the_DG_deg;
+}
-int FGSteam::_UpdatesPending = 1000000; /* Forces filter to reset */
+double
+FGSteam::get_DG_err () const
+{
+ return the_DG_err;
+}
+void
+FGSteam::set_DG_err (double approx_magvar)
+{
+ the_DG_err = approx_magvar;
+}
- // FIXME: no need to use static
- // functions any longer.
+double
+FGSteam::get_TC_rad () const
+{
+ return the_TC_rad;
+}
-void FGSteam::update ( int timesteps )
+double
+FGSteam::get_TC_std () const
{
- if (!isTied) {
- isTied = true;
- fgTie("/steam/airspeed", FGSteam::get_ASI_kias);
- fgTie("/steam/altitude", FGSteam::get_ALT_ft);
- fgTie("/steam/altimeter-datum-mb",
- FGSteam::get_ALT_datum_mb, FGSteam::set_ALT_datum_mb,
- false); /* don't modify the value */
- fgTie("/steam/turn-rate", FGSteam::get_TC_std);
- fgTie("/steam/slip-skid", FGSteam::get_TC_rad);
- fgTie("/steam/vertical-speed", FGSteam::get_VSI_fps);
- fgTie("/steam/gyro-compass", FGSteam::get_DG_deg);
- fgTie("/steam/adf", FGSteam::get_HackADF_deg);
- fgTie("/steam/gyro-compass-error",
- FGSteam::get_DG_err, FGSteam::set_DG_err,
- false); /* don't modify the value */
- fgTie("/steam/mag-compass", FGSteam::get_MH_deg);
- }
- _UpdatesPending += timesteps;
+ return the_TC_std;
}
+\f
+////////////////////////////////////////////////////////////////////////
+// Recording the current time
+////////////////////////////////////////////////////////////////////////
+
+
/* tc should be (elapsed_time_between_updates / desired_smoothing_time) */
void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
{
void FGSteam::_CatchUp()
-{ if ( _UpdatesPending != 0 )
- { double dt = _UpdatesPending * 1.0 /
- fgGetInt("/sim/model-hz"); // FIXME: inefficient
+{
+ if ( _UpdateTimePending != 0 )
+ {
+ double dt = _UpdateTimePending;
double AccN, AccE, AccU;
/* int i, j; */
double d, the_ENGINE_rpm;
-#if 0
- /**************************
- There is the possibility that this is the first call.
- If this is the case, we will emit the feature registrations
- just to be on the safe side. Doing it more than once will
- waste CPU time but doesn't hurt anything really.
- */
- if ( _UpdatesPending > 999999 )
- { FGFeature::register_int ( "Avionics/NAV1/Localizer", &NAV1_LOC );
- FGFeature::register_double ( "Avionics/NAV1/Latitude", &NAV1_Lat );
- FGFeature::register_double ( "Avionics/NAV1/Longitude", &NAV1_Lon );
- FGFeature::register_double ( "Avionics/NAV1/Radial", &NAV1_Rad );
- FGFeature::register_double ( "Avionics/NAV1/Altitude", &NAV1_Alt );
- FGFeature::register_int ( "Avionics/NAV2/Localizer", &NAV2_LOC );
- FGFeature::register_double ( "Avionics/NAV2/Latitude", &NAV2_Lat );
- FGFeature::register_double ( "Avionics/NAV2/Longitude", &NAV2_Lon );
- FGFeature::register_double ( "Avionics/NAV2/Radial", &NAV2_Rad );
- FGFeature::register_double ( "Avionics/NAV2/Altitude", &NAV2_Alt );
- FGFeature::register_double ( "Avionics/ADF/Latitude", &ADF_Lat );
- FGFeature::register_double ( "Avionics/ADF/Longitude", &ADF_Lon );
- }
-#endif
-
/**************************
Someone has called our update function and
it turns out that we are running somewhat behind.
More subtle flaw is having it not move or a travel limit
occasionally due to some dirt in the tube or on the ball.
*/
- d = - current_aircraft.fdm_state->get_A_Z_pilot();
+ d = -current_aircraft.fdm_state->get_A_Z_pilot();
if ( d < 1 ) d = 1;
set_lowpass ( & the_TC_rad,
current_aircraft.fdm_state->get_A_Y_pilot () / d,
AccN = current_aircraft.fdm_state->get_V_dot_north();
AccE = current_aircraft.fdm_state->get_V_dot_east();
AccU = current_aircraft.fdm_state->get_V_dot_down()
- - 9.81 / 0.3;
- if ( fabs(the_TC_rad) > 0.2 )
+ - 9.81 * SG_METER_TO_FEET;
+ if ( fabs(the_TC_rad) > 0.2 /* 2.0 */ )
{ /* Massive sideslip jams it; it stops turning */
the_MH_degps = 0.0;
- the_MH_err = fgGetDouble("/orientation/heading") - the_MH_deg;
+ the_MH_err = _heading_deg_node->getDoubleValue() - the_MH_deg;
} else
{ double MagDip, MagVar, CosDip;
double FrcN, FrcE, FrcU, AccTot;
double EdgN, EdgE, EdgU;
double TrqN, TrqE, TrqU, Torque;
/* Find a force vector towards exact magnetic north */
- MagVar = fgGetDouble("/environment/magnetic-variation")
+ MagVar = _mag_var_deg_node->getDoubleValue()
/ SGD_RADIANS_TO_DEGREES;
- MagDip = fgGetDouble("/environment/magnetic-dip")
+ MagDip = _mag_var_deg_node->getDoubleValue()
/ SGD_RADIANS_TO_DEGREES;
CosDip = cos ( MagDip );
FrcN = CosDip * cos ( MagVar );
}
if ( the_MH_err > 180.0 ) the_MH_err -= 360.0; else
if ( the_MH_err < -180.0 ) the_MH_err += 360.0;
- the_MH_deg = fgGetDouble("/orientation/heading") - the_MH_err;
+ the_MH_deg = _heading_deg_node->getDoubleValue() - the_MH_err;
}
/**************************
scaling capability for the vacuum pump later on.
When we have a real engine model, we can ask it.
*/
- the_ENGINE_rpm = controls.get_throttle(0) * 26.0;
+ the_ENGINE_rpm = _engine_0_rpm_node->getDoubleValue();
/**************************
First, we need to know what the static line is reporting,
- which is a whole simulation area in itself. For now, we cheat.
+ which is a whole simulation area in itself.
We filter the actual value by one second to
account for the line impedance of the plumbing.
*/
- double static_inhg
- = altFtToPressInHg(fgGetDouble("/position/altitude"));
+#ifdef FG_WEATHERCM
+ sgVec3 plane_pos = { cur_fdm_state->get_Latitude(),
+ cur_fdm_state->get_Longitude(),
+ cur_fdm_state->get_Altitude() * SG_FEET_TO_METER };
+ double static_inhg = WeatherDatabase->get(plane_pos).AirPressure *
+ (0.01 / INHG_TO_MB);
+#else
+ double static_inhg = _pressure_inhg_node->getDoubleValue();
+#endif
+
set_lowpass ( & the_STATIC_inhg, static_inhg, dt );
/*
> have it tumble when you exceed the usual pitch or bank limits,
> put in those insidious turning errors ... for now anyway.
*/
- if ( _UpdatesPending > 999999 )
- the_DG_err = fgGetDouble("/environment/magnetic-variation");
+ if ( _UpdateTimePending > 999999 )
+ the_DG_err = fgGetDouble("/environment/magnetic-variation-deg");
the_DG_degps = 0.01; /* HACK! */
if (dt<1.0) the_DG_err += dt * the_DG_degps;
- the_DG_deg = fgGetDouble("/orientation/heading") - the_DG_err;
+ the_DG_deg = _heading_deg_node->getDoubleValue() - the_DG_err;
/**************************
Finished updates, now clear the timer
*/
- _UpdatesPending = 0;
+ _UpdateTimePending = 0;
} else {
// cout << "0 Updates pending" << endl;
}
// Everything below is a transient hack; expect it to disappear
////////////////////////////////////////////////////////////////////////
-
-#if 0
-
-double FGSteam::get_HackGS_deg () {
- if ( current_radiostack->get_nav1_inrange() &&
- current_radiostack->get_nav1_has_gs() )
- {
- double x = current_radiostack->get_nav1_gs_dist();
- double y = (fgGetDouble("/position/altitude")
- - current_radiostack->get_nav1_elev())
- * SG_FEET_TO_METER;
- double angle = atan2( y, x ) * SGD_RADIANS_TO_DEGREES;
- return (current_radiostack->get_nav1_target_gs() - angle) * 5.0;
- } else {
- return 0.0;
- }
-}
-
-
-double FGSteam::get_HackVOR1_deg () {
- double r;
-
- if ( current_radiostack->get_nav1_inrange() ) {
- r = current_radiostack->get_nav1_heading()
- - current_radiostack->get_nav1_radial();
- // cout << "Radial = " << current_radiostack->get_nav1_radial()
- // << " Bearing = " << current_radiostack->get_nav1_heading()
- // << endl;
-
- if (r> 180.0) r-=360.0; else
- if (r<-180.0) r+=360.0;
- if ( fabs(r) > 90.0 )
- r = ( r<0.0 ? -r-180.0 : -r+180.0 );
- // According to Robin Peel, the ILS is 4x more sensitive than a vor
- if ( current_radiostack->get_nav1_loc() ) r *= 4.0;
- } else {
- r = 0.0;
- }
-
- return r;
-}
-
-
-double FGSteam::get_HackVOR2_deg () {
- double r;
-
- if ( current_radiostack->get_nav2_inrange() ) {
- r = current_radiostack->get_nav2_heading()
- - current_radiostack->get_nav2_radial();
- // cout << "Radial = " << current_radiostack->get_nav1_radial()
- // << " Bearing = " << current_radiostack->get_nav1_heading() << endl;
-
- if (r> 180.0) r-=360.0; else
- if (r<-180.0) r+=360.0;
- if ( fabs(r) > 90.0 )
- r = ( r<0.0 ? -r-180.0 : -r+180.0 );
- } else {
- r = 0.0;
- }
-
- return r;
-}
-#endif
-
-
-double FGSteam::get_HackOBS1_deg () {
- return current_radiostack->get_nav1_radial();
+double FGSteam::get_HackOBS1_deg () const
+{
+ return current_radiostack->get_nav1_radial();
}
-
-double FGSteam::get_HackOBS2_deg () {
+double FGSteam::get_HackOBS2_deg () const
+{
return current_radiostack->get_nav2_radial();
}
-double FGSteam::get_HackADF_deg () {
- static double last_r = 0;
-
- if ( current_radiostack->get_adf_inrange() ) {
- double r = current_radiostack->get_adf_heading()
- - fgGetDouble("orientation/heading");
- last_r = r;
- // cout << "Radial = " << current_radiostack->get_adf_heading()
- // << " Heading = " << FGBFI::getHeading() << endl;
- return r;
- } else {
- return last_r;
- }
-}
-
-
// end of steam.cxx