]> git.mxchange.org Git - flightgear.git/commitdiff
Issue #809, restructure position init code.
authorJames Turner <zakalawe@mac.com>
Sun, 9 Dec 2012 19:41:31 +0000 (19:41 +0000)
committerJames Turner <zakalawe@mac.com>
Sun, 9 Dec 2012 19:41:31 +0000 (19:41 +0000)
Modify startup sequence, so position can be modified late in the startup process, right before the scenery load starts. This allows two ugly hacks to move to a permanent, less hacky location. If other position init modes required similar late evaluation in the future, this can be accommodated now.

This is a somewhat high-risk change - I've tested both carrier starts and runway-selection based on realwx METAR, but please look out for other position-init issues and test before / after this patch.

src/Environment/realwx_ctrl.cxx
src/Main/fg_init.cxx
src/Main/main.cxx
src/Main/positioninit.cxx
src/Main/positioninit.hxx

index 6be99082e6fa942bb03933a7545df663be8ed514..86c89822e9ac538774afd5d3ae4313c4c3579624 100644 (file)
@@ -102,7 +102,7 @@ void LiveMetarProperties::update( double dt )
 {
     _timeToLive -= dt;
     _pollingTimer -= dt;
-    if( _timeToLive < 0.0 ) {
+    if( _timeToLive <= 0.0 ) {
         _timeToLive = 0.0;
         std::string stationId = getStationId();
         if( stationId.empty() ) return;
@@ -234,6 +234,8 @@ BasicRealWxController::~BasicRealWxController()
 void BasicRealWxController::init()
 {
     _wasEnabled = false;
+    
+    checkNearbyMetar();
     update(0); // fetch data ASAP
     
     globals->get_event_mgr()->addTask("checkNearbyMetar", this,
@@ -419,6 +421,11 @@ void NoaaMetarRealWxController::requestMetar( MetarDataHandler * metarDataHandle
                   SG_LOG(SG_ENVIRONMENT, SG_WARN, "metar download failed:" << url() << ": reason:" << responseReason());
               }
           }
+        
+        virtual void failed()
+        {
+            SG_LOG(SG_ENVIRONMENT, SG_INFO, "metar download failure");
+        }
 
 //          bool fromMetarProxy() const
 //          { return _fromProxy; }
index 28a0e666419433abb53912966f42cc0e81b366ce..75b1b23ab0524d79d083239fc86bb047bfcdcd57 100644 (file)
@@ -581,7 +581,8 @@ void fgCreateSubsystems() {
         exit(-1);
     }
 
-
+    globals->add_subsystem( "http", new FGHTTPClient );
+    
     ////////////////////////////////////////////////////////////////////
     // Initialize the scenery management subsystem.
     ////////////////////////////////////////////////////////////////////
@@ -626,7 +627,6 @@ void fgCreateSubsystems() {
     // Initialize the Input-Output subsystem
     ////////////////////////////////////////////////////////////////////
     globals->add_subsystem( "io", new FGIO );
-    globals->add_subsystem( "http", new FGHTTPClient );
   
     ////////////////////////////////////////////////////////////////////
     // Create and register the logger.
@@ -756,29 +756,6 @@ void fgPostInitSubsystems()
     globals->get_subsystem_mgr()->postinit();
     SG_LOG(SG_GENERAL, SG_INFO, "Subsystems postinit took:" << st.elapsedMSec());
   
-    ////////////////////////////////////////////////////////////////////
-    // TODO FIXME! UGLY KLUDGE!
-    ////////////////////////////////////////////////////////////////////
-    {
-        /* Scenarios require Nasal, so FGAIManager loads the scenarios,
-         * including its models such as a/c carriers, in its 'postinit',
-         * which is the very last thing we do.
-         * flightgear::initPosition is called very early in main.cxx/fgIdleFunction,
-         * one of the first things we do, long before scenarios/carriers are
-         * loaded. => When requested "initial preset position" relates to a
-         * carrier, recalculate the 'initial' position here (how have things
-         * ever worked before this hack - this init sequence has always been
-         * this way...?)*/
-        std::string carrier = fgGetString("/sim/presets/carrier","");
-        if (carrier != "")
-        {
-            // clear preset location and re-trigger position setup
-            fgSetDouble("/sim/presets/longitude-deg", 9999);
-            fgSetDouble("/sim/presets/latitude-deg", 9999);
-            flightgear::initPosition();
-        }
-    }
-
     ////////////////////////////////////////////////////////////////////////
     // End of subsystem initialization.
     ////////////////////////////////////////////////////////////////////
index 50b1bb0264136a53bc8111cdf19c240f2469b980..2073b9e1581df3a1fe77180f868a1aa819dd6173 100644 (file)
@@ -217,39 +217,15 @@ static void fgIdleFunction ( void ) {
         }
       
     } else if ( idle_state == 10 ) {
-        idle_state = 900;
+        idle_state = 800;
         fgPostInitSubsystems();
-      
-              // Torsten Dreyer:
-        // ugly hack for automatic runway selection on startup based on
-        // metar data. Makes startup.nas obsolete and guarantees the same
-        // runway selection as for AI traffic. However, this code belongs to
-        // somewhere(?) else - if I only new where...
-        if( true == fgGetBool( "/environment/metar/valid" ) ) {
-            SG_LOG(SG_ENVIRONMENT, SG_INFO,
-                "Using METAR for runway selection: '" << fgGetString("/environment/metar/data") << "'" );
-            // the realwx_ctrl fetches metar in the foreground on init,
-            // If it was able to fetch a metar or one was given on the commandline,
-            // the valid flag is set here, otherwise it is false
-            double hdg = fgGetDouble( "/environment/metar/base-wind-dir-deg", 9999.0 );
-            string apt = fgGetString( "/sim/startup/options/airport" );
-            string rwy = fgGetString( "/sim/startup/options/runway" );
-            double strthdg = fgGetDouble( "/sim/startup/options/heading-deg", 9999.0 );
-            string parkpos = fgGetString( "/sim/presets/parkpos" );
-            bool onground = fgGetBool( "/sim/presets/onground", false );
-            // don't check for wind-speed < 1kt, this belongs to the runway-selection code
-            // the other logic is taken from former startup.nas
-            if( hdg < 360.0 && apt.length() > 0 && strthdg > 360.0 && rwy.length() == 0 && onground && parkpos.length() == 0 ) {
-                extern bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg );
-                flightgear::setPosFromAirportIDandHdg( apt, hdg );
-            }
+    } else if ( idle_state == 800 ) {
+        if (flightgear::finalizePosition()) {
+            idle_state = 900;
+            fgSplashProgress("init-graphics");
         } else {
-            SG_LOG(SG_ENVIRONMENT, SG_INFO,
-                "No METAR available to pick active runway" );
+            fgSplashProgress("finalize-position");
         }
-
-        fgSplashProgress("init-graphics");
-
     } else if ( idle_state == 900 ) {
         idle_state = 1000;
         
index cb4663cc2a8272db185a695c3286647ebd68dc5f..c904a48fa78f69957b6f4106e6fcd2234b8c4dc1 100644 (file)
@@ -39,6 +39,11 @@ using std::endl;
 
 namespace flightgear
 {
+    
+/// to avoid blocking when metar-fetch is enabled, but the network is
+/// unresponsive, we need a timeout value. This value is reset on initPosition,
+/// and tracked through each call to finalizePosition.
+static SGTimeStamp global_finalizeTime;
   
 // Set current tower position lon/lat given an airport id
 static bool fgSetTowerPosFromAirportID( const string& id) {
@@ -131,7 +136,7 @@ static void fgApplyStartOffset(const SGGeod& aStartPos, double aHeading, double
 }
 
 // Set current_options lon/lat given an airport id and heading (degrees)
-bool setPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
+static bool setPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
   if ( id.empty() )
     return false;
   
@@ -395,7 +400,8 @@ static bool fgSetPosFromFix( const string& id )
 // Set the initial position based on presets (or defaults)
 bool initPosition()
 {
-  // cout << "initPosition()" << endl;
+  global_finalizeTime = SGTimeStamp(); // reset to invalid
+  
   double gs = fgGetDouble("/sim/presets/glideslope-deg")
   * SG_DEGREES_TO_RADIANS ;
   double od = fgGetDouble("/sim/presets/offset-distance-nm");
@@ -541,4 +547,64 @@ bool initPosition()
   return true;
 }
   
+bool finalizePosition()
+{
+  // first call to finalize after an initPosition call
+  if (global_finalizeTime.get_usec() == 0) {
+    global_finalizeTime = SGTimeStamp::now();
+  }
+  
+    /* Scenarios require Nasal, so FGAIManager loads the scenarios,
+     * including its models such as a/c carriers, in its 'postinit',
+     * which is the very last thing we do.
+     * flightgear::initPosition is called very early in main.cxx/fgIdleFunction,
+     * one of the first things we do, long before scenarios/carriers are
+     * loaded. => When requested "initial preset position" relates to a
+     * carrier, recalculate the 'initial' position here 
+     */
+    std::string carrier = fgGetString("/sim/presets/carrier","");
+    if (!carrier.empty())
+    {
+        SG_LOG(SG_GENERAL, SG_INFO, "finalizePositioned: re-init-ing position on carrier");
+        // clear preset location and re-trigger position setup
+        fgSetDouble("/sim/presets/longitude-deg", 9999);
+        fgSetDouble("/sim/presets/latitude-deg", 9999);
+        return initPosition();
+    }
+
+    double hdg = fgGetDouble( "/environment/metar/base-wind-dir-deg", 9999.0 );
+    string apt = fgGetString( "/sim/startup/options/airport" );
+    string rwy = fgGetString( "/sim/startup/options/runway" );
+    double strthdg = fgGetDouble( "/sim/startup/options/heading-deg", 9999.0 );
+    string parkpos = fgGetString( "/sim/presets/parkpos" );
+    bool onground = fgGetBool( "/sim/presets/onground", false );
+// this logic is taken from former startup.nas
+    bool needMetar = (hdg < 360.0) && !apt.empty() && (strthdg > 360.0) &&
+        rwy.empty() && onground && parkpos.empty();
+    
+    if (needMetar) {
+      // timeout so we don't spin forever if the network is down
+      if (global_finalizeTime.elapsedMSec() > fgGetInt("/sim/startup/metar-fetch-timeout-msec", 5000)) {
+        SG_LOG(SG_GENERAL, SG_WARN, "finalizePosition: timed out waiting for METAR fetch");
+        return true;
+      }
+    
+      if (!fgGetBool( "/environment/metar/valid" )) {
+        // bit hacky - run these two subsystems. We can't run the whole
+        // lot since some view things aren't initialised and hence FGLight
+        // crashes.
+        globals->get_subsystem("http")->update(0.0);
+        globals->get_subsystem("environment")->update(0.0);
+        return false;
+      }
+      
+      SG_LOG(SG_ENVIRONMENT, SG_INFO,
+             "Using METAR for runway selection: '" << fgGetString("/environment/metar/data") << "'" );
+      setPosFromAirportIDandHdg( apt, hdg );
+        // fall through to return true
+    } // of need-metar case
+    
+    return true;
+}
+    
 } // of namespace flightgear
index 9e6748bfa02aba1473cc7bd0c5ed5dd1c0c69777..69a7e6809a7894fc01c35213aa86caeafa470100 100644 (file)
@@ -28,13 +28,18 @@ namespace flightgear
 // Set the initial position based on presets (or defaults)
 bool initPosition();
 
-
+/**
+ * finalize the position once subsystems, Nasal and scenarios are loaded;
+ * all of which can potentially affect the position.
+ * returns true if the position is finally set, or false if more time
+ * is required to finalize the position (eg, awaiting METAR to set the
+ * active runway)
+ */
+bool finalizePosition();
+    
 // Listen to /sim/tower/airport-id and set tower view position accordingly
 void initTowerLocationListener();
   
-// FIXME - only public becuase of the evil runway-selection hack in main.cxx
-bool setPosFromAirportIDandHdg( const std::string& id, double tgt_hdg );
-  
 } // of namespace flightgear
 
 #endif // of FG_POSITION_INIT_HXX