Merge branch 'jmt/navradio'
The previous merge claimed to have merged this branch; it didn't because I had reset the branch to someplace weird.
This commit is contained in:
commit
4023bdaf26
2 changed files with 139 additions and 60 deletions
|
@ -78,6 +78,17 @@ static SGVec3d tangentVector(const SGGeod& tail, const SGVec3d& tail_xyz,
|
||||||
return (head_xyz - tail_xyz) * (1.0/fudge);
|
return (head_xyz - tail_xyz) * (1.0/fudge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a "serviceable" node with a default value of "true"
|
||||||
|
SGPropertyNode_ptr createServiceableProp(SGPropertyNode* aParent, const char* aName)
|
||||||
|
{
|
||||||
|
SGPropertyNode_ptr n = (aParent->getChild(aName, 0, true)->getChild("serviceable", 0, true));
|
||||||
|
simgear::props::Type typ = n->getType();
|
||||||
|
if ((typ == simgear::props::NONE) || (typ == simgear::props::UNSPECIFIED)) {
|
||||||
|
n->setBoolValue(true);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
lon_node(fgGetNode("/position/longitude-deg", true)),
|
lon_node(fgGetNode("/position/longitude-deg", true)),
|
||||||
|
@ -96,6 +107,7 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
cdi_serviceable_node(NULL),
|
cdi_serviceable_node(NULL),
|
||||||
gs_serviceable_node(NULL),
|
gs_serviceable_node(NULL),
|
||||||
tofrom_serviceable_node(NULL),
|
tofrom_serviceable_node(NULL),
|
||||||
|
dme_serviceable_node(NULL),
|
||||||
fmt_freq_node(NULL),
|
fmt_freq_node(NULL),
|
||||||
fmt_alt_freq_node(NULL),
|
fmt_alt_freq_node(NULL),
|
||||||
heading_node(NULL),
|
heading_node(NULL),
|
||||||
|
@ -120,6 +132,7 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
gs_deflection_norm_node(NULL),
|
gs_deflection_norm_node(NULL),
|
||||||
gs_rate_of_climb_node(NULL),
|
gs_rate_of_climb_node(NULL),
|
||||||
gs_dist_node(NULL),
|
gs_dist_node(NULL),
|
||||||
|
gs_inrange_node(NULL),
|
||||||
nav_id_node(NULL),
|
nav_id_node(NULL),
|
||||||
id_c1_node(NULL),
|
id_c1_node(NULL),
|
||||||
id_c2_node(NULL),
|
id_c2_node(NULL),
|
||||||
|
@ -140,7 +153,8 @@ FGNavRadio::FGNavRadio(SGPropertyNode *node) :
|
||||||
_localizerWidth(5.0),
|
_localizerWidth(5.0),
|
||||||
_name(node->getStringValue("name", "nav")),
|
_name(node->getStringValue("name", "nav")),
|
||||||
_num(node->getIntValue("number", 0)),
|
_num(node->getIntValue("number", 0)),
|
||||||
_time_before_search_sec(-1.0)
|
_time_before_search_sec(-1.0),
|
||||||
|
_falseCoursesEnabled(true)
|
||||||
{
|
{
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
SGPath term = path;
|
SGPath term = path;
|
||||||
|
@ -189,14 +203,16 @@ FGNavRadio::init ()
|
||||||
audio_btn_node->setBoolValue( true );
|
audio_btn_node->setBoolValue( true );
|
||||||
backcourse_node = node->getChild("back-course-btn", 0, true);
|
backcourse_node = node->getChild("back-course-btn", 0, true);
|
||||||
backcourse_node->setBoolValue( false );
|
backcourse_node->setBoolValue( false );
|
||||||
|
|
||||||
nav_serviceable_node = node->getChild("serviceable", 0, true);
|
nav_serviceable_node = node->getChild("serviceable", 0, true);
|
||||||
cdi_serviceable_node = (node->getChild("cdi", 0, true))
|
cdi_serviceable_node = createServiceableProp(node, "cdi");
|
||||||
->getChild("serviceable", 0, true);
|
gs_serviceable_node = createServiceableProp(node, "gs");
|
||||||
gs_serviceable_node = (node->getChild("gs", 0, true))
|
tofrom_serviceable_node = createServiceableProp(node, "to-from");
|
||||||
->getChild("serviceable");
|
dme_serviceable_node = createServiceableProp(node, "dme");
|
||||||
tofrom_serviceable_node = (node->getChild("to-from", 0, true))
|
|
||||||
->getChild("serviceable", 0, true);
|
globals->get_props()->tie("sim/realism/false-radio-courses-enabled",
|
||||||
|
SGRawValuePointer<bool>(&_falseCoursesEnabled));
|
||||||
|
|
||||||
// frequencies
|
// frequencies
|
||||||
SGPropertyNode *subnode = node->getChild("frequencies", 0, true);
|
SGPropertyNode *subnode = node->getChild("frequencies", 0, true);
|
||||||
freq_node = subnode->getChild("selected-mhz", 0, true);
|
freq_node = subnode->getChild("selected-mhz", 0, true);
|
||||||
|
@ -232,12 +248,16 @@ FGNavRadio::init ()
|
||||||
gs_deflection_norm_node = node->getChild("gs-needle-deflection-norm", 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_node = node->getChild("gs-rate-of-climb", 0, true);
|
||||||
gs_dist_node = node->getChild("gs-distance", 0, true);
|
gs_dist_node = node->getChild("gs-distance", 0, true);
|
||||||
|
gs_inrange_node = node->getChild("gs-in-range", 0, true);
|
||||||
|
|
||||||
nav_id_node = node->getChild("nav-id", 0, true);
|
nav_id_node = node->getChild("nav-id", 0, true);
|
||||||
id_c1_node = node->getChild("nav-id_asc1", 0, true);
|
id_c1_node = node->getChild("nav-id_asc1", 0, true);
|
||||||
id_c2_node = node->getChild("nav-id_asc2", 0, true);
|
id_c2_node = node->getChild("nav-id_asc2", 0, true);
|
||||||
id_c3_node = node->getChild("nav-id_asc3", 0, true);
|
id_c3_node = node->getChild("nav-id_asc3", 0, true);
|
||||||
id_c4_node = node->getChild("nav-id_asc4", 0, true);
|
id_c4_node = node->getChild("nav-id_asc4", 0, true);
|
||||||
|
|
||||||
|
node->tie("dme-in-range", SGRawValuePointer<bool>(&_dmeInRange));
|
||||||
|
|
||||||
// gps slaving support
|
// gps slaving support
|
||||||
nav_slaved_to_gps_node = node->getChild("slaved-to-gps", 0, true);
|
nav_slaved_to_gps_node = node->getChild("slaved-to-gps", 0, true);
|
||||||
gps_cdi_deflection_node = fgGetNode("/instrumentation/gps/cdi-deflection", true);
|
gps_cdi_deflection_node = fgGetNode("/instrumentation/gps/cdi-deflection", true);
|
||||||
|
@ -255,20 +275,13 @@ FGNavRadio::init ()
|
||||||
void
|
void
|
||||||
FGNavRadio::bind ()
|
FGNavRadio::bind ()
|
||||||
{
|
{
|
||||||
std::ostringstream temp;
|
|
||||||
string branch;
|
|
||||||
temp << _num;
|
|
||||||
branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGNavRadio::unbind ()
|
FGNavRadio::unbind ()
|
||||||
{
|
{
|
||||||
std::ostringstream temp;
|
|
||||||
string branch;
|
|
||||||
temp << _num;
|
|
||||||
branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,6 +289,10 @@ FGNavRadio::unbind ()
|
||||||
double FGNavRadio::adjustNavRange( double stationElev, double aircraftElev,
|
double FGNavRadio::adjustNavRange( double stationElev, double aircraftElev,
|
||||||
double nominalRange )
|
double nominalRange )
|
||||||
{
|
{
|
||||||
|
if (nominalRange <= 0.0) {
|
||||||
|
nominalRange = FG_NAV_DEFAULT_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
// extend out actual usable range to be 1.3x the published safe range
|
// extend out actual usable range to be 1.3x the published safe range
|
||||||
const double usability_factor = 1.3;
|
const double usability_factor = 1.3;
|
||||||
|
|
||||||
|
@ -382,9 +399,12 @@ void FGNavRadio::clearOutputs()
|
||||||
gs_deflection_node->setDoubleValue( 0.0 );
|
gs_deflection_node->setDoubleValue( 0.0 );
|
||||||
gs_deflection_deg_node->setDoubleValue(0.0);
|
gs_deflection_deg_node->setDoubleValue(0.0);
|
||||||
gs_deflection_norm_node->setDoubleValue(0.0);
|
gs_deflection_norm_node->setDoubleValue(0.0);
|
||||||
|
gs_inrange_node->setBoolValue( false );
|
||||||
|
|
||||||
to_flag_node->setBoolValue( false );
|
to_flag_node->setBoolValue( false );
|
||||||
from_flag_node->setBoolValue( false );
|
from_flag_node->setBoolValue( false );
|
||||||
|
|
||||||
|
_dmeInRange = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGNavRadio::updateReceiver(double dt)
|
void FGNavRadio::updateReceiver(double dt)
|
||||||
|
@ -458,7 +478,7 @@ void FGNavRadio::updateReceiver(double dt)
|
||||||
effective_range
|
effective_range
|
||||||
= adjustNavRange( nav_elev, pos.getElevationM(), _navaid->get_range() );
|
= adjustNavRange( nav_elev, pos.getElevationM(), _navaid->get_range() );
|
||||||
}
|
}
|
||||||
|
|
||||||
double effective_range_m = effective_range * SG_NM_TO_METER;
|
double effective_range_m = effective_range * SG_NM_TO_METER;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
|
@ -502,12 +522,28 @@ void FGNavRadio::updateReceiver(double dt)
|
||||||
SG_NORMALIZE_RANGE(r, -180.0, 180.0);
|
SG_NORMALIZE_RANGE(r, -180.0, 180.0);
|
||||||
|
|
||||||
if ( is_loc ) {
|
if ( is_loc ) {
|
||||||
// The factor of 30.0 gives a period of 120 which gives us 3 cycles and six
|
if (_falseCoursesEnabled) {
|
||||||
// zeros i.e. six courses: one front course, one back course, and four
|
// The factor of 30.0 gives a period of 120 which gives us 3 cycles and six
|
||||||
// false courses. Three of the six are reverse sensing.
|
// zeros i.e. six courses: one front course, one back course, and four
|
||||||
_cdiDeflection = 30.0 * sawtooth(r / 30.0);
|
// false courses. Three of the six are reverse sensing.
|
||||||
|
_cdiDeflection = 30.0 * sawtooth(r / 30.0);
|
||||||
|
} else {
|
||||||
|
// no false courses, but we do need to create a back course
|
||||||
|
if (fabs(r) > 90.0) { // front course
|
||||||
|
_cdiDeflection = r - copysign(180.0, r);
|
||||||
|
} else {
|
||||||
|
_cdiDeflection = r; // back course
|
||||||
|
}
|
||||||
|
|
||||||
|
_cdiDeflection = -_cdiDeflection; // reverse for outbound radial
|
||||||
|
} // of false courses disabled
|
||||||
|
|
||||||
const double VOR_FULL_ARC = 20.0; // VOR is -10 .. 10 degree swing
|
const double VOR_FULL_ARC = 20.0; // VOR is -10 .. 10 degree swing
|
||||||
_cdiDeflection *= VOR_FULL_ARC / _localizerWidth; // increased localiser sensitivity
|
_cdiDeflection *= VOR_FULL_ARC / _localizerWidth; // increased localiser sensitivity
|
||||||
|
|
||||||
|
if (backcourse_node->getBoolValue()) {
|
||||||
|
_cdiDeflection = -_cdiDeflection;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle the TO side of the VOR
|
// handle the TO side of the VOR
|
||||||
if (fabs(r) > 90.0) {
|
if (fabs(r) > 90.0) {
|
||||||
|
@ -523,6 +559,7 @@ void FGNavRadio::updateReceiver(double dt)
|
||||||
_cdiCrossTrackErrorM = loc_dist * sin(r * SGD_DEGREES_TO_RADIANS);
|
_cdiCrossTrackErrorM = loc_dist * sin(r * SGD_DEGREES_TO_RADIANS);
|
||||||
|
|
||||||
updateGlideSlope(dt, aircraft, signal_quality_norm);
|
updateGlideSlope(dt, aircraft, signal_quality_norm);
|
||||||
|
updateDME(aircraft);
|
||||||
|
|
||||||
last_loc_dist = loc_dist;
|
last_loc_dist = loc_dist;
|
||||||
}
|
}
|
||||||
|
@ -532,12 +569,16 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig
|
||||||
_gsNeedleDeflection = 0.0;
|
_gsNeedleDeflection = 0.0;
|
||||||
if (!_gs || !inrange_node->getBoolValue()) {
|
if (!_gs || !inrange_node->getBoolValue()) {
|
||||||
gs_dist_node->setDoubleValue( 0.0 );
|
gs_dist_node->setDoubleValue( 0.0 );
|
||||||
|
gs_inrange_node->setBoolValue(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double gsDist = dist(aircraft, _gsCart);
|
double gsDist = dist(aircraft, _gsCart);
|
||||||
gs_dist_node->setDoubleValue(gsDist);
|
gs_dist_node->setDoubleValue(gsDist);
|
||||||
if (gsDist > (_gs->get_range() * SG_NM_TO_METER)) {
|
bool gsInRange = (gsDist < (_gs->get_range() * SG_NM_TO_METER));
|
||||||
|
gs_inrange_node->setBoolValue(gsInRange);
|
||||||
|
|
||||||
|
if (!gsInRange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,21 +589,23 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig
|
||||||
double dot_v = dot(pos, _gsVertical);
|
double dot_v = dot(pos, _gsVertical);
|
||||||
double angle = atan2(dot_v, dot_h) * SGD_RADIANS_TO_DEGREES;
|
double angle = atan2(dot_v, dot_h) * SGD_RADIANS_TO_DEGREES;
|
||||||
double deflectionAngle = target_gs - angle;
|
double deflectionAngle = target_gs - angle;
|
||||||
|
|
||||||
// Construct false glideslopes. The scale factor of 1.5
|
if (_falseCoursesEnabled) {
|
||||||
// in the sawtooth gives a period of 6 degrees.
|
// Construct false glideslopes. The scale factor of 1.5
|
||||||
// There will be zeros at 3, 6r, 9, 12r et cetera
|
// in the sawtooth gives a period of 6 degrees.
|
||||||
// where "r" indicates reverse sensing.
|
// There will be zeros at 3, 6r, 9, 12r et cetera
|
||||||
// This is is consistent with conventional pilot lore
|
// where "r" indicates reverse sensing.
|
||||||
// e.g. http://www.allstar.fiu.edu/aerojava/ILS.htm
|
// This is is consistent with conventional pilot lore
|
||||||
// but inconsistent with
|
// e.g. http://www.allstar.fiu.edu/aerojava/ILS.htm
|
||||||
// http://www.freepatentsonline.com/3757338.html
|
// but inconsistent with
|
||||||
//
|
// http://www.freepatentsonline.com/3757338.html
|
||||||
// It may be that some of each exist.
|
//
|
||||||
if (deflectionAngle < 0) {
|
// It may be that some of each exist.
|
||||||
deflectionAngle = 1.5 * sawtooth(deflectionAngle / 1.5);
|
if (deflectionAngle < 0) {
|
||||||
} else {
|
deflectionAngle = 1.5 * sawtooth(deflectionAngle / 1.5);
|
||||||
// no false GS below the true GS
|
} else {
|
||||||
|
// no false GS below the true GS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_gsNeedleDeflection = deflectionAngle * 5.0;
|
_gsNeedleDeflection = deflectionAngle * 5.0;
|
||||||
|
@ -590,6 +633,17 @@ void FGNavRadio::updateGlideSlope(double dt, const SGVec3d& aircraft, double sig
|
||||||
* horiz_vel * SG_METER_TO_FEET );
|
* horiz_vel * SG_METER_TO_FEET );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGNavRadio::updateDME(const SGVec3d& aircraft)
|
||||||
|
{
|
||||||
|
if (!_dme || !dme_serviceable_node->getBoolValue()) {
|
||||||
|
_dmeInRange = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double dme_distance = dist(aircraft, _dme->cart());
|
||||||
|
_dmeInRange = (dme_distance < _dme->get_range() * SG_NM_TO_METER);
|
||||||
|
}
|
||||||
|
|
||||||
void FGNavRadio::updateGPSSlaved()
|
void FGNavRadio::updateGPSSlaved()
|
||||||
{
|
{
|
||||||
has_gs_node->setBoolValue(gps_has_gs_node->getBoolValue());
|
has_gs_node->setBoolValue(gps_has_gs_node->getBoolValue());
|
||||||
|
@ -739,25 +793,34 @@ void FGNavRadio::updateAudio()
|
||||||
} else {
|
} else {
|
||||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-dme-ident sound" );
|
SG_LOG( SG_COCKPIT, SG_ALERT, "Can't find nav-dme-ident sound" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int NUM_IDENT_SLOTS = 5;
|
||||||
|
const time_t SLOT_LENGTH = 5; // seconds
|
||||||
|
|
||||||
if ( last_time < globals->get_time_params()->get_cur_time() - 30 ) {
|
// There are N slots numbered 0 through (NUM_IDENT_SLOTS-1) inclusive.
|
||||||
last_time = globals->get_time_params()->get_cur_time();
|
// Each slot is 5 seconds long.
|
||||||
play_count = 0;
|
// Slots 0 is for DME
|
||||||
|
// the rest are for azimuth.
|
||||||
|
time_t now = globals->get_time_params()->get_cur_time();
|
||||||
|
if ((now >= last_time) && (now < last_time + SLOT_LENGTH)) {
|
||||||
|
return; // wait longer
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( play_count < 4 ) {
|
last_time = now;
|
||||||
// play VOR ident
|
play_count = ++play_count % NUM_IDENT_SLOTS;
|
||||||
if ( !globals->get_soundmgr()->is_playing(nav_fx_name) ) {
|
|
||||||
globals->get_soundmgr()->play_once( nav_fx_name );
|
// Previous ident is out of time; if still playing, cut it off:
|
||||||
++play_count;
|
globals->get_soundmgr()->stop( nav_fx_name );
|
||||||
|
globals->get_soundmgr()->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 );
|
||||||
|
}
|
||||||
|
} else { // NAV slot
|
||||||
|
if (inrange_node->getBoolValue() && nav_serviceable_node->getBoolValue()) {
|
||||||
|
globals->get_soundmgr()->play_once(nav_fx_name);
|
||||||
}
|
}
|
||||||
} else if ( play_count < 5 && 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 );
|
|
||||||
++play_count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,8 +850,7 @@ void FGNavRadio::search()
|
||||||
_navaid = nav;
|
_navaid = nav;
|
||||||
char identBuffer[5] = " ";
|
char identBuffer[5] = " ";
|
||||||
if (nav) {
|
if (nav) {
|
||||||
FGNavRecord* dme = globals->get_dmelist()->findByFreq(freq, pos);
|
_dme = globals->get_dmelist()->findByFreq(freq, pos);
|
||||||
has_dme = (dme != NULL);
|
|
||||||
|
|
||||||
nav_id_node->setStringValue(nav->get_ident());
|
nav_id_node->setStringValue(nav->get_ident());
|
||||||
strncpy(identBuffer, nav->ident().c_str(), 5);
|
strncpy(identBuffer, nav->ident().c_str(), 5);
|
||||||
|
@ -800,10 +862,11 @@ void FGNavRadio::search()
|
||||||
if (nav->type() == FGPositioned::VOR) {
|
if (nav->type() == FGPositioned::VOR) {
|
||||||
target_radial = sel_radial_node->getDoubleValue();
|
target_radial = sel_radial_node->getDoubleValue();
|
||||||
_gs = NULL;
|
_gs = NULL;
|
||||||
|
has_gs_node->setBoolValue(false);
|
||||||
} else { // ILS or LOC
|
} else { // ILS or LOC
|
||||||
_gs = globals->get_gslist()->findByFreq(freq, pos);
|
_gs = globals->get_gslist()->findByFreq(freq, pos);
|
||||||
_localizerWidth = localizerWidth(nav);
|
|
||||||
has_gs_node->setBoolValue(_gs != NULL);
|
has_gs_node->setBoolValue(_gs != NULL);
|
||||||
|
_localizerWidth = localizerWidth(nav);
|
||||||
twist = 0.0;
|
twist = 0.0;
|
||||||
effective_range = nav->get_range();
|
effective_range = nav->get_range();
|
||||||
|
|
||||||
|
@ -814,14 +877,22 @@ void FGNavRadio::search()
|
||||||
int tmp = (int)(_gs->get_multiuse() / 1000.0);
|
int tmp = (int)(_gs->get_multiuse() / 1000.0);
|
||||||
target_gs = (double)tmp / 100.0;
|
target_gs = (double)tmp / 100.0;
|
||||||
|
|
||||||
|
// until penaltyForNav goes away, we cannot assume we always pick
|
||||||
|
// paired LOC/GS trasmsitters. As we pass over a runway threshold, we
|
||||||
|
// often end up picking the 'wrong' LOC, but the correct GS. To avoid
|
||||||
|
// breaking the basis computation, ensure we use the GS radial and not
|
||||||
|
// the (potentially reversed) LOC radial.
|
||||||
|
double gs_radial = fmod(_gs->get_multiuse(), 1000.0);
|
||||||
|
SG_NORMALIZE_RANGE(gs_radial, 0.0, 360.0);
|
||||||
|
|
||||||
// GS axis unit tangent vector
|
// GS axis unit tangent vector
|
||||||
// (along the runway)
|
// (along the runway)
|
||||||
_gsCart = _gs->cart();
|
_gsCart = _gs->cart();
|
||||||
_gsAxis = tangentVector(_gs->geod(), _gsCart, target_radial);
|
_gsAxis = tangentVector(_gs->geod(), _gsCart, gs_radial);
|
||||||
|
|
||||||
// GS baseline unit tangent vector
|
// GS baseline unit tangent vector
|
||||||
// (perpendicular to the runay along the ground)
|
// (perpendicular to the runay along the ground)
|
||||||
SGVec3d baseline = tangentVector(_gs->geod(), _gsCart, target_radial + 90.0);
|
SGVec3d baseline = tangentVector(_gs->geod(), _gsCart, gs_radial + 90.0);
|
||||||
_gsVertical = cross(baseline, _gsAxis);
|
_gsVertical = cross(baseline, _gsAxis);
|
||||||
} // of have glideslope
|
} // of have glideslope
|
||||||
} // of found LOC or ILS
|
} // of found LOC or ILS
|
||||||
|
@ -829,8 +900,8 @@ void FGNavRadio::search()
|
||||||
audioNavidChanged();
|
audioNavidChanged();
|
||||||
} else { // found nothing
|
} else { // found nothing
|
||||||
_gs = NULL;
|
_gs = NULL;
|
||||||
|
_dme = NULL;
|
||||||
nav_id_node->setStringValue("");
|
nav_id_node->setStringValue("");
|
||||||
has_dme = false;
|
|
||||||
globals->get_soundmgr()->remove( nav_fx_name );
|
globals->get_soundmgr()->remove( nav_fx_name );
|
||||||
globals->get_soundmgr()->remove( dme_fx_name );
|
globals->get_soundmgr()->remove( dme_fx_name );
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,8 @@ class FGNavRadio : public SGSubsystem
|
||||||
SGPropertyNode_ptr cdi_serviceable_node;
|
SGPropertyNode_ptr cdi_serviceable_node;
|
||||||
SGPropertyNode_ptr gs_serviceable_node;
|
SGPropertyNode_ptr gs_serviceable_node;
|
||||||
SGPropertyNode_ptr tofrom_serviceable_node;
|
SGPropertyNode_ptr tofrom_serviceable_node;
|
||||||
|
SGPropertyNode_ptr dme_serviceable_node;
|
||||||
|
|
||||||
// property outputs
|
// property outputs
|
||||||
SGPropertyNode_ptr fmt_freq_node; // formated frequency
|
SGPropertyNode_ptr fmt_freq_node; // formated frequency
|
||||||
SGPropertyNode_ptr fmt_alt_freq_node; // formated alternate frequency
|
SGPropertyNode_ptr fmt_alt_freq_node; // formated alternate frequency
|
||||||
|
@ -101,6 +102,7 @@ class FGNavRadio : public SGSubsystem
|
||||||
SGPropertyNode_ptr gs_deflection_norm_node;
|
SGPropertyNode_ptr gs_deflection_norm_node;
|
||||||
SGPropertyNode_ptr gs_rate_of_climb_node;
|
SGPropertyNode_ptr gs_rate_of_climb_node;
|
||||||
SGPropertyNode_ptr gs_dist_node;
|
SGPropertyNode_ptr gs_dist_node;
|
||||||
|
SGPropertyNode_ptr gs_inrange_node;
|
||||||
SGPropertyNode_ptr nav_id_node;
|
SGPropertyNode_ptr nav_id_node;
|
||||||
SGPropertyNode_ptr id_c1_node;
|
SGPropertyNode_ptr id_c1_node;
|
||||||
SGPropertyNode_ptr id_c2_node;
|
SGPropertyNode_ptr id_c2_node;
|
||||||
|
@ -124,7 +126,6 @@ class FGNavRadio : public SGSubsystem
|
||||||
string nav_fx_name;
|
string nav_fx_name;
|
||||||
string dme_fx_name;
|
string dme_fx_name;
|
||||||
|
|
||||||
bool has_dme;
|
|
||||||
double target_radial;
|
double target_radial;
|
||||||
SGTimeStamp prev_time;
|
SGTimeStamp prev_time;
|
||||||
SGTimeStamp curr_time;
|
SGTimeStamp curr_time;
|
||||||
|
@ -145,6 +146,9 @@ class FGNavRadio : public SGSubsystem
|
||||||
|
|
||||||
SGVec3d _gsCart, _gsAxis, _gsVertical;
|
SGVec3d _gsCart, _gsAxis, _gsVertical;
|
||||||
|
|
||||||
|
FGNavRecordPtr _dme;
|
||||||
|
bool _dmeInRange;
|
||||||
|
|
||||||
// CDI properties
|
// CDI properties
|
||||||
bool _toFlag, _fromFlag;
|
bool _toFlag, _fromFlag;
|
||||||
double _cdiDeflection;
|
double _cdiDeflection;
|
||||||
|
@ -152,6 +156,9 @@ class FGNavRadio : public SGSubsystem
|
||||||
double _gsNeedleDeflection;
|
double _gsNeedleDeflection;
|
||||||
double _gsNeedleDeflectionNorm;
|
double _gsNeedleDeflectionNorm;
|
||||||
|
|
||||||
|
// realism setting, are false courses and GS lobes enabled?
|
||||||
|
bool _falseCoursesEnabled;
|
||||||
|
|
||||||
bool updateWithPower(double aDt);
|
bool updateWithPower(double aDt);
|
||||||
|
|
||||||
// model standard VOR/DME/TACAN service volumes as per AIM 1-1-8
|
// model standard VOR/DME/TACAN service volumes as per AIM 1-1-8
|
||||||
|
@ -166,6 +173,7 @@ class FGNavRadio : public SGSubsystem
|
||||||
void audioNavidChanged();
|
void audioNavidChanged();
|
||||||
|
|
||||||
void updateReceiver(double dt);
|
void updateReceiver(double dt);
|
||||||
|
void updateDME(const SGVec3d& aircraft);
|
||||||
void updateGlideSlope(double dt, const SGVec3d& aircraft, double signal_quality_norm);
|
void updateGlideSlope(double dt, const SGVec3d& aircraft, double signal_quality_norm);
|
||||||
void updateGPSSlaved();
|
void updateGPSSlaved();
|
||||||
void updateCDI(double dt);
|
void updateCDI(double dt);
|
||||||
|
|
Loading…
Add table
Reference in a new issue