]> git.mxchange.org Git - flightgear.git/commitdiff
Curt Olson:
authorcurt <curt>
Fri, 28 May 2004 16:24:43 +0000 (16:24 +0000)
committercurt <curt>
Fri, 28 May 2004 16:24:43 +0000 (16:24 +0000)
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
src/Main/fg_init.cxx
src/Navaids/navdb.cxx
src/Navaids/navdb.hxx
src/Navaids/navlist.hxx
src/Navaids/navrecord.hxx

index 5c98af7ff46023ad8390e6524b2643a385996b28..78c1c6db2928c7c05ea5772caf896aa2aa750bd6 100644 (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(...)");
index 4e6988afffb10b89cb0281bb5904531abd2e797c..a9c583d7a037386c437cb6bea67594dbcea6c2c8 100644 (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" );
index 5ca43646e73af8039657b438c6f043aa73043f74..f267911200b3ab852554dc7c6d25d0667c530dc2 100644 (file)
 // $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;
+    }
+}
index 4afc27e1128e5436fbd866ea0354ccaf4664a7e7..36f1bdc42447cc7a9a558777f25bdb4b5c7710ee 100644 (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
index aee404196506560c1883e29669fb9b9e76f307f3..1298eddb254d7e86ff39149e2a92ecdda4cd2740 100644 (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; }
 };
 
 
index 544d2d1aa63508ba394cf3b310a834d5ee91d1c0..ce8fde82da75e0afb5c332f960461feabc73a435 100644 (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);
     }