From be703a92b400344740b909e5c667a8dadd2067d6 Mon Sep 17 00:00:00 2001 From: curt Date: Sun, 5 Jan 2003 00:10:36 +0000 Subject: [PATCH] Add support for in-air preset starts relative to a VOR, NDB, or Fix. --- src/Autopilot/auto_gui.cxx | 3 +- src/Main/fg_commands.cxx | 2 +- src/Main/fg_init.cxx | 142 ++++++++++++++++++++++++++++++++++++- src/Navaids/fixlist.cxx | 19 ++++- src/Navaids/fixlist.hxx | 10 ++- src/Navaids/navlist.cxx | 35 +++++++-- src/Navaids/navlist.hxx | 5 +- src/Navaids/testnavs.cxx | 7 +- src/Network/props.cxx | 19 +++-- 9 files changed, 216 insertions(+), 26 deletions(-) diff --git a/src/Autopilot/auto_gui.cxx b/src/Autopilot/auto_gui.cxx index 4aca7092e..047a75d98 100644 --- a/src/Autopilot/auto_gui.cxx +++ b/src/Autopilot/auto_gui.cxx @@ -641,8 +641,7 @@ void TgtAptDialog_OK (puObject *) globals->get_autopilot()->set_HeadingEnabled( true ); globals->get_autopilot()->set_HeadingMode( FGAutopilot::FG_HEADING_WAYPOINT ); - } else if ( current_fixlist->query( TgtAptId, 0.0, 0.0, 0.0, - &f, &t1, &t2 ) ) + } else if ( current_fixlist->query( TgtAptId, &f ) ) { SG_LOG( SG_GENERAL, SG_INFO, "Adding waypoint (fix) = " << TgtAptId ); diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index dec977679..82e7f47c9 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -662,7 +662,7 @@ static struct { { "dialog-show", do_dialog_show }, { "dialog-update", do_dialog_update }, { "dialog-apply", do_dialog_apply }, - { "presets_commit", do_presets_commit }, + { "presets-commit", do_presets_commit }, { 0, 0 } // zero-terminated }; diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index ca47053c1..223ad80f2 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -955,6 +955,104 @@ static void fgSetDistOrAltFromGlideSlope() { } +// Set current_options lon/lat given an airport id and heading (degrees) +static bool fgSetPosFromNAV( const string& id, const double& freq ) { + FGNav nav; + + // set initial position from runway and heading + if ( current_navlist->findByIdentAndFreq( id.c_str(), freq, &nav ) ) { + SG_LOG( SG_GENERAL, SG_INFO, "Attempting to set starting position for " + << id << ":" << freq ); + + double lon = nav.get_lon(); + double lat = nav.get_lat(); + + if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) + { + double odist = fgGetDouble("/sim/presets/offset-distance") + * SG_NM_TO_METER; + double oaz = fabs(fgGetDouble("/sim/presets/offset-azimuth")) + + 180.0; + while ( oaz >= 360.0 ) { oaz -= 360.0; } + double olat, olon, az2; + geo_direct_wgs_84 ( 0, lat, lon, oaz, odist, &olat, &olon, &az2 ); + + lat = olat; + lon = olon; + } + + // presets + fgSetDouble("/sim/presets/longitude-deg", lon ); + fgSetDouble("/sim/presets/latitude-deg", lat ); + + // other code depends on the actual values being set ... + fgSetDouble("/position/longitude-deg", lon ); + fgSetDouble("/position/latitude-deg", lat ); + fgSetDouble("/orientation/heading-deg", + fgGetDouble("/sim/presets/heading-deg") ); + + SG_LOG( SG_GENERAL, SG_INFO, + "Position for " << id << ":" << freq << " is (" + << lon << ", "<< lat << ")" ); + + return true; + } else { + SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = " + << id << ":" << freq ); + return false; + } +} + + +// Set current_options lon/lat given an airport id and heading (degrees) +static bool fgSetPosFromFix( const string& id ) { + FGFix fix; + + // set initial position from runway and heading + if ( current_fixlist->query( id.c_str(), &fix ) ) { + SG_LOG( SG_GENERAL, SG_INFO, "Attempting to set starting position for " + << id ); + + double lon = fix.get_lon(); + double lat = fix.get_lat(); + + if ( fabs( fgGetDouble("/sim/presets/offset-distance") ) > SG_EPSILON ) + { + double odist = fgGetDouble("/sim/presets/offset-distance") + * SG_NM_TO_METER; + double oaz = fabs(fgGetDouble("/sim/presets/offset-azimuth")) + + 180.0; + while ( oaz >= 360.0 ) { oaz -= 360.0; } + double olat, olon, az2; + geo_direct_wgs_84 ( 0, lat, lon, oaz, odist, &olat, &olon, &az2 ); + + lat = olat; + lon = olon; + } + + // presets + fgSetDouble("/sim/presets/longitude-deg", lon ); + fgSetDouble("/sim/presets/latitude-deg", lat ); + + // other code depends on the actual values being set ... + fgSetDouble("/position/longitude-deg", lon ); + fgSetDouble("/position/latitude-deg", lat ); + fgSetDouble("/orientation/heading-deg", + fgGetDouble("/sim/presets/heading-deg") ); + + SG_LOG( SG_GENERAL, SG_INFO, + "Position for " << id << " is (" + << lon << ", "<< lat << ")" ); + + return true; + } else { + SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = " + << id ); + return false; + } +} + + // Set the initial position based on presets (or defaults) bool fgInitPosition() { bool set_pos = false; @@ -981,26 +1079,64 @@ bool fgInitPosition() { string apt = fgGetString("/sim/presets/airport-id"); string rwy_no = fgGetString("/sim/presets/runway"); double hdg = fgGetDouble("/sim/presets/heading-deg"); + string vor = fgGetString("/sim/presets/vor-id"); + double vor_freq = fgGetDouble("/sim/presets/vor-freq"); + string ndb = fgGetString("/sim/presets/ndb-id"); + double ndb_freq = fgGetDouble("/sim/presets/ndb-freq"); + string fix = fgGetString("/sim/presets/fix"); if ( !set_pos && !apt.empty() && !rwy_no.empty() ) { // An airport + runway is requested if ( fgSetPosFromAirportIDandRwy( apt, rwy_no ) ) { - // set tower position (a little off the heading for single + // set position (a little off the heading for single // runway airports) fgSetTowerPosFromAirportID( apt, hdg ); set_pos = true; } } - if ( !set_pos && !apt.empty() ) { + // An airport is requested (find runway closest to hdg) if ( fgSetPosFromAirportIDandHdg( apt, hdg ) ) { - // set tower position (a little off the heading for single + // set position (a little off the heading for single // runway airports) fgSetTowerPosFromAirportID( apt, hdg ); set_pos = true; } } + if ( !set_pos && !vor.empty() ) { + // a VOR is requested + if ( fgSetPosFromNAV( vor, vor_freq ) ) { + if ( fgGetDouble("/sim/presets/altitude-ft") > -9990.0 ) { + fgSetBool("/sim/presets/onground", false); + } else { + fgSetBool("/sim/presets/onground", true); + } + set_pos = true; + } + } + if ( !set_pos && !ndb.empty() ) { + // an NDB is requested + if ( fgSetPosFromNAV( ndb, ndb_freq ) ) { + if ( fgGetDouble("/sim/presets/altitude-ft") > -9990.0 ) { + fgSetBool("/sim/presets/onground", false); + } else { + fgSetBool("/sim/presets/onground", true); + } + set_pos = true; + } + } + if ( !set_pos && !fix.empty() ) { + // a Fix is requested + if ( fgSetPosFromFix( fix ) ) { + if ( fgGetDouble("/sim/presets/altitude-ft") > -9990.0 ) { + fgSetBool("/sim/presets/onground", false); + } else { + fgSetBool("/sim/presets/onground", true); + } + set_pos = true; + } + } if ( !set_pos ) { // No lon/lat specified, no airport specified, default to diff --git a/src/Navaids/fixlist.cxx b/src/Navaids/fixlist.cxx index 3fa380e4b..31537e1d2 100644 --- a/src/Navaids/fixlist.cxx +++ b/src/Navaids/fixlist.cxx @@ -87,10 +87,23 @@ bool FGFixList::init( SGPath path ) { } -// query the database for the specified frequency, lon and lat are in +// query the database for the specified fix, lon and lat are in // degrees, elev is in meters -bool FGFixList::query( const string& ident, double lon, double lat, double elev, - FGFix *fix, double *heading, double *dist ) +bool FGFixList::query( const string& ident, FGFix *fix ) { + *fix = fixlist[ident]; + if ( ! fix->get_ident().empty() ) { + return true; + } else { + return false; + } +} + + +// query the database for the specified fix, lon and lat are in +// degrees, elev is in meters +bool FGFixList::query_and_offset( const string& ident, double lon, double lat, + double elev, FGFix *fix, double *heading, + double *dist ) { *fix = fixlist[ident]; if ( fix->get_ident().empty() ) { diff --git a/src/Navaids/fixlist.hxx b/src/Navaids/fixlist.hxx index 75d48e244..c23d4b759 100644 --- a/src/Navaids/fixlist.hxx +++ b/src/Navaids/fixlist.hxx @@ -56,10 +56,14 @@ public: // load the navaids and build the map bool init( SGPath path ); - // query the database for the specified frequency, lon and lat are + // query the database for the specified fix + bool query( const string& ident, FGFix *f ); + + // query the database for the specified fix, lon and lat are // in degrees, elev is in meters - bool query( const string& ident, double lon, double lat, double elev, - FGFix *f, double *heading, double *dist); + bool query_and_offset( const string& ident, double lon, double lat, + double elev, FGFix *f, double *heading, + double *dist ); }; diff --git a/src/Navaids/navlist.cxx b/src/Navaids/navlist.cxx index b46b4b840..aba88dddc 100644 --- a/src/Navaids/navlist.cxx +++ b/src/Navaids/navlist.cxx @@ -111,7 +111,7 @@ bool FGNavList::init( SGPath path ) { // query the database for the specified frequency, lon and lat are in // degrees, elev is in meters bool FGNavList::query( double lon, double lat, double elev, double freq, - FGNav *n ) + FGNav *nav ) { nav_list_type stations = navaids[(int)(freq*100.0 + 0.5)]; @@ -119,7 +119,7 @@ bool FGNavList::query( double lon, double lat, double elev, double freq, nav_list_iterator last = stations.end(); Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) ); - return findNavFromList(aircraft, current, last, n); + return findNavFromList(aircraft, current, last, nav); } @@ -136,9 +136,36 @@ bool FGNavList::findByIdent(const char* ident, double lon, double lat, } +bool FGNavList::findByIdentAndFreq(const char* ident, const double& freq, + FGNav *nav) +{ + cout << "ident = " << ident << endl; + nav_list_type stations = ident_navaids[ident]; + cout << " matches = " << stations.size() << endl; + nav_list_iterator current = stations.begin(); + nav_list_iterator last = stations.end(); + + if ( stations.size() > 1 ) { + // more than one match on this ident, use freq to refine + int f = (int)(freq*100.0 + 0.5); + for ( ; current != last ; ++current ) { + if ( f == (*current)->get_freq() ) { + *nav = (**current); + return true; + } + } + } else { + *nav = (**current); + return true; + } + + return false; +} + + bool FGNavList::findNavFromList(const Point3D &aircraft, nav_list_iterator current, - nav_list_iterator end, FGNav *n) + nav_list_iterator end, FGNav *nav) { // double az1, az2, s; @@ -165,7 +192,7 @@ bool FGNavList::findNavFromList(const Point3D &aircraft, if ( d2 < min_dist ) { min_dist = d2; found_one = true; - *n = (**current); + *nav = (**current); // cout << "matched = " << (*current)->get_ident() << endl; } else { // cout << "matched, but too far away = " diff --git a/src/Navaids/navlist.hxx b/src/Navaids/navlist.hxx index 1d6bea2c6..c890e0ef8 100644 --- a/src/Navaids/navlist.hxx +++ b/src/Navaids/navlist.hxx @@ -71,10 +71,13 @@ public: // query the database for the specified frequency, lon and lat are // in degrees, elev is in meters - bool query( double lon, double lat, double elev, double freq, FGNav *n ); + bool query( double lon, double lat, double elev, double freq, FGNav *nav ); // locate closest item in the DB matching the requested ident bool findByIdent(const char* ident, double lon, double lat, FGNav *nav); + + // locate item in the DB matching the requested ident + bool findByIdentAndFreq(const char* ident, const double& freq, FGNav *nav); }; diff --git a/src/Navaids/testnavs.cxx b/src/Navaids/testnavs.cxx index a6b839f44..3e95bbcff 100644 --- a/src/Navaids/testnavs.cxx +++ b/src/Navaids/testnavs.cxx @@ -66,9 +66,10 @@ int main() { // attempting to get the position relative to the OTR VOR; heading // should be 108 degrees, distance 74nm (according to my SimCharts // v1.5) - if ( current_fixlist->query( "DOGGA", -0.103 * SG_DEGREES_TO_RADIANS, - 53.698 * SG_DEGREES_TO_RADIANS, 3000, - &fix, &heading, &dist) ) + if ( current_fixlist->query_and_offset( "DOGGA", + -0.103 * SG_DEGREES_TO_RADIANS, + 53.698 * SG_DEGREES_TO_RADIANS, + 3000, &fix, &heading, &dist) ) { cout << "Found a matching fix" << endl; cout << " id = " << fix.get_ident() << endl; diff --git a/src/Network/props.cxx b/src/Network/props.cxx index 253aac701..eb4e9b0ce 100644 --- a/src/Network/props.cxx +++ b/src/Network/props.cxx @@ -311,22 +311,29 @@ PropsChannel::foundTerminator() } else if ( command == "set" ) { - if ( tokens.size() == 3 ) - { - node->getNode( tokens[1].c_str(), true )->setStringValue(tokens[2].c_str()); + if ( tokens.size() >= 2 ) + { + string value, tmp; + if ( tokens.size() == 3 ) { + value = tokens[2]; + } else { + value = ""; + } + node->getNode( tokens[1].c_str(), true ) + ->setStringValue(value.c_str()); if ( mode == PROMPT ) { // now fetch and write out the new value as confirmation // of the change - string value = node->getStringValue ( tokens[1].c_str(), "" ); - string tmp = tokens[1] + " = '" + value + "' ("; + value = node->getStringValue ( tokens[1].c_str(), "" ); + tmp = tokens[1] + " = '" + value + "' ("; tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) ); tmp += ")"; push( tmp.c_str() ); push( getTerminator() ); } - } + } } else if ( command == "run" ) { -- 2.39.5