Curt Olson:
These change add some code that at initialization time will snap all localizers into perfect alignment with their runways. It's my experience that the DAFIF/FAA data reports runway and localizer headings to a level of precision that is great for making charts, or adjusting your OBS, etc. But the level of precision of this data can be far enough off to make you visibly *un*aligned with the runway when the CDI needle is centered. There are probably cases where the localizer isn't really perfectly aligned with the runway, or intentionally misaligned to avoid obstacles or terrain. So I have made this configurable for those that trust the data more than I do. Just set "/sim/navdb/auto-align-localizers" to true/false in the preferences file to turn this feature on or off in the code.
This commit is contained in:
parent
70a6f2c014
commit
a3cde21637
6 changed files with 112 additions and 6 deletions
|
@ -100,8 +100,8 @@ static string GetReverseRunwayNo(string rwyno) {
|
||||||
if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) {
|
if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) {
|
||||||
tmp = rwyno;
|
tmp = rwyno;
|
||||||
rwyno = "0" + tmp;
|
rwyno = "0" + tmp;
|
||||||
SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from " << tmp
|
SG_LOG( SG_GENERAL, SG_INFO,
|
||||||
<< " to " << rwyno );
|
"Standardising rwy number from " << tmp << " to " << rwyno );
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[4];
|
char buf[4];
|
||||||
|
@ -121,6 +121,9 @@ static string GetReverseRunwayNo(string rwyno) {
|
||||||
} else if (rwyno.substr(2,1) == "C") {
|
} else if (rwyno.substr(2,1) == "C") {
|
||||||
buf[2] = 'C';
|
buf[2] = 'C';
|
||||||
buf[3] = '\0';
|
buf[3] = '\0';
|
||||||
|
} else if (rwyno.substr(2,1) == "T") {
|
||||||
|
buf[2] = 'T';
|
||||||
|
buf[3] = '\0';
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
|
SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
|
||||||
<< rwyno << " passed to GetReverseRunwayNo(...)");
|
<< rwyno << " passed to GetReverseRunwayNo(...)");
|
||||||
|
|
|
@ -1062,6 +1062,14 @@ fgInitNav ()
|
||||||
"Problems loading one or more navigational database" );
|
"Problems loading one or more navigational database" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( fgGetBool("/sim/navdb/auto-align-localizers", true) ) {
|
||||||
|
// align all the localizers with their corresponding runways
|
||||||
|
// since data sources are good for cockpit navigation
|
||||||
|
// purposes, but not always to the error tolerances needed to
|
||||||
|
// exactly place these items.
|
||||||
|
fgNavDBAlignLOCwithRunway( runways, loclist );
|
||||||
|
}
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, " Fixes");
|
SG_LOG(SG_GENERAL, SG_INFO, " Fixes");
|
||||||
SGPath p_fix( globals->get_fg_root() );
|
SGPath p_fix( globals->get_fg_root() );
|
||||||
p_fix.append( "Navaids/fix.dat" );
|
p_fix.append( "Navaids/fix.dat" );
|
||||||
|
|
|
@ -21,14 +21,20 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include STL_STRING
|
||||||
|
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
|
#include <Airports/runways.hxx>
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
|
|
||||||
#include "navrecord.hxx"
|
#include "navrecord.hxx"
|
||||||
|
|
||||||
#include "navdb.hxx"
|
#include "navdb.hxx"
|
||||||
|
|
||||||
|
SG_USING_STD( string );
|
||||||
|
|
||||||
|
|
||||||
// load and initialize the navigational databases
|
// load and initialize the navigational databases
|
||||||
bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
|
bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
|
||||||
|
@ -110,3 +116,80 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Given a localizer record and it's corresponding runway record,
|
||||||
|
// adjust the localizer position so it is in perfect alignment with
|
||||||
|
// the runway.
|
||||||
|
static void update_loc_position( FGNavRecord *loc, FGRunway *rwy ) {
|
||||||
|
|
||||||
|
double hdg = rwy->heading;
|
||||||
|
hdg += 180.0;
|
||||||
|
if ( hdg > 360.0 ) {
|
||||||
|
hdg -= 360.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate runway threshold point
|
||||||
|
double thresh_lat, thresh_lon, return_az;
|
||||||
|
geo_direct_wgs_84 ( 0.0, rwy->lat, rwy->lon, hdg,
|
||||||
|
rwy->length/2.0 * SG_FEET_TO_METER,
|
||||||
|
&thresh_lat, &thresh_lon, &return_az );
|
||||||
|
// cout << "Threshold = " << thresh_lat << "," << thresh_lon << endl;
|
||||||
|
|
||||||
|
// calculate distance from threshold to localizer
|
||||||
|
double az1, az2, dist_m;
|
||||||
|
geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(),
|
||||||
|
thresh_lat, thresh_lon,
|
||||||
|
&az1, &az2, &dist_m );
|
||||||
|
// cout << "Distance = " << dist_m << endl;
|
||||||
|
|
||||||
|
// back project that distance along the runway center line
|
||||||
|
double nloc_lat, nloc_lon;
|
||||||
|
geo_direct_wgs_84 ( 0.0, thresh_lat, thresh_lon, hdg + 180.0,
|
||||||
|
dist_m, &nloc_lat, &nloc_lon, &return_az );
|
||||||
|
// printf("New localizer = %.6f %.6f\n", nloc_lat, nloc_lon );
|
||||||
|
|
||||||
|
// sanity check, how far have we moved the localizer?
|
||||||
|
geo_inverse_wgs_84( 0.0, loc->get_lat(), loc->get_lon(),
|
||||||
|
nloc_lat, nloc_lon,
|
||||||
|
&az1, &az2, &dist_m );
|
||||||
|
// cout << "Distance moved = " << dist_m << endl;
|
||||||
|
|
||||||
|
loc->set_lat( nloc_lat );
|
||||||
|
loc->set_lon( nloc_lon );
|
||||||
|
loc->set_multiuse( rwy->heading );
|
||||||
|
|
||||||
|
// cout << "orig heading = " << loc->get_multiuse() << endl;
|
||||||
|
// cout << "new heading = " << rwy->heading << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This routines traverses the localizer list and attempts to match
|
||||||
|
// each entry with it's corresponding runway. When it is successful,
|
||||||
|
// it then "moves" the localizer and updates it's heading so it
|
||||||
|
// *perfectly* aligns with the runway, but is still the same distance
|
||||||
|
// from the runway threshold.
|
||||||
|
void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist ) {
|
||||||
|
nav_map_type navmap = loclist->get_navaids();
|
||||||
|
|
||||||
|
nav_map_iterator freq = navmap.begin();
|
||||||
|
while ( freq != navmap.end() ) {
|
||||||
|
nav_list_type locs = freq->second;
|
||||||
|
nav_list_iterator loc = locs.begin();
|
||||||
|
while ( loc != locs.end() ) {
|
||||||
|
string name = (*loc)->get_name();
|
||||||
|
string::size_type pos1 = name.find(" ");
|
||||||
|
string id = name.substr(0, pos1);
|
||||||
|
name = name.substr(pos1+1);
|
||||||
|
string::size_type pos2 = name.find(" ");
|
||||||
|
string rwy = name.substr(0, pos2);
|
||||||
|
|
||||||
|
FGRunway r;
|
||||||
|
if ( runways->search(id, rwy, &r) ) {
|
||||||
|
update_loc_position( (*loc), &r );
|
||||||
|
}
|
||||||
|
++loc;
|
||||||
|
}
|
||||||
|
++freq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,4 +45,12 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
|
||||||
FGNavList *dmelist, FGNavList *mkrbeacons );
|
FGNavList *dmelist, FGNavList *mkrbeacons );
|
||||||
|
|
||||||
|
|
||||||
|
// This routines traverses the localizer list and attempts to match
|
||||||
|
// each entry with it's corresponding runway. When it is successful,
|
||||||
|
// it then "moves" the localizer and updates it's heading so it
|
||||||
|
// *perfectly* aligns with the runway, but is still the same distance
|
||||||
|
// from the runway threshold.
|
||||||
|
void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist );
|
||||||
|
|
||||||
|
|
||||||
#endif // _FG_NAVDB_HXX
|
#endif // _FG_NAVDB_HXX
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
// returns the closest entry to the give lon/lat/elev
|
// returns the closest entry to the give lon/lat/elev
|
||||||
FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m );
|
FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m );
|
||||||
|
|
||||||
|
inline nav_map_type get_navaids() const { return navaids; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,9 @@ public:
|
||||||
|
|
||||||
inline int get_type() const { return type; }
|
inline int get_type() const { return type; }
|
||||||
inline double get_lon() const { return lon; }
|
inline double get_lon() const { return lon; }
|
||||||
|
inline void set_lon( double l ) { lon = l; }
|
||||||
inline double get_lat() const { return lat; }
|
inline double get_lat() const { return lat; }
|
||||||
|
inline void set_lat( double l ) { lat = l; }
|
||||||
inline double get_elev_ft() const { return elev_ft; }
|
inline double get_elev_ft() const { return elev_ft; }
|
||||||
inline double get_x() const { return x; }
|
inline double get_x() const { return x; }
|
||||||
inline double get_y() const { return y; }
|
inline double get_y() const { return y; }
|
||||||
|
@ -82,6 +84,7 @@ public:
|
||||||
inline int get_freq() const { return freq; }
|
inline int get_freq() const { return freq; }
|
||||||
inline int get_range() const { return range; }
|
inline int get_range() const { return range; }
|
||||||
inline double get_multiuse() const { return multiuse; }
|
inline double get_multiuse() const { return multiuse; }
|
||||||
|
inline void set_multiuse( double m ) { multiuse = m; }
|
||||||
inline const char *get_ident() { return ident.c_str(); }
|
inline const char *get_ident() { return ident.c_str(); }
|
||||||
inline string get_name() { return name; }
|
inline string get_name() { return name; }
|
||||||
inline bool get_serviceable() { return serviceable; }
|
inline bool get_serviceable() { return serviceable; }
|
||||||
|
@ -127,8 +130,8 @@ operator >> ( istream& in, FGNavRecord& n )
|
||||||
n.freq *= 100;
|
n.freq *= 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the space before the name
|
// Remove any leading spaces before the name
|
||||||
if ( n.name.substr(0,1) == " " ) {
|
while ( n.name.substr(0,1) == " " ) {
|
||||||
n.name = n.name.erase(0,1);
|
n.name = n.name.erase(0,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue