]> git.mxchange.org Git - flightgear.git/blobdiff - src/Cockpit/steam.cxx
Tweaks for Mips Irix compilers.
[flightgear.git] / src / Cockpit / steam.cxx
index 5955cda94e0595d8999b083d209186f732d5b6f4..af1a588963e9c906d932b1dafd43b235ded34953 100644 (file)
@@ -30,9 +30,9 @@
 #endif
 
 #include <simgear/constants.h>
-#include <simgear/math/fg_types.hxx>
+#include <simgear/math/sg_types.hxx>
+#include <simgear/misc/props.hxx>
 #include <Aircraft/aircraft.hxx>
-#include <Main/options.hxx>
 #include <Main/bfi.hxx>
 #include <NetworkOLK/features.hxx>
 
@@ -41,6 +41,8 @@ FG_USING_NAMESPACE(std);
 #include "radiostack.hxx"
 #include "steam.hxx"
 
+static bool isTied = false;
+
 
 \f
 ////////////////////////////////////////////////////////////////////////
@@ -51,9 +53,16 @@ FG_USING_NAMESPACE(std);
 
 
 double FGSteam::the_STATIC_inhg = 29.92;
-double FGSteam::the_ALT_ft = 0.0;
+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;
+}
+
 double FGSteam::get_ASI_kias() { return FGBFI::getAirspeed(); }
 
 double FGSteam::the_VSI_case = 29.92;
@@ -93,12 +102,33 @@ double FGSteam::get_TC_std () { _CatchUp(); return the_TC_std; }
 int FGSteam::_UpdatesPending = 1000000;  /* Forces filter to reset */
 
 
+                               // FIXME: no need to use static
+                               // functions any longer.
+
 void FGSteam::update ( int timesteps )
 {
+        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;
 }
 
 
+/* tc should be (elapsed_time_between_updates / desired_smoothing_time) */
 void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
 {
        if ( tc < 0.0 )
@@ -110,7 +140,7 @@ void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
                }
        } else
        if ( tc < 0.2 )
-       {       /* Normal mode of operation */
+       {       /* Normal mode of operation; fast approximation to exp(-tc) */
                (*outthe) = (*outthe) * ( 1.0 - tc )
                          +    inthe  * tc;
        } else
@@ -127,6 +157,38 @@ void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
 }
 
 
+#define INHG_TO_MB 33.86388  /* Inches_of_mercury * INHG_TO_MB == millibars. */
+
+// Convert air pressure to altitude by ICAO Standard Atmosphere
+double pressInHgToAltFt(double p_inhg)
+{
+    // Ref. Aviation Formulary, Ed Williams, www.best.com/~williams/avform.htm
+    const double P_0 = 29.92126;  // Std. MSL pressure, inHg. (=1013.25 mb)
+    const double p_Tr = 0.2233609 * P_0;  // Pressure at tropopause, same units.
+    const double h_Tr = 36089.24;  // Alt of tropopause, ft. (=11.0 km)
+
+    if (p_inhg > p_Tr)  // 0.0 to 11.0 km
+       return (1.0 - pow((p_inhg / P_0), 1.0 / 5.2558797)) / 6.8755856e-6;
+    return h_Tr + log10(p_inhg / p_Tr) / -4.806346e-5;  // 11.0 to 20.0 km
+    // We could put more code for higher altitudes here.
+}
+
+
+// Convert altitude to air pressure by ICAO Standard Atmosphere
+double altFtToPressInHg(double alt_ft)
+{
+    // Ref. Aviation Formulary, Ed Williams, www.best.com/~williams/avform.htm
+    const double P_0 = 29.92126;  // Std. MSL pressure, inHg. (=1013.25 mb)
+    const double p_Tr = 0.2233609 * P_0;  // Pressure at tropopause, same units.
+    const double h_Tr = 36089.24;  // Alt of tropopause, ft. (=11.0 km)
+
+    if (alt_ft < h_Tr)  // 0.0 to 11.0 km
+       return P_0 * pow(1.0 - 6.8755856e-6 * alt_ft, 5.2558797);
+    return p_Tr * exp(-4.806346e-5 * (alt_ft - h_Tr));  // 11.0 to 20.0 km
+    // We could put more code for higher altitudes here.
+}
+
+
 \f
 ////////////////////////////////////////////////////////////////////////
 // Here the fun really begins
@@ -135,7 +197,8 @@ void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
 
 void FGSteam::_CatchUp()
 { if ( _UpdatesPending != 0 )
-  {    double dt = _UpdatesPending * 1.0 / current_options.get_model_hz();
+  {    double dt = _UpdatesPending * 1.0 / 
+           fgGetInt("/sim/model-hz"); // FIXME: inefficient
         double AccN, AccE, AccU;
        int i /*,j*/;
        double d, the_ENGINE_rpm;
@@ -259,26 +322,16 @@ void FGSteam::_CatchUp()
        scaling capability for the vacuum pump later on.
        When we have a real engine model, we can ask it.
        */
-       the_ENGINE_rpm = FGBFI::getThrottle() * 26.0;
-
-       /**************************
-       This is just temporary, until the static source works,
-       so we just filter the actual value by one second to
-       account for the line impedance of the plumbing.
-       */
-       set_lowpass ( & the_ALT_ft, FGBFI::getAltitude(), dt );
+       the_ENGINE_rpm = controls.get_throttle(0) * 26.0;
 
        /**************************
        First, we need to know what the static line is reporting,
        which is a whole simulation area in itself.  For now, we cheat.
+       We filter the actual value by one second to
+       account for the line impedance of the plumbing.
        */
-       the_STATIC_inhg = 29.92; 
-       i = (int) the_ALT_ft;
-       while ( i > 9000 )
-       {       the_STATIC_inhg *= 0.707;
-               i -= 9000;
-       }
-       the_STATIC_inhg *= ( 1.0 - 0.293 * i / 9000.0 );
+       double static_inhg = altFtToPressInHg(FGBFI::getAltitude());
+       set_lowpass ( & the_STATIC_inhg, static_inhg, dt ); 
 
        /*
        NO alternate static source error (student feature), 
@@ -286,6 +339,21 @@ void FGSteam::_CatchUp()
        NO slip-induced error, important for C172 for example.
        */
 
+       /**************************
+       Altimeter.
+       ICAO standard atmosphere MSL pressure is 1013.25 mb, and pressure
+       gradient is about 28 ft per mb at MSL increasing to about 32 at
+       5000 and 38 at 10000 ft.
+       Standard altimeters apply the subscale offset to the output altitude,
+       not to the input pressure; I don't know exactly what pressure gradient
+       they assume for this.  I choose to make it accurate at low altitudes.
+       Remember, we are trying to simulate a real altimeter, not an ideal one.
+       */
+       set_lowpass ( & the_ALT_ft,
+           pressInHgToAltFt(the_STATIC_inhg) +
+           (the_ALT_datum_mb - 1013.25) * 28.0, /* accurate at low alt. */
+           dt * 10 ); /* smoothing time 0.1 s */
+
        /**************************
        The VSI case is a low-pass filter of the static line pressure.
        The instrument reports the difference, scaled to approx ft.
@@ -323,7 +391,7 @@ void FGSteam::_CatchUp()
 */
        if ( _UpdatesPending > 999999 )
            the_DG_err = FGBFI::getMagVar();
-       the_DG_degps = 0.0; /* HACK! */
+       the_DG_degps = 0.01; /* HACK! */
        if (dt<1.0) the_DG_err += dt * the_DG_degps;
        the_DG_deg = FGBFI::getHeading () - the_DG_err;
 
@@ -342,6 +410,8 @@ void FGSteam::_CatchUp()
 ////////////////////////////////////////////////////////////////////////
 
 
+#if 0
+
 double FGSteam::get_HackGS_deg () {
     if ( current_radiostack->get_nav1_inrange() && 
         current_radiostack->get_nav1_has_gs() )
@@ -361,14 +431,8 @@ double FGSteam::get_HackVOR1_deg () {
     double r;
 
     if ( current_radiostack->get_nav1_inrange() ) {
-       if ( current_radiostack->get_nav1_loc() ) {
-           // localizer doesn't need magvar offset
-           r = current_radiostack->get_nav1_heading()
-               - current_radiostack->get_nav1_radial();
-       } else {
-           r = current_radiostack->get_nav1_heading() - FGBFI::getMagVar()
-               - current_radiostack->get_nav1_radial();
-       }
+        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;
@@ -391,14 +455,8 @@ double FGSteam::get_HackVOR2_deg () {
     double r;
 
     if ( current_radiostack->get_nav2_inrange() ) {
-       if ( current_radiostack->get_nav2_loc() ) {
-           // localizer doesn't need magvar offset
-           r = current_radiostack->get_nav2_heading()
-               - current_radiostack->get_nav2_radial();
-       } else {
-           r = current_radiostack->get_nav2_heading() - FGBFI::getMagVar()
-               - current_radiostack->get_nav2_radial();
-       }
+        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;
     
@@ -412,6 +470,7 @@ double FGSteam::get_HackVOR2_deg () {
 
     return r;
 }
+#endif
 
 
 double FGSteam::get_HackOBS1_deg () {