X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2Fnavradio.cxx;h=4bfe15d48f9fc9071740c3471934c3d671d52dfc;hb=4265b2e2419bd9da2d6e83851c9bd0ab3e41fdb0;hp=782786fd066288822e05a57b70cce8ed9c6542a3;hpb=21122fa03ebfb676eacf9c705fb4b2a31416eb78;p=flightgear.git diff --git a/src/Instrumentation/navradio.cxx b/src/Instrumentation/navradio.cxx index 782786fd0..4bfe15d48 100644 --- a/src/Instrumentation/navradio.cxx +++ b/src/Instrumentation/navradio.cxx @@ -94,55 +94,6 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) : lon_node(fgGetNode("/position/longitude-deg", true)), lat_node(fgGetNode("/position/latitude-deg", true)), alt_node(fgGetNode("/position/altitude-ft", true)), - is_valid_node(NULL), - power_btn_node(NULL), - freq_node(NULL), - 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), - dme_serviceable_node(NULL), - fmt_freq_node(NULL), - fmt_alt_freq_node(NULL), - heading_node(NULL), - radial_node(NULL), - recip_radial_node(NULL), - target_radial_true_node(NULL), - target_auto_hdg_node(NULL), - time_to_intercept(NULL), - to_flag_node(NULL), - from_flag_node(NULL), - inrange_node(NULL), - signal_quality_norm_node(NULL), - cdi_deflection_node(NULL), - cdi_deflection_norm_node(NULL), - cdi_xtrack_error_node(NULL), - cdi_xtrack_hdg_err_node(NULL), - has_gs_node(NULL), - loc_node(NULL), - loc_dist_node(NULL), - gs_deflection_node(NULL), - gs_deflection_deg_node(NULL), - gs_deflection_norm_node(NULL), - gs_rate_of_climb_node(NULL), - gs_dist_node(NULL), - gs_inrange_node(NULL), - nav_id_node(NULL), - id_c1_node(NULL), - id_c2_node(NULL), - id_c3_node(NULL), - id_c4_node(NULL), - nav_slaved_to_gps_node(NULL), - gps_cdi_deflection_node(NULL), - gps_to_flag_node(NULL), - gps_from_flag_node(NULL), - gps_has_gs_node(NULL), play_count(0), last_time(0), target_radial(0.0), @@ -155,7 +106,7 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) : _name(node->getStringValue("name", "nav")), _num(node->getIntValue("number", 0)), _time_before_search_sec(-1.0), - _falseCoursesEnabled(true) + _sgr(NULL) { SGPath path( globals->get_fg_root() ); SGPath term = path; @@ -168,12 +119,19 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) : term_tbl = new SGInterpTable( term.str() ); low_tbl = new SGInterpTable( low.str() ); high_tbl = new SGInterpTable( high.str() ); + + + string branch("/instrumentation/" + _name); + _radio_node = fgGetNode(branch.c_str(), _num, true); } // Destructor FGNavRadio::~FGNavRadio() { + gps_course_node->removeChangeListener(this); + nav_slaved_to_gps_node->removeChangeListener(this); + delete term_tbl; delete low_tbl; delete high_tbl; @@ -183,13 +141,13 @@ FGNavRadio::~FGNavRadio() void FGNavRadio::init () { - morse.init(); - - string branch; - branch = "/instrumentation/" + _name; + SGSoundMgr *smgr = globals->get_soundmgr(); + _sgr = smgr->find("avionics", true); + _sgr->tie_to_listener(); - SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true ); + morse.init(); + SGPropertyNode* node = _radio_node.get(); bus_power_node = fgGetNode(("/systems/electrical/outputs/" + _name).c_str(), true); @@ -211,9 +169,14 @@ FGNavRadio::init () tofrom_serviceable_node = createServiceableProp(node, "to-from"); dme_serviceable_node = createServiceableProp(node, "dme"); - globals->get_props()->tie("sim/realism/false-radio-courses-enabled", - SGRawValuePointer(&_falseCoursesEnabled)); - + falseCoursesEnabledNode = + fgGetNode("/sim/realism/false-radio-courses-enabled"); + if (!falseCoursesEnabledNode) { + falseCoursesEnabledNode = + fgGetNode("/sim/realism/false-radio-courses-enabled", true); + falseCoursesEnabledNode->setBoolValue(true); + } + // frequencies SGPropertyNode *subnode = node->getChild("frequencies", 0, true); freq_node = subnode->getChild("selected-mhz", 0, true); @@ -248,6 +211,7 @@ FGNavRadio::init () gs_deflection_deg_node = node->getChild("gs-needle-deflection-deg", 0, true); gs_deflection_norm_node = node->getChild("gs-needle-deflection-norm", 0, true); gs_rate_of_climb_node = node->getChild("gs-rate-of-climb", 0, true); + gs_rate_of_climb_fpm_node = node->getChild("gs-rate-of-climb-fpm", 0, true); gs_dist_node = node->getChild("gs-distance", 0, true); gs_inrange_node = node->getChild("gs-in-range", 0, true); @@ -257,14 +221,19 @@ FGNavRadio::init () id_c3_node = node->getChild("nav-id_asc3", 0, true); id_c4_node = node->getChild("nav-id_asc4", 0, true); - node->tie("dme-in-range", SGRawValuePointer(&_dmeInRange)); - // gps slaving support nav_slaved_to_gps_node = node->getChild("slaved-to-gps", 0, true); + nav_slaved_to_gps_node->addChangeListener(this); + gps_cdi_deflection_node = fgGetNode("/instrumentation/gps/cdi-deflection", true); gps_to_flag_node = fgGetNode("/instrumentation/gps/to-flag", true); gps_from_flag_node = fgGetNode("/instrumentation/gps/from-flag", true); gps_has_gs_node = fgGetNode("/instrumentation/gps/has-gs", true); + gps_course_node = fgGetNode("/instrumentation/gps/desired-course-deg", true); + gps_course_node->addChangeListener(this); + + gps_xtrack_error_nm_node = fgGetNode("/instrumentation/gps/wp/wp[1]/course-error-nm", true); + _magvarNode = fgGetNode("/environment/magnetic-variation-deg", true); std::ostringstream temp; temp << _name << "nav-ident" << _num; @@ -276,13 +245,18 @@ FGNavRadio::init () void FGNavRadio::bind () { - + tie("dme-in-range", SGRawValuePointer(&_dmeInRange)); + tie("operable", SGRawValueMethods(*this, &FGNavRadio::isOperable, NULL)); } void FGNavRadio::unbind () { + for (unsigned int t=0; t<_tiedNodes.size(); ++t) { + _tiedNodes[t]->untie(); + } + _tiedNodes.clear(); } @@ -374,7 +348,8 @@ FGNavRadio::update(double dt) if (power_btn_node->getBoolValue() && (bus_power_node->getDoubleValue() > 1.0) && nav_serviceable_node->getBoolValue() ) - { + { + _operable = true; if (nav_slaved_to_gps_node->getBoolValue()) { updateGPSSlaved(); } else { @@ -406,6 +381,7 @@ void FGNavRadio::clearOutputs() from_flag_node->setBoolValue( false ); _dmeInRange = false; + _operable = false; } void FGNavRadio::updateReceiver(double dt) @@ -523,7 +499,7 @@ void FGNavRadio::updateReceiver(double dt) SG_NORMALIZE_RANGE(r, -180.0, 180.0); if ( is_loc ) { - if (_falseCoursesEnabled) { + if (falseCoursesEnabledNode->getBoolValue()) { // The factor of 30.0 gives a period of 120 which gives us 3 cycles and six // zeros i.e. six courses: one front course, one back course, and four // false courses. Three of the six are reverse sensing. @@ -571,6 +547,8 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig if (!_gs || !inrange_node->getBoolValue()) { gs_dist_node->setDoubleValue( 0.0 ); gs_inrange_node->setBoolValue(false); + _gsNeedleDeflection = 0.0; + _gsNeedleDeflectionNorm = 0.0; return; } @@ -580,6 +558,8 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig gs_inrange_node->setBoolValue(gsInRange); if (!gsInRange) { + _gsNeedleDeflection = 0.0; + _gsNeedleDeflectionNorm = 0.0; return; } @@ -591,7 +571,7 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig double angle = atan2(dot_v, dot_h) * SGD_RADIANS_TO_DEGREES; double deflectionAngle = target_gs - angle; - if (_falseCoursesEnabled) { + if (falseCoursesEnabledNode->getBoolValue()) { // Construct false glideslopes. The scale factor of 1.5 // in the sawtooth gives a period of 6 degrees. // There will be zeros at 3, 6r, 9, 12r et cetera @@ -621,17 +601,22 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig double gs_diff = target_gs - angle; // convert desired vertical path angle into a climb rate double des_angle = angle - 10 * gs_diff; + /* printf("target_gs=%.1f angle=%.1f gs_diff=%.1f des_angle=%.1f\n", + target_gs, angle, gs_diff, des_angle); */ // estimate horizontal speed towards ILS in meters per minute double elapsedDistance = last_x - gsDist; last_x = gsDist; double new_vel = ( elapsedDistance / dt ); - horiz_vel = 0.75 * horiz_vel + 0.25 * new_vel; + horiz_vel = 0.99 * horiz_vel + 0.01 * new_vel; + /* printf("vel=%.1f (dist=%.1f dt=%.2f)\n", horiz_vel, elapsedDistance, dt);*/ gs_rate_of_climb_node ->setDoubleValue( -sin( des_angle * SGD_DEGREES_TO_RADIANS ) * horiz_vel * SG_METER_TO_FEET ); + gs_rate_of_climb_fpm_node + ->setDoubleValue( gs_rate_of_climb_node->getDoubleValue() * 60 ); } void FGNavRadio::updateDME(const SGVec3d& aircraft) @@ -645,6 +630,26 @@ void FGNavRadio::updateDME(const SGVec3d& aircraft) _dmeInRange = (dme_distance < _dme->get_range() * SG_NM_TO_METER); } +void FGNavRadio::valueChanged (SGPropertyNode* prop) +{ + if (prop == gps_course_node) { + if (!nav_slaved_to_gps_node->getBoolValue()) { + return; + } + + // GPS desired course has changed, sync up our selected-course + double v = prop->getDoubleValue(); + if (v != sel_radial_node->getDoubleValue()) { + sel_radial_node->setDoubleValue(v); + } + } else if (prop == nav_slaved_to_gps_node) { + if (prop->getBoolValue()) { + // slaved-to-GPS activated, sync up selected course + sel_radial_node->setDoubleValue(gps_course_node->getDoubleValue()); + } + } +} + void FGNavRadio::updateGPSSlaved() { has_gs_node->setBoolValue(gps_has_gs_node->getBoolValue()); @@ -652,14 +657,30 @@ void FGNavRadio::updateGPSSlaved() _toFlag = gps_to_flag_node->getBoolValue(); _fromFlag = gps_from_flag_node->getBoolValue(); - inrange_node->setBoolValue(_toFlag | _fromFlag); + bool gpsValid = (_toFlag | _fromFlag); + inrange_node->setBoolValue(gpsValid); + if (!gpsValid) { + signal_quality_norm_node->setDoubleValue(0.0); + _cdiDeflection = 0.0; + _cdiCrossTrackErrorM = 0.0; + _gsNeedleDeflection = 0.0; + return; + } + + // this is unfortunate, but panel instruments use this value to decide + // if the navradio output is valid. + signal_quality_norm_node->setDoubleValue(1.0); _cdiDeflection = gps_cdi_deflection_node->getDoubleValue(); // clmap to some range (+/- 10 degrees) as the regular deflection SG_CLAMP_RANGE(_cdiDeflection, -10.0, 10.0 ); - _cdiCrossTrackErrorM = 0.0; // FIXME, supply this + _cdiCrossTrackErrorM = gps_xtrack_error_nm_node->getDoubleValue() * SG_NM_TO_METER; _gsNeedleDeflection = 0.0; // FIXME, supply this + + double trtrue = gps_course_node->getDoubleValue() + _magvarNode->getDoubleValue(); + SG_NORMALIZE_RANGE(trtrue, 0.0, 360.0); + target_radial_true_node->setDoubleValue( trtrue ); } void FGNavRadio::updateCDI(double dt) @@ -770,17 +791,17 @@ void FGNavRadio::updateAudio() // play station ident via audio system if on + ident, // otherwise turn it off - if (!power_btn_node->getBoolValue() + if (!power_btn_node->getBoolValue() || !(bus_power_node->getDoubleValue() > 1.0) || !ident_btn_node->getBoolValue() || !audio_btn_node->getBoolValue() ) { - globals->get_soundmgr()->stop( nav_fx_name ); - globals->get_soundmgr()->stop( dme_fx_name ); + _sgr->stop( nav_fx_name ); + _sgr->stop( dme_fx_name ); return; } - SGSoundSample *sound = globals->get_soundmgr()->find( nav_fx_name ); - double vol = vol_btn_node->getDoubleValue(); + SGSoundSample *sound = _sgr->find( nav_fx_name ); + double vol = vol_btn_node->getFloatValue(); SG_CLAMP_RANGE(vol, 0.0, 1.0); if ( sound != NULL ) { @@ -789,7 +810,7 @@ void FGNavRadio::updateAudio() SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-vor-ident sound" ); } - sound = globals->get_soundmgr()->find( dme_fx_name ); + sound = _sgr->find( dme_fx_name ); if ( sound != NULL ) { sound->set_volume( vol ); } else { @@ -812,16 +833,16 @@ void FGNavRadio::updateAudio() play_count = ++play_count % NUM_IDENT_SLOTS; // Previous ident is out of time; if still playing, cut it off: - globals->get_soundmgr()->stop( nav_fx_name ); - globals->get_soundmgr()->stop( dme_fx_name ); + _sgr->stop( nav_fx_name ); + _sgr->stop( dme_fx_name ); if (play_count == 0) { // the DME slot if (_dmeInRange && dme_serviceable_node->getBoolValue()) { // play DME ident - globals->get_soundmgr()->play_once( dme_fx_name ); + if (vol > 0.05) _sgr->play_once( dme_fx_name ); } } else { // NAV slot if (inrange_node->getBoolValue() && nav_serviceable_node->getBoolValue()) { - globals->get_soundmgr()->play_once(nav_fx_name); + if (vol > 0.05) _sgr->play_once(nav_fx_name); } } } @@ -904,8 +925,9 @@ void FGNavRadio::search() _gs = NULL; _dme = NULL; nav_id_node->setStringValue(""); - globals->get_soundmgr()->remove( nav_fx_name ); - globals->get_soundmgr()->remove( dme_fx_name ); + + _sgr->remove( nav_fx_name ); + _sgr->remove( dme_fx_name ); } is_valid_node->setBoolValue(nav != NULL); @@ -947,25 +969,25 @@ double FGNavRadio::localizerWidth(FGNavRecord* aLOC) void FGNavRadio::audioNavidChanged() { - if ( globals->get_soundmgr()->exists(nav_fx_name)) { - globals->get_soundmgr()->remove(nav_fx_name); + if (_sgr->exists(nav_fx_name)) { + _sgr->remove(nav_fx_name); } try { string trans_ident(_navaid->get_trans_ident()); SGSoundSample* sound = morse.make_ident(trans_ident, LO_FREQUENCY); sound->set_volume( 0.3 ); - if (!globals->get_soundmgr()->add( sound, nav_fx_name )) { + if (!_sgr->add( sound, nav_fx_name )) { SG_LOG(SG_COCKPIT, SG_WARN, "Failed to add v1-vor-ident sound"); } - if ( globals->get_soundmgr()->exists( dme_fx_name ) ) { - globals->get_soundmgr()->remove( dme_fx_name ); + if ( _sgr->exists( dme_fx_name ) ) { + _sgr->remove( dme_fx_name ); } sound = morse.make_ident( trans_ident, HI_FREQUENCY ); sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, dme_fx_name ); + _sgr->add( sound, dme_fx_name ); int offset = (int)(sg_random() * 30.0); play_count = offset / 4;