1
0
Fork 0
This commit is contained in:
Torsten Dreyer 2011-04-03 20:42:20 +02:00
commit 4a63946e94
27 changed files with 637 additions and 417 deletions

View file

@ -20,7 +20,7 @@
; C:\> subst X: /d ; C:\> subst X: /d
; ;
#define FGVER "v20110228" #define FGVER "v20110324"
[Setup] [Setup]
AppId=FlightGear {#FGVER} AppId=FlightGear {#FGVER}
@ -52,7 +52,7 @@ Name: "insoal"; Description: "Install OpenAL (the sound engine)"
; NOTE: run subst X: F:\ (or whatever path the expanded tree resides at) ; NOTE: run subst X: F:\ (or whatever path the expanded tree resides at)
Source: "X:\*.txt"; DestDir: "{app}"; Flags: ignoreversion Source: "X:\*.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "X:\bin\Win32\*.*"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion recursesubdirs Source: "X:\bin\Win32\*.*"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion recursesubdirs
Source: "X:\bin\vcredist_x86.exe"; DestDir: "{app}\bin"; Flags: ignoreversion ;;; Source: "X:\bin\vcredist_x86.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "X:\bin\oalinst.exe"; DestDir: "{app}\bin"; Flags: ignoreversion Source: "X:\bin\oalinst.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "X:\data\*.*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs Source: "X:\data\*.*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files ; NOTE: Don't use "Flags: ignoreversion" on any shared system files
@ -88,7 +88,7 @@ Name: "{group}\Tools\Explore Documentation Folder"; Filename: "{app}\data\Docs"
; Name: "{userdesktop}\FlightGear {#FGVER}"; Filename: "{app}\bin\Win32\fgfs.exe"; Parameters: "--fg-root=."; WorkingDir: "{app}"; Tasks: desktopicon ; Name: "{userdesktop}\FlightGear {#FGVER}"; Filename: "{app}\bin\Win32\fgfs.exe"; Parameters: "--fg-root=."; WorkingDir: "{app}"; Tasks: desktopicon
[Run] [Run]
Filename: "{app}\bin\vcredist_x86.exe"; WorkingDir: "{app}"; Parameters: "/qb!"; Description: "Installing Flightgear prerequisites" ;;; Filename: "{app}\bin\vcredist_x86.exe"; WorkingDir: "{app}"; Parameters: "/qb!"; Description: "Installing Flightgear prerequisites"
; Put installation directory into the fgrun.prefs ; Put installation directory into the fgrun.prefs
filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "--silent ""--fg-exe={app}\bin\Win32\fgfs.exe"" ""--ts-exe={app}\bin\Win32\terrasync.exe"" ""--fg-root={app}\data"" ""--fg-scenery={app}\data\Scenery;{app}\scenery;{code:TerrasyncDir}"" --ts-dir=3" filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "--silent ""--fg-exe={app}\bin\Win32\fgfs.exe"" ""--ts-exe={app}\bin\Win32\terrasync.exe"" ""--fg-root={app}\data"" ""--fg-scenery={app}\data\Scenery;{app}\scenery;{code:TerrasyncDir}"" --ts-dir=3"

View file

@ -24,13 +24,16 @@
# include "config.h" # include "config.h"
#endif #endif
#include <float.h>
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/structure/exception.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <Network/native_ctrls.hxx> #include <Network/native_ctrls.hxx>
#include <Network/native_fdm.hxx> #include <Network/native_fdm.hxx>
#include <Network/net_ctrls.hxx> #include <Network/net_ctrls.hxx>
#include <Network/net_fdm.hxx> #include <Network/net_fdm.hxx>
#include <FDM/fdm_shell.hxx>
#include "replay.hxx" #include "replay.hxx"
@ -46,7 +49,9 @@ const double FGReplay::lt_dt = 5.0; // long term sample rate (sec)
* Constructor * Constructor
*/ */
FGReplay::FGReplay() { FGReplay::FGReplay() :
last_replay_state(0)
{
} }
@ -54,73 +59,82 @@ FGReplay::FGReplay() {
* Destructor * Destructor
*/ */
FGReplay::~FGReplay() { FGReplay::~FGReplay()
while ( !short_term.empty() ) { {
//cerr << "Deleting Short term" <<endl; clear();
}
/**
* Clear all internal buffers.
*/
void FGReplay::clear()
{
while ( !short_term.empty() )
{
delete short_term.front(); delete short_term.front();
short_term.pop_front(); short_term.pop_front();
} }
while ( !medium_term.empty() ) { while ( !medium_term.empty() )
//cerr << "Deleting Medium term" <<endl; {
delete medium_term.front(); delete medium_term.front();
medium_term.pop_front(); medium_term.pop_front();
} }
while ( !long_term.empty() ) { while ( !long_term.empty() )
//cerr << "Deleting Long term" <<endl; {
delete long_term.front(); delete long_term.front();
long_term.pop_front(); long_term.pop_front();
} }
while ( !recycler.empty() ) { while ( !recycler.empty() )
//cerr << "Deleting Recycler" <<endl; {
delete recycler.front(); delete recycler.front();
recycler.pop_front(); recycler.pop_front();
} }
} }
/** /**
* Initialize the data structures * 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; sim_time = 0.0;
last_mt_time = 0.0; last_mt_time = 0.0;
last_lt_time = 0.0; last_lt_time = 0.0;
// Make sure all queues are flushed // Make sure all queues are flushed
while ( !short_term.empty() ) { clear();
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();
}
// Create an estimated nr of required ReplayData objects // Create an estimated nr of required ReplayData objects
// 120 is an estimated maximum frame rate. // 120 is an estimated maximum frame rate.
int estNrObjects = (int) ((st_list_time*120) + (mt_list_time*mt_dt) + int estNrObjects = (int) ((st_list_time*120) + (mt_list_time*mt_dt) +
(lt_list_time*lt_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); recycler.push_back(new FGReplayData);
} }
replay_master->setIntValue(0);
disable_replay->setBoolValue(0);
replay_time->setDoubleValue(0);
} }
/** /**
* Bind to the property tree * Bind to the property tree
*/ */
void FGReplay::bind() { void FGReplay::bind()
disable_replay = fgGetNode( "/sim/replay/disable", true ); {
} }
@ -128,7 +142,8 @@ void FGReplay::bind() {
* Unbind from the property tree * Unbind from the property tree
*/ */
void FGReplay::unbind() { void FGReplay::unbind()
{
// nothing to unbind // nothing to unbind
} }
@ -137,24 +152,62 @@ void FGReplay::unbind() {
* Update the saved data * Update the saved data
*/ */
void FGReplay::update( double dt ) { void FGReplay::update( double dt )
{
timingInfo.clear(); timingInfo.clear();
stamp("begin"); stamp("begin");
static SGPropertyNode *replay_master
= fgGetNode( "/sim/freeze/replay-state", true );
if( disable_replay->getBoolValue() ) { if ( disable_replay->getBoolValue() )
if ( sim_time != 0.0 ) { {
// we were recording data replay_master->setIntValue(0);
init(); replay_time->setDoubleValue(0);
} disable_replay->setBoolValue(0);
return;
} }
//stamp("point_01");
if ( replay_master->getIntValue() > 0 ) { int replay_state = replay_master->getIntValue();
// don't record the replay session
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 was active, restore most recent frame
replay(DBL_MAX);
// 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; //cerr << "Recording replay" << endl;
sim_time += dt; sim_time += dt;
@ -175,12 +228,13 @@ void FGReplay::update( double dt ) {
if (!recycler.size()) { if (!recycler.size()) {
stamp("Replay_01"); stamp("Replay_01");
r = new FGReplayData; r = new FGReplayData;
stamp("Replay_02"); stamp("Replay_02");
} else { } else {
r = recycler.front(); r = recycler.front();
recycler.pop_front(); recycler.pop_front();
//stamp("point_04be"); //stamp("point_04be");
} }
r->sim_time = sim_time; r->sim_time = sim_time;
//r->ctrls = c; //r->ctrls = c;
//stamp("point_04e"); //stamp("point_04e");

View file

@ -69,6 +69,7 @@ public:
virtual ~FGReplay(); virtual ~FGReplay();
virtual void init(); virtual void init();
virtual void reinit();
virtual void bind(); virtual void bind();
virtual void unbind(); virtual void unbind();
virtual void update( double dt ); virtual void update( double dt );
@ -78,6 +79,7 @@ public:
double get_end_time(); double get_end_time();
private: private:
void clear();
static const double st_list_time; // 60 secs of high res data static const double st_list_time; // 60 secs of high res data
static const double mt_list_time; // 10 mins of 1 fps data static const double mt_list_time; // 10 mins of 1 fps data
@ -90,12 +92,15 @@ private:
double sim_time; double sim_time;
double last_mt_time; double last_mt_time;
double last_lt_time; double last_lt_time;
int last_replay_state;
replay_list_type short_term; replay_list_type short_term;
replay_list_type medium_term; replay_list_type medium_term;
replay_list_type long_term; replay_list_type long_term;
replay_list_type recycler; replay_list_type recycler;
SGPropertyNode_ptr disable_replay; SGPropertyNode_ptr disable_replay;
SGPropertyNode_ptr replay_master;
SGPropertyNode_ptr replay_time;
}; };

View file

@ -76,12 +76,8 @@ FGEnvironmentMgr::~FGEnvironmentMgr ()
remove_subsystem("precipitation"); remove_subsystem("precipitation");
delete subsys; delete subsys;
subsys = get_subsystem("metarfetcher"); subsys = get_subsystem("realwx");
remove_subsystem("metarfetcher"); remove_subsystem("realwx");
delete subsys;
subsys = get_subsystem("metarcontroller");
remove_subsystem("metarcontroller");
delete subsys; delete subsys;
subsys = get_subsystem("controller"); subsys = get_subsystem("controller");
@ -346,9 +342,6 @@ FGEnvironmentMgr::set_cloud_layer_maxalpha (int index, double maxalpha)
thesky->get_cloud_layer(index)->setMaxAlpha(maxalpha); thesky->get_cloud_layer(index)->setMaxAlpha(maxalpha);
} }
void void
FGEnvironmentMgr::set_cloud_layer_coverage_type (int index, int type ) FGEnvironmentMgr::set_cloud_layer_coverage_type (int index, int type )
{ {

View file

@ -40,6 +40,7 @@
#include <simgear/threads/SGQueue.hxx> #include <simgear/threads/SGQueue.hxx>
#endif #endif
using simgear::PropertyList;
namespace Environment { namespace Environment {

View file

@ -570,6 +570,22 @@ void FGJSBsim::update( double dt )
/******************************************************************************/ /******************************************************************************/
void FGJSBsim::suspend()
{
fdmex->Hold();
SGSubsystem::suspend();
}
/******************************************************************************/
void FGJSBsim::resume()
{
fdmex->Resume();
SGSubsystem::resume();
}
/******************************************************************************/
// Convert from the FGInterface struct to the JSBsim generic_ struct // Convert from the FGInterface struct to the JSBsim generic_ struct
bool FGJSBsim::copy_to_JSBsim() bool FGJSBsim::copy_to_JSBsim()
@ -1011,7 +1027,9 @@ void FGJSBsim::set_Latitude(double lat)
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET ); _set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET ); fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc ); fgic->SetLatitudeRadIC( lat_geoc );
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
@ -1024,7 +1042,9 @@ void FGJSBsim::set_Longitude(double lon)
update_ic(); update_ic();
fgic->SetLongitudeRadIC( lon ); fgic->SetLongitudeRadIC( lon );
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
// Sets the altitude above sea level. // Sets the altitude above sea level.
@ -1049,7 +1069,9 @@ void FGJSBsim::set_Altitude(double alt)
"Terrain elevation: " << FGInterface::get_Runway_altitude() * SG_METER_TO_FEET ); "Terrain elevation: " << FGInterface::get_Runway_altitude() * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc ); fgic->SetLatitudeRadIC( lat_geoc );
fgic->SetAltitudeASLFtIC(alt); fgic->SetAltitudeASLFtIC(alt);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
void FGJSBsim::set_V_calibrated_kts(double vc) void FGJSBsim::set_V_calibrated_kts(double vc)
@ -1061,7 +1083,9 @@ void FGJSBsim::set_V_calibrated_kts(double vc)
update_ic(); update_ic();
fgic->SetVcalibratedKtsIC(vc); fgic->SetVcalibratedKtsIC(vc);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
void FGJSBsim::set_Mach_number(double mach) void FGJSBsim::set_Mach_number(double mach)
@ -1073,7 +1097,9 @@ void FGJSBsim::set_Mach_number(double mach)
update_ic(); update_ic();
fgic->SetMachIC(mach); fgic->SetMachIC(mach);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
void FGJSBsim::set_Velocities_Local( double north, double east, double down ) void FGJSBsim::set_Velocities_Local( double north, double east, double down )
@ -1088,7 +1114,9 @@ void FGJSBsim::set_Velocities_Local( double north, double east, double down )
fgic->SetVNorthFpsIC(north); fgic->SetVNorthFpsIC(north);
fgic->SetVEastFpsIC(east); fgic->SetVEastFpsIC(east);
fgic->SetVDownFpsIC(down); fgic->SetVDownFpsIC(down);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
void FGJSBsim::set_Velocities_Wind_Body( double u, double v, double w) void FGJSBsim::set_Velocities_Wind_Body( double u, double v, double w)
@ -1103,7 +1131,9 @@ void FGJSBsim::set_Velocities_Wind_Body( double u, double v, double w)
fgic->SetUBodyFpsIC(u); fgic->SetUBodyFpsIC(u);
fgic->SetVBodyFpsIC(v); fgic->SetVBodyFpsIC(v);
fgic->SetWBodyFpsIC(w); fgic->SetWBodyFpsIC(w);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
//Euler angles //Euler angles
@ -1119,7 +1149,9 @@ void FGJSBsim::set_Euler_Angles( double phi, double theta, double psi )
fgic->SetThetaRadIC(theta); fgic->SetThetaRadIC(theta);
fgic->SetPhiRadIC(phi); fgic->SetPhiRadIC(phi);
fgic->SetPsiRadIC(psi); fgic->SetPsiRadIC(psi);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
//Flight Path //Flight Path
@ -1137,7 +1169,9 @@ void FGJSBsim::set_Climb_Rate( double roc)
if( !(fabs(roc) > 1 && fabs(fgic->GetFlightPathAngleRadIC()) < 0.01) ) { if( !(fabs(roc) > 1 && fabs(fgic->GetFlightPathAngleRadIC()) < 0.01) ) {
fgic->SetClimbRateFpsIC(roc); fgic->SetClimbRateFpsIC(roc);
} }
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
void FGJSBsim::set_Gamma_vert_rad( double gamma) void FGJSBsim::set_Gamma_vert_rad( double gamma)
@ -1148,7 +1182,9 @@ void FGJSBsim::set_Gamma_vert_rad( double gamma)
if( !(fabs(gamma) < 0.01 && fabs(fgic->GetClimbRateFpsIC()) > 1) ) { if( !(fabs(gamma) < 0.01 && fabs(fgic->GetClimbRateFpsIC()) > 1) ) {
fgic->SetFlightPathAngleRadIC(gamma); fgic->SetFlightPathAngleRadIC(gamma);
} }
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
} }
void FGJSBsim::init_gear(void ) void FGJSBsim::init_gear(void )

View file

@ -113,6 +113,12 @@ public:
/// Unbind properties /// Unbind properties
void unbind(); void unbind();
/// Suspend integration
void suspend();
/// Resume integration
void resume();
/// @name Position Parameter Set /// @name Position Parameter Set
//@{ //@{
/** Set geocentric latitude /** Set geocentric latitude

View file

@ -236,12 +236,6 @@ TankPropertiesList::TankPropertiesList( SGPropertyNode_ptr rootNode )
} }
_tiedProperties.setRoot( rootNode ); _tiedProperties.setRoot( rootNode );
_tiedProperties.Tie("total-fuel-kg", this, &TankPropertiesList::getTotalContent_kg );
_tiedProperties.Tie("total-fuel-lbs", this, &TankPropertiesList::getTotalContent_lbs );
_tiedProperties.Tie("total-fuel-gal_us", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gals", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gal_imp", this, &TankPropertiesList::getTotalContent_gal_imp );
_tiedProperties.Tie("total-fuel-norm", this, &TankPropertiesList::getTotalContent_norm );
} }
double TankPropertiesList::getTotalContent_lbs() const double TankPropertiesList::getTotalContent_lbs() const
@ -297,6 +291,12 @@ double TankPropertiesList::getTotalContent_norm() const
void TankPropertiesList::bind() void TankPropertiesList::bind()
{ {
_tiedProperties.Tie("total-fuel-kg", this, &TankPropertiesList::getTotalContent_kg );
_tiedProperties.Tie("total-fuel-lbs", this, &TankPropertiesList::getTotalContent_lbs );
_tiedProperties.Tie("total-fuel-gal_us", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gals", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gal_imp", this, &TankPropertiesList::getTotalContent_gal_imp );
_tiedProperties.Tie("total-fuel-norm", this, &TankPropertiesList::getTotalContent_norm );
for( const_iterator it = begin(); it != end(); ++it ) { for( const_iterator it = begin(); it != end(); ++it ) {
(*it)->bind(); (*it)->bind();
} }

View file

@ -90,11 +90,11 @@ void FDMShell::reinit()
void FDMShell::bind() void FDMShell::bind()
{ {
_tankProperties.bind();
if (_impl && _impl->get_inited()) { if (_impl && _impl->get_inited()) {
if (_impl->get_bound()) { if (_impl->get_bound()) {
throw sg_exception("FDMShell::bind of bound FGInterface impl"); throw sg_exception("FDMShell::bind of bound FGInterface impl");
} }
_tankProperties.bind();
_impl->bind(); _impl->bind();
} }
} }
@ -139,8 +139,8 @@ void FDMShell::update(double dt)
// pull environmental data in, since the FDMs are lazy // pull environmental data in, since the FDMs are lazy
_impl->set_Velocities_Local_Airmass( _impl->set_Velocities_Local_Airmass(
_props->getDoubleValue("environment/wind-from-north-fps", 0.0), _props->getDoubleValue("environment/wind-from-north-fps", 0.0),
_props->getDoubleValue("environment/wind-from-east-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-down-fps", 0.0));
if (_props->getBoolValue("environment/params/control-fdm-atmosphere")) { if (_props->getBoolValue("environment/params/control-fdm-atmosphere")) {
// convert from Rankine to Celsius // convert from Rankine to Celsius
@ -160,24 +160,8 @@ void FDMShell::update(double dt)
_impl->ToggleDataLogging(doLog); _impl->ToggleDataLogging(doLog);
} }
// FIXME - replay manager should handle most of this if (!_impl->is_suspended())
int replayState = fgGetInt("/sim/freeze/replay-state", 0); _impl->update(dt);
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");
}
} }
void FDMShell::createImplementation() 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;
}

View file

@ -50,7 +50,8 @@ public:
virtual void unbind(); virtual void unbind();
virtual void update(double dt); virtual void update(double dt);
SGSubsystem* getFDM();
private: private:
void createImplementation(); void createImplementation();

File diff suppressed because it is too large Load diff

View file

@ -221,7 +221,7 @@ do_exit (const SGPropertyNode * arg)
static bool static bool
do_reset (const SGPropertyNode * arg) do_reset (const SGPropertyNode * arg)
{ {
doSimulatorReset(); fgReInitSubsystems();
return true; return true;
} }
@ -1243,8 +1243,10 @@ do_log_level (const SGPropertyNode * arg)
static bool static bool
do_replay (const SGPropertyNode * arg) do_replay (const SGPropertyNode * arg)
{ {
// freeze the master fdm // freeze the fdm, resume from sim pause
fgSetInt( "/sim/freeze/replay-state", 1 ); fgSetInt( "/sim/freeze/replay-state", 1 );
fgSetBool("/sim/freeze/master", 0 );
fgSetBool("/sim/freeze/clock", 0 );
FGReplay *r = (FGReplay *)(globals->get_subsystem( "replay" )); FGReplay *r = (FGReplay *)(globals->get_subsystem( "replay" ));

View file

@ -1517,7 +1517,7 @@ bool fgInitSubsystems() {
return true; return true;
} }
// Reset: this is what the 'reset' command (and hence, GUI) is attached to
void fgReInitSubsystems() void fgReInitSubsystems()
{ {
static const SGPropertyNode *master_freeze static const SGPropertyNode *master_freeze
@ -1553,11 +1553,17 @@ void fgReInitSubsystems()
// Initialize the FDM // Initialize the FDM
globals->get_subsystem("flight")->reinit(); globals->get_subsystem("flight")->reinit();
// reset replay buffers
globals->get_subsystem("replay")->reinit();
// reload offsets from config defaults // reload offsets from config defaults
globals->get_viewmgr()->reinit(); globals->get_viewmgr()->reinit();
globals->get_subsystem("time")->reinit(); globals->get_subsystem("time")->reinit();
// need to bind FDMshell again, since we manually unbound it above...
globals->get_subsystem("flight")->bind();
// setup state to end re-init // setup state to end re-init
fgSetBool("/sim/signals/reinit", false); fgSetBool("/sim/signals/reinit", false);
if ( !freeze ) { if ( !freeze ) {
@ -1567,13 +1573,6 @@ void fgReInitSubsystems()
} }
void doSimulatorReset(void) // from gui_local.cxx -- TODO merge with fgReInitSubsystems()
{
fgReInitSubsystems();
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// helper object to implement the --show-aircraft command. // helper object to implement the --show-aircraft command.
// resides here so we can share the fgFindAircraftInDir template above, // resides here so we can share the fgFindAircraftInDir template above,

View file

@ -62,16 +62,10 @@ bool fgInitGeneral ();
// gear, its initialization call should located in this routine. // gear, its initialization call should located in this routine.
bool fgInitSubsystems(); bool fgInitSubsystems();
// Reset // Reset: this is what the 'reset' command (and hence, GUI) is attached to
void fgReInitSubsystems(); void fgReInitSubsystems();
/**
* this is what the 'reset' command (and hence, GUI) is attached too
* it overlaps with fgReInitSubsystems quite substantially
*/
void doSimulatorReset(void);
// Set the initial position based on presets (or defaults) // Set the initial position based on presets (or defaults)
bool fgInitPosition(); bool fgInitPosition();

View file

@ -204,7 +204,7 @@ fgviewerMain(int argc, char** argv)
} }
globals->set_matlib( new SGMaterialLib ); globals->set_matlib( new SGMaterialLib );
simgear::SGModelLib::init(globals->get_fg_root()); simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
// Initialize the material property subsystem. // Initialize the material property subsystem.

View file

@ -121,6 +121,15 @@ static void fgMainLoop( void ) {
static SGPropertyNode_ptr frame_signal static SGPropertyNode_ptr frame_signal
= fgGetNode("/sim/signals/frame", true); = fgGetNode("/sim/signals/frame", true);
static SGPropertyNode_ptr _statisticsFlag
= fgGetNode("/sim/timing-statistics/enabled", true);
static SGPropertyNode_ptr _statisticsInterval
= fgGetNode("/sim/timing-statistics/interval-s", true);
static SGPropertyNode_ptr _statiticsMinJitter
= fgGetNode("/sim/timing-statistics/min-jitter-ms", true);
static SGPropertyNode_ptr _statiticsMinTime
= fgGetNode("/sim/timing-statistics/min-time-ms", true);
frame_signal->fireValueChanged(); frame_signal->fireValueChanged();
SGCloudLayer::enable_bump_mapping = fgGetBool("/sim/rendering/bump-mapping"); SGCloudLayer::enable_bump_mapping = fgGetBool("/sim/rendering/bump-mapping");
@ -206,6 +215,28 @@ static void fgMainLoop( void ) {
simgear::sleepForMSec(500); simgear::sleepForMSec(500);
} }
} }
// print timing statistics
static bool _lastStatisticsFlag = false;
if (_lastStatisticsFlag != _statisticsFlag->getBoolValue())
{
// flag has changed, update subsystem manager
_lastStatisticsFlag = _statisticsFlag->getBoolValue();
globals->get_subsystem_mgr()->collectDebugTiming(_lastStatisticsFlag);
}
if (_lastStatisticsFlag)
{
static double elapsed = 0;
elapsed += real_dt;
if (elapsed >= _statisticsInterval->getDoubleValue())
{
// print and reset timing statistics
globals->get_subsystem_mgr()->printTimingStatistics(_statiticsMinTime->getDoubleValue(),
_statiticsMinJitter->getDoubleValue());
elapsed = 0;
}
}
simgear::AtomicChangeListener::fireChangeListeners(); simgear::AtomicChangeListener::fireChangeListeners();
SG_LOG( SG_ALL, SG_DEBUG, "" ); SG_LOG( SG_ALL, SG_DEBUG, "" );
@ -359,8 +390,7 @@ static void fgIdleFunction ( void ) {
// Initialize the material manager // Initialize the material manager
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
globals->set_matlib( new SGMaterialLib ); globals->set_matlib( new SGMaterialLib );
simgear::SGModelLib::init(globals->get_fg_root()); simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
simgear::SGModelLib::setPropRoot(globals->get_props());
simgear::SGModelLib::setPanelFunc(load_panel); simgear::SGModelLib::setPanelFunc(load_panel);
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View file

@ -1,4 +1,4 @@
// model.cxx - manage a 3D aircraft model. // acmodel.cxx - manage a 3D aircraft model.
// Written by David Megginson, started 2002. // Written by David Megginson, started 2002.
// //
// This file is in the Public Domain, and comes with no warranty. // This file is in the Public Domain, and comes with no warranty.
@ -84,6 +84,7 @@ void
FGAircraftModel::reinit() FGAircraftModel::reinit()
{ {
deinit(); deinit();
_fx->reinit();
init(); init();
} }

View file

@ -1,4 +1,4 @@
// model.hxx - manage a 3D aircraft model. // acmodel.hxx - manage a 3D aircraft model.
// Written by David Megginson, started 2002. // Written by David Megginson, started 2002.
// //
// This file is in the Public Domain, and comes with no warranty. // This file is in the Public Domain, and comes with no warranty.

View file

@ -541,9 +541,9 @@ FGGeneric::reinit()
SGPropertyNode root; SGPropertyNode root;
try { try {
readProperties(path.str(), &root); readProperties(path.str(), &root);
} catch (const sg_exception &) { } catch (const sg_exception & ex) {
SG_LOG(SG_GENERAL, SG_ALERT, SG_LOG(SG_GENERAL, SG_ALERT,
"Unable to load the protocol configuration file"); "Unable to load the protocol configuration file: " << ex.getFormattedMessage() );
return; return;
} }

View file

@ -38,6 +38,31 @@
static FGNasalSys* nasalSys = 0; static FGNasalSys* nasalSys = 0;
// Listener class for loading Nasal modules on demand
class FGNasalModuleListener : public SGPropertyChangeListener
{
public:
FGNasalModuleListener(SGPropertyNode* node);
virtual void valueChanged(SGPropertyNode* node);
private:
SGPropertyNode_ptr _node;
};
FGNasalModuleListener::FGNasalModuleListener(SGPropertyNode* node) : _node(node)
{
}
void FGNasalModuleListener::valueChanged(SGPropertyNode*)
{
if (_node->getBoolValue("enabled",false)&&
!_node->getBoolValue("loaded",true))
{
nasalSys->loadPropertyScripts(_node);
}
}
// Read and return file contents in a single buffer. Note use of // Read and return file contents in a single buffer. Note use of
// stat() to get the file size. This is a win32 function, believe it // stat() to get the file size. This is a win32 function, believe it
@ -737,12 +762,15 @@ void FGNasalSys::init()
// Now load the various source files in the Nasal directory // Now load the various source files in the Nasal directory
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal")); simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas"); loadScriptDirectory(nasalDir);
for (unsigned int i=0; i<scripts.size(); ++i) { // Add modules in Nasal subdirectories to property tree
SGPath fullpath(scripts[i]); simgear::PathList directories = nasalDir.children(simgear::Dir::TYPE_DIR+
SGPath file = fullpath.file(); simgear::Dir::NO_DOT_OR_DOTDOT, "");
loadModule(fullpath, file.base().c_str()); for (unsigned int i=0; i<directories.size(); ++i) {
simgear::Dir dir(directories[i]);
simgear::PathList scripts = dir.children(simgear::Dir::TYPE_FILE, ".nas");
addModule(directories[i].file(), scripts);
} }
// set signal and remove node to avoid restoring at reinit // set signal and remove node to avoid restoring at reinit
@ -777,29 +805,75 @@ void FGNasalSys::update(double)
_context = naNewContext(); _context = naNewContext();
} }
// Loads all scripts in given directory
void FGNasalSys::loadScriptDirectory(simgear::Dir nasalDir)
{
simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas");
for (unsigned int i=0; i<scripts.size(); ++i) {
SGPath fullpath(scripts[i]);
SGPath file = fullpath.file();
loadModule(fullpath, file.base().c_str());
}
}
// Create module with list of scripts
void FGNasalSys::addModule(string moduleName, simgear::PathList scripts)
{
if (scripts.size()>0)
{
SGPropertyNode* nasal = globals->get_props()->getNode("nasal");
SGPropertyNode* module_node = nasal->getChild(moduleName,0,true);
for (unsigned int i=0; i<scripts.size(); ++i) {
SGPropertyNode* pFileNode = module_node->getChild("file",i,true);
pFileNode->setStringValue(scripts[i].c_str());
}
if (!module_node->hasChild("enabled",0))
{
SGPropertyNode* node = module_node->getChild("enabled",0,true);
node->setBoolValue(true);
node->setAttribute(SGPropertyNode::USERARCHIVE,true);
}
}
}
// Loads the scripts found under /nasal in the global tree // Loads the scripts found under /nasal in the global tree
void FGNasalSys::loadPropertyScripts() void FGNasalSys::loadPropertyScripts()
{ {
SGPropertyNode* nasal = globals->get_props()->getNode("nasal"); SGPropertyNode* nasal = globals->get_props()->getNode("nasal");
if(!nasal) return; if(!nasal) return;
for(int i=0; i<nasal->nChildren(); i++) { for(int i=0; i<nasal->nChildren(); i++)
{
SGPropertyNode* n = nasal->getChild(i); SGPropertyNode* n = nasal->getChild(i);
loadPropertyScripts(n);
}
}
const char* module = n->getName(); // Loads the scripts found under /nasal in the global tree
if(n->hasChild("module")) void FGNasalSys::loadPropertyScripts(SGPropertyNode* n)
module = n->getStringValue("module"); {
bool is_loaded = false;
const char* module = n->getName();
if(n->hasChild("module"))
module = n->getStringValue("module");
if (n->getBoolValue("enabled",true))
{
// allow multiple files to be specified within a single // allow multiple files to be specified within a single
// Nasal module tag // Nasal module tag
int j = 0; int j = 0;
SGPropertyNode *fn; SGPropertyNode *fn;
bool file_specified = false; bool file_specified = false;
bool ok=true;
while((fn = n->getChild("file", j)) != NULL) { while((fn = n->getChild("file", j)) != NULL) {
file_specified = true; file_specified = true;
const char* file = fn->getStringValue(); const char* file = fn->getStringValue();
SGPath p = globals->resolve_maybe_aircraft_path(file); SGPath p(file);
loadModule(p, module); if (!p.isAbsolute() || !p.exists())
{
p = globals->resolve_maybe_aircraft_path(file);
}
ok &= loadModule(p, module);
j++; j++;
} }
@ -809,10 +883,30 @@ void FGNasalSys::loadPropertyScripts()
createModule(module, n->getPath().c_str(), src, strlen(src)); createModule(module, n->getPath().c_str(), src, strlen(src));
if(!file_specified && !src) if(!file_specified && !src)
{
// module no longer exists - clear the archived "enable" flag
n->setAttribute(SGPropertyNode::USERARCHIVE,false);
SGPropertyNode* node = n->getChild("enabled",0,false);
if (node)
node->setAttribute(SGPropertyNode::USERARCHIVE,false);
SG_LOG(SG_NASAL, SG_ALERT, "Nasal error: " << SG_LOG(SG_NASAL, SG_ALERT, "Nasal error: " <<
"no <file> or <script> defined in " << "no <file> or <script> defined in " <<
"/nasal/" << module); "/nasal/" << module);
}
else
is_loaded = ok;
} }
else
{
SGPropertyNode* enable = n->getChild("enabled");
if (enable)
{
FGNasalModuleListener* listener = new FGNasalModuleListener(n);
enable->addChangeListener(listener, false);
}
}
n->setBoolValue("loaded",is_loaded);
} }
// Logs a runtime error, with stack trace, to the FlightGear log stream // Logs a runtime error, with stack trace, to the FlightGear log stream
@ -832,7 +926,7 @@ void FGNasalSys::logError(naContext context)
// Reads a script file, executes it, and places the resulting // Reads a script file, executes it, and places the resulting
// namespace into the global namespace under the specified module // namespace into the global namespace under the specified module
// name. // name.
void FGNasalSys::loadModule(SGPath file, const char* module) bool FGNasalSys::loadModule(SGPath file, const char* module)
{ {
int len = 0; int len = 0;
char* buf = readfile(file.c_str(), &len); char* buf = readfile(file.c_str(), &len);
@ -840,25 +934,26 @@ void FGNasalSys::loadModule(SGPath file, const char* module)
SG_LOG(SG_NASAL, SG_ALERT, SG_LOG(SG_NASAL, SG_ALERT,
"Nasal error: could not read script file " << file.c_str() "Nasal error: could not read script file " << file.c_str()
<< " into module " << module); << " into module " << module);
return; return false;
} }
createModule(module, file.c_str(), buf, len); bool ok = createModule(module, file.c_str(), buf, len);
delete[] buf; delete[] buf;
return ok;
} }
// Parse and run. Save the local variables namespace, as it will // Parse and run. Save the local variables namespace, as it will
// become a sub-object of globals. The optional "arg" argument can be // become a sub-object of globals. The optional "arg" argument can be
// used to pass an associated property node to the module, which can then // used to pass an associated property node to the module, which can then
// be accessed via cmdarg(). (This is, for example, used by XML dialogs.) // be accessed via cmdarg(). (This is, for example, used by XML dialogs.)
void FGNasalSys::createModule(const char* moduleName, const char* fileName, bool FGNasalSys::createModule(const char* moduleName, const char* fileName,
const char* src, int len, const char* src, int len,
const SGPropertyNode* cmdarg, const SGPropertyNode* cmdarg,
int argc, naRef* args) int argc, naRef* args)
{ {
naRef code = parse(fileName, src, len); naRef code = parse(fileName, src, len);
if(naIsNil(code)) if(naIsNil(code))
return; return false;
// See if we already have a module hash to use. This allows the // See if we already have a module hash to use. This allows the
// user to, for example, add functions to the built-in math // user to, for example, add functions to the built-in math
@ -873,6 +968,7 @@ void FGNasalSys::createModule(const char* moduleName, const char* fileName,
call(code, argc, args, locals); call(code, argc, args, locals);
hashset(_globals, moduleName, locals); hashset(_globals, moduleName, locals);
return true;
} }
void FGNasalSys::deleteModule(const char* moduleName) void FGNasalSys::deleteModule(const char* moduleName)

View file

@ -3,6 +3,7 @@
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/misc/sg_dir.hxx>
#include <simgear/nasal/nasal.h> #include <simgear/nasal/nasal.h>
#include <simgear/scene/model/modellib.hxx> #include <simgear/scene/model/modellib.hxx>
#include <simgear/xml/easyxml.hxx> #include <simgear/xml/easyxml.hxx>
@ -24,7 +25,7 @@ public:
// Loads a nasal script from an external file and inserts it as a // Loads a nasal script from an external file and inserts it as a
// global module of the specified name. // global module of the specified name.
void loadModule(SGPath file, const char* moduleName); bool loadModule(SGPath file, const char* moduleName);
// Simple hook to run arbitrary source code. Returns a bool to // Simple hook to run arbitrary source code. Returns a bool to
// indicate successful execution. Does *not* return any Nasal // indicate successful execution. Does *not* return any Nasal
@ -53,7 +54,7 @@ public:
// Callbacks for command and timer bindings // Callbacks for command and timer bindings
virtual bool handleCommand(const SGPropertyNode* arg); virtual bool handleCommand(const SGPropertyNode* arg);
void createModule(const char* moduleName, const char* fileName, bool createModule(const char* moduleName, const char* fileName,
const char* src, int len, const SGPropertyNode* cmdarg=0, const char* src, int len, const SGPropertyNode* cmdarg=0,
int argc=0, naRef*args=0); int argc=0, naRef*args=0);
@ -65,6 +66,7 @@ public:
private: private:
friend class FGNasalScript; friend class FGNasalScript;
friend class FGNasalListener; friend class FGNasalListener;
friend class FGNasalModuleListener;
// //
// FGTimer subclass for handling Nasal timer callbacks. // FGTimer subclass for handling Nasal timer callbacks.
@ -85,6 +87,9 @@ private:
static int _listenerId; static int _listenerId;
void loadPropertyScripts(); void loadPropertyScripts();
void loadPropertyScripts(SGPropertyNode* n);
void loadScriptDirectory(simgear::Dir nasalDir);
void addModule(string moduleName, simgear::PathList scripts);
void hashset(naRef hash, const char* key, naRef val); void hashset(naRef hash, const char* key, naRef val);
void logError(naContext); void logError(naContext);
naRef parse(const char* filename, const char* buf, int len); naRef parse(const char* filename, const char* buf, int len);

View file

@ -8,4 +8,4 @@ libSound_a_SOURCES = \
sample_queue.cxx sample_queue.hxx \ sample_queue.cxx sample_queue.hxx \
voiceplayer.cxx voiceplayer.hxx voiceplayer.cxx voiceplayer.hxx
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_builddir) -I$(top_builddir)/src

View file

@ -109,6 +109,9 @@ FGFX::init()
void void
FGFX::reinit() FGFX::reinit()
{ {
for ( unsigned int i = 0; i < _sound.size(); i++ ) {
delete _sound[i];
}
_sound.clear(); _sound.clear();
init(); init();
}; };

View file

@ -42,12 +42,6 @@
using std::string; using std::string;
#if defined( HAVE_VERSION_H ) && HAVE_VERSION_H
# include <Include/version.h>
#else
# include <Include/no_version.h>
#endif
#include "voiceplayer.hxx" #include "voiceplayer.hxx"
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View file

@ -135,6 +135,7 @@ public:
public: public:
bool silence; bool silence;
virtual ~Element() {}
virtual inline void play (float volume) {} virtual inline void play (float volume) {}
virtual inline void stop () {} virtual inline void stop () {}
virtual bool is_playing () = 0; virtual bool is_playing () = 0;
@ -186,7 +187,7 @@ public:
inline Voice (FGVoicePlayer *_player) inline Voice (FGVoicePlayer *_player)
: element(NULL), player(_player), volume(1.0) {} : element(NULL), player(_player), volume(1.0) {}
~Voice (); virtual ~Voice ();
inline void append (Element *_element) { elements.push_back(_element); } inline void append (Element *_element) { elements.push_back(_element); }
@ -229,7 +230,7 @@ public:
dev_name(_dev_name), dir_prefix(""), dev_name(_dev_name), dir_prefix(""),
speaker(this,properties_handler) {} speaker(this,properties_handler) {}
~FGVoicePlayer (); virtual ~FGVoicePlayer ();
void init (); void init ();
void pause(); void pause();

View file

@ -88,9 +88,11 @@ void TimeManager::init()
_warp->getIntValue()); _warp->getIntValue());
globals->set_time_params(_impl); globals->set_time_params(_impl);
// frame/update-rate counters // frame-rate / worst-case latency / update-rate counters
_frameRate = fgGetNode("/sim/frame-rate", true); _frameRate = fgGetNode("/sim/frame-rate", true);
_frameLatency = fgGetNode("/sim/frame-latency-max-ms", true);
_lastFrameTime = 0; _lastFrameTime = 0;
_frameLatencyMax = 0.0;
_frameCount = 0; _frameCount = 0;
} }
@ -160,7 +162,9 @@ void TimeManager::computeTimeDeltas(double& simDt, double& realDt)
SGTimeStamp currentStamp; SGTimeStamp currentStamp;
currentStamp.stamp(); currentStamp.stamp();
double dt = (currentStamp - _lastStamp).toSecs(); double dt = (currentStamp - _lastStamp).toSecs();
if (dt > _frameLatencyMax)
_frameLatencyMax = dt;
// Limit the time we need to spend in simulation loops // Limit the time we need to spend in simulation loops
// That means, if the /sim/max-simtime-per-frame value is strictly positive // That means, if the /sim/max-simtime-per-frame value is strictly positive
// you can limit the maximum amount of time you will do simulations for // you can limit the maximum amount of time you will do simulations for
@ -251,7 +255,9 @@ void TimeManager::computeFrameRate()
// Calculate frame rate average // Calculate frame rate average
if ((_impl->get_cur_time() != _lastFrameTime)) { if ((_impl->get_cur_time() != _lastFrameTime)) {
_frameRate->setIntValue(_frameCount); _frameRate->setIntValue(_frameCount);
_frameLatency->setDoubleValue(_frameLatencyMax*1000);
_frameCount = 0; _frameCount = 0;
_frameLatencyMax = 0.0;
} }
_lastFrameTime = _impl->get_cur_time(); _lastFrameTime = _impl->get_cur_time();

View file

@ -78,9 +78,11 @@ private:
SGPropertyNode_ptr _longitudeDeg; SGPropertyNode_ptr _longitudeDeg;
SGPropertyNode_ptr _latitudeDeg; SGPropertyNode_ptr _latitudeDeg;
// frame-rate / update-rate counters // frame-rate / worst-case latency / update-rate counters
SGPropertyNode_ptr _frameRate; SGPropertyNode_ptr _frameRate;
SGPropertyNode_ptr _frameLatency;
time_t _lastFrameTime; time_t _lastFrameTime;
double _frameLatencyMax;
int _frameCount; int _frameCount;
}; };