+ SG_LOG( SG_GENERAL, SG_ALERT,
+ "Glideslope given but not altitude or offset-distance." );
+ SG_LOG( SG_GENERAL, SG_ALERT, "Resetting glideslope to zero" );
+ fgSetDouble("/sim/presets/glideslope-deg", 0);
+ fgSetBool("/sim/presets/onground", true);
+ }
+}
+
+
+// Set current_options lon/lat given an airport id and heading (degrees)
+static bool fgSetPosFromNAV( const string& id, const double& freq ) {
+ FGNavRecord *nav
+ = globals->get_navlist()->findByIdentAndFreq( id.c_str(), freq );
+
+ // set initial position from runway and heading
+ if ( nav != NULL ) {
+ 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 ( globals->get_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;
+ }
+}
+
+static void parseWaypoints() {
+ string_list *waypoints = globals->get_initial_waypoints();
+ if (waypoints) {
+ vector<string>::iterator i;
+ for (i = waypoints->begin();
+ i != waypoints->end();
+ i++)
+ {
+ NewWaypoint(*i);
+ }
+ // Now were done using the way points we can deallocate the
+ // memory they used
+ while (waypoints->begin() != waypoints->end()) {
+ waypoints->pop_back();
+ }
+ delete waypoints;
+ globals->set_initial_waypoints(0);
+ }
+}
+
+
+
+
+
+/**
+ * Initialize vor/ndb/ils/fix list management and query systems (as
+ * well as simple airport db list)
+ */
+bool
+fgInitNav ()
+{
+ SG_LOG(SG_GENERAL, SG_INFO, "Loading Simple Airport List");
+ SGPath p_simple( globals->get_fg_root() );
+ p_simple.append( "Airports/basic.dat" );
+ SGPath p_metar( globals->get_fg_root() );
+ p_metar.append( "Airports/metar.dat" );
+ FGAirportList *airports = new FGAirportList(p_simple.str(), p_metar.str());
+ globals->set_airports( airports );
+
+ SG_LOG(SG_GENERAL, SG_INFO, "Loading Runway List");
+ SGPath p_runway( globals->get_fg_root() );
+ p_runway.append( "Airports/runways.dat" );
+ FGRunwayList *runways = new FGRunwayList( p_runway.str() );
+ globals->set_runways( runways );
+
+ FGNavList *navlist = new FGNavList;
+ FGNavList *loclist = new FGNavList;
+ FGNavList *gslist = new FGNavList;
+ FGNavList *dmelist = new FGNavList;
+ FGNavList *mkrlist = new FGNavList;
+
+ globals->set_navlist( navlist );
+ globals->set_loclist( loclist );
+ globals->set_gslist( gslist );
+ globals->set_dmelist( dmelist );
+ globals->set_mkrlist( mkrlist );
+
+ if ( !fgNavDBInit( navlist, loclist, gslist, dmelist, mkrlist ) ) {
+ SG_LOG( SG_GENERAL, SG_ALERT,
+ "Problems loading one or more navigational database" );
+ }
+
+ if ( fgGetBool("/sim/navdb/localizers/auto-align", 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.
+ double threshold
+ = fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg",
+ 5.0 );
+ fgNavDBAlignLOCwithRunway( runways, loclist, threshold );
+ }
+
+ SG_LOG(SG_GENERAL, SG_INFO, " Fixes");
+ SGPath p_fix( globals->get_fg_root() );
+ p_fix.append( "Navaids/fix.dat" );
+ FGFixList *fixlist = new FGFixList;
+ fixlist->init( p_fix );
+ globals->set_fixlist( fixlist );
+
+ return true;
+}
+
+
+// Set the initial position based on presets (or defaults)
+bool fgInitPosition() {
+ // cout << "fgInitPosition()" << endl;
+ double gs = fgGetDouble("/sim/presets/glideslope-deg")
+ * SG_DEGREES_TO_RADIANS ;
+ double od = fgGetDouble("/sim/presets/offset-distance");
+ double alt = fgGetDouble("/sim/presets/altitude-ft");
+
+ bool set_pos = false;
+
+ // If glideslope is specified, then calculate offset-distance or
+ // altitude relative to glide slope if either of those was not
+ // specified.
+ if ( fabs( gs ) > 0.01 ) {
+ fgSetDistOrAltFromGlideSlope();
+ }
+
+
+ // If we have an explicit, in-range lon/lat, don't change it, just use it.
+ // If not, check for an airport-id and use that.
+ // If not, default to the middle of the KSFO field.
+ // The default values for lon/lat are deliberately out of range
+ // so that the airport-id can take effect; valid lon/lat will
+ // override airport-id, however.
+ double lon_deg = fgGetDouble("/sim/presets/longitude-deg");
+ double lat_deg = fgGetDouble("/sim/presets/latitude-deg");
+ if ( lon_deg >= -180.0 && lon_deg <= 180.0
+ && lat_deg >= -90.0 && lat_deg <= 90.0 )
+ {
+ set_pos = true;
+ }
+
+ 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
+ // 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
+ // runway airports)
+ fgSetTowerPosFromAirportID( apt, hdg );
+ set_pos = true;
+ }
+ }
+
+ if ( !set_pos && !vor.empty() ) {
+ // a VOR is requested
+ if ( fgSetPosFromNAV( vor, vor_freq ) ) {
+ set_pos = true;
+ }
+ }
+
+ if ( !set_pos && !ndb.empty() ) {
+ // an NDB is requested
+ if ( fgSetPosFromNAV( ndb, ndb_freq ) ) {
+ set_pos = true;
+ }
+ }
+
+ if ( !set_pos && !fix.empty() ) {
+ // a Fix is requested
+ if ( fgSetPosFromFix( fix ) ) {
+ set_pos = true;
+ }
+ }
+
+ if ( !set_pos ) {
+ // No lon/lat specified, no airport specified, default to
+ // middle of KSFO field.
+ fgSetDouble("/sim/presets/longitude-deg", -122.374843);
+ fgSetDouble("/sim/presets/latitude-deg", 37.619002);
+ }
+
+ fgSetDouble( "/position/longitude-deg",
+ fgGetDouble("/sim/presets/longitude-deg") );
+ fgSetDouble( "/position/latitude-deg",
+ fgGetDouble("/sim/presets/latitude-deg") );
+ fgSetDouble( "/orientation/heading-deg",
+ fgGetDouble("/sim/presets/heading-deg") );
+
+ // determine if this should be an on-ground or in-air start
+ if ( fabs(gs) > 0.01 || fabs(od) > 0.1 || alt > 0.1 ) {
+ fgSetBool("/sim/presets/onground", false);
+ } else {
+ fgSetBool("/sim/presets/onground", true);