replay/FDM shell subsystem refactoring
Move final bits of replay code to where it belongs. Use subsystem suspend/resume for FDM shell during instant replay.
This commit is contained in:
parent
b6d70d2c71
commit
991beb0b5e
4 changed files with 112 additions and 71 deletions
|
@ -25,12 +25,14 @@
|
|||
#endif
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/structure/exception.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"
|
||||
|
||||
|
@ -46,7 +48,9 @@ const double FGReplay::lt_dt = 5.0; // long term sample rate (sec)
|
|||
* Constructor
|
||||
*/
|
||||
|
||||
FGReplay::FGReplay() {
|
||||
FGReplay::FGReplay() :
|
||||
last_replay_state(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,35 +58,44 @@ FGReplay::FGReplay() {
|
|||
* Destructor
|
||||
*/
|
||||
|
||||
FGReplay::~FGReplay() {
|
||||
while ( !short_term.empty() ) {
|
||||
//cerr << "Deleting Short term" <<endl;
|
||||
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() ) {
|
||||
//cerr << "Deleting Medium term" <<endl;
|
||||
delete medium_term.front();
|
||||
while ( !medium_term.empty() )
|
||||
{
|
||||
delete medium_term.front();
|
||||
medium_term.pop_front();
|
||||
}
|
||||
while ( !long_term.empty() ) {
|
||||
//cerr << "Deleting Long term" <<endl;
|
||||
delete long_term.front();
|
||||
while ( !long_term.empty() )
|
||||
{
|
||||
delete long_term.front();
|
||||
long_term.pop_front();
|
||||
}
|
||||
while ( !recycler.empty() ) {
|
||||
//cerr << "Deleting Recycler" <<endl;
|
||||
delete recycler.front();
|
||||
while ( !recycler.empty() )
|
||||
{
|
||||
delete recycler.front();
|
||||
recycler.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the data structures
|
||||
*/
|
||||
|
||||
void FGReplay::init() {
|
||||
void FGReplay::init()
|
||||
{
|
||||
reinit();
|
||||
}
|
||||
|
||||
|
@ -90,33 +103,21 @@ void FGReplay::init() {
|
|||
* Reset replay queues.
|
||||
*/
|
||||
|
||||
void FGReplay::reinit() {
|
||||
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() ) {
|
||||
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();
|
||||
}
|
||||
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++) {
|
||||
for (int i = 0; i < estNrObjects; i++)
|
||||
{
|
||||
recycler.push_back(new FGReplayData);
|
||||
}
|
||||
}
|
||||
|
@ -125,9 +126,11 @@ void FGReplay::reinit() {
|
|||
* Bind to the property tree
|
||||
*/
|
||||
|
||||
void FGReplay::bind() {
|
||||
void FGReplay::bind()
|
||||
{
|
||||
disable_replay = fgGetNode( "/sim/replay/disable", true );
|
||||
replay_master = fgGetNode( "/sim/freeze/replay-state", true );
|
||||
replay_time = fgGetNode( "/sim/replay/time", true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -135,7 +138,8 @@ void FGReplay::bind() {
|
|||
* Unbind from the property tree
|
||||
*/
|
||||
|
||||
void FGReplay::unbind() {
|
||||
void FGReplay::unbind()
|
||||
{
|
||||
// nothing to unbind
|
||||
}
|
||||
|
||||
|
@ -144,22 +148,60 @@ void FGReplay::unbind() {
|
|||
* Update the saved data
|
||||
*/
|
||||
|
||||
void FGReplay::update( double dt ) {
|
||||
void FGReplay::update( double dt )
|
||||
{
|
||||
timingInfo.clear();
|
||||
stamp("begin");
|
||||
|
||||
if( disable_replay->getBoolValue() ) {
|
||||
if ( sim_time != 0.0 ) {
|
||||
// we were recording data
|
||||
init();
|
||||
}
|
||||
return;
|
||||
if (( sim_time != 0.0 )&&
|
||||
( disable_replay->getBoolValue() ))
|
||||
{
|
||||
// we were recording data
|
||||
reinit();
|
||||
}
|
||||
//stamp("point_01");
|
||||
if ( replay_master->getIntValue() > 0 ) {
|
||||
// don't record the replay session
|
||||
return;
|
||||
|
||||
int replay_state = replay_master->getIntValue();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -180,12 +222,13 @@ void FGReplay::update( double dt ) {
|
|||
if (!recycler.size()) {
|
||||
stamp("Replay_01");
|
||||
r = new FGReplayData;
|
||||
stamp("Replay_02");
|
||||
stamp("Replay_02");
|
||||
} else {
|
||||
r = recycler.front();
|
||||
recycler.pop_front();
|
||||
//stamp("point_04be");
|
||||
r = recycler.front();
|
||||
recycler.pop_front();
|
||||
//stamp("point_04be");
|
||||
}
|
||||
|
||||
r->sim_time = sim_time;
|
||||
//r->ctrls = c;
|
||||
//stamp("point_04e");
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
double get_end_time();
|
||||
|
||||
private:
|
||||
void clear();
|
||||
|
||||
static const double st_list_time; // 60 secs of high res data
|
||||
static const double mt_list_time; // 10 mins of 1 fps data
|
||||
|
@ -91,6 +92,7 @@ private:
|
|||
double sim_time;
|
||||
double last_mt_time;
|
||||
double last_lt_time;
|
||||
int last_replay_state;
|
||||
|
||||
replay_list_type short_term;
|
||||
replay_list_type medium_term;
|
||||
|
@ -98,6 +100,7 @@ private:
|
|||
replay_list_type recycler;
|
||||
SGPropertyNode_ptr disable_replay;
|
||||
SGPropertyNode_ptr replay_master;
|
||||
SGPropertyNode_ptr replay_time;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -139,8 +139,8 @@ void FDMShell::update(double dt)
|
|||
// pull environmental data in, since the FDMs are lazy
|
||||
_impl->set_Velocities_Local_Airmass(
|
||||
_props->getDoubleValue("environment/wind-from-north-fps", 0.0),
|
||||
_props->getDoubleValue("environment/wind-from-east-fps", 0.0),
|
||||
_props->getDoubleValue("environment/wind-from-down-fps", 0.0));
|
||||
_props->getDoubleValue("environment/wind-from-east-fps", 0.0),
|
||||
_props->getDoubleValue("environment/wind-from-down-fps", 0.0));
|
||||
|
||||
if (_props->getBoolValue("environment/params/control-fdm-atmosphere")) {
|
||||
// convert from Rankine to Celsius
|
||||
|
@ -160,24 +160,8 @@ void FDMShell::update(double dt)
|
|||
_impl->ToggleDataLogging(doLog);
|
||||
}
|
||||
|
||||
// FIXME - replay manager should handle most of this
|
||||
int replayState = fgGetInt("/sim/freeze/replay-state", 0);
|
||||
if (replayState == 0) {
|
||||
_impl->update(dt); // normal code path
|
||||
} else if (replayState == 1) {
|
||||
// should be inside FGReplay!
|
||||
SGPropertyNode* replay_time = fgGetNode("/sim/replay/time", true);
|
||||
FGReplay *r = (FGReplay *)(globals->get_subsystem( "replay" ));
|
||||
r->replay( replay_time->getDoubleValue() );
|
||||
replay_time->setDoubleValue( replay_time->getDoubleValue()
|
||||
+ ( dt
|
||||
* fgGetInt("/sim/speed-up") ) );
|
||||
|
||||
} else if (replayState == 2) {
|
||||
// paused replay, no-op
|
||||
} else {
|
||||
throw sg_range_exception("unknown FGReplay state");
|
||||
}
|
||||
if (!_impl->is_suspended())
|
||||
_impl->update(dt);
|
||||
}
|
||||
|
||||
void FDMShell::createImplementation()
|
||||
|
@ -268,3 +252,13 @@ void FDMShell::createImplementation()
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Return FDM subsystem.
|
||||
*/
|
||||
|
||||
SGSubsystem* FDMShell::getFDM()
|
||||
{
|
||||
/* FIXME we could drop/replace this method, when _impl was a added
|
||||
* to the global subsystem manager - like other proper subsystems... */
|
||||
return _impl;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ public:
|
|||
virtual void unbind();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
SGSubsystem* getFDM();
|
||||
|
||||
private:
|
||||
|
||||
void createImplementation();
|
||||
|
|
Loading…
Reference in a new issue