]> git.mxchange.org Git - flightgear.git/blobdiff - src/Instrumentation/navradio.cxx
Merge branch 'maint2' into next
[flightgear.git] / src / Instrumentation / navradio.cxx
index 32aeaed8c7aeea4052b56efc8d1fb88645a1738a..b4455be10013b15952ecf0d3823739e4c52e19a8 100644 (file)
 #  include <config.h>
 #endif
 
-#include <iostream>
-#include <string>
 #include <sstream>
 
-#include <simgear/compiler.h>
 #include <simgear/sg_inlines.h>
-#include <simgear/math/sg_random.h>
+#include <simgear/timing/sg_time.hxx>
 #include <simgear/math/vector.hxx>
+#include <simgear/math/sg_random.h>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/structure/exception.hxx>
 
-#include <Aircraft/aircraft.hxx>
 #include <Navaids/navlist.hxx>
-
+#include <Main/util.hxx>
 #include "navradio.hxx"
 
-#include <string>
-SG_USING_STD(string);
-
+using std::string;
 
 // Constructor
 FGNavRadio::FGNavRadio(SGPropertyNode *node) :
@@ -56,6 +54,7 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
     vol_btn_node(NULL),
     ident_btn_node(NULL),
     audio_btn_node(NULL),
+    backcourse_node(NULL),
     nav_serviceable_node(NULL),
     cdi_serviceable_node(NULL),
     gs_serviceable_node(NULL),
@@ -71,6 +70,7 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
     to_flag_node(NULL),
     from_flag_node(NULL),
     inrange_node(NULL),
+    signal_quality_norm_node(NULL),
     cdi_deflection_node(NULL),
     cdi_xtrack_error_node(NULL),
     cdi_xtrack_hdg_err_node(NULL),
@@ -99,8 +99,8 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
     last_x(0.0),
     last_loc_dist(0.0),
     last_xtrack_error(0.0),
-    name("nav"),
-    num(0),
+    _name(node->getStringValue("name", "nav")),
+    _num(node->getIntValue("number", 0)),
     _time_before_search_sec(-1.0)
 {
     SGPath path( globals->get_fg_root() );
@@ -114,25 +114,6 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
     term_tbl = new SGInterpTable( term.str() );
     low_tbl = new SGInterpTable( low.str() );
     high_tbl = new SGInterpTable( high.str() );
-
-    int i;
-    for ( i = 0; i < node->nChildren(); ++i ) {
-        SGPropertyNode *child = node->getChild(i);
-        string cname = child->getName();
-        string cval = child->getStringValue();
-        if ( cname == "name" ) {
-            name = cval;
-        } else if ( cname == "number" ) {
-            num = child->getIntValue();
-        } else {
-            SG_LOG( SG_INSTR, SG_WARN, 
-                    "Error in nav radio config logic" );
-            if ( name.length() ) {
-                SG_LOG( SG_INSTR, SG_WARN, "Section = " << name );
-            }
-        }
-    }
-
 }
 
 
@@ -151,12 +132,12 @@ FGNavRadio::init ()
     morse.init();
 
     string branch;
-    branch = "/instrumentation/" + name;
+    branch = "/instrumentation/" + _name;
 
-    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true );
 
     bus_power_node = 
-       fgGetNode(("/systems/electrical/outputs/" + name).c_str(), true);
+       fgGetNode(("/systems/electrical/outputs/" + _name).c_str(), true);
 
     // inputs
     is_valid_node = node->getChild("data-is-valid", 0, true);
@@ -167,6 +148,8 @@ FGNavRadio::init ()
     ident_btn_node->setBoolValue( true );
     audio_btn_node = node->getChild("audio-btn", 0, true);
     audio_btn_node->setBoolValue( true );
+    backcourse_node = node->getChild("back-course-btn", 0, true);
+    backcourse_node->setBoolValue( false );
     nav_serviceable_node = node->getChild("serviceable", 0, true);
     cdi_serviceable_node = (node->getChild("cdi", 0, true))
        ->getChild("serviceable", 0, true);
@@ -196,6 +179,7 @@ FGNavRadio::init ()
     to_flag_node = node->getChild("to-flag", 0, true);
     from_flag_node = node->getChild("from-flag", 0, true);
     inrange_node = node->getChild("in-range", 0, true);
+    signal_quality_norm_node = node->getChild("signal-quality-norm", 0, true);
     cdi_deflection_node = node->getChild("heading-needle-deflection", 0, true);
     cdi_xtrack_error_node = node->getChild("crosstrack-error-m", 0, true);
     cdi_xtrack_hdg_err_node
@@ -219,9 +203,9 @@ FGNavRadio::init ()
     gps_from_flag_node = fgGetNode("/instrumentation/gps/from-flag", true);
     
     std::ostringstream temp;
-    temp << name << "nav-ident" << num;
+    temp << _name << "nav-ident" << _num;
     nav_fx_name = temp.str();
-    temp << name << "dme-ident" << num;
+    temp << _name << "dme-ident" << _num;
     dme_fx_name = temp.str();
 }
 
@@ -230,8 +214,8 @@ FGNavRadio::bind ()
 {
     std::ostringstream temp;
     string branch;
-    temp << num;
-    branch = "/instrumentation/" + name + "[" + temp.str() + "]";
+    temp << _num;
+    branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
 }
 
 
@@ -240,8 +224,8 @@ FGNavRadio::unbind ()
 {
     std::ostringstream temp;
     string branch;
-    temp << num;
-    branch = "/instrumentation/" + name + "[" + temp.str() + "]";
+    temp << _num;
+    branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
 }
 
 
@@ -334,6 +318,8 @@ FGNavRadio::update(double dt)
     bool has_gs = has_gs_node->getBoolValue();
     bool is_loc = loc_node->getBoolValue();
     double loc_dist = loc_dist_node->getDoubleValue();
+    double effective_range_m;
+    double signal_quality_norm = signal_quality_norm_node->getDoubleValue();
 
     double az1, az2, s;
 
@@ -438,18 +424,32 @@ FGNavRadio::update(double dt)
            effective_range
                 = adjustNavRange( nav_elev, pos.getElevationM(), range );
        }
+
+        effective_range_m = effective_range * SG_NM_TO_METER;
+
        // cout << "nav range = " << effective_range
        //      << " (" << range << ")" << endl;
 
-       if ( loc_dist < effective_range * SG_NM_TO_METER ) {
-           inrange = true;
-       } else if ( loc_dist < 2 * effective_range * SG_NM_TO_METER ) {
-           inrange = sg_random() < ( 2 * effective_range * SG_NM_TO_METER
-                                      - loc_dist )
-                                      / (effective_range * SG_NM_TO_METER);
-       } else {
-           inrange = false;
-       }
+        //////////////////////////////////////////////////////////
+        // compute signal quality
+        // 100% within effective_range
+        // decreases 1/x^2 further out
+        //////////////////////////////////////////////////////////
+        {
+            double last_signal_quality_norm = signal_quality_norm;
+
+           if ( loc_dist < effective_range_m ) {
+              signal_quality_norm = 1.0;
+            } else {
+              double range_exceed_norm = loc_dist/effective_range_m;
+              signal_quality_norm = 1/(range_exceed_norm*range_exceed_norm);
+            }
+
+            signal_quality_norm = fgGetLowPass( last_signal_quality_norm, 
+                   signal_quality_norm, dt );
+        }
+        signal_quality_norm_node->setDoubleValue( signal_quality_norm );
+        inrange = signal_quality_norm > 0.2;
         inrange_node->setBoolValue( inrange );
 
        if ( !is_loc ) {
@@ -459,7 +459,7 @@ FGNavRadio::update(double dt)
         //////////////////////////////////////////////////////////
         // compute to/from flag status
         //////////////////////////////////////////////////////////
-        double value = false;
+        bool value = false;
         double offset = fabs(radial - target_radial);
         if ( tofrom_serviceable ) {
             if ( nav_slaved_to_gps_node->getBoolValue() ) {
@@ -497,8 +497,8 @@ FGNavRadio::update(double dt)
         // of ( -10 , 10 )
         //////////////////////////////////////////////////////////
         double r = 0.0;
-        bool loc_bc = false;   // an in-code flag indicating that we are
-                               // on a localizer backcourse.
+        bool loc_backside = false; // an in-code flag indicating that we are
+                                   // on a localizer backcourse.
         if ( cdi_serviceable ) {
             if ( nav_slaved_to_gps_node->getBoolValue() ) {
                 r = gps_cdi_deflection_node->getDoubleValue();
@@ -516,7 +516,7 @@ FGNavRadio::update(double dt)
                     r = ( r<0.0 ? -r-180.0 : -r+180.0 );
                 } else {
                     if ( is_loc ) {
-                        loc_bc = true;
+                        loc_backside = true;
                     }
                 }
 
@@ -527,6 +527,7 @@ FGNavRadio::update(double dt)
                     r *= 4.0;
                 }
                 SG_CLAMP_RANGE( r, -10.0, 10.0 );
+                r *= signal_quality_norm;
             }
         }
         cdi_deflection_node->setDoubleValue( r );
@@ -611,6 +612,7 @@ FGNavRadio::update(double dt)
                 // cout << "dist = " << x << " height = " << y << endl;
                 double angle = asin( y / x ) * SGD_RADIANS_TO_DEGREES;
                 r = (target_gs - angle) * 5.0;
+                r *= signal_quality_norm;
             }
         }
         gs_deflection_node->setDoubleValue( r );
@@ -661,21 +663,18 @@ FGNavRadio::update(double dt)
         // compensation.
         double adjustment = cdi_deflection_node->getDoubleValue() * 3.0;
         SG_CLAMP_RANGE( adjustment, -30.0, 30.0 );
-        
+
         // determine the target heading to fly to intercept the
         // tgt_radial = target radial (true) + cdi offset adjustmest -
         // xtrack heading error adjustment
-        double nta_hdg = 0.0;
-        if ( is_loc && loc_bc ) {
-            // tuned to a localizer and positioned in backcourse range
-            // trtrue += 180.0;   // reverse the target localizer heading
-            // while ( trtrue > 360.0 ) { trtrue -= 360.0; }
-            nta_hdg = trtrue + adjustment - hdg_error; 
-            cout << "trtrue = " << trtrue << " adj = " << adjustment
-                 << " hdg_error = " << hdg_error << endl;
-       } else {
-            // all other situations (nav or loc front course)
-            nta_hdg = trtrue + adjustment - hdg_error; 
+        double nta_hdg;
+        if ( is_loc && backcourse_node->getBoolValue() ) {
+            // tuned to a localizer and backcourse mode activated
+            trtrue += 180.0;   // reverse the target localizer heading
+            while ( trtrue > 360.0 ) { trtrue -= 360.0; }
+            nta_hdg = trtrue - adjustment - hdg_error;
+        } else {
+            nta_hdg = trtrue + adjustment - hdg_error;
         }
 
         while ( nta_hdg <   0.0 ) { nta_hdg += 360.0; }
@@ -766,10 +765,8 @@ void FGNavRadio::search()
     _time_before_search_sec = 1.0;
 
     // cache values locally for speed
-    double lon = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
-    double lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
-    double elev = alt_node->getDoubleValue() * SG_FEET_TO_METER;
-
+    SGGeod pos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
+      lat_node->getDoubleValue(), alt_node->getDoubleValue());
     FGNavRecord *nav = NULL;
     FGNavRecord *loc = NULL;
     FGNavRecord *dme = NULL;
@@ -780,11 +777,11 @@ void FGNavRadio::search()
     ////////////////////////////////////////////////////////////////////////
 
     double freq = freq_node->getDoubleValue();
-    nav = globals->get_navlist()->findByFreq(freq, lon, lat, elev);
-    dme = globals->get_dmelist()->findByFreq(freq, lon, lat, elev);
+    nav = globals->get_navlist()->findByFreq(freq, pos);
+    dme = globals->get_dmelist()->findByFreq(freq, pos);
     if ( nav == NULL ) {
-        loc = globals->get_loclist()->findByFreq(freq, lon, lat, elev);
-        gs = globals->get_gslist()->findByFreq(freq, lon, lat, elev);
+        loc = globals->get_loclist()->findByFreq(freq, pos);
+        gs = globals->get_gslist()->findByFreq(freq, pos);
     }
 
     string nav_id = "";
@@ -801,7 +798,7 @@ void FGNavRadio::search()
            while ( target_radial > 360.0 ) { target_radial -= 360.0; }
            loc_lon = loc->get_lon();
            loc_lat = loc->get_lat();
-           nav_xyz = loc->get_cart();
+           nav_xyz = loc->cart();
            last_nav_id = nav_id;
            last_nav_vor = false;
            loc_node->setBoolValue( true );
@@ -813,7 +810,7 @@ void FGNavRadio::search()
                 nav_elev = gs->get_elev_ft();
                 int tmp = (int)(gs->get_multiuse() / 1000.0);
                 target_gs = (double)tmp / 100.0;
-                gs_xyz = gs->get_cart();
+                gs_xyz = gs->cart();
 
                 // derive GS baseline (perpendicular to the runay
                 // along the ground)
@@ -886,10 +883,10 @@ void FGNavRadio::search()
            nav_elev = nav->get_elev_ft();
            twist = nav->get_multiuse();
            range = nav->get_range();
-           effective_range = adjustNavRange(nav_elev, elev, range);
+           effective_range = adjustNavRange(nav_elev, pos.getElevationM(), range);
            target_gs = 0.0;
            target_radial = sel_radial_node->getDoubleValue();
-           nav_xyz = nav->get_cart();
+           nav_xyz = nav->cart();
 
            if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
                globals->get_soundmgr()->remove( nav_fx_name );
@@ -931,11 +928,8 @@ void FGNavRadio::search()
        target_radial = 0;
        trans_ident = "";
        last_nav_id = "";
-       if ( ! globals->get_soundmgr()->remove( nav_fx_name ) ) {
-            SG_LOG(SG_COCKPIT, SG_WARN, "Failed to remove nav-vor-ident sound");
-        }
+       globals->get_soundmgr()->remove( nav_fx_name );
        globals->get_soundmgr()->remove( dme_fx_name );
-       // cout << "not picking up vor1. :-(" << endl;
     }
 
     is_valid_node->setBoolValue( is_valid );