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),
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() );
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 );
- }
- }
- }
-
}
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);
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);
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();
}
{
std::ostringstream temp;
string branch;
- temp << num;
- branch = "/instrumentation/" + name + "[" + temp.str() + "]";
+ temp << _num;
+ branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
}
{
std::ostringstream temp;
string branch;
- temp << num;
- branch = "/instrumentation/" + name + "[" + temp.str() + "]";
+ temp << _num;
+ branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
}
//////////////////////////////////////////////////////////
// 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;
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 );
}
// cout << "nav range = " << effective_range
// << " (" << range << ")" << endl;
//////////////////////////////////////////////////////////
// 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() ) {
// 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
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 );
}
}
cdi_deflection_node->setDoubleValue( r );
// 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 );
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 );