From 8b05d7b2111aac07e048eed65433a2bb0ef37e1d Mon Sep 17 00:00:00 2001 From: ThorstenB Date: Sun, 9 Oct 2011 19:46:49 +0200 Subject: [PATCH] replay system: allow to resume simulation at any point of replay-time. Currently supported for YASim only. --- src/Aircraft/replay.cxx | 59 +++++++++++++++++++++++------------------ src/FDM/YASim/Gear.cpp | 12 ++++++--- src/FDM/YASim/YASim.cxx | 21 +++++++++++++-- src/FDM/YASim/YASim.hxx | 1 + src/FDM/fdm_shell.cxx | 28 ++++++++++--------- src/FDM/fdm_shell.hxx | 5 ++-- 6 files changed, 78 insertions(+), 48 deletions(-) diff --git a/src/Aircraft/replay.cxx b/src/Aircraft/replay.cxx index 8dd04d871..7ef44c202 100644 --- a/src/Aircraft/replay.cxx +++ b/src/Aircraft/replay.cxx @@ -31,7 +31,6 @@ #include #include
-#include #include "replay.hxx" #include "flightrecorder.hxx" @@ -235,43 +234,52 @@ FGReplay::update( double dt ) if ( disable_replay->getBoolValue() ) { - 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); - fgSetString("/sim/messages/copilot", "Replay stopped"); + if (fgGetBool("/sim/freeze/master",false)|| + fgGetBool("/sim/freeze/clock",false)) + { + fgSetBool("/sim/freeze/master",false); + fgSetBool("/sim/freeze/clock",false); + last_replay_state = 1; + } + 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(); - - 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)) { 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 :) fgSetBool("/sim/crashed", false); } else { - // replay was active, restore most recent frame + // normal replay exit, restore most recent frame 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 @@ -282,7 +290,8 @@ FGReplay::update( double dt ) case 0: // replay inactive, keep recording break; - case 1: + case 1: // normal replay + case 3: // prepare to resume normal flight at current replay position { // replay active double current_time = replay_time->getDoubleValue(); @@ -312,8 +321,6 @@ FGReplay::update( double dt ) return; // don't record the replay session } 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 default: throw sg_range_exception("unknown FGReplay state"); diff --git a/src/FDM/YASim/Gear.cpp b/src/FDM/YASim/Gear.cpp index ce2517c73..b4c7673cb 100644 --- a/src/FDM/YASim/Gear.cpp +++ b/src/FDM/YASim/Gear.cpp @@ -284,16 +284,20 @@ void Gear::calcForce(RigidBody* body, State *s, float* v, float* rot) // Don't bother if it's not down if(_extension < 1) - return; + { + _wow = 0; + _frac = 0; + return; + } // Dont bother if we are in the "wrong" ground if (!((_onWater&&!_ground_isSolid)||(_onSolid&&_ground_isSolid))) { - _wow = 0; - _frac = 0; + _wow = 0; + _frac = 0; _compressDist = 0; _rollSpeed = 0; _casterAngle = 0; - return; + return; } // The ground plane transformed to the local frame. diff --git a/src/FDM/YASim/YASim.cxx b/src/FDM/YASim/YASim.cxx index 95261df55..35495f119 100644 --- a/src/FDM/YASim/YASim.cxx +++ b/src/FDM/YASim/YASim.cxx @@ -195,9 +195,10 @@ void YASim::update(double dt) int iterations = _calc_multiloop(dt); // 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")) fgSetBool("/sim/crashed", true); + _fdm->getAirplane()->getModel()->setCrashed(false); return; } @@ -311,7 +312,7 @@ void YASim::copyToYASim(bool copyState) Math::set3(v, s.v); if(copyState || needCopy) - model->setState(&s); + model->setState(&s); // 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); +} diff --git a/src/FDM/YASim/YASim.hxx b/src/FDM/YASim/YASim.hxx index 2e8f77732..eb67cadec 100644 --- a/src/FDM/YASim/YASim.hxx +++ b/src/FDM/YASim/YASim.hxx @@ -13,6 +13,7 @@ public: // Load externally set stuff into the FDM virtual void init(); virtual void bind(); + virtual void reinit(); // Run an iteration virtual void update(double dt); diff --git a/src/FDM/fdm_shell.cxx b/src/FDM/fdm_shell.cxx index faa37d788..f06303e20 100644 --- a/src/FDM/fdm_shell.cxx +++ b/src/FDM/fdm_shell.cxx @@ -81,6 +81,7 @@ void FDMShell::init() _pressure_inhg = _props->getNode("environment/pressure-inhg", true); _density_slugft = _props->getNode("environment/density-slugft3", true); _data_logging = _props->getNode("/sim/temp/fdm-data-logging", true); + _replay_master = _props->getNode("/sim/freeze/replay-state", true); createImplementation(); } @@ -170,8 +171,20 @@ void FDMShell::update(double dt) _impl->ToggleDataLogging(doLog); } - if (!_impl->is_suspended()) - _impl->update(dt); + switch(_replay_master->getIntValue()) + { + 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() @@ -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; -} diff --git a/src/FDM/fdm_shell.hxx b/src/FDM/fdm_shell.hxx index 293796c76..3979067e1 100644 --- a/src/FDM/fdm_shell.hxx +++ b/src/FDM/fdm_shell.hxx @@ -41,7 +41,7 @@ class FDMShell : public SGSubsystem { public: FDMShell(); - ~FDMShell(); + virtual ~FDMShell(); virtual void init(); virtual void reinit(); @@ -50,7 +50,6 @@ public: virtual void unbind(); virtual void update(double dt); - SGSubsystem* getFDM(); private: @@ -63,7 +62,7 @@ private: SGPropertyNode_ptr _wind_north, _wind_east,_wind_down; 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