diff --git a/src/Cockpit/Makefile.am b/src/Cockpit/Makefile.am index 5796d2b98..19db9a624 100644 --- a/src/Cockpit/Makefile.am +++ b/src/Cockpit/Makefile.am @@ -9,6 +9,7 @@ libCockpit_a_SOURCES = \ hud_scal.cxx hud_tbi.cxx \ kr_87.cxx kr_87.hxx \ kt_70.cxx kt_70.hxx \ + navcom.cxx navcom.hxx \ panel.cxx panel.hxx \ panel_io.cxx panel_io.hxx \ radiostack.cxx radiostack.hxx \ diff --git a/src/Cockpit/navcom.cxx b/src/Cockpit/navcom.cxx new file mode 100644 index 000000000..aa989de2b --- /dev/null +++ b/src/Cockpit/navcom.cxx @@ -0,0 +1,644 @@ +// navcom.cxx -- class to manage a navcom instance +// +// Written by Curtis Olson, started April 2000. +// +// Copyright (C) 2000 - 2002 Curtis L. Olson - curt@flightgear.org +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> // snprintf + +#include <simgear/compiler.h> +#include <simgear/math/sg_random.h> + +#include <Aircraft/aircraft.hxx> +#include <Navaids/ilslist.hxx> +#include <Navaids/mkrbeacons.hxx> +#include <Navaids/navlist.hxx> +#include <Time/FGEventMgr.hxx> + +#include "navcom.hxx" + +#include <string> +SG_USING_STD(string); + + +/** + * Boy, this is ugly! Make the VOR range vary by altitude difference. + */ +static double kludgeRange ( double stationElev, double aircraftElev, + double nominalRange) +{ + // Assume that the nominal range (usually 50nm) applies at a 5,000 + // ft difference. Just a wild guess! + double factor = ((aircraftElev*SG_METER_TO_FEET) - stationElev) / 5000.0; + double range = fabs(nominalRange * factor); + + // Clamp the range to keep it sane; for now, never less than 25% + // or more than 500% of nominal range. + if (range < nominalRange/4.0) { + range = nominalRange/4.0; + } else if (range > nominalRange*5.0) { + range = nominalRange*5.0; + } + + return range; +} + + +// Constructor +FGNavCom::FGNavCom() : + lon_node(fgGetNode("/position/longitude-deg", true)), + lat_node(fgGetNode("/position/latitude-deg", true)), + alt_node(fgGetNode("/position/altitude-ft", true)), + last_nav_ident(""), + last_nav_vor(false), + nav_play_count(0), + nav_last_time(0), + need_update(true), + comm_freq(0.0), + comm_alt_freq(0.0), + comm_vol_btn(0.0), + nav_freq(0.0), + nav_alt_freq(0.0), + nav_radial(0.0), + nav_vol_btn(0.0) +{ + SGPath path( globals->get_fg_root() ); + SGPath term = path; + term.append( "Navaids/range.term" ); + SGPath low = path; + low.append( "Navaids/range.low" ); + SGPath high = path; + high.append( "Navaids/range.high" ); + + term_tbl = new SGInterpTable( term.str() ); + low_tbl = new SGInterpTable( low.str() ); + high_tbl = new SGInterpTable( high.str() ); + +} + + +// Destructor +FGNavCom::~FGNavCom() +{ + unbind(); // FIXME: should be called externally + + delete term_tbl; + delete low_tbl; + delete high_tbl; +} + + +void +FGNavCom::init () +{ + morse.init(); + beacon.init(); + + search(); + + update(0); // FIXME: use dt +} + +void +FGNavCom::bind () +{ + char propname[256]; + + // User inputs + sprintf( propname, "/radios/comm[%d]/frequencies/selected-mhz", index ); + fgTie( propname, this, &FGNavCom::get_comm_freq, &FGNavCom::set_comm_freq ); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/comm[%d]/frequencies/standby-mhz", index ); + fgTie( propname, this, + &FGNavCom::get_comm_alt_freq, &FGNavCom::set_comm_alt_freq ); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/comm[%d]/volume", index ); + fgTie( propname, this, + &FGNavCom::get_comm_vol_btn, &FGNavCom::set_comm_vol_btn ); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/comm[%d]/ident", index ); + fgTie( propname, this, + &FGNavCom::get_comm_ident_btn, &FGNavCom::set_comm_ident_btn ); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/nav[%d]/frequencies/selected-mhz", index ); + fgTie( propname, this, + &FGNavCom::get_nav_freq, &FGNavCom::set_nav_freq ); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/nav[%d]/frequencies/standby-mhz", index ); + fgTie( propname , this, + &FGNavCom::get_nav_alt_freq, &FGNavCom::set_nav_alt_freq); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/nav[%d]/radials/selected-deg", index ); + fgTie( propname, this, + &FGNavCom::get_nav_sel_radial, &FGNavCom::set_nav_sel_radial ); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/nav[%d]/volume", index ); + fgTie( propname, this, + &FGNavCom::get_nav_vol_btn, &FGNavCom::set_nav_vol_btn ); + fgSetArchivable( propname ); + + sprintf( propname, "/radios/nav[%d]/ident", index ); + fgTie( propname, this, + &FGNavCom::get_nav_ident_btn, &FGNavCom::set_nav_ident_btn ); + fgSetArchivable( propname ); + + // Radio outputs + sprintf( propname, "/radios/nav[%d]/radials/actual-deg", index ); + fgTie( propname, this, &FGNavCom::get_nav_radial ); + + sprintf( propname, "/radios/nav[%d]/to-flag", index ); + fgTie( propname, this, &FGNavCom::get_nav_to_flag ); + + sprintf( propname, "/radios/nav[%d]/from-flag", index ); + fgTie( propname, this, &FGNavCom::get_nav_from_flag ); + + sprintf( propname, "/radios/nav[%d]/in-range", index ); + fgTie( propname, this, &FGNavCom::get_nav_inrange ); + + sprintf( propname, "/radios/nav[%d]/heading-needle-deflection", index ); + fgTie( propname, this, &FGNavCom::get_nav_heading_needle_deflection ); + + sprintf( propname, "/radios/nav[%d]/gs-needle-deflection", index ); + fgTie( propname, this, &FGNavCom::get_nav_gs_needle_deflection ); +} + + +void +FGNavCom::unbind () +{ + char propname[256]; + + sprintf( propname, "/radios/comm[%d]/frequencies/selected-mhz", index ); + fgUntie( propname ); + sprintf( propname, "/radios/comm[%d]/frequencies/standby-mhz", index ); + fgUntie( propname ); + sprintf( propname, "/radios/comm[%d]/on", index ); + fgUntie( propname ); + sprintf( propname, "/radios/comm[%d]/ident", index ); + fgUntie( propname ); + + sprintf( propname, "/radios/nav[%d]/frequencies/selected-mhz", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/frequencies/standby-mhz", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/radials/actual-deg", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/radials/selected-deg", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/on", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/ident", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/to-flag", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/from-flag", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/in-range", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/heading-needle-deflection", index ); + fgUntie( propname ); + sprintf( propname, "/radios/nav[%d]/gs-needle-deflection", index ); + fgUntie( propname ); +} + + +// model standard VOR/DME/TACAN service volumes as per AIM 1-1-8 +double FGNavCom::adjustNavRange( double stationElev, double aircraftElev, + double nominalRange ) +{ + // extend out actual usable range to be 1.3x the published safe range + const double usability_factor = 1.3; + + // assumptions we model the standard service volume, plus + // ... rather than specifying a cylinder, we model a cone that + // contains the cylinder. Then we put an upside down cone on top + // to model diminishing returns at too-high altitudes. + + // altitude difference + double alt = ( aircraftElev * SG_METER_TO_FEET - stationElev ); + // cout << "aircraft elev = " << aircraftElev * SG_METER_TO_FEET + // << " station elev = " << stationElev << endl; + + if ( nominalRange < 25.0 + SG_EPSILON ) { + // Standard Terminal Service Volume + return term_tbl->interpolate( alt ) * usability_factor; + } else if ( nominalRange < 50.0 + SG_EPSILON ) { + // Standard Low Altitude Service Volume + // table is based on range of 40, scale to actual range + return low_tbl->interpolate( alt ) * nominalRange / 40.0 + * usability_factor; + } else { + // Standard High Altitude Service Volume + // table is based on range of 130, scale to actual range + return high_tbl->interpolate( alt ) * nominalRange / 130.0 + * usability_factor; + } +} + + +// model standard ILS service volumes as per AIM 1-1-9 +double FGNavCom::adjustILSRange( double stationElev, double aircraftElev, + double offsetDegrees, double distance ) +{ + // assumptions we model the standard service volume, plus + + // altitude difference + // double alt = ( aircraftElev * SG_METER_TO_FEET - stationElev ); + double offset = fabs( offsetDegrees ); + + if ( offset < 10 ) { + return FG_ILS_DEFAULT_RANGE; + } else if ( offset < 35 ) { + return 10 + (35 - offset) * (FG_ILS_DEFAULT_RANGE - 10) / 25; + } else if ( offset < 45 ) { + return (45 - offset); + } else if ( offset > 170 ) { + return FG_ILS_DEFAULT_RANGE; + } else if ( offset > 145 ) { + return 10 + (offset - 145) * (FG_ILS_DEFAULT_RANGE - 10) / 25; + } else if ( offset > 135 ) { + return (offset - 135); + } else { + return 0; + } +} + + +// Update the various nav values based on position and valid tuned in navs +void +FGNavCom::update(double dt) +{ + 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; + + need_update = false; + + Point3D aircraft = sgGeodToCart( Point3D( lon, lat, elev ) ); + Point3D station; + double az1, az2, s; + + //////////////////////////////////////////////////////////////////////// + // Nav. + //////////////////////////////////////////////////////////////////////// + + if ( nav_valid ) { + station = Point3D( nav_x, nav_y, nav_z ); + nav_loc_dist = aircraft.distance3D( station ); + + if ( nav_has_gs ) { + station = Point3D( nav_gs_x, nav_gs_y, nav_gs_z ); + nav_gs_dist = aircraft.distance3D( station ); + } else { + nav_gs_dist = 0.0; + } + + // wgs84 heading + geo_inverse_wgs_84( elev, lat * SGD_RADIANS_TO_DEGREES, lon * SGD_RADIANS_TO_DEGREES, + nav_loclat, nav_loclon, + &az1, &az2, &s ); + // cout << "az1 = " << az1 << " magvar = " << nav_magvar << endl; + nav_heading = az1 - nav_magvar; + // cout << " heading = " << nav_heading + // << " dist = " << nav_dist << endl; + + if ( nav_loc ) { + double offset = nav_heading - nav_radial; + while ( offset < -180.0 ) { offset += 360.0; } + while ( offset > 180.0 ) { offset -= 360.0; } + // cout << "ils offset = " << offset << endl; + nav_effective_range = adjustILSRange(nav_elev, elev, offset, + nav_loc_dist * SG_METER_TO_NM ); + } else { + nav_effective_range = adjustNavRange(nav_elev, elev, nav_range); + } + // cout << "nav range = " << nav_effective_range + // << " (" << nav_range << ")" << endl; + + if ( nav_loc_dist < nav_effective_range * SG_NM_TO_METER ) { + nav_inrange = true; + } else if ( nav_loc_dist < 2 * nav_effective_range * SG_NM_TO_METER ) { + nav_inrange = sg_random() < + ( 2 * nav_effective_range * SG_NM_TO_METER - nav_loc_dist ) / + (nav_effective_range * SG_NM_TO_METER); + } else { + nav_inrange = false; + } + + if ( !nav_loc ) { + nav_radial = nav_sel_radial; + } + } else { + nav_inrange = false; + // cout << "not picking up vor. :-(" << endl; + } + +#ifdef ENABLE_AUDIO_SUPPORT + if ( nav_valid && nav_inrange ) { + // play station ident via audio system if on + ident, + // otherwise turn it off + if ( nav_vol_btn > 0.1 && nav_ident_btn ) { + FGSimpleSound *sound; + sound = globals->get_soundmgr()->find( nav_fx_name ); + if ( sound != NULL ) { + sound->set_volume( nav_vol_btn ); + } else { + SG_LOG( SG_COCKPIT, SG_ALERT, + "Can't find nav-vor-ident sound" ); + } + sound = globals->get_soundmgr()->find( dme_fx_name ); + if ( sound != NULL ) { + sound->set_volume( nav_vol_btn ); + } else { + SG_LOG( SG_COCKPIT, SG_ALERT, + "Can't find nav-dme-ident sound" ); + } + cout << "nav_last_time = " << nav_last_time << " "; + cout << "cur_time = " << globals->get_time_params()->get_cur_time(); + if ( nav_last_time < + globals->get_time_params()->get_cur_time() - 30 ) { + nav_last_time = globals->get_time_params()->get_cur_time(); + nav_play_count = 0; + } + cout << " nav_play_count = " << nav_play_count << endl; + cout << "playing = " + << globals->get_soundmgr()->is_playing(nav_fx_name) + << endl; + if ( nav_play_count < 4 ) { + // play VOR ident + if ( !globals->get_soundmgr()->is_playing(nav_fx_name) ) { + globals->get_soundmgr()->play_once( nav_fx_name ); + ++nav_play_count; + } + } else if ( nav_play_count < 5 && nav_has_dme ) { + // play DME ident + if ( !globals->get_soundmgr()->is_playing(nav_fx_name) && + !globals->get_soundmgr()->is_playing(dme_fx_name) ) { + globals->get_soundmgr()->play_once( dme_fx_name ); + ++nav_play_count; + } + } + } else { + globals->get_soundmgr()->stop( nav_fx_name ); + globals->get_soundmgr()->stop( dme_fx_name ); + } + } +#endif + +} + + +// Update current nav/adf radio stations based on current postition +void FGNavCom::search() +{ + 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; + + FGILS ils; + FGNav nav; + + //////////////////////////////////////////////////////////////////////// + // Nav. + //////////////////////////////////////////////////////////////////////// + + if ( current_ilslist->query( lon, lat, elev, nav_freq, &ils ) ) { + nav_ident = ils.get_locident(); + nav_valid = true; + if ( last_nav_ident != nav_ident || last_nav_vor ) { + nav_trans_ident = ils.get_trans_ident(); + last_nav_ident = nav_ident; + last_nav_vor = false; + nav_loc = true; + nav_has_dme = ils.get_has_dme(); + nav_has_gs = ils.get_has_gs(); + + nav_loclon = ils.get_loclon(); + nav_loclat = ils.get_loclat(); + nav_gslon = ils.get_gslon(); + nav_gslat = ils.get_gslat(); + nav_elev = ils.get_gselev(); + nav_magvar = 0; + nav_range = FG_ILS_DEFAULT_RANGE; + nav_effective_range = nav_range; + nav_target_gs = ils.get_gsangle(); + nav_radial = ils.get_locheading(); + while ( nav_radial < 0.0 ) { nav_radial += 360.0; } + while ( nav_radial > 360.0 ) { nav_radial -= 360.0; } + nav_x = ils.get_x(); + nav_y = ils.get_y(); + nav_z = ils.get_z(); + nav_gs_x = ils.get_gs_x(); + nav_gs_y = ils.get_gs_y(); + nav_gs_z = ils.get_gs_z(); + +#ifdef ENABLE_AUDIO_SUPPORT + if ( globals->get_soundmgr()->exists( nav_fx_name ) ) { + globals->get_soundmgr()->remove( nav_fx_name ); + } + FGSimpleSound *sound; + sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY ); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, nav_fx_name ); + + if ( globals->get_soundmgr()->exists( dme_fx_name ) ) { + globals->get_soundmgr()->remove( dme_fx_name ); + } + sound = morse.make_ident( nav_trans_ident, HI_FREQUENCY ); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, dme_fx_name ); + + int offset = (int)(sg_random() * 30.0); + nav_play_count = offset / 4; + nav_last_time = globals->get_time_params()->get_cur_time() - + offset; + cout << "offset = " << offset << " play_count = " + << nav_play_count + << " nav_last_time = " << nav_last_time + << " current time = " + << globals->get_time_params()->get_cur_time() << endl; +#endif + + // cout << "Found an ils station in range" << endl; + // cout << " id = " << ils.get_locident() << endl; + } + } else if ( current_navlist->query( lon, lat, elev, nav_freq, &nav ) ) { + nav_ident = nav.get_ident(); + nav_valid = true; + if ( last_nav_ident != nav_ident || !last_nav_vor ) { + last_nav_ident = nav_ident; + last_nav_vor = true; + nav_trans_ident = nav.get_trans_ident(); + nav_loc = false; + nav_has_dme = nav.get_has_dme(); + nav_has_gs = false; + nav_loclon = nav.get_lon(); + nav_loclat = nav.get_lat(); + nav_elev = nav.get_elev(); + nav_magvar = nav.get_magvar(); + nav_range = nav.get_range(); + nav_effective_range = adjustNavRange(nav_elev, elev, nav_range); + nav_target_gs = 0.0; + nav_radial = nav_sel_radial; + nav_x = nav.get_x(); + nav_y = nav.get_y(); + nav_z = nav.get_z(); + +#ifdef ENABLE_AUDIO_SUPPORT + if ( globals->get_soundmgr()->exists( nav_fx_name ) ) { + globals->get_soundmgr()->remove( nav_fx_name ); + } + FGSimpleSound *sound; + sound = morse.make_ident( nav_trans_ident, LO_FREQUENCY ); + sound->set_volume( 0.3 ); + if ( globals->get_soundmgr()->add( sound, nav_fx_name ) ) { + cout << "Added nav-vor-ident sound" << endl; + } else { + cout << "Failed to add v1-vor-ident sound" << endl; + } + + if ( globals->get_soundmgr()->exists( dme_fx_name ) ) { + globals->get_soundmgr()->remove( dme_fx_name ); + } + sound = morse.make_ident( nav_trans_ident, HI_FREQUENCY ); + sound->set_volume( 0.3 ); + globals->get_soundmgr()->add( sound, dme_fx_name ); + + int offset = (int)(sg_random() * 30.0); + nav_play_count = offset / 4; + nav_last_time = globals->get_time_params()->get_cur_time() - + offset; + cout << "offset = " << offset << " play_count = " + << nav_play_count << " nav_last_time = " + << nav_last_time << " current time = " + << globals->get_time_params()->get_cur_time() << endl; +#endif + + // cout << "Found a vor station in range" << endl; + // cout << " id = " << nav.get_ident() << endl; + } + } else { + nav_valid = false; + nav_ident = ""; + nav_radial = 0; + nav_trans_ident = ""; + last_nav_ident = ""; +#ifdef ENABLE_AUDIO_SUPPORT + if ( ! globals->get_soundmgr()->remove( nav_fx_name ) ) { + cout << "Failed to remove nav-vor-ident sound" << endl; + } + globals->get_soundmgr()->remove( dme_fx_name ); +#endif + // cout << "not picking up vor1. :-(" << endl; + } +} + + +// return the amount of heading needle deflection, returns a value +// clamped to the range of ( -10 , 10 ) +double FGNavCom::get_nav_heading_needle_deflection() const { + double r; + + if ( nav_inrange ) { + r = nav_heading - nav_radial; + // cout << "Radial = " << nav_radial + // << " Bearing = " << nav_heading << 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 ); + if ( nav_loc ) { + r = -r; + } + } + + // According to Robin Peel, the ILS is 4x more sensitive than a vor + if ( nav_loc ) { r *= 4.0; } + if ( r < -10.0 ) { r = -10.0; } + if ( r > 10.0 ) { r = 10.0; } + } else { + r = 0.0; + } + + return r; +} + + +// return the amount of glide slope needle deflection (.i.e. the +// number of degrees we are off the glide slope * 5.0 +double FGNavCom::get_nav_gs_needle_deflection() const { + if ( nav_inrange && nav_has_gs ) { + double x = nav_gs_dist; + double y = (fgGetDouble("/position/altitude-ft") - nav_elev) + * SG_FEET_TO_METER; + double angle = atan2( y, x ) * SGD_RADIANS_TO_DEGREES; + return (nav_target_gs - angle) * 5.0; + } else { + return 0.0; + } +} + + +/** + * Return true if the NAV TO flag should be active. + */ +bool +FGNavCom::get_nav_to_flag () const +{ + if (nav_inrange) { + double offset = fabs(nav_heading - nav_radial); + if (nav_loc) + return true; + else + return (offset <= 90.0 || offset >= 270.0); + } else { + return false; + } +} + + +/** + * Return true if the NAV FROM flag should be active. + */ +bool +FGNavCom::get_nav_from_flag () const +{ + if (nav_inrange) { + double offset = fabs(nav_heading - nav_radial); + if (nav_loc) + return false; + else + return (offset > 90.0 && offset < 270.0); + } else { + return false; + } +} diff --git a/src/Cockpit/navcom.hxx b/src/Cockpit/navcom.hxx new file mode 100644 index 000000000..94698eb21 --- /dev/null +++ b/src/Cockpit/navcom.hxx @@ -0,0 +1,209 @@ +// navcom.hxx -- class to manage a navcom instance +// +// Written by Curtis Olson, started April 2000. +// +// Copyright (C) 2000 - 2002 Curtis L. Olson - curt@flightgear.org +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#ifndef _FG_NAVCOM_HXX +#define _FG_NAVCOM_HXX + + +#include <Main/fgfs.hxx> +#include <Main/fg_props.hxx> + +#include <simgear/compiler.h> + +#include <simgear/math/interpolater.hxx> +#include <simgear/timing/timestamp.hxx> + +#include <Navaids/ilslist.hxx> +#include <Navaids/navlist.hxx> +#include <Sound/beacon.hxx> +#include <Sound/morse.hxx> + +class FGNavCom : public FGSubsystem +{ + FGBeacon beacon; + FGMorse morse; + + SGInterpTable *term_tbl; + SGInterpTable *low_tbl; + SGInterpTable *high_tbl; + + SGPropertyNode *lon_node; + SGPropertyNode *lat_node; + SGPropertyNode *alt_node; + + string last_nav_ident; + bool last_nav_vor; + int nav_play_count; + time_t nav_last_time; + + int index; // used for property binding + char nav_fx_name[256]; + char dme_fx_name[256]; + + bool need_update; + + string comm_ident; + bool comm_valid; + bool comm_inrange; + double comm_freq; + double comm_alt_freq; + double comm_vol_btn; + bool comm_ident_btn; + double comm_x; + double comm_y; + double comm_z; + double comm_dist; + double comm_elev; + double comm_range; + double comm_effective_range; + + string nav_ident; + string nav_trans_ident; + bool nav_valid; + bool nav_inrange; + bool nav_has_dme; + bool nav_has_gs; + bool nav_loc; + double nav_freq; + double nav_alt_freq; + double nav_radial; + double nav_sel_radial; + double nav_loclon; + double nav_loclat; + double nav_x; + double nav_y; + double nav_z; + double nav_loc_dist; + double nav_gslon; + double nav_gslat; + double nav_gs_x; + double nav_gs_y; + double nav_gs_z; + double nav_gs_dist; + SGTimeStamp prev_time; + SGTimeStamp curr_time; + double nav_elev; + double nav_range; + double nav_effective_range; + double nav_heading; + double nav_target_gs; + double nav_magvar; + double nav_vol_btn; + bool nav_ident_btn; + + // model standard VOR/DME/TACAN service volumes as per AIM 1-1-8 + double adjustNavRange( double stationElev, double aircraftElev, + double nominalRange ); + + // model standard ILS service volumes as per AIM 1-1-9 + double adjustILSRange( double stationElev, double aircraftElev, + double offsetDegrees, double distance ); + +public: + + FGNavCom(); + ~FGNavCom(); + + void init (); + void bind (); + void unbind (); + void update (double dt); + + // Update nav/adf radios based on current postition + void search (); + + inline void set_bind_index( int i ) { + index = i; + sprintf( nav_fx_name, "nav%d-vor-ident", index ); + sprintf( dme_fx_name, "dme%d-vor-ident", index ); + } + + // COMM Setters + inline void set_comm_freq( double freq ) { + comm_freq = freq; need_update = true; + } + inline void set_comm_alt_freq( double freq ) { comm_alt_freq = freq; } + inline void set_comm_vol_btn( double val ) { + if ( val < 0.0 ) val = 0.0; + if ( val > 1.0 ) val = 1.0; + comm_vol_btn = val; + } + inline void set_comm_ident_btn( bool val ) { comm_ident_btn = val; } + + // NAV Setters + inline void set_nav_freq( double freq ) { + nav_freq = freq; need_update = true; + } + inline void set_nav_alt_freq( double freq ) { nav_alt_freq = freq; } + inline void set_nav_sel_radial( double radial ) { + nav_sel_radial = radial; need_update = true; + } + inline void set_nav_vol_btn( double val ) { + if ( val < 0.0 ) val = 0.0; + if ( val > 1.0 ) val = 1.0; + nav_vol_btn = val; + } + inline void set_nav_ident_btn( bool val ) { nav_ident_btn = val; } + + // COMM Accessors + inline double get_comm_freq () const { return comm_freq; } + inline double get_comm_alt_freq () const { return comm_alt_freq; } + + // NAV Accessors + inline double get_nav_freq () const { return nav_freq; } + inline double get_nav_alt_freq () const { return nav_alt_freq; } + inline double get_nav_sel_radial() const { return nav_sel_radial; } + + // Calculated values. + inline bool get_comm_inrange() const { return comm_inrange; } + inline double get_comm_vol_btn() const { return comm_vol_btn; } + inline bool get_comm_ident_btn() const { return comm_ident_btn; } + + inline bool get_nav_inrange() const { return nav_inrange; } + bool get_nav_to_flag () const; + bool get_nav_from_flag () const; + inline bool get_nav_has_dme() const { return nav_has_dme; } + inline bool get_nav_dme_inrange () const { + return nav_inrange && nav_has_dme; + } + inline bool get_nav_has_gs() const { return nav_has_gs; } + inline bool get_nav_loc() const { return nav_loc; } + inline double get_nav_loclon() const { return nav_loclon; } + inline double get_nav_loclat() const { return nav_loclat; } + inline double get_nav_loc_dist() const { return nav_loc_dist; } + inline double get_nav_gslon() const { return nav_gslon; } + inline double get_nav_gslat() const { return nav_gslat; } + inline double get_nav_gs_dist() const { return nav_gs_dist; } + inline double get_nav_elev() const { return nav_elev; } + inline double get_nav_heading() const { return nav_heading; } + inline double get_nav_radial() const { return nav_radial; } + inline double get_nav_target_gs() const { return nav_target_gs; } + inline double get_nav_magvar() const { return nav_magvar; } + double get_nav_heading_needle_deflection() const; + double get_nav_gs_needle_deflection() const; + inline double get_nav_vol_btn() const { return nav_vol_btn; } + inline bool get_nav_ident_btn() const { return nav_ident_btn; } +}; + + +#endif // _FG_NAVCOM_HXX diff --git a/src/Cockpit/radiostack.cxx b/src/Cockpit/radiostack.cxx index 54f235b47..264c33b11 100644 --- a/src/Cockpit/radiostack.cxx +++ b/src/Cockpit/radiostack.cxx @@ -41,11 +41,6 @@ #include <string> SG_USING_STD(string); -static int nav1_play_count = 0; -static int nav2_play_count = 0; -static time_t nav1_last_time = 0; -static time_t nav2_last_time = 0; - FGRadioStack *current_radiostack; @@ -81,20 +76,6 @@ FGRadioStack::FGRadioStack() : lat_node(fgGetNode("/position/latitude-deg", true)), alt_node(fgGetNode("/position/altitude-ft", true)), need_update(true), - comm1_freq(0.0), - comm1_alt_freq(0.0), - comm1_vol_btn(0.0), - comm2_freq(0.0), - comm2_alt_freq(0.0), - comm2_vol_btn(0.0), - nav1_freq(0.0), - nav1_alt_freq(0.0), - nav1_radial(0.0), - nav1_vol_btn(0.0), - nav2_freq(0.0), - nav2_alt_freq(0.0), - nav2_radial(0.0), - nav2_vol_btn(0.0), dme_freq(0.0), dme_dist(0.0), dme_prev_dist(0.0), @@ -122,6 +103,8 @@ FGRadioStack::FGRadioStack() : // Destructor FGRadioStack::~FGRadioStack() { + navcom1.unbind(); + navcom2.unbind(); adf.unbind(); xponder.unbind(); unbind(); // FIXME: should be called externally @@ -135,6 +118,12 @@ FGRadioStack::~FGRadioStack() void FGRadioStack::init () { + navcom1.set_bind_index( 0 ); + navcom1.init(); + + navcom2.set_bind_index( 1 ); + navcom2.init(); + adf.init(); xponder.init(); @@ -143,10 +132,14 @@ FGRadioStack::init () blink.stamp(); search(); + navcom1.search(); + navcom2.search(); adf.search(); xponder.search(); update(0); // FIXME: use dt + navcom1.update(0); + navcom2.update(0); adf.update(0); xponder.update(0); @@ -159,97 +152,6 @@ FGRadioStack::init () void FGRadioStack::bind () { - // User inputs - fgTie("/radios/comm[0]/frequencies/selected-mhz", this, - &FGRadioStack::get_comm1_freq, &FGRadioStack::set_comm1_freq); - fgSetArchivable("/radios/comm[0]/frequencies/selected-mhz"); - fgTie("/radios/comm[0]/frequencies/standby-mhz", this, - &FGRadioStack::get_comm1_alt_freq, &FGRadioStack::set_comm1_alt_freq); - fgSetArchivable("/radios/comm[0]/frequencies/standby-mhz"); - fgTie("/radios/comm[0]/volume", this, - &FGRadioStack::get_comm1_vol_btn, - &FGRadioStack::set_comm1_vol_btn); - fgSetArchivable("/radios/comm[0]/volume"); - fgTie("/radios/comm[0]/ident", this, - &FGRadioStack::get_comm1_ident_btn, - &FGRadioStack::set_comm1_ident_btn); - fgSetArchivable("/radios/comm[0]/ident"); - - fgTie("/radios/comm[1]/frequencies/selected-mhz", this, - &FGRadioStack::get_comm2_freq, &FGRadioStack::set_comm2_freq); - fgSetArchivable("/radios/comm[0]/frequencies/selected-mhz"); - fgTie("/radios/comm[1]/frequencies/standby-mhz", this, - &FGRadioStack::get_comm2_alt_freq, &FGRadioStack::set_comm2_alt_freq); - fgSetArchivable("/radios/comm[0]/frequencies/standby-mhz"); - fgTie("/radios/comm[1]/volume", this, - &FGRadioStack::get_comm2_vol_btn, - &FGRadioStack::set_comm2_vol_btn); - fgSetArchivable("/radios/comm[0]/volume"); - fgTie("/radios/comm[1]/ident", this, - &FGRadioStack::get_comm2_ident_btn, - &FGRadioStack::set_comm2_ident_btn); - fgSetArchivable("/radios/comm[1]/ident"); - - fgTie("/radios/nav[0]/frequencies/selected-mhz", this, - &FGRadioStack::get_nav1_freq, &FGRadioStack::set_nav1_freq); - fgSetArchivable("/radios/nav[0]/frequencies/selected-mhz"); - fgTie("/radios/nav[0]/frequencies/standby-mhz", this, - &FGRadioStack::get_nav1_alt_freq, &FGRadioStack::set_nav1_alt_freq); - fgSetArchivable("/radios/nav[0]/frequencies/standby-mhz"); - fgTie("/radios/nav[0]/radials/selected-deg", this, - &FGRadioStack::get_nav1_sel_radial, - &FGRadioStack::set_nav1_sel_radial); - fgSetArchivable("/radios/nav[0]/radials/selected-deg"); - fgTie("/radios/nav[0]/volume", this, - &FGRadioStack::get_nav1_vol_btn, - &FGRadioStack::set_nav1_vol_btn); - fgSetArchivable("/radios/nav[0]/volume"); - fgTie("/radios/nav[0]/ident", this, - &FGRadioStack::get_nav1_ident_btn, - &FGRadioStack::set_nav1_ident_btn); - fgSetArchivable("/radios/nav[0]/ident"); - - // Radio outputs - fgTie("/radios/nav[0]/radials/actual-deg", this, - &FGRadioStack::get_nav1_radial); - fgTie("/radios/nav[0]/to-flag", this, &FGRadioStack::get_nav1_to_flag); - fgTie("/radios/nav[0]/from-flag", this, &FGRadioStack::get_nav1_from_flag); - fgTie("/radios/nav[0]/in-range", this, &FGRadioStack::get_nav1_inrange); - fgTie("/radios/nav[0]/heading-needle-deflection", this, - &FGRadioStack::get_nav1_heading_needle_deflection); - fgTie("/radios/nav[0]/gs-needle-deflection", this, - &FGRadioStack::get_nav1_gs_needle_deflection); - - // User inputs - fgTie("/radios/nav[1]/frequencies/selected-mhz", this, - &FGRadioStack::get_nav2_freq, &FGRadioStack::set_nav2_freq); - fgSetArchivable("/radios/nav[1]/frequencies/selected-mhz"); - fgTie("/radios/nav[1]/frequencies/standby-mhz", this, - &FGRadioStack::get_nav2_alt_freq, &FGRadioStack::set_nav2_alt_freq); - fgSetArchivable("/radios/nav[1]/frequencies/standby-mhz"); - fgTie("/radios/nav[1]/radials/selected-deg", this, - &FGRadioStack::get_nav2_sel_radial, - &FGRadioStack::set_nav2_sel_radial); - fgSetArchivable("/radios/nav[1]/radials/selected-deg"); - fgTie("/radios/nav[1]/volume", this, - &FGRadioStack::get_nav2_vol_btn, - &FGRadioStack::set_nav2_vol_btn); - fgSetArchivable("/radios/nav[1]/volume"); - fgTie("/radios/nav[1]/ident", this, - &FGRadioStack::get_nav2_ident_btn, - &FGRadioStack::set_nav2_ident_btn); - fgSetArchivable("/radios/nav[1]/ident"); - - // Radio outputs - fgTie("/radios/nav[1]/radials/actual-deg", this, - &FGRadioStack::get_nav2_radial); - fgTie("/radios/nav[1]/to-flag", this, &FGRadioStack::get_nav2_to_flag); - fgTie("/radios/nav[1]/from-flag", this, &FGRadioStack::get_nav2_from_flag); - fgTie("/radios/nav[1]/in-range", this, &FGRadioStack::get_nav2_inrange); - fgTie("/radios/nav[1]/heading-needle-deflection", this, - &FGRadioStack::get_nav2_heading_needle_deflection); - fgTie("/radios/nav[1]/gs-needle-deflection", this, - &FGRadioStack::get_nav2_gs_needle_deflection); // User inputs fgTie("/radios/dme/frequencies/selected-khz", this, @@ -257,17 +159,26 @@ FGRadioStack::bind () // Radio outputs fgTie("/radios/dme/in-range", this, &FGRadioStack::get_dme_inrange); + fgTie("/radios/dme/distance-nm", this, &FGRadioStack::get_dme_dist); + fgTie("/radios/dme/speed-kt", this, &FGRadioStack::get_dme_spd); + fgTie("/radios/dme/ete-min", this, &FGRadioStack::get_dme_ete); fgTie("/radios/marker-beacon/inner", this, &FGRadioStack::get_inner_blink); + fgTie("/radios/marker-beacon/middle", this, &FGRadioStack::get_middle_blink); + fgTie("/radios/marker-beacon/outer", this, &FGRadioStack::get_outer_blink); + navcom1.set_bind_index( 0 ); + navcom1.bind(); + navcom2.set_bind_index( 1 ); + navcom2.bind(); adf.bind(); xponder.bind(); } @@ -275,40 +186,6 @@ FGRadioStack::bind () void FGRadioStack::unbind () { - fgUntie("/radios/comm[0]/frequencies/selected-mhz"); - fgUntie("/radios/comm[0]/frequencies/standby-mhz"); - fgUntie("/radios/comm[0]/on"); - fgUntie("/radios/comm[0]/ident"); - - fgUntie("/radios/comm[1]/frequencies/selected-mhz"); - fgUntie("/radios/comm[1]/frequencies/standby-mhz"); - fgUntie("/radios/comm[1]/on"); - fgUntie("/radios/comm[1]/ident"); - - fgUntie("/radios/nav[0]/frequencies/selected-mhz"); - fgUntie("/radios/nav[0]/frequencies/standby-mhz"); - fgUntie("/radios/nav[0]/radials/actual-deg"); - fgUntie("/radios/nav[0]/radials/selected-deg"); - fgUntie("/radios/nav[0]/on"); - fgUntie("/radios/nav[0]/ident"); - fgUntie("/radios/nav[0]/to-flag"); - fgUntie("/radios/nav[0]/from-flag"); - fgUntie("/radios/nav[0]/in-range"); - fgUntie("/radios/nav[0]/heading-needle-deflection"); - fgUntie("/radios/nav[0]/gs-needle-deflection"); - - fgUntie("/radios/nav[1]/frequencies/selected-mhz"); - fgUntie("/radios/nav[1]/frequencies/standby-mhz"); - fgUntie("/radios/nav[1]/radials/actual-deg"); - fgUntie("/radios/nav[1]/radials/selected-deg"); - fgUntie("/radios/nav[1]/on"); - fgUntie("/radios/nav[1]/ident"); - fgUntie("/radios/nav[1]/to-flag"); - fgUntie("/radios/nav[1]/from-flag"); - fgUntie("/radios/nav[1]/in-range"); - fgUntie("/radios/nav[1]/heading-needle-deflection"); - fgUntie("/radios/nav[1]/gs-needle-deflection"); - fgUntie("/radios/dme/frequencies/selected-khz"); // Radio outputs @@ -321,6 +198,8 @@ FGRadioStack::unbind () fgUntie("/radios/marker-beacon/middle"); fgUntie("/radios/marker-beacon/outer"); + navcom1.unbind(); + navcom2.unbind(); adf.unbind(); xponder.unbind(); } @@ -400,216 +279,9 @@ FGRadioStack::update(double dt) Point3D aircraft = sgGeodToCart( Point3D( lon, lat, elev ) ); Point3D station; - double az1, az2, s; - - //////////////////////////////////////////////////////////////////////// - // Nav1. - //////////////////////////////////////////////////////////////////////// - - if ( nav1_valid ) { - station = Point3D( nav1_x, nav1_y, nav1_z ); - nav1_loc_dist = aircraft.distance3D( station ); - - if ( nav1_has_gs ) { - station = Point3D( nav1_gs_x, nav1_gs_y, nav1_gs_z ); - nav1_gs_dist = aircraft.distance3D( station ); - } else { - nav1_gs_dist = 0.0; - } - - // wgs84 heading - geo_inverse_wgs_84( elev, lat * SGD_RADIANS_TO_DEGREES, lon * SGD_RADIANS_TO_DEGREES, - nav1_loclat, nav1_loclon, - &az1, &az2, &s ); - // cout << "az1 = " << az1 << " magvar = " << nav1_magvar << endl; - nav1_heading = az1 - nav1_magvar; - // cout << " heading = " << nav1_heading - // << " dist = " << nav1_dist << endl; - - if ( nav1_loc ) { - double offset = nav1_heading - nav1_radial; - while ( offset < -180.0 ) { offset += 360.0; } - while ( offset > 180.0 ) { offset -= 360.0; } - // cout << "ils offset = " << offset << endl; - nav1_effective_range = adjustILSRange(nav1_elev, elev, offset, - nav1_loc_dist * SG_METER_TO_NM ); - } else { - nav1_effective_range = adjustNavRange(nav1_elev, elev, nav1_range); - } - // cout << "nav1 range = " << nav1_effective_range - // << " (" << nav1_range << ")" << endl; - - if ( nav1_loc_dist < nav1_effective_range * SG_NM_TO_METER ) { - nav1_inrange = true; - } else if ( nav1_loc_dist < 2 * nav1_effective_range * SG_NM_TO_METER ) { - nav1_inrange = sg_random() < - ( 2 * nav1_effective_range * SG_NM_TO_METER - nav1_loc_dist ) / - (nav1_effective_range * SG_NM_TO_METER); - } else { - nav1_inrange = false; - } - - if ( !nav1_loc ) { - nav1_radial = nav1_sel_radial; - } - } else { - nav1_inrange = false; - // cout << "not picking up vor. :-(" << endl; - } - -#ifdef ENABLE_AUDIO_SUPPORT - if ( nav1_valid && nav1_inrange ) { - // play station ident via audio system if on + ident, - // otherwise turn it off - if ( nav1_vol_btn > 0.1 && nav1_ident_btn ) { - FGSimpleSound *sound; - sound = globals->get_soundmgr()->find( "nav1-vor-ident" ); - if ( sound != NULL ) { - sound->set_volume( nav1_vol_btn ); - } else { - SG_LOG( SG_COCKPIT, SG_ALERT, - "Can't find nav1-vor-ident sound" ); - } - sound = globals->get_soundmgr()->find( "nav1-dme-ident" ); - if ( sound != NULL ) { - sound->set_volume( nav1_vol_btn ); - } else { - SG_LOG( SG_COCKPIT, SG_ALERT, - "Can't find nav1-dme-ident sound" ); - } - // cout << "nav1_last_time = " << nav1_last_time << " "; - // cout << "cur_time = " << globals->get_time_params()->get_cur_time(); - if ( nav1_last_time < - globals->get_time_params()->get_cur_time() - 30 ) { - nav1_last_time = globals->get_time_params()->get_cur_time(); - nav1_play_count = 0; - } - // cout << " nav1_play_count = " << nav1_play_count << endl; - // cout << "playing = " - // << globals->get_soundmgr()->is_playing("nav1-vor-ident") - // << endl; - if ( nav1_play_count < 4 ) { - // play VOR ident - if ( !globals->get_soundmgr()->is_playing("nav1-vor-ident") ) { - globals->get_soundmgr()->play_once( "nav1-vor-ident" ); - ++nav1_play_count; - } - } else if ( nav1_play_count < 5 && nav1_has_dme ) { - // play DME ident - if ( !globals->get_soundmgr()->is_playing("nav1-vor-ident") && - !globals->get_soundmgr()->is_playing("nav1-dme-ident") ) { - globals->get_soundmgr()->play_once( "nav1-dme-ident" ); - ++nav1_play_count; - } - } - } else { - globals->get_soundmgr()->stop( "nav1-vor-ident" ); - globals->get_soundmgr()->stop( "nav1-dme-ident" ); - } - } -#endif - - - //////////////////////////////////////////////////////////////////////// - // Nav2. - //////////////////////////////////////////////////////////////////////// - - if ( nav2_valid ) { - station = Point3D( nav2_x, nav2_y, nav2_z ); - nav2_loc_dist = aircraft.distance3D( station ); - - if ( nav2_has_gs ) { - station = Point3D( nav2_gs_x, nav2_gs_y, nav2_gs_z ); - nav2_gs_dist = aircraft.distance3D( station ); - } else { - nav2_gs_dist = 0.0; - } - - // wgs84 heading - geo_inverse_wgs_84( elev, lat * SGD_RADIANS_TO_DEGREES, lon * SGD_RADIANS_TO_DEGREES, - nav2_loclat, nav2_loclon, - &az1, &az2, &s ); - nav2_heading = az1 - nav2_magvar; - // cout << " heading = " << nav2_heading - // << " dist = " << nav2_dist << endl; - - if ( nav2_loc ) { - double offset = nav2_heading - nav2_radial; - while ( offset < -180.0 ) { offset += 360.0; } - while ( offset > 180.0 ) { offset -= 360.0; } - // cout << "ils offset = " << offset << endl; - nav2_effective_range = adjustILSRange(nav2_elev, elev, offset, - nav2_loc_dist * SG_METER_TO_NM ); - } else { - nav2_effective_range = adjustNavRange(nav2_elev, elev, nav2_range); - } - // cout << "nav2 range = " << nav2_effective_range - // << " (" << nav2_range << ")" << endl; - - if ( nav2_loc_dist < nav2_effective_range * SG_NM_TO_METER ) { - nav2_inrange = true; - } else if ( nav2_loc_dist < 2 * nav2_effective_range * SG_NM_TO_METER ) { - nav2_inrange = sg_random() < - ( 2 * nav2_effective_range * SG_NM_TO_METER - nav2_loc_dist ) / - (nav2_effective_range * SG_NM_TO_METER); - } else { - nav2_inrange = false; - } - - if ( !nav2_loc ) { - nav2_radial = nav2_sel_radial; - } - } else { - nav2_inrange = false; - // cout << "not picking up vor. :-(" << endl; - } - -#ifdef ENABLE_AUDIO_SUPPORT - if ( nav2_valid && nav2_inrange ) { - // play station ident via audio system if on + ident, - // otherwise turn it off - if ( nav2_vol_btn > 0.1 && nav2_ident_btn ) { - FGSimpleSound *sound; - sound = globals->get_soundmgr()->find( "nav2-vor-ident" ); - if ( sound != NULL ) { - sound->set_volume( nav2_vol_btn ); - } else { - SG_LOG( SG_COCKPIT, SG_ALERT, - "Can't find nav2-vor-ident sound" ); - } - sound = globals->get_soundmgr()->find( "nav2-dme-ident" ); - if ( sound != NULL ) { - sound->set_volume( nav2_vol_btn ); - } else { - SG_LOG( SG_COCKPIT, SG_ALERT, - "Can't find nav2-dme-ident sound" ); - } - if ( nav2_last_time < - globals->get_time_params()->get_cur_time() - 30 ) { - nav2_last_time = globals->get_time_params()->get_cur_time(); - nav2_play_count = 0; - } - if ( nav2_play_count < 4 ) { - // play VOR ident - if ( !globals->get_soundmgr()->is_playing("nav2-vor-ident") ) { - globals->get_soundmgr()->play_once( "nav2-vor-ident" ); - ++nav2_play_count; - } - } else if ( nav2_play_count < 5 && nav2_has_dme ) { - // play DME ident - if ( !globals->get_soundmgr()->is_playing("nav2-vor-ident") && - !globals->get_soundmgr()->is_playing("nav2-dme-ident") ) { - globals->get_soundmgr()->play_once( "nav2-dme-ident" ); - ++nav2_play_count; - } - } - } else { - globals->get_soundmgr()->stop( "nav2-vor-ident" ); - globals->get_soundmgr()->stop( "nav2-dme-ident" ); - } - } -#endif + navcom1.update( dt ); + navcom2.update( dt ); //////////////////////////////////////////////////////////////////////// // DME. @@ -712,13 +384,13 @@ void FGRadioStack::search() dme_freq = 0; dme_inrange = false; } else if (dme_switch_pos == 1) { - if (dme_freq != nav1_freq) { - dme_freq = nav1_freq; + if (dme_freq != navcom1.get_nav_freq()) { + dme_freq = navcom1.get_nav_freq(); need_update = true; } } else if (dme_switch_pos == 3) { - if (dme_freq != nav2_freq) { - dme_freq = nav2_freq; + if (dme_freq != navcom2.get_nav_freq()) { + dme_freq = navcom2.get_nav_freq(); need_update = true; } } @@ -726,271 +398,8 @@ void FGRadioStack::search() FGILS ils; FGNav nav; - static string last_nav1_ident = ""; - static string last_nav2_ident = ""; - static bool last_nav1_vor = false; - static bool last_nav2_vor = false; - - //////////////////////////////////////////////////////////////////////// - // Nav1. - //////////////////////////////////////////////////////////////////////// - - if ( current_ilslist->query( lon, lat, elev, nav1_freq, &ils ) ) { - nav1_ident = ils.get_locident(); - nav1_valid = true; - if ( last_nav1_ident != nav1_ident || last_nav1_vor ) { - nav1_trans_ident = ils.get_trans_ident(); - last_nav1_ident = nav1_ident; - last_nav1_vor = false; - nav1_loc = true; - nav1_has_dme = ils.get_has_dme(); - nav1_has_gs = ils.get_has_gs(); - - nav1_loclon = ils.get_loclon(); - nav1_loclat = ils.get_loclat(); - nav1_gslon = ils.get_gslon(); - nav1_gslat = ils.get_gslat(); - nav1_elev = ils.get_gselev(); - nav1_magvar = 0; - nav1_range = FG_ILS_DEFAULT_RANGE; - nav1_effective_range = nav1_range; - nav1_target_gs = ils.get_gsangle(); - nav1_radial = ils.get_locheading(); - while ( nav1_radial < 0.0 ) { nav1_radial += 360.0; } - while ( nav1_radial > 360.0 ) { nav1_radial -= 360.0; } - nav1_x = ils.get_x(); - nav1_y = ils.get_y(); - nav1_z = ils.get_z(); - nav1_gs_x = ils.get_gs_x(); - nav1_gs_y = ils.get_gs_y(); - nav1_gs_z = ils.get_gs_z(); - -#ifdef ENABLE_AUDIO_SUPPORT - if ( globals->get_soundmgr()->exists( "nav1-vor-ident" ) ) { - globals->get_soundmgr()->remove( "nav1-vor-ident" ); - } - FGSimpleSound *sound; - sound = morse.make_ident( nav1_trans_ident, LO_FREQUENCY ); - sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "nav1-vor-ident" ); - - if ( globals->get_soundmgr()->exists( "nav1-dme-ident" ) ) { - globals->get_soundmgr()->remove( "nav1-dme-ident" ); - } - sound = morse.make_ident( nav1_trans_ident, HI_FREQUENCY ); - sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "nav1-dme-ident" ); - - int offset = (int)(sg_random() * 30.0); - nav1_play_count = offset / 4; - nav1_last_time = globals->get_time_params()->get_cur_time() - - offset; - // cout << "offset = " << offset << " play_count = " - // << nav1_play_count - // << " nav1_last_time = " << nav1_last_time - // << " current time = " - // << globals->get_time_params()->get_cur_time() << endl; -#endif - - // cout << "Found an ils station in range" << endl; - // cout << " id = " << ils.get_locident() << endl; - } - } else if ( current_navlist->query( lon, lat, elev, nav1_freq, &nav ) ) { - nav1_ident = nav.get_ident(); - nav1_valid = true; - if ( last_nav1_ident != nav1_ident || !last_nav1_vor ) { - last_nav1_ident = nav1_ident; - last_nav1_vor = true; - nav1_trans_ident = nav.get_trans_ident(); - nav1_loc = false; - nav1_has_dme = nav.get_has_dme(); - nav1_has_gs = false; - nav1_loclon = nav.get_lon(); - nav1_loclat = nav.get_lat(); - nav1_elev = nav.get_elev(); - nav1_magvar = nav.get_magvar(); - nav1_range = nav.get_range(); - nav1_effective_range = adjustNavRange(nav1_elev, elev, nav1_range); - nav1_target_gs = 0.0; - nav1_radial = nav1_sel_radial; - nav1_x = nav.get_x(); - nav1_y = nav.get_y(); - nav1_z = nav.get_z(); - -#ifdef ENABLE_AUDIO_SUPPORT - if ( globals->get_soundmgr()->exists( "nav1-vor-ident" ) ) { - globals->get_soundmgr()->remove( "nav1-vor-ident" ); - } - FGSimpleSound *sound; - sound = morse.make_ident( nav1_trans_ident, LO_FREQUENCY ); - sound->set_volume( 0.3 ); - if ( globals->get_soundmgr()->add( sound, "nav1-vor-ident" ) ) { - // cout << "Added nav1-vor-ident sound" << endl; - } else { - // cout << "Failed to add v1-vor-ident sound" << endl; - } - - if ( globals->get_soundmgr()->exists( "nav1-dme-ident" ) ) { - globals->get_soundmgr()->remove( "nav1-dme-ident" ); - } - sound = morse.make_ident( nav1_trans_ident, HI_FREQUENCY ); - sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "nav1-dme-ident" ); - - int offset = (int)(sg_random() * 30.0); - nav1_play_count = offset / 4; - nav1_last_time = globals->get_time_params()->get_cur_time() - - offset; - // cout << "offset = " << offset << " play_count = " - // << nav1_play_count << " nav1_last_time = " - // << nav1_last_time << " current time = " - // << globals->get_time_params()->get_cur_time() << endl; -#endif - - // cout << "Found a vor station in range" << endl; - // cout << " id = " << nav.get_ident() << endl; - } - } else { - nav1_valid = false; - nav1_ident = ""; - nav1_radial = 0; - nav1_trans_ident = ""; - last_nav1_ident = ""; -#ifdef ENABLE_AUDIO_SUPPORT - if ( ! globals->get_soundmgr()->remove( "nav1-vor-ident" ) ) { - // cout << "Failed to remove nav1-vor-ident sound" << endl; - } - globals->get_soundmgr()->remove( "nav1-dme-ident" ); -#endif - // cout << "not picking up vor1. :-(" << endl; - } - - - //////////////////////////////////////////////////////////////////////// - // Nav2. - //////////////////////////////////////////////////////////////////////// - - if ( current_ilslist->query( lon, lat, elev, nav2_freq, &ils ) ) { - nav2_ident = ils.get_locident(); - nav2_valid = true; - if ( last_nav2_ident != nav2_ident || last_nav2_vor ) { - last_nav2_ident = nav2_ident; - last_nav2_vor = false; - nav2_trans_ident = ils.get_trans_ident(); - nav2_loc = true; - nav2_has_dme = ils.get_has_dme(); - nav2_has_gs = ils.get_has_gs(); - - nav2_loclon = ils.get_loclon(); - nav2_loclat = ils.get_loclat(); - nav2_elev = ils.get_gselev(); - nav2_magvar = 0; - nav2_range = FG_ILS_DEFAULT_RANGE; - nav2_effective_range = nav2_range; - nav2_target_gs = ils.get_gsangle(); - nav2_radial = ils.get_locheading(); - while ( nav2_radial < 0.0 ) { nav2_radial += 360.0; } - while ( nav2_radial > 360.0 ) { nav2_radial -= 360.0; } - nav2_x = ils.get_x(); - nav2_y = ils.get_y(); - nav2_z = ils.get_z(); - nav2_gs_x = ils.get_gs_x(); - nav2_gs_y = ils.get_gs_y(); - nav2_gs_z = ils.get_gs_z(); - -#ifdef ENABLE_AUDIO_SUPPORT - if ( globals->get_soundmgr()->exists( "nav2-vor-ident" ) ) { - globals->get_soundmgr()->remove( "nav2-vor-ident" ); - } - FGSimpleSound *sound; - sound = morse.make_ident( nav2_trans_ident, LO_FREQUENCY ); - sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "nav2-vor-ident" ); - - if ( globals->get_soundmgr()->exists( "nav2-dme-ident" ) ) { - globals->get_soundmgr()->remove( "nav2-dme-ident" ); - } - sound = morse.make_ident( nav2_trans_ident, HI_FREQUENCY ); - sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "nav2-dme-ident" ); - - int offset = (int)(sg_random() * 30.0); - nav2_play_count = offset / 4; - nav2_last_time = globals->get_time_params()->get_cur_time() - - offset; - // cout << "offset = " << offset << " play_count = " - // << nav2_play_count << " nav2_last_time = " - // << nav2_last_time << " current time = " - // << globals->get_time_params()->get_cur_time() << endl; -#endif - - // cout << "Found an ils station in range" << endl; - // cout << " id = " << ils.get_locident() << endl; - } - } else if ( current_navlist->query( lon, lat, elev, nav2_freq, &nav ) ) { - nav2_ident = nav.get_ident(); - nav2_valid = true; - if ( last_nav2_ident != nav2_ident || !last_nav2_vor ) { - last_nav2_ident = nav2_ident; - last_nav2_vor = true; - nav2_trans_ident = nav.get_trans_ident(); - nav2_loc = false; - nav2_has_dme = nav.get_has_dme(); - nav2_has_dme = false; - nav2_loclon = nav.get_lon(); - nav2_loclat = nav.get_lat(); - nav2_elev = nav.get_elev(); - nav2_magvar = nav.get_magvar(); - nav2_range = nav.get_range(); - nav2_effective_range = adjustNavRange(nav2_elev, elev, nav2_range); - nav2_target_gs = 0.0; - nav2_radial = nav2_sel_radial; - nav2_x = nav.get_x(); - nav2_y = nav.get_y(); - nav2_z = nav.get_z(); - -#ifdef ENABLE_AUDIO_SUPPORT - if ( globals->get_soundmgr()->exists( "nav2-vor-ident" ) ) { - globals->get_soundmgr()->remove( "nav2-vor-ident" ); - } - FGSimpleSound *sound; - sound = morse.make_ident( nav2_trans_ident, LO_FREQUENCY ); - sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "nav2-vor-ident" ); - - if ( globals->get_soundmgr()->exists( "nav2-dme-ident" ) ) { - globals->get_soundmgr()->remove( "nav2-dme-ident" ); - } - sound = morse.make_ident( nav2_trans_ident, HI_FREQUENCY ); - sound->set_volume( 0.3 ); - globals->get_soundmgr()->add( sound, "nav2-dme-ident" ); - - int offset = (int)(sg_random() * 30.0); - nav2_play_count = offset / 4; - nav2_last_time = globals->get_time_params()->get_cur_time() - - offset; - // cout << "offset = " << offset << " play_count = " - // << nav2_play_count << " nav2_last_time = " - // << nav2_last_time << " current time = " - // << globals->get_time_params()->get_cur_time() << endl; -#endif - - // cout << "Found a vor station in range" << endl; - // cout << " id = " << nav.get_ident() << endl; - } - } else { - nav2_valid = false; - nav2_ident = ""; - nav2_radial = 0; - nav2_trans_ident = ""; - last_nav2_ident = ""; -#ifdef ENABLE_AUDIO_SUPPORT - globals->get_soundmgr()->remove( "nav2-vor-ident" ); - globals->get_soundmgr()->remove( "nav2-dme-ident" ); -#endif - // cout << "not picking up vor1. :-(" << endl; - } - + navcom1.search(); + navcom2.search(); //////////////////////////////////////////////////////////////////////// // DME @@ -1091,163 +500,8 @@ void FGRadioStack::search() } last_beacon = beacon_type; + navcom1.search(); + navcom2.search(); adf.search(); xponder.search(); } - - -// return the amount of heading needle deflection, returns a value -// clamped to the range of ( -10 , 10 ) -double FGRadioStack::get_nav1_heading_needle_deflection() const { - double r; - - if ( nav1_inrange ) { - r = nav1_heading - nav1_radial; - // cout << "Radial = " << nav1_radial - // << " Bearing = " << nav1_heading << 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 ); - if ( nav1_loc ) { - r = -r; - } - } - - // According to Robin Peel, the ILS is 4x more sensitive than a vor - if ( nav1_loc ) { r *= 4.0; } - if ( r < -10.0 ) { r = -10.0; } - if ( r > 10.0 ) { r = 10.0; } - } else { - r = 0.0; - } - - return r; -} - -// return the amount of heading needle deflection, returns a value -// clamped to the range of ( -10 , 10 ) -double FGRadioStack::get_nav2_heading_needle_deflection() const { - double r; - - if ( nav2_inrange ) { - r = nav2_heading - nav2_radial; - // cout << "Radial = " << nav2_radial - // << " Bearing = " << nav2_heading << 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 ); - // According to Robin Peel, the ILS is 4x more sensitive than a vor - if ( nav2_loc ) r *= 4.0; - if ( r < -10.0 ) r = -10.0; - if ( r > 10.0 ) r = 10.0; - } else { - r = 0.0; - } - - return r; -} - -// return the amount of glide slope needle deflection (.i.e. the -// number of degrees we are off the glide slope * 5.0 -double FGRadioStack::get_nav1_gs_needle_deflection() const { - if ( nav1_inrange && nav1_has_gs ) { - double x = nav1_gs_dist; - double y = (fgGetDouble("/position/altitude-ft") - nav1_elev) - * SG_FEET_TO_METER; - double angle = atan2( y, x ) * SGD_RADIANS_TO_DEGREES; - return (nav1_target_gs - angle) * 5.0; - } else { - return 0.0; - } -} - - -// return the amount of glide slope needle deflection (.i.e. the -// number of degrees we are off the glide slope * 5.0 -double FGRadioStack::get_nav2_gs_needle_deflection() const { - if ( nav2_inrange && nav2_has_gs ) { - double x = nav2_gs_dist; - double y = (fgGetDouble("/position/altitude-ft") - nav2_elev) - * SG_FEET_TO_METER; - double angle = atan2( y, x ) * SGD_RADIANS_TO_DEGREES; - return (nav2_target_gs - angle) * 5.0; - } else { - return 0.0; - } -} - - -/** - * Return true if the NAV1 TO flag should be active. - */ -bool -FGRadioStack::get_nav1_to_flag () const -{ - if (nav1_inrange) { - double offset = fabs(nav1_heading - nav1_radial); - if (nav1_loc) - return true; - else - return (offset <= 90.0 || offset >= 270.0); - } else { - return false; - } -} - - -/** - * Return true if the NAV1 FROM flag should be active. - */ -bool -FGRadioStack::get_nav1_from_flag () const -{ - if (nav1_inrange) { - double offset = fabs(nav1_heading - nav1_radial); - if (nav1_loc) - return false; - else - return (offset > 90.0 && offset < 270.0); - } else { - return false; - } -} - - -/** - * Return true if the NAV2 TO flag should be active. - */ -bool -FGRadioStack::get_nav2_to_flag () const -{ - if (nav2_inrange) { - double offset = fabs(nav2_heading - nav2_radial); - if (nav2_loc) - return true; - else - return (offset <= 90.0 || offset >= 270.0); - } else { - return false; - } -} - - -/** - * Return true if the NAV2 FROM flag should be active. - */ -bool -FGRadioStack::get_nav2_from_flag () const -{ - if (nav2_inrange) { - double offset = fabs(nav2_heading - nav2_radial); - if (nav2_loc) - return false; - else - return (offset > 90.0 && offset < 270.0); - } else { - return false; - } -} diff --git a/src/Cockpit/radiostack.hxx b/src/Cockpit/radiostack.hxx index eb4c32e0a..b93542331 100644 --- a/src/Cockpit/radiostack.hxx +++ b/src/Cockpit/radiostack.hxx @@ -40,6 +40,7 @@ #include "kr_87.hxx" // ADF #include "kt_70.hxx" // Transponder +#include "navcom.hxx" class FGRadioStack : public FGSubsystem { @@ -56,102 +57,6 @@ class FGRadioStack : public FGSubsystem bool need_update; - string comm1_ident; - bool comm1_valid; - bool comm1_inrange; - double comm1_freq; - double comm1_alt_freq; - double comm1_vol_btn; - bool comm1_ident_btn; - double comm1_x; - double comm1_y; - double comm1_z; - double comm1_dist; - double comm1_elev; - double comm1_range; - double comm1_effective_range; - - string comm2_ident; - bool comm2_valid; - bool comm2_inrange; - double comm2_freq; - double comm2_alt_freq; - double comm2_vol_btn; - bool comm2_ident_btn; - double comm2_x; - double comm2_y; - double comm2_z; - double comm2_dist; - double comm2_elev; - double comm2_range; - double comm2_effective_range; - - string nav1_ident; - string nav1_trans_ident; - bool nav1_valid; - bool nav1_inrange; - bool nav1_has_dme; - bool nav1_has_gs; - bool nav1_loc; - double nav1_freq; - double nav1_alt_freq; - double nav1_radial; - double nav1_sel_radial; - double nav1_loclon; - double nav1_loclat; - double nav1_x; - double nav1_y; - double nav1_z; - double nav1_loc_dist; - double nav1_gslon; - double nav1_gslat; - double nav1_gs_x; - double nav1_gs_y; - double nav1_gs_z; - double nav1_gs_dist; - SGTimeStamp prev_time; - SGTimeStamp curr_time; - double nav1_elev; - double nav1_range; - double nav1_effective_range; - double nav1_heading; - double nav1_target_gs; - double nav1_magvar; - double nav1_vol_btn; - bool nav1_ident_btn; - - string nav2_ident; - string nav2_trans_ident; - bool nav2_valid; - bool nav2_inrange; - bool nav2_has_dme; - bool nav2_has_gs; - bool nav2_loc; - double nav2_freq; - double nav2_alt_freq; - double nav2_radial; - double nav2_sel_radial; - double nav2_loclon; - double nav2_loclat; - double nav2_x; - double nav2_y; - double nav2_z; - double nav2_loc_dist; - double nav2_gslon; - double nav2_gslat; - double nav2_gs_x; - double nav2_gs_y; - double nav2_gs_z; - double nav2_gs_dist; - double nav2_elev; - double nav2_range; - double nav2_effective_range; - double nav2_heading; - double nav2_target_gs; - double nav2_magvar; - double nav2_vol_btn; - bool nav2_ident_btn; - bool dme_valid; bool dme_inrange; double dme_freq; @@ -180,6 +85,8 @@ class FGRadioStack : public FGSubsystem FGKR_87 adf; // King KR 87 Digital ADF model FGKT_70 xponder; // Bendix/King KT 70 Panel-Mounted Transponder + FGNavCom navcom1; + FGNavCom navcom2; // model standard VOR/DME/TACAN service volumes as per AIM 1-1-8 double adjustNavRange( double stationElev, double aircraftElev, @@ -202,82 +109,14 @@ public: // Update nav/adf radios based on current postition void search (); - // COMM1 Setters - inline void set_comm1_freq( double freq ) { - comm1_freq = freq; need_update = true; - } - inline void set_comm1_alt_freq( double freq ) { comm1_alt_freq = freq; } - inline void set_comm1_vol_btn( double val ) { - if ( val < 0.0 ) val = 0.0; - if ( val > 1.0 ) val = 1.0; - comm1_vol_btn = val; - } - inline void set_comm1_ident_btn( bool val ) { comm1_ident_btn = val; } - - // COMM2 Setters - inline void set_comm2_freq( double freq ) { - comm2_freq = freq; need_update = true; - } - inline void set_comm2_alt_freq( double freq ) { comm2_alt_freq = freq; } - inline void set_comm2_vol_btn( double val ) { - if ( val < 0.0 ) val = 0.0; - if ( val > 1.0 ) val = 1.0; - comm2_vol_btn = val; - } - inline void set_comm2_ident_btn( bool val ) { comm2_ident_btn = val; } - - // NAV1 Setters - inline void set_nav1_freq( double freq ) { - nav1_freq = freq; need_update = true; - } - inline void set_nav1_alt_freq( double freq ) { nav1_alt_freq = freq; } - inline void set_nav1_sel_radial( double radial ) { - nav1_sel_radial = radial; need_update = true; - } - inline void set_nav1_vol_btn( double val ) { - if ( val < 0.0 ) val = 0.0; - if ( val > 1.0 ) val = 1.0; - nav1_vol_btn = val; - } - inline void set_nav1_ident_btn( bool val ) { nav1_ident_btn = val; } - - // NAV2 Setters - inline void set_nav2_freq( double freq ) { - nav2_freq = freq; need_update = true; - } - inline void set_nav2_alt_freq( double freq ) { nav2_alt_freq = freq; } - inline void set_nav2_sel_radial( double radial ) { - nav2_sel_radial = radial; need_update = true; - } - inline void set_nav2_vol_btn( double val ) { - if ( val < 0.0 ) val = 0.0; - if ( val > 1.0 ) val = 1.0; - nav2_vol_btn = val; - } - inline void set_nav2_ident_btn( bool val ) { nav2_ident_btn = val; } + inline FGNavCom *get_navcom1() { return &navcom1; } + inline FGNavCom *get_navcom2() { return &navcom2; } // DME Setters inline void set_dme_freq (double freq) { dme_freq = freq; need_update = true; } - // COMM1 Accessors - inline double get_comm1_freq () const { return comm1_freq; } - inline double get_comm1_alt_freq () const { return comm1_alt_freq; } - - // COMM2 Accessors - inline double get_comm2_freq () const { return comm2_freq; } - inline double get_comm2_alt_freq () const { return comm2_alt_freq; } - - // NAV1 Accessors - inline double get_nav1_freq () const { return nav1_freq; } - inline double get_nav1_alt_freq () const { return nav1_alt_freq; } - inline double get_nav1_sel_radial() const { return nav1_sel_radial; } - - // NAV2 Accessors - inline double get_nav2_freq () const { return nav2_freq; } - inline double get_nav2_alt_freq () const { return nav2_alt_freq; } - inline double get_nav2_sel_radial() const { return nav2_sel_radial; } // DME Accessors inline double get_dme_freq () const { return dme_freq; } @@ -288,64 +127,6 @@ public: inline bool get_outer_blink () const { return outer_blink; } // Calculated values. - inline bool get_comm1_inrange() const { return comm1_inrange; } - inline double get_comm1_vol_btn() const { return comm1_vol_btn; } - inline bool get_comm1_ident_btn() const { return comm1_ident_btn; } - - inline bool get_comm2_inrange() const { return comm2_inrange; } - inline double get_comm2_vol_btn() const { return comm2_vol_btn; } - inline bool get_comm2_ident_btn() const { return comm2_ident_btn; } - - inline bool get_nav1_inrange() const { return nav1_inrange; } - bool get_nav1_to_flag () const; - bool get_nav1_from_flag () const; - inline bool get_nav1_has_dme() const { return nav1_has_dme; } - inline bool get_nav1_dme_inrange () const { - return nav1_inrange && nav1_has_dme; - } - inline bool get_nav1_has_gs() const { return nav1_has_gs; } - inline bool get_nav1_loc() const { return nav1_loc; } - inline double get_nav1_loclon() const { return nav1_loclon; } - inline double get_nav1_loclat() const { return nav1_loclat; } - inline double get_nav1_loc_dist() const { return nav1_loc_dist; } - inline double get_nav1_gslon() const { return nav1_gslon; } - inline double get_nav1_gslat() const { return nav1_gslat; } - inline double get_nav1_gs_dist() const { return nav1_gs_dist; } - inline double get_nav1_elev() const { return nav1_elev; } - inline double get_nav1_heading() const { return nav1_heading; } - inline double get_nav1_radial() const { return nav1_radial; } - inline double get_nav1_target_gs() const { return nav1_target_gs; } - inline double get_nav1_magvar() const { return nav1_magvar; } - double get_nav1_heading_needle_deflection() const; - double get_nav1_gs_needle_deflection() const; - inline double get_nav1_vol_btn() const { return nav1_vol_btn; } - inline bool get_nav1_ident_btn() const { return nav1_ident_btn; } - - inline bool get_nav2_inrange() const { return nav2_inrange; } - bool get_nav2_to_flag () const; - bool get_nav2_from_flag () const; - inline bool get_nav2_has_dme() const { return nav2_has_dme; } - inline bool get_nav2_dme_inrange () const { - return nav2_inrange && nav2_has_dme; - } - inline bool get_nav2_has_gs() const { return nav2_has_gs; } - inline bool get_nav2_loc() const { return nav2_loc; } - inline double get_nav2_loclon() const { return nav2_loclon; } - inline double get_nav2_loclat() const { return nav2_loclat; } - inline double get_nav2_loc_dist() const { return nav2_loc_dist; } - inline double get_nav2_gslon() const { return nav2_gslon; } - inline double get_nav2_gslat() const { return nav2_gslat; } - inline double get_nav2_gs_dist() const { return nav2_gs_dist; } - inline double get_nav2_elev() const { return nav2_elev; } - inline double get_nav2_heading() const { return nav2_heading; } - inline double get_nav2_radial() const { return nav2_radial; } - inline double get_nav2_target_gs() const { return nav2_target_gs; } - inline double get_nav2_magvar() const { return nav2_magvar; } - double get_nav2_heading_needle_deflection() const; - double get_nav2_gs_needle_deflection() const; - inline double get_nav2_vol_btn() const { return nav2_vol_btn; } - inline bool get_nav2_ident_btn() const { return nav2_ident_btn; } - inline bool get_dme_inrange () const { return dme_inrange; } inline double get_dme_dist () const { return dme_dist; } inline double get_dme_spd () const { return dme_spd; } diff --git a/src/Cockpit/steam.cxx b/src/Cockpit/steam.cxx index 4bc4fe6e7..e5f058407 100644 --- a/src/Cockpit/steam.cxx +++ b/src/Cockpit/steam.cxx @@ -494,12 +494,12 @@ void FGSteam::_CatchUp() double FGSteam::get_HackOBS1_deg () const { - return current_radiostack->get_nav1_radial(); + return current_radiostack->get_navcom1()->get_nav_radial(); } double FGSteam::get_HackOBS2_deg () const { - return current_radiostack->get_nav2_radial(); + return current_radiostack->get_navcom2()->get_nav_radial(); }