1
0
Fork 0

replay system: allow to resume simulation at any point of replay-time.

Currently supported for YASim only.
This commit is contained in:
ThorstenB 2011-10-09 19:46:49 +02:00
parent 9022c6a58d
commit 8b05d7b211
6 changed files with 78 additions and 48 deletions

View file

@ -31,7 +31,6 @@
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <FDM/fdm_shell.hxx>
#include "replay.hxx" #include "replay.hxx"
#include "flightrecorder.hxx" #include "flightrecorder.hxx"
@ -235,43 +234,52 @@ FGReplay::update( double dt )
if ( disable_replay->getBoolValue() ) if ( disable_replay->getBoolValue() )
{ {
current_replay_state = replay_master->getIntValue(); if (fgGetBool("/sim/freeze/master",false)||
replay_master->setIntValue(0); fgGetBool("/sim/freeze/clock",false))
replay_time->setDoubleValue(0); {
replay_time_str->setStringValue(""); fgSetBool("/sim/freeze/master",false);
disable_replay->setBoolValue(0); fgSetBool("/sim/freeze/clock",false);
speed_up->setDoubleValue(1.0); last_replay_state = 1;
fgSetString("/sim/messages/copilot", "Replay stopped"); }
else
if ((replay_master->getIntValue() != 3)||
(last_replay_state == 3))
{
current_replay_state = replay_master->getIntValue();
replay_master->setIntValue(0);
replay_time->setDoubleValue(0);
replay_time_str->setStringValue("");
disable_replay->setBoolValue(0);
speed_up->setDoubleValue(1.0);
speed_up->setDoubleValue(1.0);
if (fgGetBool("/sim/replay/mute",false))
{
fgSetBool("/sim/sound/enabled",true);
fgSetBool("/sim/replay/mute",false);
}
fgSetString("/sim/messages/copilot", "Replay stopped. Your controls!");
}
} }
int replay_state = replay_master->getIntValue(); 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)&& if ((replay_state == 0)&&
(last_replay_state > 0)) (last_replay_state > 0))
{ {
if (current_replay_state == 3) if (current_replay_state == 3)
{ {
// "my controls!" requested: pilot takes control at current replay position... // take control at current replay position ("My controls!").
// May need to uncrash the aircraft here :) // May need to uncrash the aircraft here :)
fgSetBool("/sim/crashed", false); fgSetBool("/sim/crashed", false);
} }
else else
{ {
// replay was active, restore most recent frame // normal replay exit, restore most recent frame
replay(DBL_MAX); replay(DBL_MAX);
} }
// replay is finished, resume FDM
((FDMShell*) globals->get_subsystem("flight"))->getFDM()->resume(); // replay is finished
last_replay_state = replay_state;
return;
} }
// remember recent state // remember recent state
@ -282,7 +290,8 @@ FGReplay::update( double dt )
case 0: case 0:
// replay inactive, keep recording // replay inactive, keep recording
break; break;
case 1: case 1: // normal replay
case 3: // prepare to resume normal flight at current replay position
{ {
// replay active // replay active
double current_time = replay_time->getDoubleValue(); double current_time = replay_time->getDoubleValue();
@ -312,8 +321,6 @@ FGReplay::update( double dt )
return; // don't record the replay session return; // don't record the replay session
} }
case 2: // normal replay operation case 2: // normal replay operation
case 3: // replay operation, prepare to resume normal flight at current replay position
// replay paused, no-op
return; // don't record the replay session return; // don't record the replay session
default: default:
throw sg_range_exception("unknown FGReplay state"); throw sg_range_exception("unknown FGReplay state");

View file

@ -284,16 +284,20 @@ void Gear::calcForce(RigidBody* body, State *s, float* v, float* rot)
// Don't bother if it's not down // Don't bother if it's not down
if(_extension < 1) if(_extension < 1)
return; {
_wow = 0;
_frac = 0;
return;
}
// Dont bother if we are in the "wrong" ground // Dont bother if we are in the "wrong" ground
if (!((_onWater&&!_ground_isSolid)||(_onSolid&&_ground_isSolid))) { if (!((_onWater&&!_ground_isSolid)||(_onSolid&&_ground_isSolid))) {
_wow = 0; _wow = 0;
_frac = 0; _frac = 0;
_compressDist = 0; _compressDist = 0;
_rollSpeed = 0; _rollSpeed = 0;
_casterAngle = 0; _casterAngle = 0;
return; return;
} }
// The ground plane transformed to the local frame. // The ground plane transformed to the local frame.

View file

@ -195,9 +195,10 @@ void YASim::update(double dt)
int iterations = _calc_multiloop(dt); int iterations = _calc_multiloop(dt);
// If we're crashed, then we don't care // If we're crashed, then we don't care
if(_fdm->getAirplane()->getModel()->isCrashed()) { if(fgGetBool("/sim/crashed") || _fdm->getAirplane()->getModel()->isCrashed()) {
if(!fgGetBool("/sim/crashed")) if(!fgGetBool("/sim/crashed"))
fgSetBool("/sim/crashed", true); fgSetBool("/sim/crashed", true);
_fdm->getAirplane()->getModel()->setCrashed(false);
return; return;
} }
@ -311,7 +312,7 @@ void YASim::copyToYASim(bool copyState)
Math::set3(v, s.v); Math::set3(v, s.v);
if(copyState || needCopy) if(copyState || needCopy)
model->setState(&s); model->setState(&s);
// wind // wind
Math::tmul33(xyz2ned, wind, wind); Math::tmul33(xyz2ned, wind, wind);
@ -505,3 +506,19 @@ void YASim::copyFromYASim()
} }
} }
/** Reinit the FDM.
* This is only used after a replay session and when the user requested to resume at
* a past point of time. In thise case the FDM must reload all values from the property
* tree (as given by the replay system). */
void YASim::reinit()
{
// Process inputs. Use excessive value for dt to make sure all transition effects
// have reached their final state (i.e. gear is extended/retracted) - which is vital
// for many properties to be complete before the first FDM run (otherwise the gear may
// still be up, thrust-reversers/speed-brakes/... may still be partially deployed...).
_fdm->getExternalInput(1000);
// get current FDM values from the property tree
copyToYASim(true);
}

View file

@ -13,6 +13,7 @@ public:
// Load externally set stuff into the FDM // Load externally set stuff into the FDM
virtual void init(); virtual void init();
virtual void bind(); virtual void bind();
virtual void reinit();
// Run an iteration // Run an iteration
virtual void update(double dt); virtual void update(double dt);

View file

@ -81,6 +81,7 @@ void FDMShell::init()
_pressure_inhg = _props->getNode("environment/pressure-inhg", true); _pressure_inhg = _props->getNode("environment/pressure-inhg", true);
_density_slugft = _props->getNode("environment/density-slugft3", true); _density_slugft = _props->getNode("environment/density-slugft3", true);
_data_logging = _props->getNode("/sim/temp/fdm-data-logging", true); _data_logging = _props->getNode("/sim/temp/fdm-data-logging", true);
_replay_master = _props->getNode("/sim/freeze/replay-state", true);
createImplementation(); createImplementation();
} }
@ -170,8 +171,20 @@ void FDMShell::update(double dt)
_impl->ToggleDataLogging(doLog); _impl->ToggleDataLogging(doLog);
} }
if (!_impl->is_suspended()) switch(_replay_master->getIntValue())
_impl->update(dt); {
case 0:
// normal FDM operation
_impl->update(dt);
break;
case 3:
// resume FDM operation at current replay position
_impl->reinit();
break;
default:
// replay is active
break;
}
} }
void FDMShell::createImplementation() void FDMShell::createImplementation()
@ -261,14 +274,3 @@ 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;
}

View file

@ -41,7 +41,7 @@ class FDMShell : public SGSubsystem
{ {
public: public:
FDMShell(); FDMShell();
~FDMShell(); virtual ~FDMShell();
virtual void init(); virtual void init();
virtual void reinit(); virtual void reinit();
@ -50,7 +50,6 @@ public:
virtual void unbind(); virtual void unbind();
virtual void update(double dt); virtual void update(double dt);
SGSubsystem* getFDM();
private: private:
@ -63,7 +62,7 @@ private:
SGPropertyNode_ptr _wind_north, _wind_east,_wind_down; SGPropertyNode_ptr _wind_north, _wind_east,_wind_down;
SGPropertyNode_ptr _control_fdm_atmo,_temp_degc,_pressure_inhg; SGPropertyNode_ptr _control_fdm_atmo,_temp_degc,_pressure_inhg;
SGPropertyNode_ptr _density_slugft, _data_logging; SGPropertyNode_ptr _density_slugft, _data_logging, _replay_master;
}; };
#endif // of FG_FDM_SHELL_HXX #endif // of FG_FDM_SHELL_HXX