diff --git a/src/Instrumentation/navradio.cxx b/src/Instrumentation/navradio.cxx index 8d55fcf..667854c 100644 --- a/src/Instrumentation/navradio.cxx +++ b/src/Instrumentation/navradio.cxx @@ -264,7 +264,8 @@ double FGNavRadio::adjustNavRange( double stationElev, double aircraftElev, // model standard ILS service volumes as per AIM 1-1-9 -double FGNavRadio::adjustILSRange( double stationElev, double aircraftElev, +double FGNavRadio::adjustILSRange( const double range, + double stationElev, double aircraftElev, double offsetDegrees, double distance ) { // assumptions we model the standard service volume, plus @@ -288,7 +289,15 @@ double FGNavRadio::adjustILSRange( double stationElev, double aircraftElev, // } else { // return 0; // } - return FG_LOC_DEFAULT_RANGE; + return range; +} + +// Odd function. +// Inversion symmetry about the origin. +// Unit slope at the origin +// Max 1, min 1, period 4. +inline double sawtooth(double xx){ + return 4.0 * fabs(xx/4.0 + 0.25 - floor(xx/4.0 + 0.75)) - 1.0; } @@ -407,27 +416,46 @@ 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; while ( offset < -180.0 ) { offset += 360.0; } while ( offset > 180.0 ) { offset -= 360.0; } // cout << "ils offset = " << offset << endl; + + ////////////////////////////////////////////////////////// + // FIXME: This assumes GS range is the same as LOC range, + // which is not correct. + ////////////////////////////////////////////////////////// effective_range - = adjustILSRange( nav_elev, pos.getElevationM(), offset, + = adjustILSRange( range, nav_elev, pos.getElevationM(), offset, loc_dist * SG_METER_TO_NM ); } else { effective_range = adjustNavRange( nav_elev, pos.getElevationM(), range ); } - // cout << "nav range = " << effective_range - // << " (" << range << ")" << endl; - +#if 0 + { + time_t cur_time = globals->get_time_params()->get_cur_time(); + if ( cur_time > msg_time) { + msg_time = cur_time; + cout << "nav: " << trans_ident + << " range: " << effective_range + << " (" << range << ")" << endl; + } + } +#endif if ( loc_dist < effective_range * SG_NM_TO_METER ) { inrange = true; } else if ( loc_dist < 2 * effective_range * SG_NM_TO_METER ) { + ////////////////////////////////////////////////////////// + // FIXME: This randomness in the inrange indication + // looks nice if only the /flag/ is fluctuating, + // but it does not look nice if the needle is + // fluctuating at frame rate. + // At the very least, one could argue for a + // low-pass filter on the needle position. + ////////////////////////////////////////////////////////// inrange = sg_random() < ( 2 * effective_range * SG_NM_TO_METER - loc_dist ) / (effective_range * SG_NM_TO_METER); @@ -477,12 +505,12 @@ FGNavRadio::update(double dt) from_flag_node->setBoolValue( value ); ////////////////////////////////////////////////////////// - // compute the deflection of the CDI needle, clamped to the range - // of ( -10 , 10 ) + // compute the deflection of the CDI needle. + // GPS clamped to range ( -12.5 , 12.5 ) + // VOR and LOC clamped to range ( -10 , 10 ) + // FIXME: Why the difference? ////////////////////////////////////////////////////////// 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(); @@ -490,26 +518,27 @@ FGNavRadio::update(double dt) // to -12.5/12.5 SG_CLAMP_RANGE( r, -12.5, 12.5 ); } else if ( inrange ) { - r = radial - target_radial; + r = target_radial - radial; // cout << "Target radial = " << target_radial // << " Actual radial = " << radial << endl; while ( r > 180.0 ) { r -= 360.0;} 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; - } - } - r = -r; // reverse, since radial is outbound if ( is_loc ) { + // The factor of 30.0 makes six zeros: + // one front course, one back course, + // and four false courses. + // Three of the six are reverse sensing. + r = 30.0 * sawtooth(r / 30.0); // According to Robin Peel, the ILS is 4x more // sensitive than a vor r *= 4.0; - } + } else { + if ( fabs(r) > 90.0 ) { + r = ( r<0.0 ? -r-180.0 : -r+180.0 ); + } + } SG_CLAMP_RANGE( r, -10.0, 10.0 ); } } @@ -584,7 +613,14 @@ FGNavRadio::update(double dt) // needle animation. This means that the needle should peg // when this values is +/-3.5. ////////////////////////////////////////////////////////// - r = 0.0; + // FIXME: When out of range, the GS needle should go + // to the "parking" position, which is not + // necessarily the zero position. + // Many instruments (especially modern ones) + // park the needle at full-scale up, or even + // move it out of sight. + ////////////////////////////////////////////////////////// + r = 0.0; // parking??? if ( has_gs && gs_serviceable_node->getBoolValue() ) { if ( nav_slaved_to_gps_node->getBoolValue() ) { // FIXME/FINISHME, what should be set here? @@ -593,9 +629,16 @@ FGNavRadio::update(double dt) double y = (fgGetDouble("/position/altitude-ft") - nav_elev) * SG_FEET_TO_METER; // cout << "dist = " << x << " height = " << y << endl; + ////////////////////////////////////////////////////////// + // FIXME: There should be false glidepaths (some + // reverse sensing) at large angles. + // See "sawtooth" code in LOC section. + ////////////////////////////////////////////////////////// double angle = asin( y / x ) * SGD_RADIANS_TO_DEGREES; r = (target_gs - angle) * 5.0; - } + } else { + // out of range + } } gs_deflection_node->setDoubleValue( r ); @@ -819,7 +862,7 @@ void FGNavRadio::search() nav_elev = loc->get_elev_ft(); } twist = 0; - range = FG_LOC_DEFAULT_RANGE; + range = loc->get_range(); effective_range = range; if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {