1
0
Fork 0

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:
curt 2004-05-28 16:24:43 +00:00
parent 70a6f2c014
commit a3cde21637
6 changed files with 112 additions and 6 deletions

View file

@ -100,8 +100,8 @@ static string GetReverseRunwayNo(string rwyno) {
if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) {
tmp = rwyno;
rwyno = "0" + tmp;
SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from " << tmp
<< " to " << rwyno );
SG_LOG( SG_GENERAL, SG_INFO,
"Standardising rwy number from " << tmp << " to " << rwyno );
}
char buf[4];
@ -121,6 +121,9 @@ static string GetReverseRunwayNo(string rwyno) {
} else if (rwyno.substr(2,1) == "C") {
buf[2] = 'C';
buf[3] = '\0';
} else if (rwyno.substr(2,1) == "T") {
buf[2] = 'T';
buf[3] = '\0';
} else {
SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
<< rwyno << " passed to GetReverseRunwayNo(...)");

View file

@ -1062,6 +1062,14 @@ fgInitNav ()
"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");
SGPath p_fix( globals->get_fg_root() );
p_fix.append( "Navaids/fix.dat" );

View file

@ -21,14 +21,20 @@
// $Id$
#include <simgear/compiler.h>
#include STL_STRING
#include <simgear/debug/logstream.hxx>
#include <Airports/runways.hxx>
#include <Main/globals.hxx>
#include "navrecord.hxx"
#include "navdb.hxx"
SG_USING_STD( string );
// load and initialize the navigational databases
bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
@ -110,3 +116,80 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
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;
}
}

View file

@ -45,4 +45,12 @@ bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
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

View file

@ -61,7 +61,7 @@ class FGNavList {
// Given a point and a list of stations, return the closest one to
// the specified point.
FGNavRecord *findNavFromList( const Point3D &aircraft,
const nav_list_type &stations );
const nav_list_type &stations );
public:
@ -97,6 +97,7 @@ public:
// returns the closest entry to the give lon/lat/elev
FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m );
inline nav_map_type get_navaids() const { return navaids; }
};

View file

@ -74,7 +74,9 @@ public:
inline int get_type() const { return type; }
inline double get_lon() const { return lon; }
inline void set_lon( double l ) { lon = l; }
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_x() const { return x; }
inline double get_y() const { return y; }
@ -82,6 +84,7 @@ public:
inline int get_freq() const { return freq; }
inline int get_range() const { return range; }
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 string get_name() { return name; }
inline bool get_serviceable() { return serviceable; }
@ -127,8 +130,8 @@ operator >> ( istream& in, FGNavRecord& n )
n.freq *= 100;
}
// Remove the space before the name
if ( n.name.substr(0,1) == " " ) {
// Remove any leading spaces before the name
while ( n.name.substr(0,1) == " " ) {
n.name = n.name.erase(0,1);
}