From f2e2101264085d502a7525d6bf79b22f397b7290 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 20 Mar 2003 09:38:06 +0000 Subject: [PATCH] David Luff writes: I've fixed a bug in FGRunways::search(aptid, tgt_hdg) which wasn't working properly for airports with multiple parallel runways. I've also firmed up and pulled out into it's own function the GetReverseRunwayNo code, and done some input checking. As a result of fixing the above in runways.cxx, I've pulled out the parallel implementation in the functions that set position by airport and heading/runway number in fg_init.cxx and called the runways functions instead. --- src/Airports/runways.cxx | 105 ++++++++++------- src/Main/fg_init.cxx | 249 +++++++++++---------------------------- 2 files changed, 132 insertions(+), 222 deletions(-) diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index 0cc274262..07f1cf224 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -90,6 +90,47 @@ FGRunways::FGRunways( const string& file ) { } +// Return reverse rwy number +// eg 01 -> 19 +// 03L -> 21R +static string GetReverseRunwayNo(string rwyno) { + // cout << "Original rwyno = " << rwyNo << '\n'; + + // standardize input number + string tmp = rwyno.substr(1, 1); + if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) { + tmp = rwyno; + cout << "Standardising rwy number from " << tmp; + rwyno = "0" + tmp; + cout << " to " << rwyno << '\n'; + } + + char buf[4]; + int rn = atoi(rwyno.substr(0,2).c_str()); + rn += 18; + while(rn > 36) { + rn -= 36; + } + sprintf(buf, "%02i", rn); + if(rwyno.size() == 3) { + if(rwyno.substr(2,1) == "L") { + buf[2] = 'R'; + buf[3] = '\0'; + } else if (rwyno.substr(2,1) == "R") { + buf[2] = 'L'; + buf[3] = '\0'; + } else if (rwyno.substr(2,1) == "C") { + buf[2] = 'C'; + buf[3] = '\0'; + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code " + << rwyno << " passed to GetReverseRunwayNo(...)"); + } + } + return((string)buf); +} + + // search for the specified apt id bool FGRunways::search( const string& aptid, FGRunway* r ) { c4_StringProp pID ("ID"); @@ -132,6 +173,7 @@ bool FGRunways::search( const string& aptid, FGRunway* r ) { // search for the specified apt id and runway no bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) { + string runwayno = rwyno; c4_StringProp pID ("ID"); c4_StringProp pRwy ("Rwy"); c4_FloatProp pLon ("Longitude"); @@ -149,6 +191,15 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) if ( index == -1 ) { return false; } + + // standardize input number + string tmp = runwayno.substr(1, 1); + if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (runwayno.size() == 1)) { + tmp = runwayno; + cout << "Standardising rwy number from " << tmp; + runwayno = "0" + tmp; + cout << " to " << runwayno << '\n'; + } c4_RowRef row = vRunway->GetAt(index); string rowid = (const char *) pID(row); @@ -156,7 +207,7 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) while ( rowid == aptid ) { next_index = index + 1; - if ( rowrwyno == rwyno ) { + if ( rowrwyno == runwayno ) { r->id = (const char *) pID(row); r->rwy_no = (const char *) pRwy(row); r->lon = (double) pLon(row); @@ -171,34 +222,11 @@ bool FGRunways::search( const string& aptid, const string& rwyno, FGRunway* r ) return true; } - // Check reverse rwy number - // eg 01 -> 19 - // 03L -> 21R - // cout << "Original rowrwyno = " << rowrwyno << '\n'; - char buf[4]; - int rn = atoi(rowrwyno.substr(0,2).c_str()); - rn += 18; - while(rn > 36) { - rn -= 36; - } - sprintf(buf, "%02i", rn); - if(rowrwyno.size() == 3) { - if(rowrwyno.substr(2,1) == "L") { - buf[2] = 'R'; - buf[3] = '\0'; - } else if (rowrwyno.substr(2,1) == "R") { - buf[2] = 'L'; - buf[3] = '\0'; - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code " - << rowrwyno << " found in FGRunways.search(...)"); - } - } - rowrwyno = buf; - // cout << "New rowrwyno = " << rowrwyno << '\n'; // Search again with the other-end runway number - // Remember we have to munge the heading result if this one matches - if ( rowrwyno == rwyno ) { + // Remember we have to munge the heading and rwy_no results if this one matches + rowrwyno = GetReverseRunwayNo(rowrwyno); + // cout << "New rowrwyno = " << rowrwyno << '\n'; + if ( rowrwyno == runwayno ) { r->id = (const char *) pID(row); r->rwy_no = rowrwyno; r->lon = (double) pLon(row); @@ -285,10 +313,11 @@ bool FGRunways::search( const string& aptid, const int tgt_hdg, // Return the runway number of the runway closest to a given heading string FGRunways::search( const string& aptid, const int tgt_hdg ) { FGRunway r; + FGRunway tmp_r; string rn; double found_dir = 0.0; - if ( !search( aptid, &r ) ) { + if ( !search( aptid, &tmp_r ) ) { SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find " << aptid << " in database." ); return "NN"; @@ -297,7 +326,9 @@ string FGRunways::search( const string& aptid, const int tgt_hdg ) { double diff; double min_diff = 360.0; - while ( r.id == aptid ) { + while ( tmp_r.id == aptid ) { + r = tmp_r; + // forward direction diff = tgt_hdg - r.heading; while ( diff < -180.0 ) { diff += 360.0; } @@ -327,22 +358,16 @@ string FGRunways::search( const string& aptid, const int tgt_hdg ) { found_dir = 180.0; } - next( &r ); + next( &tmp_r ); } // SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << r.rwy_no // << " + " << found_dir ); - // rn = r.rwy_no; + rn = r.rwy_no; // cout << "In search, rn = " << rn << endl; if ( found_dir == 180 ) { - int irn = atoi(rn.c_str()); - irn += 18; - if ( irn > 36 ) { - irn -= 36; - } - char buf[4]; // 2 chars + string terminator + 1 for safety - sprintf(buf, "%i", irn); - rn = buf; + rn = GetReverseRunwayNo(rn); + //cout << "New rn = " << rn << '\n'; } return rn; diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 0731cc05c..15fcf922e 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -254,7 +254,7 @@ bool fgInitFGRoot ( int argc, char **argv ) { root = fgScanForOption( "--fg-root=", config.str() ); } } - + // Next check if fg-root is set as an env variable if ( root.empty() ) { envp = ::getenv( "FG_ROOT" ); @@ -655,8 +655,6 @@ static bool fgSetTowerPosFromAirportID( const string& id, double hdg ) { // Set current_options lon/lat given an airport id and heading (degrees) static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) { FGRunway r; - FGRunway found_r; - double found_dir = 0.0; if ( id.length() ) { // set initial position from runway and heading @@ -667,72 +665,30 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) { FGRunways runways( path.c_str() ); SG_LOG( SG_GENERAL, SG_INFO, - "Attempting to set starting position from runway code " + "Attempting to set starting position from airport code " << id << " heading " << tgt_hdg ); - - if ( ! runways.search( id, &r ) ) { + + if ( ! runways.search( id, (int)tgt_hdg, &r ) ) { SG_LOG( SG_GENERAL, SG_ALERT, - "Failed to find " << id << " in database." ); + "Failed to find a good runway for " << id << '\n' ); return false; - } - - double diff; - double min_diff = 360.0; - - while ( r.id == id ) { - // forward direction - diff = tgt_hdg - r.heading; - while ( diff < -180.0 ) { diff += 360.0; } - while ( diff > 180.0 ) { diff -= 360.0; } - diff = fabs(diff); - SG_LOG( SG_GENERAL, SG_INFO, - "Runway " << r.rwy_no << " heading = " << r.heading << - " diff = " << diff ); - if ( diff < min_diff ) { - min_diff = diff; - found_r = r; - found_dir = 0; - } - - // reverse direction - diff = tgt_hdg - r.heading - 180.0; - while ( diff < -180.0 ) { diff += 360.0; } - while ( diff > 180.0 ) { diff -= 360.0; } - diff = fabs(diff); - SG_LOG( SG_GENERAL, SG_INFO, - "Runway -" << r.rwy_no << " heading = " << - r.heading + 180.0 << - " diff = " << diff ); - if ( diff < min_diff ) { - min_diff = diff; - found_r = r; - found_dir = 180.0; - } - - runways.next( &r ); - } - - SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << found_r.rwy_no - << " + " << found_dir ); - + } } else { return false; } - double heading = found_r.heading + found_dir; - while ( heading >= 360.0 ) { heading -= 360.0; } - double lat2, lon2, az2; - double azimuth = found_r.heading + found_dir + 180.0; + double heading = r.heading; + double azimuth = heading + 180.0; while ( azimuth >= 360.0 ) { azimuth -= 360.0; } SG_LOG( SG_GENERAL, SG_INFO, - "runway = " << found_r.lon << ", " << found_r.lat - << " length = " << found_r.length * SG_FEET_TO_METER * 0.5 + "runway = " << r.lon << ", " << r.lat + << " length = " << r.length * SG_FEET_TO_METER << " heading = " << azimuth ); - - geo_direct_wgs_84 ( 0, found_r.lat, found_r.lon, - azimuth, found_r.length * SG_FEET_TO_METER * 0.5 - 5.0, + + geo_direct_wgs_84 ( 0, r.lat, r.lon, azimuth, + r.length * SG_FEET_TO_METER * 0.5 - 5.0, &lat2, &lon2, &az2 ); if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) { @@ -764,30 +720,17 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) { << lon2 << ", " << lat2 << ") new heading is " << heading ); - + return true; } -// Set current_options lon/lat given an airport id and heading (degrees) +// Set current_options lon/lat given an airport id and runway number static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) { FGRunway r; - FGRunway found_r; - double heading = 0.0; - string runway; - bool match = false; - - // standardize input number - string tmp = rwy.substr(1, 1); - if ( tmp == "L" || tmp == "R" || tmp == "C" ) { - runway = "0"; - runway += rwy; - } else { - runway = rwy; - } if ( id.length() ) { - // set initial position from runway and heading + // set initial position from airport and runway number SGPath path( globals->get_fg_root() ); path.append( "Airports" ); @@ -798,122 +741,64 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) { "Attempting to set starting position for " << id << ":" << runway ); - if ( ! runways.search( id, &r ) ) { + if ( ! runways.search( id, rwy, &r ) ) { SG_LOG( SG_GENERAL, SG_ALERT, - "Failed to find " << id << " in database." ); + "Failed to find runway " << rwy << + " at airport " << id ); return false; } - - while ( r.id == id ) { - // forward direction - if ( r.rwy_no == runway ) { - found_r = r; - heading = r.heading; - match = true; - SG_LOG( SG_GENERAL, SG_INFO, - "Runway " << r.rwy_no << " heading = " << heading ); - } - - // calculate reciprocal runway number - string snum = r.rwy_no; - int len = snum.length(); - string letter = ""; - string rev_letter = ""; - int i; - for ( i = 0; i < len; ++i ) { - string tmp = snum.substr(i, 1); - if ( tmp == "L" ) { - letter = "L"; - rev_letter = "R"; - } else if ( tmp == "R" ) { - letter = "R"; - rev_letter = "L"; - } else if ( tmp == "C" ) { - letter == "C"; - rev_letter = "C"; - } - } - for ( i = 0; i < len; ++i ) { - string tmp = snum.substr(i, 1); - if ( tmp == "L" || tmp == "R" || tmp == "C" || tmp == " " ) { - snum = snum.substr(0, i); - } - } - SG_LOG(SG_GENERAL, SG_DEBUG, "Runway num = '" << snum << "'"); - int num = atoi( snum.c_str() ) + 18; - while ( num > 36 ) { num -= 36; } - while ( num <= 0 ) { num += 36; } - - char recip_no[10]; - snprintf( recip_no, 10, "%02d%s", num, rev_letter.c_str() ); - - // reverse direction - if ( (string)recip_no == runway ) { - found_r = r; - heading = r.heading + 180; - while ( heading > 360.0 ) { heading -= 360; } - match = true; - SG_LOG( SG_GENERAL, SG_INFO, - "Runway " << r.rwy_no << " heading = " << heading ); - } - - runways.next( &r ); - } } else { return false; } - if ( match ) { - double lat2, lon2, az2; - double azimuth = heading + 180.0; - while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - - SG_LOG( SG_GENERAL, SG_INFO, - "runway = " << found_r.lon << ", " << found_r.lat - << " length = " << found_r.length * SG_FEET_TO_METER * 0.5 - << " heading = " << azimuth ); + double lat2, lon2, az2; + double heading = r.heading; + double azimuth = heading + 180.0; + while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - geo_direct_wgs_84 ( 0, found_r.lat, found_r.lon, - azimuth, - found_r.length * SG_FEET_TO_METER * 0.5 - 5.0, - &lat2, &lon2, &az2 ); - - if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) - { - double olat, olon; - double odist = fgGetDouble("/sim/presets/offset-distance"); - odist *= SG_NM_TO_METER; - double oaz = azimuth; - if ( fabs(fgGetDouble("/sim/presets/offset-azimuth")) > SG_EPSILON ) - { - oaz = fgGetDouble("/sim/presets/offset-azimuth") + 180; - } - while ( oaz >= 360.0 ) { oaz -= 360.0; } - geo_direct_wgs_84 ( 0, lat2, lon2, oaz, odist, &olat, &olon, &az2 ); - lat2=olat; - lon2=olon; - } - - // presets - fgSetDouble("/sim/presets/longitude-deg", lon2 ); - fgSetDouble("/sim/presets/latitude-deg", lat2 ); - fgSetDouble("/sim/presets/heading-deg", heading ); - - // other code depends on the actual values being set ... - fgSetDouble("/position/longitude-deg", lon2 ); - fgSetDouble("/position/latitude-deg", lat2 ); - fgSetDouble("/orientation/heading-deg", heading ); - - SG_LOG( SG_GENERAL, SG_INFO, - "Position for " << id << " is (" - << lon2 << ", " - << lat2 << ") new heading is " - << heading ); - - return true; - } else { - return false; + SG_LOG( SG_GENERAL, SG_INFO, + "runway = " << r.lon << ", " << r.lat + << " length = " << r.length * SG_FEET_TO_METER + << " heading = " << azimuth ); + + geo_direct_wgs_84 ( 0, r.lat, r.lon, + azimuth, + r.length * SG_FEET_TO_METER * 0.5 - 5.0, + &lat2, &lon2, &az2 ); + + if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) + { + double olat, olon; + double odist = fgGetDouble("/sim/presets/offset-distance"); + odist *= SG_NM_TO_METER; + double oaz = azimuth; + if ( fabs(fgGetDouble("/sim/presets/offset-azimuth")) > SG_EPSILON ) + { + oaz = fgGetDouble("/sim/presets/offset-azimuth") + 180; + } + while ( oaz >= 360.0 ) { oaz -= 360.0; } + geo_direct_wgs_84 ( 0, lat2, lon2, oaz, odist, &olat, &olon, &az2 ); + lat2=olat; + lon2=olon; } + + // presets + fgSetDouble("/sim/presets/longitude-deg", lon2 ); + fgSetDouble("/sim/presets/latitude-deg", lat2 ); + fgSetDouble("/sim/presets/heading-deg", heading ); + + // other code depends on the actual values being set ... + fgSetDouble("/position/longitude-deg", lon2 ); + fgSetDouble("/position/latitude-deg", lat2 ); + fgSetDouble("/orientation/heading-deg", heading ); + + SG_LOG( SG_GENERAL, SG_INFO, + "Position for " << id << " is (" + << lon2 << ", " + << lat2 << ") new heading is " + << heading ); + + return true; } @@ -956,7 +841,7 @@ static void fgSetDistOrAltFromGlideSlope() { SG_LOG( SG_GENERAL, SG_ALERT, "Resetting glideslope to zero" ); fgSetDouble("/sim/presets/glideslope-deg", 0); fgSetBool("/sim/presets/onground", true); - } + } } @@ -1721,7 +1606,7 @@ bool fgInitSubsystems() { current_panel->bind(); } - + //////////////////////////////////////////////////////////////////// // Initialize the default (kludged) properties. ////////////////////////////////////////////////////////////////////