Add support for in-air preset starts relative to a VOR, NDB, or Fix.
This commit is contained in:
parent
30dc5aab90
commit
be703a92b4
9 changed files with 216 additions and 26 deletions
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() ) {
|
||||
|
|
|
@ -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 );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 = "
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" )
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue