From 183b871b483c153d3b55f68948b91179a62e232f Mon Sep 17 00:00:00 2001
From: frohlich <frohlich>
Date: Tue, 17 Mar 2009 06:51:48 +0000
Subject: [PATCH] Fix a problem with two concurent 'round to multiple of basic
 simulation time' code paths. The problem may lead to skipped fdm updates at
 very high frame rates. The most visible effect of that was that the aircraft
 slips backwards wrt the forward moving carrier. Remove unused stuff.

Modified Files:
	configure.ac projects/VC7.1/FlightGear.vcproj
	projects/VC8/FlightGearLib.vcproj src/Cockpit/cockpit.cxx
 	src/FDM/Makefile.am src/FDM/flight.cxx src/FDM/flight.hxx
 	src/FDM/SP/Balloon.cxx src/FDM/SP/BalloonSim.cpp
 	src/FDM/SP/BalloonSim.h src/Main/Makefile.am
 	src/Main/fg_init.cxx src/Main/main.cxx src/Time/Makefile.am
Removed Files:
 	src/Time/fg_timer.cxx src/Time/fg_timer.hxx
---
 projects/VC7.1/FlightGear.vcproj  |   6 --
 projects/VC8/FlightGearLib.vcproj |   8 --
 src/Cockpit/cockpit.cxx           |   1 -
 src/FDM/flight.cxx                |  54 ++------------
 src/FDM/flight.hxx                |   2 -
 src/Main/main.cxx                 |  47 +++---------
 src/Time/Makefile.am              |   1 -
 src/Time/fg_timer.cxx             | 120 ------------------------------
 src/Time/fg_timer.hxx             |  47 ------------
 9 files changed, 16 insertions(+), 270 deletions(-)
 delete mode 100644 src/Time/fg_timer.cxx
 delete mode 100644 src/Time/fg_timer.hxx

diff --git a/projects/VC7.1/FlightGear.vcproj b/projects/VC7.1/FlightGear.vcproj
index 85cc1dcff..f4f252542 100755
--- a/projects/VC7.1/FlightGear.vcproj
+++ b/projects/VC7.1/FlightGear.vcproj
@@ -2223,12 +2223,6 @@
 		<Filter
 			Name="Lib_Time"
 			Filter="">
-			<File
-				RelativePath="..\..\src\Time\fg_timer.cxx">
-			</File>
-			<File
-				RelativePath="..\..\src\Time\fg_timer.hxx">
-			</File>
 			<File
 				RelativePath="..\..\src\Time\light.cxx">
 			</File>
diff --git a/projects/VC8/FlightGearLib.vcproj b/projects/VC8/FlightGearLib.vcproj
index 58e0ba086..9e46a281f 100755
--- a/projects/VC8/FlightGearLib.vcproj
+++ b/projects/VC8/FlightGearLib.vcproj
@@ -488,10 +488,6 @@
 				RelativePath="..\..\src\include\fg_stl_config.h"
 				>
 			</File>
-			<File
-				RelativePath="..\..\src\time\fg_timer.hxx"
-				>
-			</File>
 			<File
 				RelativePath="..\..\src\include\fg_typedefs.h"
 				>
@@ -2198,10 +2194,6 @@
 				RelativePath="..\..\src\main\fg_props.cxx"
 				>
 			</File>
-			<File
-				RelativePath="..\..\src\time\fg_timer.cxx"
-				>
-			</File>
 			<File
 				RelativePath="..\..\src\FDM\JSBSim\models\flight_control\FGActuator.cpp"
 				>
diff --git a/src/Cockpit/cockpit.cxx b/src/Cockpit/cockpit.cxx
index 3865ce718..4e7651f7c 100644
--- a/src/Cockpit/cockpit.cxx
+++ b/src/Cockpit/cockpit.cxx
@@ -45,7 +45,6 @@
 #include <Main/fg_props.hxx>
 #include <Main/viewmgr.hxx>
 #include <Scenery/scenery.hxx>
-#include <Time/fg_timer.hxx>
 #include <GUI/gui.h>
 
 #include "cockpit.hxx"
diff --git a/src/FDM/flight.cxx b/src/FDM/flight.cxx
index 0e4ff912a..bc5b3059a 100644
--- a/src/FDM/flight.cxx
+++ b/src/FDM/flight.cxx
@@ -44,23 +44,15 @@ static inline void assign(double* ptr, const SGVec3d& vec)
   ptr[2] = vec[2];
 }
 
-// base_fdm_state is the internal state that is updated in integer
-// multiples of "dt".  This leads to "jitter" with respect to the real
-// world time, so we introduce cur_fdm_state which is extrapolated by
-// the difference between sim time and real world time
-
 FGInterface *cur_fdm_state = 0;
-FGInterface base_fdm_state;
 
 // Constructor
 FGInterface::FGInterface()
-  : remainder(0)
 {
     _setup();
 }
 
 FGInterface::FGInterface( double dt )
-  : remainder(0)
 {
     _setup();
 }
@@ -70,33 +62,18 @@ FGInterface::~FGInterface() {
     // unbind();                   // FIXME: should be called explicitly
 }
 
-
 int
 FGInterface::_calc_multiloop (double dt)
 {
+  // Since some time the simulation time increments we get here are
+  // already a multiple of the basic update freqency.
+  // So, there is no need to do our own multiloop rounding with all bad
+  // roundoff problems when we already have nearly accurate values.
+  // Only the speedup thing must be still handled here
   int hz = fgGetInt("/sim/model-hz");
+  int multiloop = SGMiscd::roundToInt(dt*hz);
   int speedup = fgGetInt("/sim/speed-up");
-
-  dt += remainder;
-  remainder = 0;
-  double ml = dt * hz;
-  // Avoid roundoff problems by adding the roundoff itself.
-  // ... ok, two times the roundoff to have enough room.
-  int multiloop = int(floor(ml * (1.0 + 2.0*DBL_EPSILON)));
-  remainder = (ml - multiloop) / hz;
-
-  // If we artificially inflate ml above by a tiny amount to get the
-  // closest integer, then subtract the integer from the original
-  // slightly smaller value, we can get a negative remainder.
-  // Logically this should never happen, and we definitely don't want
-  // to carry a negative remainder over to the next iteration, so
-  // never let the remainder go below zero.
-  // 
-  // Note: this fixes a problem where we run 1, 3, 1, 3, 1, 3... loops
-  // of the FDM when in fact we want to run 2, 2, 2, 2, 2...
-  if ( remainder < 0 ) { remainder = 0; }
-
-  return (multiloop * speedup);
+  return multiloop * speedup;
 }
 
 
@@ -165,9 +142,6 @@ FGInterface::common_init ()
 
     ground_cache.set_cache_time_offset(globals->get_sim_time_sec());
 
-//     stamp();
-//     set_remainder( 0 );
-
     // Set initial position
     SG_LOG( SG_FLIGHT, SG_INFO, "...initializing position..." );
     double lon = fgGetDouble("/sim/presets/longitude-deg")
@@ -261,16 +235,6 @@ FGInterface::bind ()
 {
   bound = true;
 
-                                // Time management (read-only)
-//   fgTie("/fdm/time/delta_t", this,
-//         &FGInterface::get_delta_t); // read-only
-//   fgTie("/fdm/time/elapsed", this,
-//         &FGInterface::get_elapsed); // read-only
-//   fgTie("/fdm/time/remainder", this,
-//         &FGInterface::get_remainder); // read-only
-//   fgTie("/fdm/time/multi_loop", this,
-//         &FGInterface::get_multi_loop); // read-only
-
 			// Aircraft position
   fgTie("/position/latitude-deg", this,
         &FGInterface::get_Latitude_deg,
@@ -429,10 +393,6 @@ FGInterface::unbind ()
 {
   bound = false;
 
-  // fgUntie("/fdm/time/delta_t");
-  // fgUntie("/fdm/time/elapsed");
-  // fgUntie("/fdm/time/remainder");
-  // fgUntie("/fdm/time/multi_loop");
   fgUntie("/position/latitude-deg");
   fgUntie("/position/longitude-deg");
   fgUntie("/position/altitude-ft");
diff --git a/src/FDM/flight.hxx b/src/FDM/flight.hxx
index 1ce5ab5d5..ba9551456 100644
--- a/src/FDM/flight.hxx
+++ b/src/FDM/flight.hxx
@@ -111,8 +111,6 @@ private:
     // next elapsed time.  This yields a small amount of temporal
     // jitter ( < dt ) but in practice seems to work well.
 
-    double remainder;		// remainder time from last run
-
     // CG position w.r.t. ref. point
     SGVec3d d_cg_rp_body_v;
 
diff --git a/src/Main/main.cxx b/src/Main/main.cxx
index 10fc58ce1..ecc0b88ac 100644
--- a/src/Main/main.cxx
+++ b/src/Main/main.cxx
@@ -67,7 +67,6 @@
 #include <ATCDCL/ATCmgr.hxx>
 #include <ATCDCL/AIMgr.hxx>
 #include <Time/tmp.hxx>
-#include <Time/fg_timer.hxx>
 #include <Environment/environment_mgr.hxx>
 #include <GUI/new_gui.hxx>
 #include <MultiPlayer/multiplaymgr.hxx>
@@ -304,15 +303,12 @@ static void fgMainLoop( void ) {
 
     // round the real time down to a multiple of 1/model-hz.
     // this way all systems are updated the _same_ amount of dt.
-    {
-        static double rem = 0.0;
-        real_delta_time_sec += rem;
-        double hz = model_hz;
-        double nit = floor(real_delta_time_sec*hz);
-        rem = real_delta_time_sec - nit/hz;
-        real_delta_time_sec = nit/hz;
-    }
-
+    static double reminder = 0.0;
+    real_delta_time_sec += reminder;
+    global_multi_loop = long(floor(real_delta_time_sec*model_hz));
+    global_multi_loop = SGMisc<long>::max(0, global_multi_loop);
+    reminder = real_delta_time_sec - double(global_multi_loop)/double(model_hz);
+    real_delta_time_sec = double(global_multi_loop)/double(model_hz);
 
     if (clock_freeze->getBoolValue() || wait_for_scenery) {
         delta_time_sec = 0;
@@ -326,8 +322,6 @@ static void fgMainLoop( void ) {
     fgSetDouble("/sim/time/delta-realtime-sec", real_delta_time_sec);
     fgSetDouble("/sim/time/delta-sec", delta_time_sec);
 
-    static long remainder = 0;
-    long elapsed;
 #ifdef FANCY_FRAME_COUNTER
     int i;
     double accum;
@@ -400,12 +394,6 @@ static void fgMainLoop( void ) {
                                 altitude->getDoubleValue() * SG_FEET_TO_METER,
                                 globals->get_time_params()->getJD() );
 
-    // Get elapsed time (in usec) for this past frame
-    elapsed = fgGetTimeInterval();
-    SG_LOG( SG_ALL, SG_DEBUG,
-            "Elapsed time interval is = " << elapsed
-            << ", previous remainder is = " << remainder );
-
     // Calculate frame rate average
 #ifdef FANCY_FRAME_COUNTER
     /* old fps calculation */
@@ -452,27 +440,10 @@ static void fgMainLoop( void ) {
         globals->get_AI_mgr()->update(delta_time_sec);
 
     // Run flight model
-
-    // Calculate model iterations needed for next frame
-    elapsed += remainder;
-
-    global_multi_loop = (long)(((double)elapsed * 0.000001) * model_hz );
-    remainder = elapsed - ( (global_multi_loop*1000000) / model_hz );
-    SG_LOG( SG_ALL, SG_DEBUG,
-            "Model iterations needed = " << global_multi_loop
-            << ", new remainder = " << remainder );
-
-    // chop max iterations to something reasonable if the sim was
-    // delayed for an excessive amount of time
-    if ( global_multi_loop > 2.0 * model_hz ) {
-        global_multi_loop = (int)(2.0 * model_hz );
-        remainder = 0;
-    }
-
-    // flight model
-    if ( global_multi_loop > 0) {
+    if (0 < global_multi_loop) {
         // first run the flight model each frame until it is initialized
-        // then continue running each frame only after initial scenery load is complete.
+        // then continue running each frame only after initial scenery
+        // load is complete.
         fgUpdateTimeDepCalcs();
     } else {
         SG_LOG( SG_ALL, SG_DEBUG,
diff --git a/src/Time/Makefile.am b/src/Time/Makefile.am
index 98f634176..7c824d8d0 100644
--- a/src/Time/Makefile.am
+++ b/src/Time/Makefile.am
@@ -1,7 +1,6 @@
 noinst_LIBRARIES = libTime.a
 
 libTime_a_SOURCES = \
-	fg_timer.cxx fg_timer.hxx \
 	light.cxx light.hxx \
 	sunsolver.cxx sunsolver.hxx \
 	tmp.cxx tmp.hxx
diff --git a/src/Time/fg_timer.cxx b/src/Time/fg_timer.cxx
deleted file mode 100644
index 7f6fef851..000000000
--- a/src/Time/fg_timer.cxx
+++ /dev/null
@@ -1,120 +0,0 @@
-// fg_timer.cxx -- time handling routines
-//
-// Written by Curtis Olson, started June 1997.
-//
-// Copyright (C) 1997  Curtis L. Olson  - http://www.flightgear.org/~curt
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// $Id$
-
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <signal.h>    // for timer routines
-#include <stdio.h>     // for printf()
-
-#ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-#  include <sys/time.h>  // for get/setitimer, gettimeofday, struct timeval
-#endif
-
-#include <simgear/timing/timestamp.hxx>
-
-#include "fg_timer.hxx"
-
-
-unsigned long int fgSimTime;
-
-#ifdef HAVE_SETITIMER
-  static struct itimerval t, ot;
-  static void (*callbackfunc)(int multi_loop);
-
-
-// This routine catches the SIGALRM
-void fgTimerCatch( int dummy ) {
-    int warning_avoider;
-
-    // get past a compiler warning
-    warning_avoider = dummy;
-
-    // ignore any SIGALRM's until we come back from our EOM iteration
-    signal(SIGALRM, SIG_IGN);
-
-    // printf("In fgTimerCatch()\n");
-
-    // -1 tells the routine to use default interval rather than
-    // something dynamically calculated based on frame rate
-    callbackfunc(-1); 
-
-    signal(SIGALRM, fgTimerCatch);
-}
-
-
-// this routine initializes the interval timer to generate a SIGALRM
-// after the specified interval (dt)
-void fgTimerInit(float dt, void (*f)( int )) {
-    int terr;
-    int isec;
-    int usec;
-
-    callbackfunc = f;
-
-    isec = (int) dt;
-    usec = 1000000 * ((int)dt - isec);
-
-    t.it_interval.tv_sec = isec;
-    t.it_interval.tv_usec = usec;
-    t.it_value.tv_sec = isec;
-    t.it_value.tv_usec = usec;
-    // printf("fgTimerInit() called\n");
-    fgTimerCatch(0);   // set up for SIGALRM signal catch
-    terr = setitimer( ITIMER_REAL, &t, &ot );
-    if (terr) {
-	printf("Error returned from setitimer");
-	exit(0);
-    }
-}
-#endif // HAVE_SETITIMER
-
-
-// This function returns the number of microseconds since the last
-// time it was called.
-int fgGetTimeInterval( void ) {
-    int interval;
-    static int inited = 0;
-    static SGTimeStamp last;
-    SGTimeStamp current;
-
-    
-    if ( ! inited ) {
-	inited = 1;
-	last.stamp();
-	interval = 0;
-    } else {
-        current.stamp();
-	interval = (current - last).toUSecs();
-	last = current;
-    }
-
-    return interval;
-}
-
-
diff --git a/src/Time/fg_timer.hxx b/src/Time/fg_timer.hxx
deleted file mode 100644
index dd37fb6e2..000000000
--- a/src/Time/fg_timer.hxx
+++ /dev/null
@@ -1,47 +0,0 @@
-// fg_timer.hxx -- time handling routines
-//
-// Written by Curtis Olson, started June 1997.
-//
-// Copyright (C) 1997  Curtis L. Olson  - http://www.flightgear.org/~curt
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// $Id$
-
-
-#ifndef _FG_TIMER_HXX
-#define _FG_TIMER_HXX
-
-
-#ifndef __cplusplus                                                          
-# error This library requires C++
-#endif                                   
-
-
-extern unsigned long int fgSimTime;
-
-// this routine initializes the interval timer to generate a SIGALRM
-// after the specified interval (dt) the function f() will be called
-// at each signal
-void fgTimerInit( float dt, void (*f)( int ) );
-
-// This function returns the number of milleseconds since the last
-// time it was called.
-int fgGetTimeInterval( void );
-
-
-#endif // _FG_TIMER_HXX
-
-