X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2Fnavradio.cxx;h=b4455be10013b15952ecf0d3823739e4c52e19a8;hb=c6045147544badd6daefdcab9d4de1ed6936533b;hp=dd8a15dad247fdf2b6ab7f2486fa319a33b04135;hpb=94badeabcdfa669c16a316adff19a4f9f6a4b753;p=flightgear.git diff --git a/src/Instrumentation/navradio.cxx b/src/Instrumentation/navradio.cxx index dd8a15dad..b4455be10 100644 --- a/src/Instrumentation/navradio.cxx +++ b/src/Instrumentation/navradio.cxx @@ -25,23 +25,21 @@ # include #endif -#include -#include #include -#include #include -#include +#include #include +#include +#include +#include +#include -#include #include - +#include
#include "navradio.hxx" -#include -SG_USING_STD(string); - +using std::string; // Constructor FGNavRadio::FGNavRadio(SGPropertyNode *node) : @@ -52,16 +50,17 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) : power_btn_node(NULL), freq_node(NULL), alt_freq_node(NULL), - fmt_freq_node(NULL), - fmt_alt_freq_node(NULL), sel_radial_node(NULL), 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), tofrom_serviceable_node(NULL), + fmt_freq_node(NULL), + fmt_alt_freq_node(NULL), heading_node(NULL), radial_node(NULL), recip_radial_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; @@ -423,6 +409,8 @@ FGNavRadio::update(double dt) ////////////////////////////////////////////////////////// // adjust reception range for altitude + // FIXME: make sure we are using the navdata range now that + // it is valid in the data file ////////////////////////////////////////////////////////// if ( is_loc ) { double offset = radial - target_radial; @@ -430,23 +418,38 @@ FGNavRadio::update(double dt) while ( offset > 180.0 ) { offset -= 360.0; } // cout << "ils offset = " << offset << endl; effective_range - = adjustILSRange( nav_elev, pos.getElevationM(), offset, - loc_dist * SG_METER_TO_NM ); + = adjustILSRange( nav_elev, pos.getElevationM(), offset, + loc_dist * SG_METER_TO_NM ); } else { - effective_range = adjustNavRange( nav_elev, pos.getElevationM(), range ); + 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 ) { @@ -456,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() ) { @@ -494,13 +497,14 @@ FGNavRadio::update(double dt) // of ( -10 , 10 ) ////////////////////////////////////////////////////////// double r = 0.0; + 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(); // We want +- 5 dots deflection for the gps, so clamp // to -12.5/12.5 - if ( r < -12.5 ) { r = -12.5; } - if ( r > 12.5 ) { r = 12.5; } + SG_CLAMP_RANGE( r, -12.5, 12.5 ); } else if ( inrange ) { r = radial - target_radial; // cout << "Target radial = " << target_radial @@ -510,14 +514,20 @@ FGNavRadio::update(double dt) while ( r < -180.0 ) { r += 360.0;} if ( fabs(r) > 90.0 ) { r = ( r<0.0 ? -r-180.0 : -r+180.0 ); + } else { + if ( is_loc ) { + loc_backside = true; + } } - // According to Robin Peel, the ILS is 4x more - // sensitive than a vor r = -r; // reverse, since radial is outbound - if ( is_loc ) { r *= 4.0; } - if ( r < -10.0 ) { r = -10.0; } - if ( r > 10.0 ) { r = 10.0; } + if ( is_loc ) { + // According to Robin Peel, the ILS is 4x more + // sensitive than a vor + r *= 4.0; + } + SG_CLAMP_RANGE( r, -10.0, 10.0 ); + r *= signal_quality_norm; } } cdi_deflection_node->setDoubleValue( r ); @@ -602,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 ); @@ -643,30 +654,29 @@ FGNavRadio::update(double dt) // a nav/ils radial. ////////////////////////////////////////////////////////// - // FIXME: this smells odd, there must be a better (or more - // linear) solution + // Now that we have cross track heading adjustment built in, + // we shouldn't need to overdrive the heading angle within 8km + // of the station. // - // determine the heading adjustment needed. - // over 8km scale by 3.0 - // (3 is chosen because max deflection is 10 - // and 30 is clamped angle to radial) - // under 8km scale by 10.0 - // because the overstated error helps drive it to the radial in a - // moderate cross wind. - double adjustment = 0.0; - if ( loc_dist > 8000 ) { - adjustment = cdi_deflection_node->getDoubleValue() * 3.0; - } else { - adjustment = cdi_deflection_node->getDoubleValue() * 10.0; - } + // The cdi deflection should be +/-10 for a full range of deflection + // so multiplying this by 3 gives us +/- 30 degrees heading + // 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 = trtrue + adjustment - hdg_error; - // cout << "trtrue = " << trtrue << " adj = " << adjustment - // << " hdg_error = " << hdg_error << endl; + 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; } while ( nta_hdg >= 360.0 ) { nta_hdg -= 360.0; } target_auto_hdg_node->setDoubleValue( nta_hdg ); @@ -755,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; @@ -769,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 = ""; @@ -790,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 ); @@ -802,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) @@ -875,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 ); @@ -920,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 );