]> git.mxchange.org Git - flightgear.git/blobdiff - src/Aircraft/replay.cxx
Improve timing statistics
[flightgear.git] / src / Aircraft / replay.cxx
index 1794decb615fd9cb2c89421cbf4bf6e41430c440..538546c81087faa5fde5a2203c60fcfd1a56fb66 100644 (file)
 #endif
 
 #include <simgear/constants.h>
+#include <simgear/structure/exception.hxx>
 
-#include <FDM/flight.hxx>
 #include <Main/fg_props.hxx>
 #include <Network/native_ctrls.hxx>
 #include <Network/native_fdm.hxx>
 #include <Network/net_ctrls.hxx>
 #include <Network/net_fdm.hxx>
+#include <FDM/fdm_shell.hxx>
 
 #include "replay.hxx"
 
@@ -47,7 +48,9 @@ const double FGReplay::lt_dt = 5.0; // long term sample rate (sec)
  * Constructor
  */
 
-FGReplay::FGReplay() {
+FGReplay::FGReplay() :
+    last_replay_state(0)
+{
 }
 
 
@@ -55,39 +58,82 @@ FGReplay::FGReplay() {
  * Destructor
  */
 
-FGReplay::~FGReplay() {
-    // no dynamically allocated memory to free
+FGReplay::~FGReplay()
+{
+    clear();
 }
 
+/**
+ * Clear all internal buffers.
+ */
+void FGReplay::clear()
+{
+    while ( !short_term.empty() )
+    {
+        delete short_term.front();
+        short_term.pop_front();
+    }
+    while ( !medium_term.empty() )
+    {
+        delete medium_term.front();
+        medium_term.pop_front();
+    }
+    while ( !long_term.empty() )
+    {
+        delete long_term.front();
+        long_term.pop_front();
+    }
+    while ( !recycler.empty() )
+    {
+        delete recycler.front();
+        recycler.pop_front();
+    }
+}
 
 /** 
  * Initialize the data structures
  */
 
-void FGReplay::init() {
+void FGReplay::init()
+{
+    disable_replay = fgGetNode( "/sim/replay/disable", true );
+    replay_master = fgGetNode( "/sim/freeze/replay-state", true );
+    replay_time = fgGetNode( "/sim/replay/time", true);
+    reinit();
+}
+
+/** 
+ * Reset replay queues.
+ */
+
+void FGReplay::reinit()
+{
     sim_time = 0.0;
     last_mt_time = 0.0;
     last_lt_time = 0.0;
 
     // Make sure all queues are flushed
-    while ( !short_term.empty() ) {
-        short_term.pop_front();
-    }
-    while ( !medium_term.empty() ) {
-        medium_term.pop_front();
-    }
-    while ( !medium_term.empty() ) {
-        medium_term.pop_front();
+    clear();
+
+    // Create an estimated nr of required ReplayData objects
+    // 120 is an estimated maximum frame rate. 
+    int estNrObjects = (int) ((st_list_time*120) + (mt_list_time*mt_dt) +
+                             (lt_list_time*lt_dt)); 
+    for (int i = 0; i < estNrObjects; i++)
+    {
+        recycler.push_back(new FGReplayData);
     }
+    replay_master->setIntValue(0);
+    disable_replay->setBoolValue(0);
+    replay_time->setDoubleValue(0);
 }
 
-
 /** 
  * Bind to the property tree
  */
 
-void FGReplay::bind() {
-    disable_replay = fgGetNode( "/sim/replay/disable", true );
+void FGReplay::bind()
+{
 }
 
 
@@ -95,7 +141,8 @@ void FGReplay::bind() {
  *  Unbind from the property tree
  */
 
-void FGReplay::unbind() {
+void FGReplay::unbind()
+{
     // nothing to unbind
 }
 
@@ -104,73 +151,135 @@ void FGReplay::unbind() {
  *  Update the saved data
  */
 
-void FGReplay::update( double dt ) {
-    static SGPropertyNode *replay_master
-        = fgGetNode( "/sim/freeze/replay", true );
+void FGReplay::update( double dt )
+{
+    timingInfo.clear();
+    stamp("begin");
+
+    if (( sim_time != 0.0 )&&
+        ( disable_replay->getBoolValue() ))
+    {
+        // we were recording data
+        reinit();
+    }
+
+    int replay_state = replay_master->getIntValue();
 
-    if( disable_replay->getBoolValue() ) {
-        if( sim_time != 0.0 ) {
-            // we were recording data
-            init();
-        }
-        return;
+    if ((replay_state > 0)&&
+       (last_replay_state == 0))
+    {
+        // replay is starting, suspend FDM
+        /* FIXME we need to suspend/resume the FDM - not the entire FDM shell.
+         * FDM isn't available via the global subsystem manager yet, so need a
+         * method at the FDMshell for now */
+        ((FDMShell*) globals->get_subsystem("flight"))->getFDM()->suspend();
+    }
+    else
+    if ((replay_state == 0)&&
+        (last_replay_state > 0))
+    {
+        // replay is finished, resume FDM
+        ((FDMShell*) globals->get_subsystem("flight"))->getFDM()->resume();
     }
 
-    if ( replay_master->getBoolValue() ) {
-        // don't record the replay session
-        return;
+    // remember recent state
+    last_replay_state = replay_state;
+
+    switch(replay_state)
+    {
+        case 0:
+            // replay inactive, keep recording
+            break;
+        case 1:
+            // replay active
+            replay( replay_time->getDoubleValue() );
+            replay_time->setDoubleValue( replay_time->getDoubleValue()
+                                         + ( dt * fgGetInt("/sim/speed-up") ) );
+            return; // don't record the replay session 
+        case 2:
+            // replay paused, no-op
+            return; // don't record the replay session
+        default:
+            throw sg_range_exception("unknown FGReplay state");
     }
 
+    // flight recording
+
+    //cerr << "Recording replay" << endl;
     sim_time += dt;
 
     // build the replay record
-    FGNetFDM f;
-    FGProps2NetFDM( &f, false );
+    //FGNetFDM f;
+    //FGProps2NetFDM( &f, false );
 
     // sanity check, don't collect data if FDM data isn't good
-    if ( !cur_fdm_state->get_inited() ) {
+    if (!fgGetBool("/sim/fdm-initialized", false)) {
         return;
     }
+    
+    //FGNetCtrls c;
+    //FGProps2NetCtrls( &c, false, false );
+    //stamp("point_04ba");
+    FGReplayData *r;
+    //stamp("point_04bb");
+    if (!recycler.size()) {
+        stamp("Replay_01");
+        r = new FGReplayData;
+        stamp("Replay_02");
+    } else {
+        r = recycler.front();
+        recycler.pop_front();
+        //stamp("point_04be");
+    }
 
-    FGNetCtrls c;
-    FGProps2NetCtrls( &c, false, false );
-
-    FGReplayData r;
-    r.sim_time = sim_time;
-    r.ctrls = c;
-    r.fdm = f;
+    r->sim_time = sim_time;
+    //r->ctrls = c;
+    //stamp("point_04e");
+    FGProps2NetFDM( &(r->fdm), false );
+    FGProps2NetCtrls( &(r->ctrls), false, false );
+    //r->fdm = f;
+    //stamp("point_05");
 
     // update the short term list
+    //stamp("point_06");
     short_term.push_back( r );
-
-    FGReplayData st_front = short_term.front();
-    if ( sim_time - st_front.sim_time > st_list_time ) {
-        while ( sim_time - st_front.sim_time > st_list_time ) {
+    //stamp("point_07");
+    FGReplayData *st_front = short_term.front();
+    if ( sim_time - st_front->sim_time > st_list_time ) {
+        while ( sim_time - st_front->sim_time > st_list_time ) {
             st_front = short_term.front();
+            recycler.push_back(st_front);
             short_term.pop_front();
         }
-
+        //stamp("point_08");
         // update the medium term list
         if ( sim_time - last_mt_time > mt_dt ) {
             last_mt_time = sim_time;
+            st_front = short_term.front();
             medium_term.push_back( st_front );
+            short_term.pop_front();
 
-            FGReplayData mt_front = medium_term.front();
-            if ( sim_time - mt_front.sim_time > mt_list_time ) {
-                while ( sim_time - mt_front.sim_time > mt_list_time ) {
+            FGReplayData *mt_front = medium_term.front();
+            if ( sim_time - mt_front->sim_time > mt_list_time ) {
+            //stamp("point_09");
+                while ( sim_time - mt_front->sim_time > mt_list_time ) {
                     mt_front = medium_term.front();
+                    recycler.push_back(mt_front);
                     medium_term.pop_front();
                 }
-
                 // update the long term list
                 if ( sim_time - last_lt_time > lt_dt ) {
                     last_lt_time = sim_time;
+                    mt_front = medium_term.front();
                     long_term.push_back( mt_front );
+                    medium_term.pop_front();
 
-                    FGReplayData lt_front = long_term.front();
-                    if ( sim_time - lt_front.sim_time > lt_list_time ) {
-                        while ( sim_time - lt_front.sim_time > lt_list_time ) {
+                    FGReplayData *lt_front = long_term.front();
+                    if ( sim_time - lt_front->sim_time > lt_list_time ) {
+                       //stamp("point_10");
+                        while ( sim_time - lt_front->sim_time > lt_list_time ) {
                             lt_front = long_term.front();
+                            recycler.push_back(lt_front);
                             long_term.pop_front();
                         }
                     }
@@ -190,6 +299,7 @@ void FGReplay::update( double dt ) {
          << "  time = " << sim_time - long_term.front().sim_time
          << endl;
 #endif
+   //stamp("point_finished");
 }
 
 
@@ -278,6 +388,8 @@ static FGReplayData interpolate( double time, FGReplayData f1, FGReplayData f2 )
         result.fdm.rpm[i] = weight( fdm1.rpm[i], fdm2.rpm[i], ratio );
         result.fdm.fuel_flow[i]
             = weight( fdm1.fuel_flow[i], fdm2.fuel_flow[i], ratio );
+        result.fdm.fuel_px[i]
+            = weight( fdm1.fuel_px[i], fdm2.fuel_px[i], ratio );
         result.fdm.egt[i] = weight( fdm1.egt[i], fdm2.egt[i], ratio );
         result.fdm.cht[i] = weight( fdm1.cht[i], fdm2.cht[i], ratio );
         result.fdm.mp_osi[i] = weight( fdm1.mp_osi[i], fdm2.mp_osi[i], ratio );
@@ -407,7 +519,7 @@ static void interpolate( double time, const replay_list_type &list ) {
         return;
     } else if ( list.size() == 1 ) {
         // handle list size == 1
-        update_fdm( list[0] );
+        update_fdm( (*list[0]) );
         return;
     }
 
@@ -421,11 +533,11 @@ static void interpolate( double time, const replay_list_type &list ) {
         // cout << "  " << first << " <=> " << last << endl;
         if ( last == first ) {
             done = true;
-        } else if ( list[mid].sim_time < time && list[mid+1].sim_time < time ) {
+        } else if ( list[mid]->sim_time < time && list[mid+1]->sim_time < time ) {
             // too low
             first = mid;
             mid = ( last + first ) / 2;
-        } else if ( list[mid].sim_time > time && list[mid+1].sim_time > time ) {
+        } else if ( list[mid]->sim_time > time && list[mid+1]->sim_time > time ) {
             // too high
             last = mid;
             mid = ( last + first ) / 2;
@@ -434,7 +546,7 @@ static void interpolate( double time, const replay_list_type &list ) {
         }
     }
 
-    FGReplayData result = interpolate( time, list[mid], list[mid+1] );
+    FGReplayData result = interpolate( time, (*list[mid]), (*list[mid+1]) );
 
     update_fdm( result );
 }
@@ -451,60 +563,60 @@ void FGReplay::replay( double time ) {
     double t1, t2;
 
     if ( short_term.size() > 0 ) {
-        t1 = short_term.back().sim_time;
-        t2 = short_term.front().sim_time;
+        t1 = short_term.back()->sim_time;
+        t2 = short_term.front()->sim_time;
         if ( time > t1 ) {
             // replay the most recent frame
-            update_fdm( short_term.back() );
+            update_fdm( (*short_term.back()) );
             // cout << "first frame" << endl;
         } else if ( time <= t1 && time >= t2 ) {
             interpolate( time, short_term );
             // cout << "from short term" << endl;
         } else if ( medium_term.size() > 0 ) {
-            t1 = short_term.front().sim_time;
-            t2 = medium_term.back().sim_time;
+            t1 = short_term.front()->sim_time;
+            t2 = medium_term.back()->sim_time;
             if ( time <= t1 && time >= t2 ) {
                 FGReplayData result = interpolate( time,
-                                                   medium_term.back(),
-                                                   short_term.front() );
+                                                   (*medium_term.back()),
+                                                   (*short_term.front()) );
                 update_fdm( result );
                 // cout << "from short/medium term" << endl;
             } else {
-                t1 = medium_term.back().sim_time;
-                t2 = medium_term.front().sim_time;
+                t1 = medium_term.back()->sim_time;
+                t2 = medium_term.front()->sim_time;
                 if ( time <= t1 && time >= t2 ) {
                     interpolate( time, medium_term );
                     // cout << "from medium term" << endl;
                 } else if ( long_term.size() > 0 ) {
-                    t1 = medium_term.front().sim_time;
-                    t2 = long_term.back().sim_time;
+                    t1 = medium_term.front()->sim_time;
+                    t2 = long_term.back()->sim_time;
                     if ( time <= t1 && time >= t2 ) {
                         FGReplayData result = interpolate( time,
-                                                           long_term.back(),
-                                                           medium_term.front());
+                                                           (*long_term.back()),
+                                                           (*medium_term.front()));
                         update_fdm( result );
                         // cout << "from medium/long term" << endl;
                     } else {
-                        t1 = long_term.back().sim_time;
-                        t2 = long_term.front().sim_time;
+                        t1 = long_term.back()->sim_time;
+                        t2 = long_term.front()->sim_time;
                         if ( time <= t1 && time >= t2 ) {
                             interpolate( time, long_term );
                             // cout << "from long term" << endl;
                         } else {
                             // replay the oldest long term frame
-                            update_fdm( long_term.front() );
+                            update_fdm( (*long_term.front()) );
                             // cout << "oldest long term frame" << endl;
                         }
                     }
                 } else {
                     // replay the oldest medium term frame
-                    update_fdm( medium_term.front() );
+                    update_fdm( (*medium_term.front()) );
                     // cout << "oldest medium term frame" << endl;
                 }
             }
         } else {
             // replay the oldest short term frame
-            update_fdm( short_term.front() );
+            update_fdm( (*short_term.front()) );
             // cout << "oldest short term frame" << endl;
         }
     } else {
@@ -515,11 +627,11 @@ void FGReplay::replay( double time ) {
 
 double FGReplay::get_start_time() {
     if ( long_term.size() > 0 ) {
-        return long_term.front().sim_time;
+        return (*long_term.front()).sim_time;
     } else if ( medium_term.size() > 0 ) {
-        return medium_term.front().sim_time;
+        return (*medium_term.front()).sim_time;
     } else if ( short_term.size() ) {
-        return short_term.front().sim_time;
+        return (*short_term.front()).sim_time;
     } else {
         return 0.0;
     }
@@ -527,7 +639,7 @@ double FGReplay::get_start_time() {
 
 double FGReplay::get_end_time() {
     if ( short_term.size() ) {
-        return short_term.back().sim_time;
+        return (*short_term.back()).sim_time;
     } else {
         return 0.0;
     }