From a3cde21637df5058d460d5786c365eeb949fee16 Mon Sep 17 00:00:00 2001 From: curt Date: Fri, 28 May 2004 16:24:43 +0000 Subject: [PATCH] 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. --- src/Airports/runways.cxx | 7 +++- src/Main/fg_init.cxx | 8 ++++ src/Navaids/navdb.cxx | 85 ++++++++++++++++++++++++++++++++++++++- src/Navaids/navdb.hxx | 8 ++++ src/Navaids/navlist.hxx | 3 +- src/Navaids/navrecord.hxx | 7 +++- 6 files changed, 112 insertions(+), 6 deletions(-) diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index 5c98af7ff..78c1c6db2 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -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(...)"); diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 4e6988aff..a9c583d7a 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -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" ); diff --git a/src/Navaids/navdb.cxx b/src/Navaids/navdb.cxx index 5ca43646e..f26791120 100644 --- a/src/Navaids/navdb.cxx +++ b/src/Navaids/navdb.cxx @@ -21,14 +21,20 @@ // $Id$ +#include + +#include STL_STRING + #include +#include #include
#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; + } +} diff --git a/src/Navaids/navdb.hxx b/src/Navaids/navdb.hxx index 4afc27e11..36f1bdc42 100644 --- a/src/Navaids/navdb.hxx +++ b/src/Navaids/navdb.hxx @@ -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 diff --git a/src/Navaids/navlist.hxx b/src/Navaids/navlist.hxx index aee404196..1298eddb2 100644 --- a/src/Navaids/navlist.hxx +++ b/src/Navaids/navlist.hxx @@ -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; } }; diff --git a/src/Navaids/navrecord.hxx b/src/Navaids/navrecord.hxx index 544d2d1aa..ce8fde82d 100644 --- a/src/Navaids/navrecord.hxx +++ b/src/Navaids/navrecord.hxx @@ -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); }