replay system: allow to resume simulation at any point of replay-time.
Currently supported for YASim only.
This commit is contained in:
parent
9022c6a58d
commit
8b05d7b211
6 changed files with 78 additions and 48 deletions
|
@ -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");
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue