1
0
Fork 0

Merge branch 'next' of git://gitorious.org/fg/flightgear

Conflicts:
	src/Environment/environment_mgr.cxx
This commit is contained in:
Stuart Buchanan 2011-04-21 20:55:49 +01:00
commit 0becb0df2b
104 changed files with 5103 additions and 634 deletions

View file

@ -296,6 +296,14 @@ if test "x$have_rti13" = "xyes" ; then
AC_SUBST(HLA_LIBS, "-lsghla13 -lsghla $hla_libs")
fi
dnl EXPERIMENTAL fgpanel application
# defaults to no
AC_ARG_WITH(fgpanel, [ --with-fgpanel Include fgpanel application (EXPERIMENTAL) [default=no]], [], [with_fgpanel=no])
if test "x$with_fgpanel" = "xyes"; then
AC_DEFINE([WITH_FGPANEL], 1, [Define to enable fgpanel application])
fi
AM_CONDITIONAL(WITH_FGPANEL, test "x$with_fgpanel" = "xyes")
dnl Used by JSBSim to conditionally compile in fgfs interface code
AC_DEFINE([FGFS], 1, [Define so that JSBSim compiles in 'library' mode])
@ -940,7 +948,8 @@ AC_CONFIG_FILES([ \
utils/propmerge/Makefile \
utils/TerraSync/Makefile \
utils/xmlgrep/Makefile \
utils/fgviewer/Makefile
utils/fgviewer/Makefile \
utils/fgpanel/Makefile
])
AC_OUTPUT
@ -977,6 +986,12 @@ else
echo "Event input: no"
fi
if test "x$with_fgpanel" = "xyes"; then
echo "fgpanel: yes"
else
echo "fgpanel: no"
fi
if test "x$enable_sp_fdms" != "xno"; then
echo "Include special purpose flight models: yes"
else

View file

@ -42,6 +42,7 @@
#include "precipitation_mgr.hxx"
#include "ridge_lift.hxx"
#include "terrainsampler.hxx"
#include "Airports/simple.hxx"
class SGSky;
extern SGSky *thesky;
@ -49,8 +50,11 @@ extern SGSky *thesky;
FGEnvironmentMgr::FGEnvironmentMgr () :
_environment(new FGEnvironment()),
fgClouds(new FGClouds()),
_cloudLayersDirty(true),
_altitudeNode(fgGetNode("/position/altitude-ft", true)),
_cloudLayersDirty(true)
_longitude_n(fgGetNode( "/position/longitude-deg", true )),
_latitude_n( fgGetNode( "/position/latitude-deg", true )),
_positionTimeToLive(0.0)
{
set_subsystem("controller", Environment::LayerInterpolateController::createInstance( fgGetNode("/environment/config", true ) ));
set_subsystem("realwx", Environment::RealWxController::createInstance( fgGetNode("/environment/realwx", true ) ), 1.0 );
@ -76,12 +80,8 @@ FGEnvironmentMgr::~FGEnvironmentMgr ()
remove_subsystem("precipitation");
delete subsys;
subsys = get_subsystem("metarfetcher");
remove_subsystem("metarfetcher");
delete subsys;
subsys = get_subsystem("metarcontroller");
remove_subsystem("metarcontroller");
subsys = get_subsystem("realwx");
remove_subsystem("realwx");
delete subsys;
subsys = get_subsystem("controller");
@ -116,73 +116,73 @@ FGEnvironmentMgr::bind ()
_tiedProperties.setRoot( fgGetNode( "/environment", true ) );
_tiedProperties.Tie( "effective-visibility-m", thesky,
&SGSky::get_visibility );
&SGSky::get_visibility );
_tiedProperties.Tie("rebuild-layers", fgClouds,
&FGClouds::get_update_event,
&FGClouds::set_update_event);
&FGClouds::get_update_event,
&FGClouds::set_update_event);
_tiedProperties.Tie("turbulence/use-cloud-turbulence", &sgEnviro,
&SGEnviro::get_turbulence_enable_state,
&SGEnviro::set_turbulence_enable_state);
&SGEnviro::get_turbulence_enable_state,
&SGEnviro::set_turbulence_enable_state);
for (int i = 0; i < MAX_CLOUD_LAYERS; i++) {
SGPropertyNode_ptr layerNode = fgGetNode("/environment/clouds",true)->getChild("layer", i, true );
SGPropertyNode_ptr layerNode = fgGetNode("/environment/clouds",true)->getChild("layer", i, true );
_tiedProperties.Tie( layerNode->getNode("span-m",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_span_m,
&FGEnvironmentMgr::set_cloud_layer_span_m);
_tiedProperties.Tie( layerNode->getNode("span-m",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_span_m,
&FGEnvironmentMgr::set_cloud_layer_span_m);
_tiedProperties.Tie( layerNode->getNode("elevation-ft",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_elevation_ft,
&FGEnvironmentMgr::set_cloud_layer_elevation_ft);
_tiedProperties.Tie( layerNode->getNode("elevation-ft",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_elevation_ft,
&FGEnvironmentMgr::set_cloud_layer_elevation_ft);
_tiedProperties.Tie( layerNode->getNode("thickness-ft",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_thickness_ft,
&FGEnvironmentMgr::set_cloud_layer_thickness_ft);
_tiedProperties.Tie( layerNode->getNode("thickness-ft",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_thickness_ft,
&FGEnvironmentMgr::set_cloud_layer_thickness_ft);
_tiedProperties.Tie( layerNode->getNode("transition-ft",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_transition_ft,
&FGEnvironmentMgr::set_cloud_layer_transition_ft);
_tiedProperties.Tie( layerNode->getNode("transition-ft",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_transition_ft,
&FGEnvironmentMgr::set_cloud_layer_transition_ft);
_tiedProperties.Tie( layerNode->getNode("coverage",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_coverage,
&FGEnvironmentMgr::set_cloud_layer_coverage);
_tiedProperties.Tie( layerNode->getNode("coverage",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_coverage,
&FGEnvironmentMgr::set_cloud_layer_coverage);
_tiedProperties.Tie( layerNode->getNode("coverage-type",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_coverage_type,
&FGEnvironmentMgr::set_cloud_layer_coverage_type);
_tiedProperties.Tie( layerNode->getNode("coverage-type",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_coverage_type,
&FGEnvironmentMgr::set_cloud_layer_coverage_type);
_tiedProperties.Tie( layerNode->getNode( "visibility-m",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_visibility_m,
&FGEnvironmentMgr::set_cloud_layer_visibility_m);
_tiedProperties.Tie( layerNode->getNode( "visibility-m",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_visibility_m,
&FGEnvironmentMgr::set_cloud_layer_visibility_m);
_tiedProperties.Tie( layerNode->getNode( "alpha",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_maxalpha,
&FGEnvironmentMgr::set_cloud_layer_maxalpha);
_tiedProperties.Tie( layerNode->getNode( "alpha",true), this, i,
&FGEnvironmentMgr::get_cloud_layer_maxalpha,
&FGEnvironmentMgr::set_cloud_layer_maxalpha);
}
_tiedProperties.setRoot( fgGetNode("/sim/rendering", true ) );
_tiedProperties.Tie( "clouds3d-enable", fgClouds,
&FGClouds::get_3dClouds,
&FGClouds::set_3dClouds);
&FGClouds::get_3dClouds,
&FGClouds::set_3dClouds);
_tiedProperties.Tie( "clouds3d-density", thesky,
&SGSky::get_3dCloudDensity,
&SGSky::set_3dCloudDensity);
&SGSky::get_3dCloudDensity,
&SGSky::set_3dCloudDensity);
_tiedProperties.Tie("clouds3d-vis-range", thesky,
&SGSky::get_3dCloudVisRange,
&SGSky::set_3dCloudVisRange);
&SGSky::get_3dCloudVisRange,
&SGSky::set_3dCloudVisRange);
_tiedProperties.Tie("precipitation-enable", &sgEnviro,
&SGEnviro::get_precipitation_enable_state,
&SGEnviro::set_precipitation_enable_state);
&SGEnviro::get_precipitation_enable_state,
&SGEnviro::set_precipitation_enable_state);
_tiedProperties.Tie("lightning-enable", &sgEnviro,
&SGEnviro::get_lightning_enable_state,
&SGEnviro::set_lightning_enable_state);
&SGEnviro::get_lightning_enable_state,
&SGEnviro::set_lightning_enable_state);
sgEnviro.config(fgGetNode("/sim/rendering/precipitation"));
}
@ -203,11 +203,38 @@ FGEnvironmentMgr::update (double dt)
_environment->set_elevation_ft( _altitudeNode->getDoubleValue() );
simgear::Particles::setWindFrom( _environment->get_wind_from_heading_deg(),
_environment->get_wind_speed_kt() );
_environment->get_wind_speed_kt() );
if( _cloudLayersDirty ) {
_cloudLayersDirty = false;
fgClouds->set_update_event( fgClouds->get_update_event()+1 );
}
_positionTimeToLive -= dt;
if( _positionTimeToLive <= 0.0 )
{
// update closest airport information
_positionTimeToLive = 30.0;
SG_LOG(SG_ALL, SG_INFO, "FGEnvironmentMgr::update: updating closest airport");
SGGeod pos = SGGeod::fromDeg(_longitude_n->getDoubleValue(),
_latitude_n->getDoubleValue());
FGAirport * nearestAirport = FGAirport::findClosest(pos, 100.0);
if( nearestAirport == NULL )
{
SG_LOG(SG_ALL,SG_WARN,"FGEnvironmentMgr::update: No airport within 100NM range");
}
else
{
const string currentId = fgGetString("/sim/airport/closest-airport-id", "");
if (currentId != nearestAirport->ident())
{
fgSetString("/sim/airport/closest-airport-id",
nearestAirport->ident().c_str());
}
}
}
}
FGEnvironment
@ -347,9 +374,6 @@ FGEnvironmentMgr::set_cloud_layer_maxalpha (int index, double maxalpha)
thesky->get_cloud_layer(index)->setMaxAlpha(maxalpha);
}
void
FGEnvironmentMgr::set_cloud_layer_coverage_type (int index, int type )
{

View file

@ -94,8 +94,11 @@ private:
FGEnvironment * _environment; // always the same, for now
FGClouds *fgClouds;
SGPropertyNode_ptr _altitudeNode;
bool _cloudLayersDirty;
SGPropertyNode_ptr _altitudeNode;
SGPropertyNode_ptr _longitude_n;
SGPropertyNode_ptr _latitude_n;
double _positionTimeToLive;
simgear::TiedPropertyList _tiedProperties;
};

View file

@ -71,7 +71,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.84 2011/01/16 16:26:14 bcoconni Exp $";
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.91 2011/04/05 20:20:21 andgi Exp $";
static const char *IdHdr = ID_FDMEXEC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -116,6 +116,10 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
// run in standalone mode with no initialization file.
AircraftPath = "aircraft";
EnginePath = "engine";
SystemsPath = "systems";
try {
char* num = getenv("JSBSIM_DEBUG");
if (num) debug_lvl = atoi(num); // set debug level
@ -154,12 +158,13 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
Constructing = true;
typedef int (FGFDMExec::*iPMF)(void) const;
// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis);
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim);
instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions);
// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
instance->Tie("simulation/terminate", (int *)&Terminate);
instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
instance->Tie("simulation/frame", (int *)&Frame, false);
Constructing = false;
}
@ -350,6 +355,8 @@ bool FGFDMExec::RunIC(void)
void FGFDMExec::Initialize(FGInitialCondition *FGIC)
{
Setsim_time(0.0);
Propagate->SetInitialState( FGIC );
Atmosphere->Run();
@ -358,6 +365,9 @@ void FGFDMExec::Initialize(FGInitialCondition *FGIC)
FGIC->GetWindDFpsIC() );
FGColumnVector3 vAeroUVW;
//ToDo: move this to the Auxiliary class !?
vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED();
double alpha, beta;
@ -629,7 +639,9 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
// Process the output element[s]. This element is OPTIONAL, and there may be more than one.
unsigned int idx=0;
typedef int (FGOutput::*iOPMF)(void) const;
typedef double (FGOutput::*iOPMF)(void) const;
typedef int (FGFDMExec::*iOPV)(void) const;
typedef void (FGFDMExec::*vOPI)(int) const;
element = document->FindElement("output");
while (element) {
if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " ";
@ -643,7 +655,8 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
} else {
Outputs.push_back(Output);
string outputProp = CreateIndexedPropertyName("simulation/output",idx);
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate);
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
instance->Tie("simulation/force-output", this, (iOPV)0, &FGFDMExec::ForceOutput, false);
idx++;
}
element = document->FindNextElement("output");
@ -679,15 +692,6 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
<< fgdef << endl;
}
// Late bind previously undefined FCS inputs.
try {
FCS->LateBind();
} catch (string prop) {
cerr << endl << fgred << " Could not late bind property " << prop
<< ". Aborting." << reset << endl;
result = false;
}
if (result) {
struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = "";
@ -918,6 +922,13 @@ void FGFDMExec::EnableOutput(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::ForceOutput(int idx)
{
if (idx >= 0 && idx < Outputs.size()) Outputs[idx]->Print();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::SetOutputDirectives(const string& fname)
{
bool result;
@ -930,9 +941,9 @@ bool FGFDMExec::SetOutputDirectives(const string& fname)
if (result) {
Outputs.push_back(Output);
typedef int (FGOutput::*iOPMF)(void) const;
typedef double (FGOutput::*iOPMF)(void) const;
string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1);
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate);
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate, false);
}
return result;

View file

@ -44,11 +44,9 @@ INCLUDES
#include <vector>
#include <string>
//#include "models/FGModel.h"
#include "models/FGOutput.h"
#include "models/FGInput.h"
#include "initialization/FGTrim.h"
#include "initialization/FGInitialCondition.h"
#include "FGJSBBase.h"
#include "input_output/FGPropertyManager.h"
#include "input_output/FGGroundCallback.h"
@ -60,7 +58,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.56 2010/11/18 20:37:10 jberndt Exp $"
#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.63 2011/02/19 16:44:41 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -183,7 +181,7 @@ CLASS DOCUMENTATION
property actually maps toa function call of DoTrim().
@author Jon S. Berndt
@version $Revision: 1.56 $
@version $Revision: 1.63 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -286,8 +284,11 @@ public:
/** Loads a script
@param Script the full path name and file name for the script to be loaded.
@param deltaT The simulation integration step size, if given. If no value is supplied
then 0.0 is used and the value is expected to be supplied in
the script file itself.
@return true if successfully loadsd; false otherwise. */
bool LoadScript(const string& Script, double deltaT);
bool LoadScript(const string& Script, double deltaT=0.0);
/** Sets the path to the engine config file directories.
@param path path to the directory under which engine config
@ -401,6 +402,9 @@ public:
*/
bool SetOutputDirectives(const string& fname);
/** Forces the specified output object to print its items once */
void ForceOutput(int idx=0);
/** Sets (or overrides) the output filename
@param fname the name of the file to output data to
@return true if successful, false if there is no output specified for the flight model */
@ -514,7 +518,7 @@ public:
@param rootDir the string containing the root directory. */
void SetRootDir(const string& rootDir) {RootDir = rootDir;}
/** Retrieves teh Root Directory.
/** Retrieves the Root Directory.
@return the string representing the root (base) JSBSim directory. */
const string& GetRootDir(void) const {return RootDir;}

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.56 2011/01/23 12:13:44 bcoconni Exp $";
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.59 2011/04/03 13:18:51 bcoconni Exp $";
static const char *IdHdr = ID_INITIALCONDITION;
//******************************************************************************
@ -700,6 +700,8 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt)
case setve:
SetVtrueFpsIC(ve0 * sqrt(rho/rhoSL));
break;
default: // Make the compiler stop complaining about missing enums
break;
}
position.SetRadius(alt + sea_level_radius);
@ -998,6 +1000,18 @@ bool FGInitialCondition::Load_v1(void)
SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf"));
}
// Refer to Stevens and Lewis, 1.5-14a, pg. 49.
// This is the rotation rate of the "Local" frame, expressed in the local frame.
double radInv = 1.0 / position.GetRadius();
FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vUVW_NED(eEast),
-radInv*vUVW_NED(eNorth),
-radInv*vUVW_NED(eEast)*position.GetTanLatitude() );
p = vOmegaLocal(eP);
q = vOmegaLocal(eR);
r = vOmegaLocal(eQ);
return result;
}
@ -1032,7 +1046,7 @@ bool FGInitialCondition::Load_v2(void)
if (position_el->FindElement("radius")) {
position.SetRadius(position_el->FindElementValueAsNumberConvertTo("radius", "FT"));
} else if (position_el->FindElement("altitudeAGL")) {
position.SetRadius(sea_level_radius + terrain_elevation + position_el->FindElementValueAsNumberConvertTo("altitude", "FT"));
position.SetRadius(sea_level_radius + terrain_elevation + position_el->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
} else if (position_el->FindElement("altitudeMSL")) {
position.SetRadius(sea_level_radius + position_el->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
} else {
@ -1096,7 +1110,7 @@ bool FGInitialCondition::Load_v2(void)
//
// Or, using quaternions (note reverse ordering compared to matrix representation):
//
// Q_b/l = Q_e/l * Q_b/i
// Q_b/l = Q_i/l * Q_b/i
FGQuaternion QuatI2Body = FGQuaternion(vOrient);
QuatI2Body.Normalize();
@ -1196,6 +1210,9 @@ bool FGInitialCondition::Load_v2(void)
FGColumnVector3 vLocalRate;
Element* attrate_el = document->FindElement("attitude_rate");
// Refer to Stevens and Lewis, 1.5-14a, pg. 49.
// This is the rotation rate of the "Local" frame, expressed in the local frame.
double radInv = 1.0 / position.GetRadius();
FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vUVW_NED(eEast),
@ -1209,11 +1226,11 @@ bool FGInitialCondition::Load_v2(void)
FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC");
if (frame == "eci") {
vLocalRate = Tl2b * (position.GetTi2l() * (vAttRate - vOmegaEarth) - vOmegaLocal);
vLocalRate = Tl2b * position.GetTi2l() * (vAttRate - vOmegaEarth);
} else if (frame == "ecef") {
vLocalRate = Tl2b * (position.GetTec2l() * vAttRate - vOmegaLocal);
vLocalRate = Tl2b * position.GetTec2l() * vAttRate;
} else if (frame == "local") {
vLocalRate = vAttRate;
vLocalRate = vAttRate + vOmegaLocal;
} else if (!frame.empty()) { // misspelling of frame
cerr << endl << fgred << " Attitude rate frame type: \"" << frame
@ -1221,11 +1238,11 @@ bool FGInitialCondition::Load_v2(void)
result = false;
} else if (frame.empty()) {
vLocalRate = vOmegaLocal;
}
} else { // Body frame attitude rate assumed 0 relative to local.
vLocalRate.InitMatrix();
vLocalRate = vOmegaLocal;
}
p = vLocalRate(eP);

View file

@ -41,19 +41,10 @@ scheme. */
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <cstdlib>
#include <iomanip>
#include "FGTrim.h"
#include "models/FGAtmosphere.h"
#include "FGInitialCondition.h"
#include "models/FGAircraft.h"
#include "models/FGMassBalance.h"
#include "models/FGGroundReactions.h"
#include "models/FGInertial.h"
#include "models/FGAerodynamics.h"
#include "models/FGPropulsion.h"
#include "models/propulsion/FGEngine.h"
#include "math/FGColumnVector3.h"
#if _MSC_VER
#pragma warning (disable : 4786 4788)
@ -63,7 +54,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTrim.cpp,v 1.13 2010/04/23 17:23:40 dpculp Exp $";
static const char *IdSrc = "$Id: FGTrim.cpp,v 1.15 2011/02/19 16:29:29 bcoconni Exp $";
static const char *IdHdr = ID_TRIM;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -241,7 +232,7 @@ bool FGTrim::DoTrim(void) {
fdmex->DisableOutput();
setEngineTrimMode(true);
fdmex->SetTrimStatus(true);
fgic->SetPRadpsIC(0.0);
fgic->SetQRadpsIC(0.0);
@ -358,7 +349,7 @@ bool FGTrim::DoTrim(void) {
for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
}
setEngineTrimMode(false);
fdmex->SetTrimStatus(false);
fdmex->EnableOutput();
return !trim_failed;
}
@ -625,15 +616,6 @@ void FGTrim::setDebug(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTrim::setEngineTrimMode(bool mode) {
FGPropulsion* prop = fdmex->GetPropulsion();
for (unsigned int i=0; i<prop->GetNumEngines(); i++) {
prop->GetEngine(i)->SetTrimMode(mode);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTrim::SetMode(TrimMode tt) {
ClearStates();
mode=tt;

View file

@ -60,7 +60,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TRIM "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
#define ID_TRIM "$Id: FGTrim.h,v 1.8 2011/01/24 13:01:55 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -120,7 +120,7 @@ CLASS DOCUMENTATION
@endcode
@author Tony Peden
@version "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
@version "$Id: FGTrim.h,v 1.8 2011/01/24 13:01:55 jberndt Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -176,7 +176,6 @@ private:
void setupTurn(void);
void updateRates(void);
void setEngineTrimMode(bool mode);
void setDebug(void);
public:

71
src/FDM/JSBSim/input_output/FGPropertyManager.cpp Normal file → Executable file
View file

@ -49,17 +49,17 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
namespace JSBSim {
bool FGPropertyManager::suppress_warning = true;
std::vector<std::string> FGPropertyManager::tied_properties;
std::vector<SGPropertyNode_ptr> FGPropertyManager::tied_properties;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Unbind(void)
{
vector<string>::iterator it;
vector<SGPropertyNode_ptr>::iterator it;
for (it = tied_properties.begin();it < tied_properties.end();it++)
{
Untie(*it);
}
(*it)->untie();
tied_properties.clear();
}
@ -102,7 +102,6 @@ FGPropertyManager::GetNode (const string &relpath, int index, bool create)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::HasNode (const string &path)
{
// Checking if a node exists shouldn't write a warning if it doesn't exist
@ -314,11 +313,17 @@ void FGPropertyManager::Untie (const string &name)
void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
{
if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer), useDefault))
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<bool>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(name);
if (debug_lvl & 0x20) std::cout << name << std::endl;
tied_properties.push_back(property);
if (debug_lvl & 0x20) cout << name << endl;
}
}
@ -327,11 +332,17 @@ void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
void FGPropertyManager::Tie (const string &name, int *pointer,
bool useDefault )
{
if (!tie(name.c_str(), SGRawValuePointer<int>(pointer), useDefault))
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<int>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(name);
if (debug_lvl & 0x20) std::cout << name << std::endl;
tied_properties.push_back(property);
if (debug_lvl & 0x20) cout << name << endl;
}
}
@ -340,11 +351,17 @@ void FGPropertyManager::Tie (const string &name, int *pointer,
void FGPropertyManager::Tie (const string &name, long *pointer,
bool useDefault )
{
if (!tie(name.c_str(), SGRawValuePointer<long>(pointer), useDefault))
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<long>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(name);
if (debug_lvl & 0x20) std::cout << name << std::endl;
tied_properties.push_back(property);
if (debug_lvl & 0x20) cout << name << endl;
}
}
@ -353,11 +370,17 @@ void FGPropertyManager::Tie (const string &name, long *pointer,
void FGPropertyManager::Tie (const string &name, float *pointer,
bool useDefault )
{
if (!tie(name.c_str(), SGRawValuePointer<float>(pointer), useDefault))
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<float>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(name);
if (debug_lvl & 0x20) std::cout << name << std::endl;
tied_properties.push_back(property);
if (debug_lvl & 0x20) cout << name << endl;
}
}
@ -365,11 +388,17 @@ void FGPropertyManager::Tie (const string &name, float *pointer,
void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault)
{
if (!tie(name.c_str(), SGRawValuePointer<double>(pointer), useDefault))
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
}
if (!property->tie(SGRawValuePointer<double>(pointer), useDefault))
cerr << "Failed to tie property " << name << " to a pointer" << endl;
else {
tied_properties.push_back(name);
if (debug_lvl & 0x20) std::cout << name << std::endl;
tied_properties.push_back(property);
if (debug_lvl & 0x20) cout << name << endl;
}
}

View file

@ -53,7 +53,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.17 2010/07/08 11:36:28 jberndt Exp $"
#define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.20 2011/02/13 00:42:45 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -77,7 +77,7 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
{
private:
static bool suppress_warning;
static std::vector<std::string> tied_properties;
static std::vector<SGPropertyNode_ptr> tied_properties;
public:
/// Constructor
FGPropertyManager(void) {suppress_warning = false;}
@ -532,10 +532,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
template <class V> inline void
Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter), useDefault))
std::cout << "Failed to tie property " << name << " to functions" << std::endl;
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
std::cerr << "Could not get or create property " << name << std::endl;
return;
}
if (!property->tie(SGRawValueFunctions<V>(getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
else {
tied_properties.push_back(name);
tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl;
}
}
@ -562,10 +568,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(), SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
std::cout << "Failed to tie property " << name << " to indexed functions" << std::endl;
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
std::cerr << "Could not get or create property " << name << std::endl;
return;
}
if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
else {
tied_properties.push_back(name);
tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl;
}
}
@ -594,10 +606,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
Tie (const std::string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(), SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
std::cout << "Failed to tie property " << name << " to object methods" << std::endl;
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
std::cerr << "Could not get or create property " << name << std::endl;
return;
}
if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
else {
tied_properties.push_back(name);
tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl;
}
}
@ -625,10 +643,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
void (T::*setter)(int, V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(), SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
std::cout << "Failed to tie property " << name << " to indexed object methods" << std::endl;
SGPropertyNode* property = getNode(name.c_str(), true);
if (!property) {
std::cerr << "Could not get or create property " << name << std::endl;
return;
}
if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
else {
tied_properties.push_back(name);
tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl;
}
}

40
src/FDM/JSBSim/input_output/FGScript.cpp Normal file → Executable file
View file

@ -54,7 +54,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGScript.cpp,v 1.43 2011/01/16 15:27:34 jberndt Exp $";
static const char *IdSrc = "$Id: FGScript.cpp,v 1.46 2011/02/18 12:44:16 jberndt Exp $";
static const char *IdHdr = ID_FGSCRIPT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -78,12 +78,19 @@ FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
FGScript::~FGScript()
{
unsigned int i;
unsigned int i, j;
for (i=0; i<local_properties.size(); i++) delete local_properties[i];
for (i=0; i<local_properties.size(); i++) {
delete local_properties[i]->value;
delete local_properties[i];
}
local_properties.clear();
for (i=0; i<Events.size(); i++) delete Events[i].Condition;
for (i=0; i<Events.size(); i++) {
delete Events[i].Condition;
for (j=0; j<Events[i].Functions.size(); j++)
delete Events[i].Functions[j];
}
Events.clear();
Debug(1);
@ -139,6 +146,8 @@ bool FGScript::LoadScript(string script, double deltaT)
StartTime = run_element->GetAttributeValueAsNumber("start");
FDMExec->Setsim_time(StartTime);
EndTime = run_element->GetAttributeValueAsNumber("end");
// Make sure that the desired time is reached and executed.
EndTime += 0.99*FDMExec->GetDeltaT();
if (deltaT == 0.0)
dt = run_element->GetAttributeValueAsNumber("dt");
@ -240,11 +249,13 @@ bool FGScript::LoadScript(string script, double deltaT)
newCondition = new FGCondition(condition_element, PropertyManager);
} catch(string str) {
cout << endl << fgred << str << reset << endl << endl;
delete newEvent;
return false;
}
newEvent->Condition = newCondition;
} else {
cerr << "No condition specified in script event " << newEvent->Name << endl;
delete newEvent;
return false;
}
@ -258,16 +269,29 @@ bool FGScript::LoadScript(string script, double deltaT)
// Notify about when this event is triggered?
if ((notify_element = event_element->FindElement("notify")) != 0) {
newEvent->Notify = true;
// Check here for new <description> tag that gets echoed
string notify_description = notify_element->FindElementValue("description");
if (!notify_description.empty()) {
newEvent->Description = notify_description;
}
notify_property_element = notify_element->FindElement("property");
while (notify_property_element) {
notifyPropertyName = notify_property_element->GetDataLine();
if (PropertyManager->GetNode(notifyPropertyName)) {
newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) );
string caption_attribute = notify_property_element->GetAttributeValue("caption");
if (caption_attribute.empty()) {
newEvent->DisplayString.push_back(notifyPropertyName);
} else {
newEvent->DisplayString.push_back(caption_attribute);
}
} else {
cout << endl << fgred << " Could not find the property named "
<< notifyPropertyName << " in script" << endl << " \""
<< ScriptName << "\". Execution is aborted. Please recheck "
<< "your input files and scripts." << reset << endl;
delete newEvent->Condition;
delete newEvent;
return false;
}
notify_property_element = notify_element->FindNextElement("property");
@ -339,7 +363,7 @@ bool FGScript::RunScript(void)
double currentTime = FDMExec->GetSimTime();
double newSetValue = 0;
if (currentTime > EndTime) return false; //Script done!
if (currentTime > EndTime) return false;
// Iterate over all events.
for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
@ -426,8 +450,12 @@ bool FGScript::RunScript(void)
if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
<< " executed at time: " << currentTime << endl;
if (!Events[ev_ctr].Description.empty()) {
cout << " " << Events[ev_ctr].Description << endl;
}
for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
cout << " " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
// cout << " " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
cout << " " << Events[ev_ctr].DisplayString[j]
<< " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
}
cout << endl;

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FGSCRIPT "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
#define ID_FGSCRIPT "$Id: FGScript.h,v 1.20 2011/02/11 12:43:28 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -157,7 +157,7 @@ CLASS DOCUMENTATION
comes the &quot;run&quot; section, where the conditions are
described in &quot;event&quot; clauses.</p>
@author Jon S. Berndt
@version "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
@version "$Id: FGScript.h,v 1.20 2011/02/11 12:43:28 jberndt Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -178,7 +178,7 @@ public:
has been supplied on the command line, it will be override the script-
specified simulation step size.
@param script the filename (including path name, if any) for the script.
@param deltaT a simulation step size from the command line
@param deltaT a simulation step size.
@return true if successful */
bool LoadScript(string script, double deltaT);
@ -215,8 +215,10 @@ private:
double StartTime;
double TimeSpan;
string Name;
string Description;
vector <FGPropertyManager*> SetParam;
vector <FGPropertyManager*> NotifyProperties;
vector <string> DisplayString;
vector <eAction> Action;
vector <eType> Type;
vector <double> SetValue;

8
src/FDM/JSBSim/input_output/FGXMLElement.cpp Normal file → Executable file
View file

@ -42,7 +42,7 @@ FORWARD DECLARATIONS
namespace JSBSim {
static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.31 2010/09/29 02:22:03 jberndt Exp $";
static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.32 2011/02/13 00:42:45 jberndt Exp $";
static const char *IdHdr = ID_XMLELEMENT;
bool Element::converterIsInitialized = false;
@ -64,6 +64,8 @@ Element::Element(const string& nm)
// Length
convert["M"]["FT"] = 3.2808399;
convert["FT"]["M"] = 1.0/convert["M"]["FT"];
convert["KM"]["FT"] = 3280.8399;
convert["FT"]["KM"] = 1.0/convert["KM"]["FT"];
convert["FT"]["IN"] = 12.0;
convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
@ -121,6 +123,8 @@ Element::Element(const string& nm)
convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
convert["M/SEC"]["FT/SEC"] = 3.2808399;
convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"];
convert["KM/SEC"]["FT/SEC"] = 3280.8399;
convert["FT/SEC"]["KM/SEC"] = 1.0/convert["KM/SEC"]["FT/SEC"];
// Torque
convert["FT*LBS"]["N*M"] = 1.35581795;
convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
@ -153,6 +157,7 @@ Element::Element(const string& nm)
// Length
convert["M"]["M"] = 1.00;
convert["KM"]["KM"] = 1.00;
convert["FT"]["FT"] = 1.00;
convert["IN"]["IN"] = 1.00;
// Area
@ -195,6 +200,7 @@ Element::Element(const string& nm)
convert["KTS"]["KTS"] = 1.00;
convert["M/S"]["M/S"] = 1.0;
convert["M/SEC"]["M/SEC"] = 1.0;
convert["KM/SEC"]["KM/SEC"] = 1.0;
// Torque
convert["FT*LBS"]["FT*LBS"] = 1.00;
convert["N*M"]["N*M"] = 1.00;

View file

@ -35,6 +35,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGCondition.h"
#include "FGPropertyValue.h"
#include "input_output/FGXMLElement.h"
#include "input_output/FGPropertyManager.h"
#include <iostream>
@ -44,7 +45,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGCondition.cpp,v 1.13 2010/07/14 05:50:40 ehofman Exp $";
static const char *IdSrc = "$Id: FGCondition.cpp,v 1.14 2011/04/05 20:20:21 andgi Exp $";
static const char *IdHdr = ID_CONDITION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -122,12 +123,11 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
exit(-1);
}
TestParam1 = PropertyManager->GetNode(property1, false);
if (!TestParam1) {
cerr << fgred << " In condition: " << test << ". Unknown property "
<< property1 << " referenced." << endl
<< "Creating property. Check usage." << reset << endl;
TestParam1 = PropertyManager->GetNode(property1, true);
FGPropertyManager *node = PropertyManager->GetNode(property1, false);
if (node) {
TestParam1 = new FGPropertyValue(node);
} else {
TestParam1 = new FGPropertyValue(property1, PropertyManager);
}
Comparison = mComparison[conditional];
if (Comparison == ecUndef) {
@ -136,12 +136,11 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
if (is_number(property2)) {
TestValue = atof(property2.c_str());
} else {
TestParam2 = PropertyManager->GetNode(property2, false);
if (!TestParam2) {
cerr << fgred << " In condition: " << test << ". Unknown property "
<< property2 << " referenced." << endl
<< "Creating property. Check usage." << reset << endl;
TestParam2 = PropertyManager->GetNode(property2, true);
node = PropertyManager->GetNode(property2, false);
if (node) {
TestParam2 = new FGPropertyValue(node);
} else {
TestParam2 = new FGPropertyValue(property2, PropertyManager);
}
}
}
@ -174,6 +173,8 @@ void FGCondition::InitializeConditionals(void)
FGCondition::~FGCondition(void)
{
delete TestParam1;
delete TestParam2;
for (unsigned int i=0; i<conditions.size(); i++) delete conditions[i];
Debug(1);
@ -267,11 +268,11 @@ void FGCondition::PrintCondition(void )
} else {
if (TestParam2 != 0L)
cout << " " << TestParam1->GetRelativeName() << " "
cout << " " << TestParam1->GetName() << " "
<< conditional << " "
<< TestParam2->GetRelativeName();
<< TestParam2->GetName();
else
cout << " " << TestParam1->GetRelativeName() << " "
cout << " " << TestParam1->GetName() << " "
<< conditional << " " << TestValue;
}
}

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_CONDITION "$Id: FGCondition.h,v 1.5 2009/10/24 22:59:30 jberndt Exp $"
#define ID_CONDITION "$Id: FGCondition.h,v 1.6 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -53,6 +53,7 @@ FORWARD DECLARATIONS
namespace JSBSim {
class FGPropertyManager;
class FGPropertyValue;
class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -82,7 +83,8 @@ private:
std::map <std::string, eComparison> mComparison;
eLogic Logic;
FGPropertyManager *TestParam1, *TestParam2, *PropertyManager;
FGPropertyManager *PropertyManager;
FGPropertyValue *TestParam1, *TestParam2;
double TestValue;
eComparison Comparison;
bool isGroup;

20
src/FDM/JSBSim/math/FGFunction.cpp Normal file → Executable file
View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFunction.cpp,v 1.35 2010/08/28 12:41:56 jberndt Exp $";
static const char *IdSrc = "$Id: FGFunction.cpp,v 1.36 2011/04/05 20:20:21 andgi Exp $";
static const char *IdHdr = ID_FUNCTION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -177,9 +177,10 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
newNode = PropertyManager->GetNode(property_name);
Parameters.push_back(new FGPropertyValue( newNode ));
} else {
cerr << fgcyan << "The property " + property_name + " is initially undefined."
cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined."
<< reset << endl;
Parameters.push_back(new FGPropertyValue( property_name ));
Parameters.push_back(new FGPropertyValue( property_name,
PropertyManager ));
}
} else if (operation == value_string || operation == v_string) {
Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
@ -252,17 +253,8 @@ double FGFunction::GetValue(void) const
if (cached) return cachedValue;
try {
temp = Parameters[0]->GetValue();
} catch (string prop) {
if (PropertyManager->HasNode(prop)) {
((FGPropertyValue*)Parameters[0])->SetNode(PropertyManager->GetNode(prop));
temp = Parameters[0]->GetValue();
} else {
throw("Property " + prop + " was not defined anywhere.");
}
}
temp = Parameters[0]->GetValue();
switch (Type) {
case eTopLevel:
break;

6
src/FDM/JSBSim/math/FGParameter.h Normal file → Executable file
View file

@ -40,7 +40,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PARAMETER "$Id: FGParameter.h,v 1.5 2009/08/30 03:51:28 jberndt Exp $"
#define ID_PARAMETER "$Id: FGParameter.h,v 1.6 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -65,6 +65,10 @@ class FGParameter : public FGJSBBase
public:
virtual ~FGParameter(void) {};
virtual double GetValue(void) const = 0;
virtual std::string GetName(void) const = 0;
// SGPropertyNode impersonation.
double getDoubleValue(void) const { return GetValue(); }
protected:
};

38
src/FDM/JSBSim/math/FGPropertyValue.cpp Normal file → Executable file
View file

@ -6,6 +6,7 @@ Date started: 12/10/2004
Purpose: Stores property values
------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) -------------
------ Copyright (C) 2010 - 2011 Anders Gidenstam (anders(at)gidenstam.org) -
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
@ -32,36 +33,53 @@ INCLUDES
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.6 2010/08/24 10:30:14 jberndt Exp $";
static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.7 2011/04/05 20:20:21 andgi Exp $";
static const char *IdHdr = ID_PROPERTYVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode) : PropertyManager(propNode)
FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode)
: PropertyManager(0L), PropertyNode(propNode)
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyValue::FGPropertyValue(std::string propName) : PropertyManager(0L)
FGPropertyValue::FGPropertyValue(std::string propName, FGPropertyManager* propertyManager)
: PropertyManager(propertyManager), PropertyNode(0L), PropertyName(propName)
{
PropertyName = propName;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGPropertyValue::GetValue(void) const
{
double val;
try {
val = PropertyManager->getDoubleValue();
} catch (...) {
throw(PropertyName);
FGPropertyManager* node = PropertyNode;
if (!PropertyNode) {
// The node cannot be cached since this is a const method.
node = PropertyManager->GetNode(PropertyName);
if (!node) {
throw(std::string("FGPropertyValue::GetValue() The property " +
PropertyName + " does not exist."));
}
}
return val;
return node->getDoubleValue();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
std::string FGPropertyValue::GetName(void) const
{
if (PropertyNode) {
return PropertyNode->GetName();
} else {
return PropertyName;
}
}
}

16
src/FDM/JSBSim/math/FGPropertyValue.h Normal file → Executable file
View file

@ -5,6 +5,7 @@ Author: Jon Berndt
Date started: December 10 2004
------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) -------------
------ Copyright (C) 2010 - 2011 Anders Gidenstam (anders(at)gidenstam.org) -
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
@ -41,7 +42,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.8 2010/08/24 10:30:14 jberndt Exp $"
#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.9 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -53,8 +54,8 @@ namespace JSBSim {
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Represents a property value
@author Jon Berndt
/** Represents a property value which can use late binding.
@author Jon Berndt, Anders Gidenstam
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -66,14 +67,17 @@ class FGPropertyValue : public FGParameter
public:
FGPropertyValue(FGPropertyManager* propNode);
FGPropertyValue(std::string propName);
FGPropertyValue(std::string propName, FGPropertyManager* propertyManager);
~FGPropertyValue() {};
double GetValue(void) const;
void SetNode(FGPropertyManager* node) {PropertyManager = node;}
void SetNode(FGPropertyManager* node) {PropertyNode = node;}
std::string GetName(void) const;
private:
FGPropertyManager* PropertyManager;
FGPropertyManager* PropertyManager; // Property root used to do late binding.
FGPropertyManager* PropertyNode;
std::string PropertyName;
};

View file

@ -40,7 +40,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_REALVALUE "$Id: FGRealValue.h,v 1.4 2009/08/30 03:51:28 jberndt Exp $"
#define ID_REALVALUE "$Id: FGRealValue.h,v 1.5 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -68,6 +68,7 @@ public:
~FGRealValue() {};
double GetValue(void) const;
std::string GetName(void) const {return "constant";}
private:
double Value;

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TABLE "$Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $"
#define ID_TABLE "$Id: FGTable.h,v 1.13 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
@endcode
@author Jon S. Berndt
@version $Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $
@version $Id: FGTable.h,v 1.13 2011/04/05 20:20:21 andgi Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -292,6 +292,8 @@ public:
void Print(void);
std::string GetName(void) const {return Name;}
private:
enum type {tt1D, tt2D, tt3D} Type;
enum axis {eRow=0, eColumn, eTable};

View file

@ -52,7 +52,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.36 2011/01/19 12:41:19 jberndt Exp $";
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.37 2011/03/11 13:02:26 jberndt Exp $";
static const char *IdHdr = ID_AERODYNAMICS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -80,7 +80,7 @@ FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
axisType = atNone;
Coeff = new CoeffArray[6];
AeroFunctions = new AeroFunctionArray[6];
impending_stall = stall_hyst = 0.0;
alphaclmin = alphaclmax = 0.0;
@ -103,10 +103,10 @@ FGAerodynamics::~FGAerodynamics()
unsigned int i,j;
for (i=0; i<6; i++)
for (j=0; j<Coeff[i].size(); j++)
delete Coeff[i][j];
for (j=0; j<AeroFunctions[i].size(); j++)
delete AeroFunctions[i][j];
delete[] Coeff;
delete[] AeroFunctions;
delete AeroRPShift;
@ -142,7 +142,7 @@ bool FGAerodynamics::Run(void)
const double alpha=FDMExec->GetAuxiliary()->Getalpha();
const double twovel=2*FDMExec->GetAuxiliary()->GetVt();
const double qbar = FDMExec->GetAuxiliary()->Getqbar();
const double wingarea = FDMExec->GetAircraft()->GetWingArea();
const double wingarea = FDMExec->GetAircraft()->GetWingArea(); // TODO: Make these constants constant!
const double wingspan = FDMExec->GetAircraft()->GetWingSpan();
const double wingchord = FDMExec->GetAircraft()->Getcbar();
const double wingincidence = FDMExec->GetAircraft()->GetWingIncidence();
@ -177,8 +177,8 @@ bool FGAerodynamics::Run(void)
vFnative.InitMatrix();
for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) {
vFnative(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue();
for (ctr=0; ctr < AeroFunctions[axis_ctr].size(); ctr++) {
vFnative(axis_ctr+1) += AeroFunctions[axis_ctr][ctr]->GetValue();
}
}
@ -224,8 +224,8 @@ bool FGAerodynamics::Run(void)
vMoments = vDXYZcg*vForces; // M = r X F
for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) {
vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->GetValue();
for (ctr = 0; ctr < AeroFunctions[axis_ctr+3].size(); ctr++) {
vMoments(axis_ctr+1) += AeroFunctions[axis_ctr+3][ctr]->GetValue();
}
}
@ -349,7 +349,7 @@ bool FGAerodynamics::Load(Element *element)
axis_element = document->FindElement("axis");
while (axis_element) {
CoeffArray ca;
AeroFunctionArray ca;
axis = axis_element->GetAttributeValue("name");
function_element = axis_element->FindElement("function");
while (function_element) {
@ -363,7 +363,7 @@ bool FGAerodynamics::Load(Element *element)
}
function_element = axis_element->FindNextElement("function");
}
Coeff[AxisIdx[axis]] = ca;
AeroFunctions[AxisIdx[axis]] = ca;
axis_element = document->FindNextElement("axis");
}
@ -427,35 +427,35 @@ void FGAerodynamics::DetermineAxisSystem()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGAerodynamics::GetCoefficientStrings(const string& delimeter) const
string FGAerodynamics::GetAeroFunctionStrings(const string& delimeter) const
{
string CoeffStrings = "";
string AeroFunctionStrings = "";
bool firstime = true;
unsigned int axis, sd;
for (axis = 0; axis < 6; axis++) {
for (sd = 0; sd < Coeff[axis].size(); sd++) {
for (sd = 0; sd < AeroFunctions[axis].size(); sd++) {
if (firstime) {
firstime = false;
} else {
CoeffStrings += delimeter;
AeroFunctionStrings += delimeter;
}
CoeffStrings += Coeff[axis][sd]->GetName();
AeroFunctionStrings += AeroFunctions[axis][sd]->GetName();
}
}
return CoeffStrings;
return AeroFunctionStrings;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGAerodynamics::GetCoefficientValues(const string& delimeter) const
string FGAerodynamics::GetAeroFunctionValues(const string& delimeter) const
{
ostringstream buf;
for (unsigned int axis = 0; axis < 6; axis++) {
for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
for (unsigned int sd = 0; sd < AeroFunctions[axis].size(); sd++) {
if (buf.tellp() > 0) buf << delimeter;
buf << setw(9) << Coeff[axis][sd]->GetValue();
buf << setw(9) << AeroFunctions[axis][sd]->GetValue();
}
}

View file

@ -52,7 +52,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.21 2010/11/18 12:38:06 jberndt Exp $"
#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -89,7 +89,7 @@ CLASS DOCUMENTATION
{function contents}
</function>
<axis name="{LIFT | DRAG | SIDE | ROLL | PITCH | YAW}">
{force coefficient definitions}
{force or moment definitions}
</axis>
{additional axis definitions}
</aerodynamics>
@ -103,13 +103,13 @@ CLASS DOCUMENTATION
<br>
2) Axial-Normal coordinate system:
@code
<axis name="{AXIAL | NORMAL}">
<axis name="{AXIAL | NORMAL | SIDE}">
@endcode
<br>
Systems may NOT be combined, or a load error will occur.
@author Jon S. Berndt, Tony Peden
@version $Revision: 1.21 $
@version $Revision: 1.22 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -186,16 +186,16 @@ public:
void SetAlphaCLMax(double tt) { alphaclmax=tt; }
void SetAlphaCLMin(double tt) { alphaclmin=tt; }
/** Gets the strings for the current set of coefficients.
/** Gets the strings for the current set of aero functions.
@param delimeter either a tab or comma string depending on output type
@return a string containing the descriptive names for all coefficients */
std::string GetCoefficientStrings(const std::string& delimeter) const;
@return a string containing the descriptive names for all aero functions */
std::string GetAeroFunctionStrings(const std::string& delimeter) const;
/** Gets the coefficient values.
/** Gets the aero function values.
@param delimeter either a tab or comma string depending on output type
@return a string containing the numeric values for the current set of
coefficients */
std::string GetCoefficientValues(const std::string& delimeter) const;
aero functions */
std::string GetAeroFunctionValues(const std::string& delimeter) const;
/** Calculates and returns the wind-to-body axis transformation matrix.
@return a reference to the wind-to-body transformation matrix.
@ -207,15 +207,15 @@ public:
*/
FGMatrix33& GetTb2w(void);
std::vector <FGFunction*> * GetCoeff(void) const { return Coeff; }
std::vector <FGFunction*> * GetAeroFunctions(void) const { return AeroFunctions; }
private:
enum eAxisType {atNone, atLiftDrag, atAxialNormal, atBodyXYZ} axisType;
typedef std::map<std::string,int> AxisIndex;
AxisIndex AxisIdx;
FGFunction* AeroRPShift;
typedef vector <FGFunction*> CoeffArray;
CoeffArray* Coeff;
typedef vector <FGFunction*> AeroFunctionArray;
AeroFunctionArray* AeroFunctions;
FGColumnVector3 vFnative;
FGColumnVector3 vFw;
FGColumnVector3 vForces;

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.41 2010/11/30 12:19:57 jberndt Exp $";
static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.42 2011/02/18 12:44:16 jberndt Exp $";
static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -124,6 +124,7 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
FGAtmosphere::~FGAtmosphere()
{
delete(POE_Table);
Debug(1);
}

View file

@ -59,7 +59,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.45 2010/11/18 12:38:06 jberndt Exp $";
static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.47 2011/03/29 11:49:27 jberndt Exp $";
static const char *IdHdr = ID_AUXILIARY;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -180,33 +180,30 @@ bool FGAuxiliary::Run()
vAeroUVW = vUVW - wind;
Vt = vAeroUVW.Magnitude();
double Vt2 = Vt*Vt;
alpha = beta = adot = bdot = 0;
double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
if ( Vt > 1.0 ) {
if (vAeroUVW(eW) != 0.0)
alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
if (vAeroUVW(eV) != 0.0)
beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV),
sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
beta = mUW > 0.0 ? atan2(vAeroUVW(eV), sqrt(mUW)) : 0.0;
double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
double signU=1;
if (vAeroUVW(eU) < 0.0) signU=-1;
if ( mUW < 1.0 ) {
adot = 0.0;
bdot = 0.0;
} else {
if ( mUW >= 1.0 ) {
adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW;
bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU)
+ vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
bdot = (signU*mUW*vUVWdot(eV)
- vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU) + vAeroUVW(eW)*vUVWdot(eW)))/(Vt2*sqrt(mUW));
}
} else {
alpha = beta = adot = bdot = 0;
}
Re = Vt * FDMExec->GetAircraft()->Getcbar() / FDMExec->GetAtmosphere()->GetKinematicViscosity();
qbar = 0.5*density*Vt*Vt;
qbarUW = 0.5*density*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
qbar = 0.5*density*Vt2;
qbarUW = 0.5*density*(mUW);
qbarUV = 0.5*density*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
Mach = Vt / soundspeed;
MachU = vMachUVW(eU) = vAeroUVW(eU) / soundspeed;
@ -291,6 +288,7 @@ bool FGAuxiliary::Run()
//
// A positive headwind is blowing with you, a negative headwind is blowing against you.
// psi is the direction the wind is blowing *towards*.
// ToDo: should this simply be in the atmosphere class? Same with Get Crosswind.
double FGAuxiliary::GetHeadWind(void) const
{

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.14 2010/11/18 12:38:06 jberndt Exp $";
static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.16 2011/03/23 11:58:29 jberndt Exp $";
static const char *IdHdr = ID_BUOYANTFORCES;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -213,13 +213,13 @@ string FGBuoyantForces::GetBuoyancyStrings(string delimeter)
}
for (axis = 0; axis < 6; axis++) {
for (sd = 0; sd < Coeff[axis].size(); sd++) {
for (sd = 0; sd < AeroFunctions[axis].size(); sd++) {
if (firstime) {
firstime = false;
} else {
CoeffStrings += delimeter;
}
CoeffStrings += Coeff[axis][sd]->GetName();
CoeffStrings += AeroFunctions[axis][sd]->GetName();
}
}
*/
@ -243,13 +243,13 @@ string FGBuoyantForces::GetBuoyancyValues(string delimeter)
}
for (unsigned int axis = 0; axis < 6; axis++) {
for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
for (unsigned int sd = 0; sd < AeroFunctions[axis].size(); sd++) {
if (firstime) {
firstime = false;
} else {
SDValues += delimeter;
}
SDValues += Coeff[axis][sd]->GetValueAsString();
SDValues += AeroFunctions[axis][sd]->GetValueAsString();
}
}
*/
@ -260,19 +260,20 @@ string FGBuoyantForces::GetBuoyancyValues(string delimeter)
void FGBuoyantForces::bind(void)
{
typedef double (FGBuoyantForces::*PMF)(int) const;
typedef double (FGBuoyantForces::*PGF)(int) const;
typedef void (FGBuoyantForces::*PSF)(int, double);
PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL,
(PMF)&FGBuoyantForces::GetMoments);
(PGF)&FGBuoyantForces::GetMoments, (PSF)0, false);
PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM,
(PMF)&FGBuoyantForces::GetMoments);
(PGF)&FGBuoyantForces::GetMoments, (PSF)0, false);
PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN,
(PMF)&FGBuoyantForces::GetMoments);
(PGF)&FGBuoyantForces::GetMoments, (PSF)0, false);
PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX,
(PMF)&FGBuoyantForces::GetForces);
(PGF)&FGBuoyantForces::GetForces, (PSF)0, false);
PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY,
(PMF)&FGBuoyantForces::GetForces);
(PGF)&FGBuoyantForces::GetForces, (PSF)0, false);
PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ,
(PMF)&FGBuoyantForces::GetForces);
(PGF)&FGBuoyantForces::GetForces, (PSF)0, false);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -63,7 +63,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.72 2010/11/18 12:38:06 jberndt Exp $";
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.73 2011/04/05 20:20:21 andgi Exp $";
static const char *IdHdr = ID_FCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -182,17 +182,6 @@ bool FGFCS::InitModel(void)
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::LateBind(void)
{
unsigned int i;
for (i=0; i<Systems.size(); i++) Systems[i]->LateBind();
for (i=0; i<APComponents.size(); i++) APComponents[i]->LateBind();
for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->LateBind();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Notes: In this logic the default engine commands are set. This is simply a

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCS "$Id: FGFCS.h,v 1.31 2010/09/22 11:33:40 jberndt Exp $"
#define ID_FCS "$Id: FGFCS.h,v 1.35 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -168,7 +168,7 @@ CLASS DOCUMENTATION
@property gear/tailhook-pos-norm
@author Jon S. Berndt
@version $Revision: 1.31 $
@version $Revision: 1.35 $
@see FGActuator
@see FGDeadBand
@see FGFCSFunction
@ -540,7 +540,7 @@ public:
FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
void LateBind(void);
bool GetTrimStatus(void) const { return FDMExec->GetTrimStatus(); }
private:
double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd;

View file

@ -62,7 +62,7 @@ DEFINITIONS
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id: FGLGear.cpp,v 1.79 2010/11/28 13:20:47 bcoconni Exp $";
static const char *IdSrc = "$Id: FGLGear.cpp,v 1.80 2011/01/24 13:01:56 jberndt Exp $";
static const char *IdHdr = ID_LGEAR;
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
@ -374,13 +374,15 @@ FGColumnVector3& FGLGear::GetBodyForces(void)
}
}
ReportTakeoffOrLanding();
if (!fdmex->GetTrimStatus()) {
ReportTakeoffOrLanding();
// Require both WOW and LastWOW to be true before checking crash conditions
// to allow the WOW flag to be used in terminating a scripted run.
if (WOW && lastWOW) CrashDetect();
// Require both WOW and LastWOW to be true before checking crash conditions
// to allow the WOW flag to be used in terminating a scripted run.
if (WOW && lastWOW) CrashDetect();
lastWOW = WOW;
lastWOW = WOW;
}
return FGForce::GetBodyForces();
}

View file

@ -57,7 +57,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGModel.cpp,v 1.16 2010/11/18 12:38:06 jberndt Exp $";
static const char *IdSrc = "$Id: FGModel.cpp,v 1.17 2011/02/16 12:30:53 jberndt Exp $";
static const char *IdHdr = ID_MODEL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -77,7 +77,7 @@ FGModel::FGModel(FGFDMExec* fdmex)
//must be brought up now.
PropertyManager = FDMExec->GetPropertyManager();
exe_ctr = 1;
exe_ctr = 0;
rate = 1;
if (debug_lvl & 2) cout << " FGModel Base Class" << endl;
@ -105,7 +105,7 @@ bool FGModel::Run()
if (rate == 1) return false; // Fast exit if nothing to do
if (exe_ctr >= rate) exe_ctr = 1;
if (exe_ctr >= rate) exe_ctr = 0;
if (exe_ctr++ == 1) return false;
else return true;

View file

@ -74,7 +74,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGOutput.cpp,v 1.50 2010/11/18 12:38:06 jberndt Exp $";
static const char *IdSrc = "$Id: FGOutput.cpp,v 1.54 2011/03/11 13:02:26 jberndt Exp $";
static const char *IdHdr = ID_OUTPUT;
// (stolen from FGFS native_fdm.cxx)
@ -182,21 +182,9 @@ bool FGOutput::Run(void)
{
if (FGModel::Run()) return true;
if (enabled && !FDMExec->IntegrationSuspended()&& !FDMExec->Holding()) {
if (enabled && !FDMExec->IntegrationSuspended() && !FDMExec->Holding()) {
RunPreFunctions();
if (Type == otSocket) {
SocketOutput();
} else if (Type == otFlightGear) {
FlightGearSocketOutput();
} else if (Type == otCSV || Type == otTab) {
DelimitedOutput(Filename);
} else if (Type == otTerminal) {
// Not done yet
} else if (Type == otNone) {
// Do nothing
} else {
// Not a valid type of output
}
Print();
RunPostFunctions();
}
return false;
@ -204,6 +192,25 @@ bool FGOutput::Run(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGOutput::Print(void)
{
if (Type == otSocket) {
SocketOutput();
} else if (Type == otFlightGear) {
FlightGearSocketOutput();
} else if (Type == otCSV || Type == otTab) {
DelimitedOutput(Filename);
} else if (Type == otTerminal) {
// Not done yet
} else if (Type == otNone) {
// Do nothing
} else {
// Not a valid type of output
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGOutput::SetType(const string& type)
{
if (type == "CSV") {
@ -296,6 +303,7 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter;
outstream << "V_{X_{inertial}} (ft/s)" + delimeter + "V_{Y_{inertial}} (ft/s)" + delimeter + "V_{Z_{inertial}} (ft/s)" + delimeter;
outstream << "V_{X_{ecef}} (ft/s)" + delimeter + "V_{Y_{ecef}} (ft/s)" + delimeter + "V_{Z_{ecef}} (ft/s)" + delimeter;
outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)";
}
if (SubSystems & ssForces) {
@ -359,8 +367,8 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << "Distance AGL (ft)" + delimeter;
outstream << "Terrain Elevation (ft)";
}
if (SubSystems & ssCoefficients) {
scratch = Aerodynamics->GetCoefficientStrings(delimeter);
if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetAeroFunctionStrings(delimeter);
if (scratch.length() != 0) outstream << delimeter << scratch;
}
if (SubSystems & ssFCS) {
@ -415,6 +423,7 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter;
outstream << Propagate->GetECEFVelocity().Dump(delimeter) << delimeter;
outstream << Propagate->GetVel().Dump(delimeter);
outstream.precision(10);
}
@ -475,8 +484,8 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << Propagate->GetTerrainElevation();
outstream.precision(10);
}
if (SubSystems & ssCoefficients) {
scratch = Aerodynamics->GetCoefficientValues(delimeter);
if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetAeroFunctionValues(delimeter);
if (scratch.length() != 0) outstream << delimeter << scratch;
}
if (SubSystems & ssFCS) {
@ -826,8 +835,8 @@ void FGOutput::SocketOutput(void)
socket->Append("Latitude (deg)");
socket->Append("Longitude (deg)");
}
if (SubSystems & ssCoefficients) {
scratch = Aerodynamics->GetCoefficientStrings(",");
if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetAeroFunctionStrings(",");
if (scratch.length() != 0) socket->Append(scratch);
}
if (SubSystems & ssFCS) {
@ -932,8 +941,8 @@ void FGOutput::SocketOutput(void)
socket->Append(Propagate->GetLocation().GetLatitudeDeg());
socket->Append(Propagate->GetLocation().GetLongitudeDeg());
}
if (SubSystems & ssCoefficients) {
scratch = Aerodynamics->GetCoefficientValues(",");
if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetAeroFunctionValues(",");
if (scratch.length() != 0) socket->Append(scratch);
}
if (SubSystems & ssFCS) {
@ -974,7 +983,7 @@ bool FGOutput::Load(Element* element)
{
string parameter="";
string name="";
int OutRate = 0;
double OutRate = 0.0;
unsigned int port;
Element *property_element;
@ -1003,7 +1012,7 @@ bool FGOutput::Load(Element* element)
BaseFilename = Filename = name;
}
if (!document->GetAttributeValue("rate").empty()) {
OutRate = (int)document->GetAttributeValueAsNumber("rate");
OutRate = document->GetAttributeValueAsNumber("rate");
} else {
OutRate = 1;
}
@ -1027,7 +1036,7 @@ bool FGOutput::Load(Element* element)
if (document->FindElementValue("position") == string("ON"))
SubSystems += ssPropagate;
if (document->FindElementValue("coefficients") == string("ON"))
SubSystems += ssCoefficients;
SubSystems += ssAeroFunctions;
if (document->FindElementValue("ground_reactions") == string("ON"))
SubSystems += ssGroundReactions;
if (document->FindElementValue("fcs") == string("ON"))
@ -1058,7 +1067,7 @@ bool FGOutput::Load(Element* element)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGOutput::SetRate(int rtHz)
void FGOutput::SetRate(double rtHz)
{
rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz);
if (rtHz > 0) {
@ -1128,7 +1137,7 @@ void FGOutput::Debug(int from)
if (SubSystems & ssMoments) cout << " Moments parameters logged" << endl;
if (SubSystems & ssAtmosphere) cout << " Atmosphere parameters logged" << endl;
if (SubSystems & ssMassProps) cout << " Mass parameters logged" << endl;
if (SubSystems & ssCoefficients) cout << " Coefficient parameters logged" << endl;
if (SubSystems & ssAeroFunctions) cout << " Coefficient parameters logged" << endl;
if (SubSystems & ssPropagate) cout << " Propagate parameters logged" << endl;
if (SubSystems & ssGroundReactions) cout << " Ground parameters logged" << endl;
if (SubSystems & ssFCS) cout << " FCS parameters logged" << endl;

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_OUTPUT "$Id: FGOutput.h,v 1.19 2010/10/31 04:48:46 jberndt Exp $"
#define ID_OUTPUT "$Id: FGOutput.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -124,7 +124,7 @@ CLASS DOCUMENTATION
propulsion ON|OFF
</pre>
NOTE that Time is always output with the data.
@version $Id: FGOutput.h,v 1.19 2010/10/31 04:48:46 jberndt Exp $
@version $Id: FGOutput.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -140,6 +140,7 @@ public:
bool InitModel(void);
bool Run(void);
void Print(void);
void DelimitedOutput(const std::string&);
void SocketOutput(void);
void FlightGearSocketOutput(void);
@ -153,7 +154,7 @@ public:
void SetSubsystems(int tt) {SubSystems = tt;}
void SetOutputFileName(const std::string& fname) {Filename = fname;}
void SetDirectivesFile(const std::string& fname) {DirectivesFile = fname;}
void SetRate(int rt);
void SetRate(double rt);
void Enable(void) { enabled = true; }
void Disable(void) { enabled = false; }
bool Toggle(void) {enabled = !enabled; return enabled;}
@ -171,7 +172,7 @@ public:
/** Subsystem: Moments (= 32) */ ssMoments = 32,
/** Subsystem: Atmosphere (= 64) */ ssAtmosphere = 64,
/** Subsystem: Mass Properties (= 128) */ ssMassProps = 128,
/** Subsystem: Coefficients (= 256) */ ssCoefficients = 256,
/** Subsystem: Coefficients (= 256) */ ssAeroFunctions = 256,
/** Subsystem: Propagate (= 512) */ ssPropagate = 512,
/** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024,
/** Subsystem: FCS (= 2048) */ ssFCS = 2048,

View file

@ -71,29 +71,35 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.76 2011/01/16 16:10:59 bcoconni Exp $";
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.85 2011/04/03 19:24:58 jberndt Exp $";
static const char *IdHdr = ID_PROPAGATE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex),
LocalTerrainRadius(0), SeaLevelRadius(0), VehicleRadius(0)
FGPropagate::FGPropagate(FGFDMExec* fdmex)
: FGModel(fdmex),
LocalTerrainRadius(0),
SeaLevelRadius(0),
VehicleRadius(0)
{
Debug(0);
Name = "FGPropagate";
gravType = gtWGS84;
vPQRdot.InitMatrix();
vPQRidot.InitMatrix();
vQtrndot = FGQuaternion(0,0,0);
vUVWdot.InitMatrix();
vUVWidot.InitMatrix();
vInertialVelocity.InitMatrix();
integrator_rotational_rate = eAdamsBashforth2;
integrator_translational_rate = eTrapezoidal;
integrator_rotational_position = eAdamsBashforth2;
integrator_translational_position = eTrapezoidal;
/// These define the indices use to select the various integrators.
// eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3, eAdamsBashforth4};
integrator_rotational_rate = eRectEuler;
integrator_translational_rate = eAdamsBashforth2;
integrator_rotational_position = eRectEuler;
integrator_translational_position = eAdamsBashforth3;
VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
@ -124,9 +130,9 @@ bool FGPropagate::InitModel(void)
VState.vLocation.SetEllipse(FDMExec->GetInertial()->GetSemimajor(), FDMExec->GetInertial()->GetSemiminor());
vOmegaEarth = FGColumnVector3( 0.0, 0.0, FDMExec->GetInertial()->omega() ); // Earth rotation vector
vPQRdot.InitMatrix();
vPQRidot.InitMatrix();
vQtrndot = FGQuaternion(0,0,0);
vUVWdot.InitMatrix();
vUVWidot.InitMatrix();
vInertialVelocity.InitMatrix();
VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
@ -189,23 +195,13 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
VehicleRadius = GetRadius();
double radInv = 1.0/VehicleRadius;
// Refer to Stevens and Lewis, 1.5-14a, pg. 49.
// This is the rotation rate of the "Local" frame, expressed in the local frame.
FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vVel(eEast),
-radInv*vVel(eNorth),
-radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
// Set the angular velocities of the body frame relative to the ECEF frame,
// expressed in the body frame. Effectively, this is:
// w_b/e = w_b/l + w_l/e
// expressed in the body frame.
VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
FGIC->GetQRadpsIC(),
FGIC->GetRRadpsIC() ) + Tl2b*vOmegaLocal;
FGIC->GetRRadpsIC() );
VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
VState.vPQRi_i = Tb2i * VState.vPQRi;
// Make an initial run and set past values
InitializeDerivatives();
@ -245,11 +241,10 @@ bool FGPropagate::Run(void)
CalculateUVWdot(); // Translational rate derivative
ResolveFrictionForces(dt); // Update rate derivatives with friction forces
CalculateQuatdot(); // Angular orientation derivative
CalculateUVW(); // Translational position derivative (velocities are integrated in the inertial frame)
// Propagate rotational / translational velocity, angular /translational position, respectively.
Integrate(VState.vPQRi_i, vPQRidot, VState.dqPQRidot, dt, integrator_rotational_rate); // ECI integration
Integrate(VState.vPQRi, vPQRidot, VState.dqPQRidot, dt, integrator_rotational_rate);
Integrate(VState.qAttitudeECI, vQtrndot, VState.dqQtrndot, dt, integrator_rotational_position);
Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position);
Integrate(VState.vInertialVelocity, vUVWidot, VState.dqUVWidot, dt, integrator_translational_rate);
@ -278,12 +273,13 @@ bool FGPropagate::Run(void)
// orientation quaternion and vLocation vector.
UpdateBodyMatrices();
CalculateUVW(); // Translational position derivative (velocities are integrated in the inertial frame)
// Set auxililary state variables
RecomputeLocalTerrainRadius();
VehicleRadius = GetRadius(); // Calculate current aircraft radius from center of planet
VState.vPQRi = Ti2b * VState.vPQRi_i;
VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
VState.qAttitudeLocal = Tl2b.GetQuaternion();
@ -321,8 +317,8 @@ void FGPropagate::CalculatePQRdot(void)
// moments and the total inertial angular velocity expressed in the body
// frame.
vPQRdot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi));
vPQRidot = Tb2i * vPQRdot;
vPQRidot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi));
vPQRdot = vPQRidot - VState.vPQRi * (Ti2b * vOmegaEarth);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -605,7 +601,7 @@ void FGPropagate::ResolveFrictionForces(double dt)
vUVWdot += invMass * Fc;
vUVWidot += invMass * Tb2i * Fc;
vPQRdot += Jinv * Mc;
vPQRidot += Tb2i* Jinv * Mc;
vPQRidot += Jinv * Mc;
// Save the value of the Lagrange multipliers to accelerate the convergence
// of the Gauss-Seidel algorithm at next iteration.
@ -658,8 +654,7 @@ void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::SetInertialRates(FGColumnVector3 vRates) {
VState.vPQRi_i = vRates;
VState.vPQRi = Ti2b * VState.vPQRi_i;
VState.vPQRi = Ti2b * vRates;
VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
}
@ -681,7 +676,7 @@ void FGPropagate::InitializeDerivatives(void)
VState.dqQtrndot.clear();
for (int i=0; i<4; i++) {
VState.dqPQRidot.push_front(vPQRidot);
VState.dqUVWidot.push_front(vUVWdot);
VState.dqUVWidot.push_front(vUVWidot);
VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
VState.dqQtrndot.push_front(vQtrndot);
}
@ -739,7 +734,6 @@ void FGPropagate::SetVState(const VehicleState& vstate)
vVel = Tb2l * VState.vUVW;
VState.vPQR = vstate.vPQR;
VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
VState.vPQRi_i = Tb2i * VState.vPQRi;
VState.vInertialPosition = vstate.vInertialPosition;
InitializeDerivatives();

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.55 2011/01/16 16:10:59 bcoconni Exp $"
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.58 2011/04/03 19:24:58 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -102,7 +102,7 @@ CLASS DOCUMENTATION
@endcode
@author Jon S. Berndt, Mathias Froehlich
@version $Id: FGPropagate.h,v 1.55 2011/01/16 16:10:59 bcoconni Exp $
@version $Id: FGPropagate.h,v 1.58 2011/04/03 19:24:58 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -135,11 +135,6 @@ public:
units rad/sec */
FGColumnVector3 vPQRi;
/** The angular velocity vector for the vehicle body frame relative to the
ECI frame, expressed in the ECI frame.
units rad/sec */
FGColumnVector3 vPQRi_i;
/** The current orientation of the vehicle, that is, the orientation of the
body frame relative to the local, NED frame. */
FGQuaternion qAttitudeLocal;
@ -338,6 +333,10 @@ public:
*/
const FGColumnVector3& GetInertialPosition(void) const { return VState.vInertialPosition; }
/** Calculates and retrieves the velocity vector relative to the earth centered earth fixed (ECEF) frame.
*/
const FGColumnVector3 GetECEFVelocity(void) const {return Tb2ec * VState.vUVW; }
/** Returns the current altitude above sea level.
This function returns the altitude above sea level.
units ft
@ -581,8 +580,8 @@ public:
void RecomputeLocalTerrainRadius(void);
void NudgeBodyLocation(FGColumnVector3 deltaLoc) {
vDeltaXYZEC = Tb2ec*deltaLoc;
VState.vLocation -= vDeltaXYZEC;
VState.vInertialPosition -= Tb2i*deltaLoc;
VState.vLocation -= Tb2ec*deltaLoc;
}
struct LagrangeMultiplier {
@ -602,8 +601,7 @@ private:
struct VehicleState VState;
FGColumnVector3 vVel;
FGColumnVector3 vPQRdot;
FGColumnVector3 vPQRidot;
FGColumnVector3 vPQRdot, vPQRidot;
FGColumnVector3 vUVWdot, vUVWidot;
FGColumnVector3 vInertialVelocity;
FGColumnVector3 vLocation;

View file

@ -65,7 +65,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.43 2010/11/18 12:38:06 jberndt Exp $";
static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.45 2011/02/13 00:42:45 jberndt Exp $";
static const char *IdHdr = ID_PROPULSION;
extern short debug_lvl;
@ -194,14 +194,16 @@ bool FGPropulsion::GetSteadyState(void)
double currentThrust = 0, lastThrust = -1;
int steady_count = 0, j = 0;
bool steady = false;
bool TrimMode = FDMExec->GetTrimStatus();
vForces.InitMatrix();
vMoments.InitMatrix();
if (!FGModel::Run()) {
FDMExec->SetTrimStatus(true);
for (unsigned int i=0; i<numEngines; i++) {
// cout << " Finding steady state for engine " << i << endl;
Engines[i]->SetTrimMode(true);
steady=false;
steady_count=0;
j=0;
@ -225,9 +227,10 @@ bool FGPropulsion::GetSteadyState(void)
// }
vForces += Engines[i]->GetBodyForces(); // sum body frame forces
vMoments += Engines[i]->GetMoments(); // sum body frame moments
Engines[i]->SetTrimMode(false);
}
FDMExec->SetTrimStatus(TrimMode);
return false;
} else {
return true;
@ -648,13 +651,13 @@ void FGPropulsion::bind(void)
IsBound = true;
PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, false);
if (HaveTurbineEngine) {
PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false);
PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, false);
}
if (HavePistonEngine) {
PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false);
PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, false);
}
PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGActuator.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdSrc = "$Id: FGActuator.cpp,v 1.17 2011/02/13 00:42:45 jberndt Exp $";
static const char *IdHdr = ID_ACTUATOR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -114,10 +114,12 @@ bool FGActuator::Run(void )
// the Input will be further processed and the eventual Output
// will be overwritten from this perfect value.
if (lag != 0.0) Lag(); // models actuator lag
if (rate_limit != 0) RateLimit(); // limit the actuator rate
if (!fcs->GetTrimStatus()) {
if (lag != 0.0) Lag(); // models actuator lag
if (rate_limit != 0) RateLimit(); // limit the actuator rate
}
if (deadband_width != 0.0) Deadband();
if (hysteresis_width != 0.0) Hysteresis();
if (!fcs->GetTrimStatus() && hysteresis_width != 0.0) Hysteresis();
if (bias != 0.0) Bias(); // models a finite bias
if (fail_stuck) Output = PreviousOutput;
@ -187,6 +189,18 @@ void FGActuator::RateLimit(void)
void FGActuator::Deadband(void)
{
// Note: this function acts cumulatively on the "Output" parameter. So, "Output"
// is - for the purposes of this Deadband method - really the input to the
// method.
double input = Output;
if (input < -deadband_width/2.0) {
Output = (input + deadband_width/2.0);
} else if (input > deadband_width/2.0) {
Output = (input - deadband_width/2.0);
} else {
Output = 0.0;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -232,9 +246,9 @@ void FGActuator::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl;
cout << " INPUT: -" << InputNames[0] << endl;
else
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNames[0] << endl;
if (IsOutput) {
for (unsigned int i=0; i<OutputNodes.size(); i++)

View file

@ -142,7 +142,7 @@ void FGDeadBand::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNodes[0]->GetName() << endl;
if (WidthPropertyNode != 0) {
cout << " DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl;
} else {

View file

@ -40,6 +40,7 @@ INCLUDES
#include "FGFCSComponent.h"
#include "input_output/FGPropertyManager.h"
#include "input_output/FGXMLElement.h"
#include "math/FGPropertyValue.h"
#include <iostream>
#include <cstdlib>
@ -47,7 +48,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.29 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.30 2011/04/05 20:20:21 andgi Exp $";
static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -111,8 +112,6 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
Name = element->GetAttributeValue("name");
FGPropertyManager *tmp=0;
input_element = element->FindElement("input");
while (input_element) {
input = input_element->GetDataLine();
@ -122,14 +121,14 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
} else {
InputSigns.push_back( 1.0);
}
FGPropertyManager* node = 0L;
if (PropertyManager->HasNode(input)) {
tmp = PropertyManager->GetNode(input);
node = PropertyManager->GetNode(input);
InputNodes.push_back(new FGPropertyValue( node ));
} else {
tmp = 0L;
// cerr << fgcyan << "In component: " + Name + " property "
// + input + " is initially undefined." << reset << endl;
InputNodes.push_back(new FGPropertyValue( input,
PropertyManager ));
}
InputNodes.push_back( tmp );
InputNames.push_back( input );
input_element = element->FindNextElement("input");
@ -200,6 +199,9 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
FGFCSComponent::~FGFCSComponent()
{
Debug(1);
for (unsigned int i=0; i<InputNodes.size(); i++) {
delete InputNodes[i];
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -238,24 +240,6 @@ void FGFCSComponent::Clip(void)
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::LateBind(void)
{
FGPropertyManager* node = 0L;
for (unsigned int i=0; i<InputNodes.size(); i++) {
if (!InputNodes[i]) {
if (PropertyManager->HasNode(InputNames[i])) {
node = PropertyManager->GetNode(InputNames[i]);
InputNodes[i] = node;
} else {
throw(InputNames[i]);
}
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// The old way of naming FCS components allowed upper or lower case, spaces, etc.

View file

@ -38,6 +38,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include "math/FGPropertyValue.h"
#include <string>
#include <vector>
@ -45,7 +46,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $"
#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.18 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -80,7 +81,7 @@ CLASS DOCUMENTATION
- FGActuator
@author Jon S. Berndt
@version $Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $
@version $Id: FGFCSComponent.h,v 1.18 2011/04/05 20:20:21 andgi Exp $
@see Documentation for the FGFCS class, and for the configuration file class
*/
@ -98,7 +99,6 @@ public:
virtual bool Run(void);
virtual void SetOutput(void);
void LateBind(void);
double GetOutput (void) const {return Output;}
std::string GetName(void) const {return Name;}
std::string GetType(void) const { return Type; }
@ -111,7 +111,7 @@ protected:
std::vector <FGPropertyManager*> OutputNodes;
FGPropertyManager* ClipMinPropertyNode;
FGPropertyManager* ClipMaxPropertyNode;
std::vector <FGPropertyManager*> InputNodes;
std::vector <FGPropertyValue*> InputNodes;
std::vector <std::string> InputNames;
std::vector <float> InputSigns;
std::vector <double> output_array;

View file

@ -121,7 +121,7 @@ void FGFCSFunction::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (InputNodes.size()>0)
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNodes[0]->GetName() << endl;
// cout << " Function: " << endl;
if (IsOutput) {
for (unsigned int i=0; i<OutputNodes.size(); i++)

View file

@ -259,7 +259,7 @@ void FGFilter::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNodes[0]->GetName() << endl;
switch (FilterType) {
case eLag:
if (PropertySign[1] < 0.0) sgn="-";

View file

@ -209,9 +209,9 @@ void FGGain::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl;
cout << " INPUT: -" << InputNodes[0]->GetName() << endl;
else
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNodes[0]->GetName() << endl;
if (GainPropertyNode != 0) {
cout << " GAIN: " << GainPropertyNode->GetName() << endl;

View file

@ -188,7 +188,7 @@ void FGKinemat::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNodes[0]->GetName() << endl;
cout << " DETENTS: " << NumDetents << endl;
for (int i=0;i<NumDetents;i++) {
cout << " " << Detents[i] << " " << TransitionTimes[i] << endl;

View file

@ -189,9 +189,9 @@ void FGPID::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl;
cout << " INPUT: -" << InputNodes[0]->GetName() << endl;
else
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNodes[0]->GetName() << endl;
if (IsOutput) {
for (unsigned int i=0; i<OutputNodes.size(); i++)

View file

@ -293,9 +293,9 @@ void FGSensor::Debug(int from)
if (from == 0) { // Constructor
if (InputSigns.size() > 0) {
if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl;
cout << " INPUT: -" << InputNodes[0]->GetName() << endl;
else
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " INPUT: " << InputNodes[0]->GetName() << endl;
}
if (bits != 0) {
if (quant_property.empty())

View file

@ -69,7 +69,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.19 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.20 2011/04/05 20:20:21 andgi Exp $";
static const char *IdHdr = ID_SWITCH;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -135,7 +135,13 @@ FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
} else {
current_test->sign = 1.0;
}
current_test->OutputProp = PropertyManager->GetNode(value);
FGPropertyManager *node = PropertyManager->GetNode(value, false);
if (node) {
current_test->OutputProp = new FGPropertyValue(node);
} else {
current_test->OutputProp = new FGPropertyValue(value,
PropertyManager);
}
}
}
}
@ -151,6 +157,7 @@ FGSwitch::~FGSwitch()
{
for (unsigned int i=0; i<tests.size(); i++) {
for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j];
delete tests[i]->OutputProp;
delete tests[i];
}

View file

@ -40,12 +40,13 @@ INCLUDES
#include "FGFCSComponent.h"
#include "input_output/FGXMLElement.h"
#include "math/FGCondition.h"
#include "math/FGPropertyValue.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_SWITCH "$Id: FGSwitch.h,v 1.13 2009/10/02 10:30:09 jberndt Exp $"
#define ID_SWITCH "$Id: FGSwitch.h,v 1.14 2011/04/05 20:20:21 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -124,7 +125,7 @@ ap/attitude_hold takes the value 1), the value of the switch component will be
whatever value fcs/roll-ap-error-summer is.
@author Jon S. Berndt
@version $Id: FGSwitch.h,v 1.13 2009/10/02 10:30:09 jberndt Exp $
@version $Id: FGSwitch.h,v 1.14 2011/04/05 20:20:21 andgi Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -156,12 +157,12 @@ private:
vector <FGCondition*> conditions;
eLogic Logic;
double OutputVal;
FGPropertyManager *OutputProp;
FGPropertyValue *OutputProp;
float sign;
double GetValue(void) {
if (OutputProp == 0L) return OutputVal;
else return OutputProp->getDoubleValue()*sign;
else return OutputProp->GetValue()*sign;
}
test(void) { // constructor for the test structure

View file

@ -50,7 +50,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGElectric.cpp,v 1.9 2010/08/21 17:13:48 jberndt Exp $";
static const char *IdSrc = "$Id: FGElectric.cpp,v 1.10 2011/03/10 01:35:25 dpculp Exp $";
static const char *IdHdr = ID_ELECTRIC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -92,16 +92,21 @@ void FGElectric::Calculate(void)
RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
HP = PowerWatts * Throttle / hptowatts;
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
Thruster->Calculate(PowerAvailable);
Thruster->Calculate(HP * hptoftlbssec);
RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGElectric::CalcFuelNeed(void)
{
return 0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGElectric::GetEngineLabels(const string& delimiter)
{
std::ostringstream buf;
@ -174,10 +179,4 @@ void FGElectric::Debug(int from)
}
}
double
FGElectric::CalcFuelNeed(void)
{
return 0;
}
} // namespace JSBSim

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ELECTRIC "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $";
#define ID_ELECTRIC "$Id: FGElectric.h,v 1.10 2011/03/10 01:35:25 dpculp Exp $";
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -65,7 +65,7 @@ CLASS DOCUMENTATION
there is no battery model available, so this motor does not consume any
energy. There is no internal friction.
@author David Culp
@version "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $"
@version "$Id: FGElectric.h,v 1.10 2011/03/10 01:35:25 dpculp Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -81,7 +81,7 @@ public:
~FGElectric();
void Calculate(void);
double GetPowerAvailable(void) {return PowerAvailable;}
double GetPowerAvailable(void) {return (HP * hptoftlbssec);}
double getRPM(void) {return RPM;}
std::string GetEngineLabels(const std::string& delimiter);
std::string GetEngineValues(const std::string& delimiter);
@ -91,7 +91,6 @@ private:
double CalcFuelNeed(void);
double BrakeHorsePower;
double PowerAvailable;
// timestep
double dt;
@ -101,7 +100,7 @@ private:
double PowerWatts; // maximum engine power
double RPM; // revolutions per minute
double HP;
double HP; // engine output, in horsepower
void Debug(int from);
};

View file

@ -54,7 +54,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGEngine.cpp,v 1.40 2010/10/15 11:32:41 jberndt Exp $";
static const char *IdSrc = "$Id: FGEngine.cpp,v 1.42 2011/03/03 12:16:26 jberndt Exp $";
static const char *IdHdr = ID_ENGINE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -151,6 +151,8 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust);
property_name = base_property_name + "/fuel-flow-rate-pps";
PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate);
property_name = base_property_name + "/fuel-used-lbs";
PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelUsedLbs);
PostLoad(engine_element, PropertyManager, to_string(EngineNumber));
@ -177,11 +179,11 @@ void FGEngine::ResetToIC(void)
FuelExpended = 0.0;
Starved = Running = Cranking = false;
PctPower = 0.0;
TrimMode = false;
FuelFlow_gph = 0.0;
FuelFlow_pph = 0.0;
FuelFlowRate = 0.0;
FuelFreeze = false;
FuelUsedLbs = 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -194,7 +196,7 @@ void FGEngine::ResetToIC(void)
void FGEngine::ConsumeFuel(void)
{
if (FuelFreeze) return;
if (TrimMode) return;
if (FDMExec->GetTrimStatus()) return;
unsigned int i;
double Fshortage, FuelNeeded;
@ -240,6 +242,7 @@ void FGEngine::ConsumeFuel(void)
Tank = Propulsion->GetTank(FeedList[i]);
Tank->Drain(FuelNeeded);
}
FuelUsedLbs += FuelToBurn;
}

View file

@ -55,7 +55,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ENGINE "$Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $"
#define ID_ENGINE "$Id: FGEngine.h,v 1.23 2011/03/03 12:16:26 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -118,7 +118,7 @@ CLASS DOCUMENTATION
documentation for engine and thruster classes.
</pre>
@author Jon S. Berndt
@version $Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $
@version $Id: FGEngine.h,v 1.23 2011/03/03 12:16:26 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -146,6 +146,7 @@ public:
virtual double getFuelFlow_gph () const {return FuelFlow_gph;}
virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
virtual double GetFuelFlowRate(void) const {return FuelFlowRate;}
virtual double GetFuelUsedLbs(void) const {return FuelUsedLbs;}
virtual bool GetStarved(void) { return Starved; }
virtual bool GetRunning(void) const { return Running; }
virtual bool GetCranking(void) { return Cranking; }
@ -173,9 +174,6 @@ public:
virtual double GetPowerAvailable(void) {return 0.0;};
virtual bool GetTrimMode(void) {return TrimMode;}
virtual void SetTrimMode(bool state) {TrimMode = state;}
virtual FGColumnVector3& GetBodyForces(void);
virtual FGColumnVector3& GetMoments(void);
@ -219,12 +217,12 @@ protected:
bool Starved;
bool Running;
bool Cranking;
bool TrimMode;
bool FuelFreeze;
double FuelFlow_gph;
double FuelFlow_pph;
double FuelDensity;
double FuelUsedLbs;
FGFDMExec* FDMExec;
FGAtmosphere* Atmosphere;

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGForce.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdSrc = "$Id: FGForce.cpp,v 1.15 2011/02/17 00:20:52 jberndt Exp $";
static const char *IdHdr = ID_FORCE;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -62,9 +62,20 @@ FGForce::FGForce(FGFDMExec *FDMExec) :
fdmex(FDMExec),
ttype(tNone)
{
mT(1,1) = 1; //identity matrix
mT(2,2) = 1;
mT(3,3) = 1;
vFn.InitMatrix();
vMn.InitMatrix();
vH.InitMatrix();
vOrient.InitMatrix();
vXYZn.InitMatrix();
vActingXYZn.InitMatrix();
vFb.InitMatrix();
vM.InitMatrix();
vDXYZ.InitMatrix();
mT.InitMatrix(1., 0., 0.,
0., 1., 0.,
0., 0., 1.);
Debug(0);
}

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPiston.cpp,v 1.54 2010/11/30 12:17:10 jberndt Exp $";
static const char *IdSrc = "$Id: FGPiston.cpp,v 1.55 2011/03/10 01:35:25 dpculp Exp $";
static const char *IdHdr = ID_PISTON;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -442,8 +442,7 @@ void FGPiston::Calculate(void)
((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
}
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
Thruster->Calculate(PowerAvailable);
Thruster->Calculate(HP * hptoftlbssec);
RunPostFunctions();
}
@ -872,7 +871,7 @@ string FGPiston::GetEngineLabels(const string& delimiter)
{
std::ostringstream buf;
buf << Name << " Power Available (engine " << EngineNumber << " in HP)" << delimiter
buf << Name << " Power Available (engine " << EngineNumber << " in ft-lbs/sec)" << delimiter
<< Name << " HP (engine " << EngineNumber << ")" << delimiter
<< Name << " equivalent ratio (engine " << EngineNumber << ")" << delimiter
<< Name << " MAP (engine " << EngineNumber << " in inHg)" << delimiter
@ -887,7 +886,7 @@ string FGPiston::GetEngineValues(const string& delimiter)
{
std::ostringstream buf;
buf << PowerAvailable << delimiter << HP << delimiter
buf << (HP * hptoftlbssec) << delimiter << HP << delimiter
<< equivalence_ratio << delimiter << ManifoldPressure_inHg << delimiter
<< Thruster->GetThrusterValues(EngineNumber, delimiter);

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PISTON "$Id: FGPiston.h,v 1.25 2010/11/30 12:17:10 jberndt Exp $";
#define ID_PISTON "$Id: FGPiston.h,v 1.26 2011/03/10 01:35:25 dpculp Exp $";
#define FG_MAX_BOOST_SPEEDS 3
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -182,7 +182,7 @@ CLASS DOCUMENTATION
@author Dave Luff (engine operational code)
@author David Megginson (initial porting and additional code)
@author Ron Jensen (additional engine code)
@version $Id: FGPiston.h,v 1.25 2010/11/30 12:17:10 jberndt Exp $
@version $Id: FGPiston.h,v 1.26 2011/03/10 01:35:25 dpculp Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -201,7 +201,7 @@ public:
std::string GetEngineValues(const std::string& delimiter);
void Calculate(void);
double GetPowerAvailable(void) const {return PowerAvailable;}
double GetPowerAvailable(void) const {return (HP * hptoftlbssec);}
double CalcFuelNeed(void);
void ResetToIC(void);
@ -227,7 +227,6 @@ private:
double FMEP;
double FMEPDynamic;
double FMEPStatic;
double PowerAvailable;
// timestep
double dt;

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.32 2010/10/21 03:27:40 jberndt Exp $";
static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.33 2011/03/10 01:35:25 dpculp Exp $";
static const char *IdHdr = ID_PROPELLER;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -185,23 +185,22 @@ FGPropeller::~FGPropeller()
// We must be getting the aerodynamic velocity here, NOT the inertial velocity.
// We need the velocity with respect to the wind.
//
// Note that PowerAvailable is the excess power available after the drag of the
// propeller has been subtracted. At equilibrium, PowerAvailable will be zero -
// indicating that the propeller will not accelerate or decelerate.
// Remembering that Torque * omega = Power, we can derive the torque on the
// propeller and its acceleration to give a new RPM. The current RPM will be
// used to calculate thrust.
//
// Because RPM could be zero, we need to be creative about what RPM is stated as.
double FGPropeller::Calculate(double PowerAvailable)
double FGPropeller::Calculate(double EnginePower)
{
double omega, alpha, beta;
double omega, alpha, beta, PowerAvailable;
double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU);
double rho = fdmex->GetAtmosphere()->GetDensity();
double RPS = RPM/60.0;
PowerAvailable = EnginePower - GetPowerRequired();
// Calculate helical tip Mach
double Area = 0.25*Diameter*Diameter*M_PI;
double Vtip = RPS * Diameter * M_PI;

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPELLER "$Id: FGPropeller.h,v 1.16 2010/04/09 12:44:06 jberndt Exp $"
#define ID_PROPELLER "$Id: FGPropeller.h,v 1.17 2011/03/10 01:35:25 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -141,7 +141,7 @@ CLASS DOCUMENTATION
<li>Various NACA Technical Notes and Reports</li>
</ul>
@author Jon S. Berndt
@version $Id: FGPropeller.h,v 1.16 2010/04/09 12:44:06 jberndt Exp $
@version $Id: FGPropeller.h,v 1.17 2011/03/10 01:35:25 dpculp Exp $
@see FGEngine
@see FGThruster
*/
@ -247,7 +247,7 @@ public:
accelerate the prop. It could be negative, dictating that the propeller
would be slowed.
@return the thrust in pounds */
double Calculate(double PowerAvailable);
double Calculate(double EnginePower);
FGColumnVector3 GetPFactor(void);
string GetThrusterLabels(int id, string delimeter);
string GetThrusterValues(int id, string delimeter);

View file

@ -49,7 +49,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGRocket.cpp,v 1.22 2010/12/30 13:35:09 jberndt Exp $";
static const char *IdSrc = "$Id: FGRocket.cpp,v 1.23 2011/01/24 13:01:56 jberndt Exp $";
static const char *IdHdr = ID_ROCKET;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -202,7 +202,7 @@ void FGRocket::ConsumeFuel(void)
double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0;
if (FuelFreeze) return;
if (TrimMode) return;
if (FDMExec->GetTrimStatus()) return;
// Count how many assigned tanks have fuel for this engine at this time.
// If there is/are fuel tanks but no oxidizer tanks, this indicates

View file

@ -34,6 +34,8 @@ HISTORY
11/15/10 T.Kreitler treated flow solver bug, flow and torque calculations
simplified, tiploss influence removed from flapping angles
01/10/11 T.Kreitler changed to single rotor model
03/06/11 T.Kreitler added brake, clutch, and experimental free-wheeling-unit,
reasonable estimate for inflowlag
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
@ -56,7 +58,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGRotor.cpp,v 1.11 2011/01/17 22:09:59 jberndt Exp $";
static const char *IdSrc = "$Id: FGRotor.cpp,v 1.12 2011/03/10 01:35:25 dpculp Exp $";
static const char *IdHdr = ID_ROTOR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -109,7 +111,11 @@ FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num)
// control
ControlMap(eMainCtrl),
CollectiveCtrl(0.0), LateralCtrl(0.0), LongitudinalCtrl(0.0)
CollectiveCtrl(0.0), LateralCtrl(0.0), LongitudinalCtrl(0.0),
BrakeCtrlNorm(0.0), MaxBrakePower(0.0),
// free-wheeling-unit (FWU)
FreeWheelPresent(0), FreeWheelThresh(0.0), FreeWheelTransmission(0.0)
{
FGColumnVector3 location(0.0, 0.0, 0.0), orientation(0.0, 0.0, 0.0);
@ -190,6 +196,9 @@ FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num)
// calculation would cause jumps too. 1Hz seems sufficient.
damp_hagl = Filter(1.0,dt);
// avoid too abrupt changes in power transmission
FreeWheelLag = Filter(200.0,dt);
// enable import-export
BindModel();
@ -248,7 +257,7 @@ double FGRotor::ConfigValue(Element* el, const string& ename, double default_val
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 1. read configuration and try to fill holes, ymmv
// 2. calculate derived parameters and transforms
// 2. calculate derived parameters
void FGRotor::Configure(Element* rotor_element)
{
@ -279,22 +288,24 @@ void FGRotor::Configure(Element* rotor_element)
estimate = sqr(BladeChord) * sqr(Radius - HingeOffset) * 0.57;
BladeFlappingMoment = ConfigValueConv(rotor_element, "flappingmoment", estimate, "SLUG*FT2");
BladeFlappingMoment = Constrain(0.001, BladeFlappingMoment, 1e9);
BladeFlappingMoment = Constrain(1.0e-6, BladeFlappingMoment, 1e9);
// guess mass from moment of a thin stick, and multiply by the blades cg distance
estimate = ( 3.0 * BladeFlappingMoment / sqr(Radius) ) * (0.45 * Radius) ;
BladeMassMoment = ConfigValue(rotor_element, "massmoment", estimate); // unit is slug-ft
BladeMassMoment = Constrain(0.001, BladeMassMoment, 1e9);
TipLossB = ConfigValue(rotor_element, "tiplossfactor", 1.0, silent);
estimate = 1.1 * BladeFlappingMoment * BladeNum;
PolarMoment = ConfigValueConv(rotor_element, "polarmoment", estimate, "SLUG*FT2");
PolarMoment = Constrain(0.001, PolarMoment, 1e9);
PolarMoment = Constrain(1e-6, PolarMoment, 1e9);
InflowLag = ConfigValue(rotor_element, "inflowlag", 0.2, yell); // fixme, depends on size
InflowLag = Constrain(1e-6, InflowLag, 2.0);
// "inflowlag" is treated further down.
TipLossB = ConfigValue(rotor_element, "tiplossfactor", 1.0, silent);
estimate = 0.01 * PolarMoment ; // guesses for huey, bo105 20-30hp
MaxBrakePower = ConfigValueConv(rotor_element, "maxbrakepower", estimate, "HP");
MaxBrakePower *= hptoftlbssec;
// ground effect
if (rotor_element->FindElement("cgroundeffect")) {
@ -309,6 +320,17 @@ void FGRotor::Configure(Element* rotor_element)
GroundEffectExp = ConfigValue(rotor_element, "groundeffectexp", 0.0);
GroundEffectShift = ConfigValueConv(rotor_element, "groundeffectshift", 0.0, "FT");
// handle optional free-wheeling-unit (FWU)
FreeWheelPresent = 0;
FreeWheelTransmission = 1.0;
if (rotor_element->FindElement("freewheelthresh")) {
FreeWheelThresh = rotor_element->FindElementValueAsNumber("freewheelthresh");
if (FreeWheelThresh > 1.0) {
FreeWheelPresent = 1;
FreeWheelTransmission = 0.0;
}
}
// precalc often used powers
R[0]=1.0; R[1]=Radius; R[2]=R[1]*R[1]; R[3]=R[2]*R[1]; R[4]=R[3]*R[1];
B[0]=1.0; B[1]=TipLossB; B[2]=B[1]*B[1]; B[3]=B[2]*B[1]; B[4]=B[3]*B[1];
@ -317,6 +339,13 @@ void FGRotor::Configure(Element* rotor_element)
LockNumberByRho = LiftCurveSlope * BladeChord * R[4] / BladeFlappingMoment;
Solidity = BladeNum * BladeChord / (M_PI * Radius);
// estimate inflow lag, see /GE49/ eqn(1)
double omega_tmp = (NominalRPM/60.0)*2.0*M_PI;
estimate = 16.0/(LockNumberByRho*rho * omega_tmp ); // 16/(gamma*Omega)
// printf("# Est. InflowLag: %f\n", estimate);
InflowLag = ConfigValue(rotor_element, "inflowlag", estimate, yell);
InflowLag = Constrain(1.0e-6, InflowLag, 2.0);
return;
} // Configure
@ -362,7 +391,7 @@ FGColumnVector3 FGRotor::fus_angvel_body2ca( const FGColumnVector3 &pqr)
av_w_fus(eP)= av_s_fus(eP)*cos(beta_orient) + av_s_fus(eQ)*sin(beta_orient);
av_w_fus(eQ)= - av_s_fus(eP)*sin(beta_orient) + av_s_fus(eQ)*cos(beta_orient);
av_w_fus(eR)= av_s_fus(eR);
return av_w_fus;
}
@ -382,7 +411,7 @@ void FGRotor::calc_flow_and_thrust( double theta_0, double Uw, double Ww,
double ct_over_sigma = 0.0;
double c0, ct_l, ct_t0, ct_t1;
double mu2;
double mu2;
mu = Uw/(Omega*Radius); // /SH79/ eqn(24)
mu2 = sqr(mu);
@ -390,7 +419,7 @@ void FGRotor::calc_flow_and_thrust( double theta_0, double Uw, double Ww,
ct_t0 = (1.0/3.0*B[3] + 1.0/2.0 * TipLossB*mu2 - 4.0/(9.0*M_PI) * mu*mu2 ) * theta_0;
ct_t1 = (1.0/4.0*B[4] + 1.0/4.0 * B[2]*mu2) * BladeTwist;
ct_l = (1.0/2.0*B[2] + 1.0/4.0 * mu2) * lambda; // first time
ct_l = (1.0/2.0*B[2] + 1.0/4.0 * mu2) * lambda; // first time
c0 = (LiftCurveSlope/2.0)*(ct_l + ct_t0 + ct_t1) * Solidity;
c0 = c0 / ( 2.0 * sqrt( sqr(mu) + sqr(lambda) ) + 1e-15);
@ -473,7 +502,7 @@ void FGRotor::calc_flapping_angles(double theta_0, const FGColumnVector3 &pqr_fu
void FGRotor::calc_drag_and_side_forces(double theta_0)
{
double cy_over_sigma ;
double cy_over_sigma;
double t075 = theta_0 + 0.75 * BladeTwist;
H_drag = Thrust * a_dw;
@ -494,7 +523,7 @@ void FGRotor::calc_drag_and_side_forces(double theta_0)
// Simplified version of /SH79/ eqn(36). Uses an estimate for blade drag
// (a new config parameter to come...).
// From "Bramwell's Helicopter Dynamics" ­ second edition, eqn(3.43) and (3.44)
// From "Bramwell's Helicopter Dynamics", second edition, eqn(3.43) and (3.44)
void FGRotor::calc_torque(double theta_0)
{
@ -560,7 +589,7 @@ void FGRotor::CalcStatePart1(void)
FGColumnVector3 vHub_ca, avFus_ca;
double h_agl_ft, filtered_hagl = 0.0;
double ge_factor = 1.0;
double ge_factor = 1.0;
// fetch needed values from environment
Vt = fdmex->GetAuxiliary()->GetVt(); // total vehicle velocity including wind
@ -637,18 +666,52 @@ void FGRotor::CalcStatePart2(double PowerAvailable)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGRotor::GetPowerRequired(void)
{
CalcStatePart1();
PowerRequired = Torque * Omega;
return PowerRequired;
// Simulation of a free-wheeling-unit (FWU). Might need improvements.
void FGRotor::calc_freewheel_state(double p_source, double p_load) {
// engine is off/detached, release.
if (p_source<1e-3) {
FreeWheelTransmission = 0.0;
return;
}
// engine is driving the rotor, engage.
if (p_source >= p_load) {
FreeWheelTransmission = 1.0;
return;
}
// releases if engine is detached, but stays calm if
// the load changes due to rotor dynamics.
if (p_source > 0.0 && p_load/(p_source+0.1) > FreeWheelThresh ) {
FreeWheelTransmission = 0.0;
return;
}
return;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGRotor::Calculate(double PowerAvailable)
double FGRotor::Calculate(double EnginePower)
{
CalcStatePart2(PowerAvailable);
double FWmult = 1.0;
double DeltaPower;
CalcStatePart1();
PowerRequired = Torque * Omega + BrakeCtrlNorm * MaxBrakePower;
if (FreeWheelPresent) {
calc_freewheel_state(EnginePower * ClutchCtrlNorm, PowerRequired);
FWmult = FreeWheelLag.execute(FreeWheelTransmission);
}
DeltaPower = EnginePower * ClutchCtrlNorm * FWmult - PowerRequired;
CalcStatePart2(DeltaPower);
return Thrust;
}
@ -702,7 +765,7 @@ bool FGRotor::BindModel(void)
property_name = base_property_name + "/phi-downwash-rad";
PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetPhiDW );
switch (ControlMap) {
case eTailCtrl:
property_name = base_property_name + "/antitorque-ctrl-rad";
@ -725,6 +788,11 @@ bool FGRotor::BindModel(void)
PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetLongitudinalCtrl, &FGRotor::SetLongitudinalCtrl);
}
property_name = base_property_name + "/brake-ctrl-norm";
PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetBrakeCtrl, &FGRotor::SetBrakeCtrl);
property_name = base_property_name + "/free-wheel-transmission";
PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetFreeWheelTransmission);
if (ExternalRPM) {
if (RPMdefinition == -1) {
property_name = base_property_name + "/x-rpm-dict";
@ -826,6 +894,7 @@ void FGRotor::Debug(int from)
cout << " Tip Loss = " << TipLossB << endl;
cout << " Lock Number = " << LockNumberByRho * 0.002356 << " (SL)" << endl;
cout << " Solidity = " << Solidity << endl;
cout << " Max Brake Power = " << MaxBrakePower/hptoftlbssec << " HP" << endl;
switch (ControlMap) {
case eTailCtrl: ControlMapName = "Tail Rotor"; break;
@ -834,6 +903,12 @@ void FGRotor::Debug(int from)
}
cout << " Control Mapping = " << ControlMapName << endl;
if (FreeWheelPresent) {
cout << " Free Wheel Threshold = " << FreeWheelThresh << endl;
} else {
cout << " No FWU present" << endl;
}
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification

View file

@ -27,6 +27,7 @@ HISTORY
--------------------------------------------------------------------------------
01/01/10 T.Kreitler test implementation
01/10/11 T.Kreitler changed to single rotor model
03/06/11 T.Kreitler added brake, clutch, and experimental free-wheeling-unit
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
@ -45,7 +46,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ROTOR "$Id: FGRotor.h,v 1.8 2011/01/17 22:09:59 jberndt Exp $"
#define ID_ROTOR "$Id: FGRotor.h,v 1.9 2011/03/10 01:35:25 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -76,12 +77,15 @@ CLASS DOCUMENTATION
<polarmoment unit="{MOMENT}"> {number} </polarmoment>
<inflowlag> {number} </inflowlag>
<tiplossfactor> {number} </tiplossfactor>
<maxbrakepower unit="{POWER}"> {number} </maxbrakepower>
<controlmap> {MAIN|TAIL|TANDEM} </controlmap>
<ExternalRPM> {number} </ExternalRPM>
<groundeffectexp> {number} </groundeffectexp>
<groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>
<freewheelthresh> {number} </freewheelthresh>
</rotor>
// LENGTH means any of the supported units, same for ANGLE and MOMENT.
@ -108,10 +112,11 @@ CLASS DOCUMENTATION
\<massmoment> - Blade mass moment. Mass of a single blade times the blade's
cg-distance from the hub, optional.
\<polarmoment> - Moment of inertia for the whole rotor disk, optional.
\<inflowlag> - Rotor inflow time constant, sec. Smaller values yield to
quicker responses to control input (defaults to 0.2).
\<inflowlag> - Rotor inflow time constant, sec. Smaller values yield to quicker
responses (typical values for main rotor: 0.1 - 0.2 s).
\<tiplossfactor> - Tip-loss factor. The Blade fraction that produces lift.
Value usually ranges between 0.95 - 1.0, optional (B).
\<maxbrakepower> - Rotor brake, 20-30 hp should work for a mid size helicopter.
\<controlmap> - Defines the control inputs used (see notes).
\<ExternalRPM> - Links the rotor to another rotor, or an user controllable property.
@ -125,6 +130,10 @@ CLASS DOCUMENTATION
Omitting or setting to 0.0 disables the effect calculation.
\<groundeffectshift> - Further adjustment of ground effect, approx. hub height or slightly above.
\<freewheelthresh> - Ratio of thruster power to engine power. The FWU will release when above
the threshold. The value shouldn't be too close to 1.0, 1.5 seems ok.
0 disables this feature, which is also the default.
</pre>
<h3>Notes:</h3>
@ -165,8 +174,6 @@ CLASS DOCUMENTATION
<h4>- Engine issues -</h4>
Currently the rotor can only be driven with piston and electrical engines. An adaption
for the turboprop engine might become available in the future.
In order to keep the rotor speed constant, use of a RPM-Governor system is
encouraged (see examples).
@ -188,11 +195,13 @@ CLASS DOCUMENTATION
<dt>/AM50/</dt><dd>Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a
Comparison With Flight Measurements", NACA TN-2136, 1950.</dd>
<dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment
Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd>
Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd>
<dt>/GE49/</dt><dd>Gessow, Alfred, Amer, Kenneth B. "An Introduction to the Physical
Aspects of Helicopter Stability", NACA TN-1982, 1949.</dd>
</dl>
@author Thomas Kreitler
@version $Id: FGRotor.h,v 1.8 2011/01/17 22:09:59 jberndt Exp $
@version $Id: FGRotor.h,v 1.9 2011/03/10 01:35:25 dpculp Exp $
*/
@ -216,14 +225,11 @@ public:
/// Destructor for FGRotor
~FGRotor();
/** Returns the power required by the rotor. Well, to achieve this the rotor
is cycled through the whole machinery, yielding to a new state.
(hmm, sort of a huge side effect)
*/
double GetPowerRequired(void);
/** Returns the power required by the rotor. */
double GetPowerRequired(void)const { return PowerRequired; }
/** Returns the scalar thrust of the rotor, and adjusts the RPM value. */
double Calculate(double PowerAvailable);
double Calculate(double EnginePower);
/// Retrieves the RPMs of the rotor.
@ -257,6 +263,8 @@ public:
double GetCT(void) const { return C_T; }
/// Retrieves the torque
double GetTorque(void) const { return Torque; }
/// Retrieves the state of the free-wheeling-unit (FWU).
double GetFreeWheelTransmission(void) const { return FreeWheelTransmission; }
/// Downwash angle - currently only valid for a rotor that spins horizontally
double GetThetaDW(void) const { return theta_downwash; }
@ -269,6 +277,8 @@ public:
double GetLateralCtrl(void) const { return LateralCtrl; }
/// Retrieves the longitudinal control input in radians.
double GetLongitudinalCtrl(void) const { return LongitudinalCtrl; }
/// Retrieves the normalized brake control input.
double GetBrakeCtrl(void) const { return BrakeCtrlNorm; }
/// Sets the collective control input in radians.
void SetCollectiveCtrl(double c) { CollectiveCtrl = c; }
@ -276,6 +286,8 @@ public:
void SetLateralCtrl(double c) { LateralCtrl = c; }
/// Sets the longitudinal control input in radians.
void SetLongitudinalCtrl(double c) { LongitudinalCtrl = c; }
/// Sets the normalized brake control input.
void SetBrakeCtrl(double c) { BrakeCtrlNorm = c; }
// Stubs. Only main rotor RPM is returned
string GetThrusterLabels(int id, string delimeter);
@ -303,6 +315,8 @@ private:
void calc_drag_and_side_forces(double theta_0);
void calc_torque(double theta_0);
void calc_freewheel_state(double pwr_in, double pwr_out);
// transformations
FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr,
double a_ic = 0.0 , double b_ic = 0.0 );
@ -380,6 +394,15 @@ private:
double LateralCtrl;
double LongitudinalCtrl;
double BrakeCtrlNorm, MaxBrakePower;
// free-wheeling-unit (FWU)
int FreeWheelPresent; // 'installed' or not
double FreeWheelThresh; // when to release
Filter FreeWheelLag;
double FreeWheelTransmission; // state, 0: free, 1:locked
};
}

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGThruster.cpp,v 1.13 2010/08/21 22:56:11 jberndt Exp $";
static const char *IdSrc = "$Id: FGThruster.cpp,v 1.14 2011/03/10 01:35:25 dpculp Exp $";
static const char *IdHdr = ID_THRUSTER;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -66,6 +66,7 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
GearRatio = 1.0;
ReverserAngle = 0.0;
ClutchCtrlNorm = 1.0;
EngineNum = num;
PropertyManager = FDMExec->GetPropertyManager();
@ -98,6 +99,13 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
&FGThruster::SetReverserAngle);
}
if (el->GetName() == "rotor") // At this time only a rotor can have a clutch.
{
property_name = base_property_name + "/clutch-ctrl-norm";
PropertyManager->Tie( property_name.c_str(), (FGThruster *)this, &FGThruster::GetClutchCtrl,
&FGThruster::SetClutchCtrl);
}
Debug(0);
}

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_THRUSTER "$Id: FGThruster.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $"
#define ID_THRUSTER "$Id: FGThruster.h,v 1.16 2011/03/10 01:35:25 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -74,7 +74,7 @@ CLASS DOCUMENTATION
1.57 (pi/2) results in no thrust at all.
@author Jon Berndt
@version $Id: FGThruster.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $
@version $Id: FGThruster.h,v 1.16 2011/03/10 01:35:25 dpculp Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -105,6 +105,8 @@ public:
string GetName(void) {return Name;}
void SetReverserAngle(double angle) {ReverserAngle = angle;}
double GetReverserAngle(void) const {return ReverserAngle;}
double GetClutchCtrl(void) const { return ClutchCtrlNorm; }
void SetClutchCtrl(double c) { ClutchCtrlNorm = c; }
virtual double GetRPM(void) const { return 0.0; };
double GetGearRatio(void) {return GearRatio; }
virtual string GetThrusterLabels(int id, string delimeter);
@ -119,6 +121,7 @@ protected:
double GearRatio;
double ThrustCoeff;
double ReverserAngle;
double ClutchCtrlNorm;
int EngineNum;
FGPropertyManager* PropertyManager;
virtual void Debug(int from);

View file

@ -51,7 +51,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.29 2010/08/31 04:01:32 jberndt Exp $";
static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.31 2011/03/03 12:16:26 jberndt Exp $";
static const char *IdHdr = ID_TURBINE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -74,6 +74,7 @@ FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number)
BypassRatio = BleedDemand = 0.0;
IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0;
N1_spinup = 1.0; N2_spinup = 3.0;
EPR = 1.0;
ResetToIC();
@ -96,6 +97,9 @@ FGTurbine::~FGTurbine()
void FGTurbine::ResetToIC(void)
{
FGEngine::ResetToIC();
N1 = N2 = 0.0;
N2norm = 0.0;
correctedTSFC = TSFC;
@ -534,6 +538,8 @@ void FGTurbine::bindmodel()
PropertyManager->Tie( property_name.c_str(), &Seized);
property_name = base_property_name + "/stalled";
PropertyManager->Tie( property_name.c_str(), &Stalled);
property_name = base_property_name + "/bleed-factor";
PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this, &FGTurbine::GetBleedDemand, &FGTurbine::SetBleedDemand);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -34,6 +34,7 @@ based on parameters given in the engine config file for this class
HISTORY
--------------------------------------------------------------------------------
05/14/2004 Created
02/08/2011 T. Kreitler, added rotor support
//JVK (mark)
@ -45,6 +46,7 @@ INCLUDES
#include <sstream>
#include "FGTurboProp.h"
#include "FGPropeller.h"
#include "FGRotor.h"
#include "models/FGPropulsion.h"
#include "models/FGAuxiliary.h"
@ -52,7 +54,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.17 2010/08/21 17:13:48 jberndt Exp $";
static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.19 2011/03/10 01:35:25 dpculp Exp $";
static const char *IdHdr = ID_TURBOPROP;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -64,8 +66,10 @@ FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number)
ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL)
{
SetDefaults();
thrusterType = Thruster->GetType();
Load(exec, el);
bindmodel();
Debug(0);
}
@ -101,6 +105,7 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
MaxN2 = el->FindElementValueAsNumber("maxn2");
if (el->FindElement("betarangeend"))
BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0;
BetaRangeThrottleEnd = Constrain(0.0, BetaRangeThrottleEnd, 0.99999);
if (el->FindElement("reversemaxpower"))
ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0;
@ -146,10 +151,10 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
delay=1;
N1_factor = MaxN1 - IdleN1;
N2_factor = MaxN2 - IdleN2;
OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
OilTemp_degK = Auxiliary->GetTAT_C() + 273.0;
if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate
cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n";
// cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << endl;
return true;
}
@ -162,29 +167,29 @@ void FGTurboProp::Calculate(void)
{
RunPreFunctions();
TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
TAT = Auxiliary->GetTAT_C();
dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
Throttle = FCS->GetThrottlePos(EngineNumber);
Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
if (Thruster->GetType() == FGThruster::ttPropeller) {
RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
if (thrusterType == FGThruster::ttPropeller) {
((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
((FGPropeller*)Thruster)->SetReverse(Reversed);
if (Reversed) {
((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd);
((FGPropeller*)Thruster)->SetReverseCoef(Throttle);
} else {
((FGPropeller*)Thruster)->SetReverseCoef(0.0);
}
}
if (Reversed) {
if (ThrottleCmd < BetaRangeThrottleEnd) {
ThrottleCmd = 0.0; // idle when in Beta-range
} else {
// when reversed:
ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
if (Reversed) {
if (Throttle < BetaRangeThrottleEnd) {
Throttle = 0.0; // idle when in Beta-range
} else {
// when reversed:
Throttle = (Throttle-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
}
}
}
@ -223,36 +228,41 @@ void FGTurboProp::Calculate(void)
StartTime=-1;
}
if (Condition < 1) {
if (Ielu_max_torque > 0
&& -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque()
&& ThrottleCmd >= OldThrottle ) {
ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down
Ielu_intervent = true;
} else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) {
ThrottleCmd = OldThrottle;
ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up
Ielu_intervent = true;
// limiter intervention wanted?
if (Ielu_max_torque > 0.0) {
double torque = 0.0;
if (thrusterType == FGThruster::ttPropeller) {
torque = ((FGPropeller*)(Thruster))->GetTorque();
} else if (thrusterType == FGThruster::ttRotor) {
torque = ((FGRotor*)(Thruster))->GetTorque();
}
if (Condition < 1) {
if ( abs(torque) > Ielu_max_torque && Throttle >= OldThrottle ) {
Throttle = OldThrottle - 0.1 * dt; //IELU down
Ielu_intervent = true;
} else if ( Ielu_intervent && Throttle >= OldThrottle) {
Throttle = OldThrottle + 0.05 * dt; //IELU up
Ielu_intervent = true;
} else {
Ielu_intervent = false;
}
} else {
Ielu_intervent = false;
}
} else {
Ielu_intervent = false;
OldThrottle = Throttle;
}
OldThrottle = ThrottleCmd;
switch (phase) {
case tpOff: Eng_HP = Off(); break;
case tpRun: Eng_HP = Run(); break;
case tpSpinUp: Eng_HP = SpinUp(); break;
case tpStart: Eng_HP = Start(); break;
default: Eng_HP = 0;
case tpOff: HP = Off(); break;
case tpRun: HP = Run(); break;
case tpSpinUp: HP = SpinUp(); break;
case tpStart: HP = Start(); break;
default: HP = 0;
}
//printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power);
PowerAvailable = (Eng_HP * hptoftlbssec) - Thruster->GetPowerRequired();
Thruster->Calculate(PowerAvailable);
Thruster->Calculate(HP * hptoftlbssec);
RunPostFunctions();
}
@ -280,7 +290,7 @@ double FGTurboProp::Off(void)
ConsumeFuel(); // for possible setting Starved = false when fuel tank
// is refilled (fuel crossfeed etc.)
if (Prop_RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
if (RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
return 0.0;
}
@ -293,9 +303,9 @@ double FGTurboProp::Run(void)
//---
double old_N1 = N1;
N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
N1 = ExpSeek(&N1, IdleN1 + Throttle * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
EngPower_HP *= EnginePowerVC->GetValue();
if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
@ -346,7 +356,7 @@ double FGTurboProp::SpinUp(void)
OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
NozzlePosition = 1.0;
EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
EngPower_HP *= EnginePowerVC->GetValue();
if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
@ -366,13 +376,15 @@ double FGTurboProp::SpinUp(void)
double FGTurboProp::Start(void)
{
double EngPower_HP,eff_coef;
double EngPower_HP = 0.0;
double eff_coef;
EngStarting = false;
if ((N1 > 15.0) && !Starved) { // minimum 15% N2 needed for start
double old_N1 = N1;
Cranking = true; // provided for sound effects signal
if (N1 < IdleN1) {
EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
EngPower_HP *= EnginePowerVC->GetValue();
if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4);
@ -391,7 +403,6 @@ double FGTurboProp::Start(void)
Starter = false;
Cranking = false;
FuelFlow_pph = 0;
EngPower_HP=0.0;
}
} else { // no start if N2 < 15% or Starved
phase = tpOff;
@ -449,13 +460,14 @@ void FGTurboProp::SetDefaults(void)
{
// Name = "Not defined";
N1 = N2 = 0.0;
HP = 0.0;
Type = etTurboprop;
MilThrust = 10000.0;
IdleN1 = 30.0;
IdleN2 = 60.0;
MaxN1 = 100.0;
MaxN2 = 100.0;
ThrottleCmd = 0.0;
Throttle = 0.0;
InletPosition = 1.0;
NozzlePosition = 1.0;
Reversed = false;
@ -472,6 +484,11 @@ void FGTurboProp::SetDefaults(void)
Ielu_intervent=false;
Idle_Max_Delay = 1.0;
Throttle = OldThrottle = 0.0;
ITT_Delay = 0.05;
ReverseMaxPower = 0.0;
BetaRangeThrottleEnd = 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -495,9 +512,9 @@ string FGTurboProp::GetEngineValues(const string& delimiter)
{
std::ostringstream buf;
buf << PowerAvailable << delimiter
<< N1 << delimiter
buf << N1 << delimiter
<< N2 << delimiter
<< HP << delimiter
<< Thruster->GetThrusterValues(EngineNumber,delimiter);
return buf.str();
@ -524,10 +541,18 @@ void FGTurboProp::bindmodel()
base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
property_name = base_property_name + "/n1";
PropertyManager->Tie( property_name.c_str(), &N1);
property_name = base_property_name + "/n2";
PropertyManager->Tie( property_name.c_str(), &N2);
// property_name = base_property_name + "/n2";
// PropertyManager->Tie( property_name.c_str(), &N2);
property_name = base_property_name + "/reverser";
PropertyManager->Tie( property_name.c_str(), &Reversed);
property_name = base_property_name + "/power-hp";
PropertyManager->Tie( property_name.c_str(), &HP);
property_name = base_property_name + "/itt-c";
PropertyManager->Tie( property_name.c_str(), &Eng_ITT_degC);
property_name = base_property_name + "/engtemp-c";
PropertyManager->Tie( property_name.c_str(), &Eng_Temperature);
property_name = base_property_name + "/ielu_intervent";
PropertyManager->Tie( property_name.c_str(), &Ielu_intervent);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -27,6 +27,7 @@
HISTORY
--------------------------------------------------------------------------------
05/14/2004 Created
02/08/2011 T. Kreitler, added rotor support
//JVK (mark)
@ -46,7 +47,7 @@ INCLUDES
#include "input_output/FGXMLElement.h"
#include "math/FGTable.h"
#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.12 2010/08/21 18:08:37 jberndt Exp $"
#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.14 2011/03/10 01:35:25 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -107,11 +108,10 @@ public:
void Calculate(void);
double CalcFuelNeed(void);
inline double GetPowerAvailable(void) const {return (Eng_HP * hptoftlbssec);}
inline double GetPowerAvailable_HP(void) const {return (Eng_HP);}
inline double GetPropRPM(void) const {return (Prop_RPM);}
inline double GetThrottleCmd(void) const {return (ThrottleCmd);}
inline bool GetIeluIntervent(void) const { return Ielu_intervent; }
double GetPowerAvailable(void) const { return (HP * hptoftlbssec); }
double GetRPM(void) const { return (RPM); }
double GetIeluThrottle(void) const { return (Throttle); }
bool GetIeluIntervent(void) const { return Ielu_intervent; }
double Seek(double* var, double target, double accel, double decel);
double ExpSeek(double* var, double target, double accel, double decel);
@ -165,9 +165,8 @@ private:
double dt; ///< Simulator time slice
double N1_factor; ///< factor to tie N1 and throttle
double N2_factor; ///< factor to tie N2 and throttle
double ThrottleCmd; ///< FCS-supplied throttle position
double Throttle; ///< FCS-supplied throttle position
double TAT; ///< total air temperature (deg C)
double PowerAvailable;
bool Stalled; ///< true if engine is compressor-stalled
bool Seized; ///< true if inner spool is seized
bool Overtemp; ///< true if EGT exceeds limits
@ -189,26 +188,27 @@ private:
double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range
double ReverseMaxPower; // coef (0-1) multiplies max throttle on reverse
double Idle_Max_Delay; // time delay for exponencial
double Idle_Max_Delay; // time delay for exponential
double MaxPower; // max engine power [HP]
double StarterN1; // rotates of generator maked by starter [%]
double StarterN1; // rotates of generator maked by starter [%]
double MaxStartingTime; // maximal time for start [s] (-1 means not used)
double Prop_RPM; // propeller RPM
double RPM; // shaft RPM
double Velocity;
double rho;
double PSFC; // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency
double Eng_HP; // current engine power
double HP; // engine power output
double StartTime; // engine strating time [s] (0 when start button pushed)
double StartTime; // engine starting time [s] (0 when start button pushed)
double ITT_Delay; // time delay for exponencial grow of ITT
double ITT_Delay; // time delay for exponential growth of ITT
double Eng_ITT_degC;
double Eng_Temperature; // temperature inside engine
bool EngStarting; // logicaly output - TRUE if engine is starting
bool GeneratorPower;
int Condition;
int thrusterType; // the attached thruster
double Off(void);
double Run(void);

View file

@ -236,12 +236,6 @@ TankPropertiesList::TankPropertiesList( SGPropertyNode_ptr 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
@ -297,6 +291,12 @@ double TankPropertiesList::getTotalContent_norm() const
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 ) {
(*it)->bind();
}

View file

@ -671,8 +671,8 @@ void Airplane::compile()
t->handle = body->addMass(0, t->pos);
totalFuel += t->cap;
}
_cruiseWeight = _emptyWeight + totalFuel*0.5f;
_approachWeight = _emptyWeight + totalFuel*0.2f;
_cruiseWeight = _emptyWeight + totalFuel*_cruiseFuel;
_approachWeight = _emptyWeight + totalFuel*_approachFuel;
body->recalc();
@ -795,7 +795,7 @@ void Airplane::setupWeights(bool isApproach)
void Airplane::runCruise()
{
setupState(_cruiseAoA, _cruiseSpeed,_approachGlideAngle, &_cruiseState);
setupState(_cruiseAoA, _cruiseSpeed,_cruiseGlideAngle, &_cruiseState);
_model.setState(&_cruiseState);
_model.setAir(_cruiseP, _cruiseT,
Atmosphere::calcStdDensity(_cruiseP, _cruiseT));

View file

@ -90,13 +90,13 @@ void FDMShell::reinit()
void FDMShell::bind()
{
_tankProperties.bind();
if (_impl && _impl->get_inited()) {
if (_impl->get_bound()) {
throw sg_exception("FDMShell::bind of bound FGInterface impl");
}
_impl->bind();
}
_tankProperties.bind();
}
void FDMShell::unbind()

View file

@ -527,7 +527,6 @@ void MapWidget::draw(int dx, int dy)
if (_root->getBoolValue("centre-on-aircraft")) {
_projectionCenter = _aircraft;
_root->setBoolValue("centre-on-aircraft", false);
}
double julianDate = globals->get_time_params()->getJD();
@ -1396,7 +1395,7 @@ void MapWidget::drawAIShip(const SGPropertyNode* model, const SGGeod& pos, doubl
{
SGVec2d p = project(pos);
glColor3f(0.0, 0.0, 0.3);
glColor3f(0.0, 0.0, 0.5);
glLineWidth(2.0);
circleAt(p, 4, 6.0); // blue diamond (to differentiate from aircraft.

View file

@ -55,10 +55,15 @@ FGJoystickInput::joystick::joystick ()
FGJoystickInput::joystick::~joystick ()
{
// delete js? why not?
// delete js;
// delete js? no, since js == this - and we're in the destructor already.
delete[] axes;
delete[] buttons;
jsnum = 0;
js = NULL;
naxes = 0;
nbuttons = 0;
axes = NULL;
buttons = NULL;
}
@ -68,13 +73,24 @@ FGJoystickInput::FGJoystickInput()
FGJoystickInput::~FGJoystickInput()
{
_remove();
}
void FGJoystickInput::_remove()
{
SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
js_nodes->removeChildren("js", false);
for (int i = 0; i < MAX_JOYSTICKS; i++)
{
if (bindings[i].js)
delete bindings[i].js;
bindings[i].js = NULL;
}
}
void FGJoystickInput::init()
{
jsInit();
// TODO: zero the old bindings first.
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick bindings");
SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
@ -121,8 +137,7 @@ void FGJoystickInput::init()
void FGJoystickInput::reinit() {
SG_LOG(SG_INPUT, SG_DEBUG, "Re-Initializing joystick bindings");
SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
js_nodes->removeChildren("js", false);
_remove();
FGJoystickInput::init();
FGJoystickInput::postinit();
}

View file

@ -52,6 +52,8 @@ public:
static const int MAX_JOYSTICK_BUTTONS = 32;
private:
void _remove();
/**
* Settings for a single joystick axis.
*/

View file

@ -47,7 +47,7 @@
#include "groundradar.hxx"
static const char* airport_source_node_name = "airport-id-source";
static const char* default_airport_node_name = "/sim/tower/airport-id";
static const char* default_airport_node_name = "/sim/airport/closest-airport-id";
static const char* texture_node_name = "texture-name";
static const char* default_texture_name = "Aircraft/Instruments/Textures/od_groundradar.rgb";
static const char* range_source_node_name = "range-source";

View file

@ -793,14 +793,44 @@ static bool fgSetTowerPosFromAirportID( const string& id) {
struct FGTowerLocationListener : SGPropertyChangeListener {
void valueChanged(SGPropertyNode* node) {
const string id(node->getStringValue());
string id(node->getStringValue());
if (fgGetBool("/sim/tower/auto-position",true))
{
// enforce using closest airport when auto-positioning is enabled
const char* closest_airport = fgGetString("/sim/airport/closest-airport-id", "");
if (closest_airport && (id != closest_airport))
{
id = closest_airport;
node->setStringValue(id);
}
}
fgSetTowerPosFromAirportID(id);
}
};
struct FGClosestTowerLocationListener : SGPropertyChangeListener
{
void valueChanged(SGPropertyNode* )
{
// closest airport has changed
if (fgGetBool("/sim/tower/auto-position",true))
{
// update tower position
const char* id = fgGetString("/sim/airport/closest-airport-id", "");
if (id && *id!=0)
fgSetString("/sim/tower/airport-id", id);
}
}
};
void fgInitTowerLocationListener() {
fgGetNode("/sim/tower/airport-id", true)
->addChangeListener( new FGTowerLocationListener(), true );
FGClosestTowerLocationListener* ntcl = new FGClosestTowerLocationListener();
fgGetNode("/sim/airport/closest-airport-id", true)
->addChangeListener(ntcl , true );
fgGetNode("/sim/tower/auto-position", true)
->addChangeListener(ntcl, true );
}
static void fgApplyStartOffset(const SGGeod& aStartPos, double aHeading, double aTargetHeading = HUGE_VAL)
@ -1163,6 +1193,7 @@ bool fgInitPosition() {
// An airport + parking position is requested
if ( fgSetPosFromAirportIDandParkpos( apt, parkpos ) ) {
// set tower position
fgSetString("/sim/airport/closest-airport-id", apt.c_str());
fgSetString("/sim/tower/airport-id", apt.c_str());
set_pos = true;
}
@ -1173,7 +1204,8 @@ bool fgInitPosition() {
if ( fgSetPosFromAirportIDandRwy( apt, rwy_no, rwy_req ) ) {
// set tower position (a little off the heading for single
// runway airports)
fgSetString("/sim/tower/airport-id", apt.c_str());
fgSetString("/sim/airport/closest-airport-id", apt.c_str());
fgSetString("/sim/tower/airport-id", apt.c_str());
set_pos = true;
}
}
@ -1183,7 +1215,8 @@ bool fgInitPosition() {
if ( fgSetPosFromAirportIDandHdg( apt, hdg ) ) {
// set tower position (a little off the heading for single
// runway airports)
fgSetString("/sim/tower/airport-id", apt.c_str());
fgSetString("/sim/airport/closest-airport-id", apt.c_str());
fgSetString("/sim/tower/airport-id", apt.c_str());
set_pos = true;
}
}
@ -1561,6 +1594,9 @@ void fgReInitSubsystems()
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
fgSetBool("/sim/signals/reinit", false);
if ( !freeze ) {

View file

@ -204,7 +204,7 @@ fgviewerMain(int argc, char** argv)
}
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.

View file

@ -390,8 +390,7 @@ static void fgIdleFunction ( void ) {
// Initialize the material manager
////////////////////////////////////////////////////////////////////
globals->set_matlib( new SGMaterialLib );
simgear::SGModelLib::init(globals->get_fg_root());
simgear::SGModelLib::setPropRoot(globals->get_props());
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
simgear::SGModelLib::setPanelFunc(load_panel);
////////////////////////////////////////////////////////////////////

View file

@ -1150,12 +1150,22 @@ fgOptNAV2( const char * arg )
}
static int
fgOptADF( const char * arg )
fgOptADF1( const char * arg )
{
double rot, freq;
if (parse_colon(arg, &rot, &freq))
fgSetDouble("/instrumentation/adf/rotation-deg", rot);
fgSetDouble("/instrumentation/adf/frequencies/selected-khz", freq);
fgSetDouble("/instrumentation/adf[0]/rotation-deg", rot);
fgSetDouble("/instrumentation/adf[0]/frequencies/selected-khz", freq);
return FG_OPTIONS_OK;
}
static int
fgOptADF2( const char * arg )
{
double rot, freq;
if (parse_colon(arg, &rot, &freq))
fgSetDouble("/instrumentation/adf[1]/rotation-deg", rot);
fgSetDouble("/instrumentation/adf[1]/frequencies/selected-khz", freq);
return FG_OPTIONS_OK;
}
@ -1493,7 +1503,9 @@ struct OptionDesc {
{"com2", true, OPTION_DOUBLE, "/instrumentation/comm[1]/frequencies/selected-mhz", false, "", 0 },
{"nav1", true, OPTION_FUNC, "", false, "", fgOptNAV1 },
{"nav2", true, OPTION_FUNC, "", false, "", fgOptNAV2 },
{"adf", true, OPTION_FUNC, "", false, "", fgOptADF },
{"adf", /*legacy*/ true, OPTION_FUNC, "", false, "", fgOptADF1 },
{"adf1", true, OPTION_FUNC, "", false, "", fgOptADF1 },
{"adf2", true, OPTION_FUNC, "", false, "", fgOptADF2 },
{"dme", true, OPTION_FUNC, "", false, "", fgOptDME },
{"min-status", true, OPTION_STRING, "/sim/aircraft-min-status", false, "all", 0 },
{"livery", true, OPTION_FUNC, "", false, "", fgOptLivery },

View file

@ -613,11 +613,11 @@ FGRenderer::update( bool refresh_camera_settings ) {
if ( fgGetBool("/sim/rendering/textures") ) {
SGVec4f clearColor(l->adj_fog_color());
camera->setClearColor(toOsg(clearColor));
camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
}
} else {
SGVec4f clearColor(l->sky_color());
camera->setClearColor(toOsg(clearColor));
camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
}
// update fog params if visibility has changed

View file

@ -88,6 +88,8 @@ FGTileMgr::~FGTileMgr() {
group->removeChildren(0, group->getNumChildren());
delete _propListener;
_propListener = NULL;
// clear OSG cache
osgDB::Registry::instance()->clearObjectCache();
}
@ -122,6 +124,12 @@ void FGTileMgr::reinit()
group->removeChildren(0, group->getNumChildren());
tile_cache.init();
// clear OSG cache, except on initial start-up
if (state != Start)
{
osgDB::Registry::instance()->clearObjectCache();
}
state = Inited;
previous_bucket.make_bad();

View file

@ -38,6 +38,31 @@
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
// 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
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
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());
loadScriptDirectory(nasalDir);
// Add modules in Nasal subdirectories to property tree
simgear::PathList directories = nasalDir.children(simgear::Dir::TYPE_DIR+
simgear::Dir::NO_DOT_OR_DOTDOT, "");
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
@ -777,29 +805,75 @@ void FGNasalSys::update(double)
_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
void FGNasalSys::loadPropertyScripts()
{
SGPropertyNode* nasal = globals->get_props()->getNode("nasal");
if(!nasal) return;
for(int i=0; i<nasal->nChildren(); i++) {
for(int i=0; i<nasal->nChildren(); i++)
{
SGPropertyNode* n = nasal->getChild(i);
loadPropertyScripts(n);
}
}
const char* module = n->getName();
if(n->hasChild("module"))
module = n->getStringValue("module");
// Loads the scripts found under /nasal in the global tree
void FGNasalSys::loadPropertyScripts(SGPropertyNode* n)
{
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
// Nasal module tag
int j = 0;
SGPropertyNode *fn;
bool file_specified = false;
bool ok=true;
while((fn = n->getChild("file", j)) != NULL) {
file_specified = true;
const char* file = fn->getStringValue();
SGPath p = globals->resolve_maybe_aircraft_path(file);
loadModule(p, module);
SGPath p(file);
if (!p.isAbsolute() || !p.exists())
{
p = globals->resolve_maybe_aircraft_path(file);
}
ok &= loadModule(p, module);
j++;
}
@ -809,10 +883,30 @@ void FGNasalSys::loadPropertyScripts()
createModule(module, n->getPath().c_str(), src, strlen(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: " <<
"no <file> or <script> defined in " <<
"/nasal/" << module);
"no <file> or <script> defined in " <<
"/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
@ -832,7 +926,7 @@ void FGNasalSys::logError(naContext context)
// Reads a script file, executes it, and places the resulting
// namespace into the global namespace under the specified module
// name.
void FGNasalSys::loadModule(SGPath file, const char* module)
bool FGNasalSys::loadModule(SGPath file, const char* module)
{
int len = 0;
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,
"Nasal error: could not read script file " << file.c_str()
<< " into module " << module);
return;
return false;
}
createModule(module, file.c_str(), buf, len);
bool ok = createModule(module, file.c_str(), buf, len);
delete[] buf;
return ok;
}
// Parse and run. Save the local variables namespace, as it will
// 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
// 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 SGPropertyNode* cmdarg,
int argc, naRef* args)
{
naRef code = parse(fileName, src, len);
if(naIsNil(code))
return;
return false;
// See if we already have a module hash to use. This allows the
// 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);
hashset(_globals, moduleName, locals);
return true;
}
void FGNasalSys::deleteModule(const char* moduleName)

View file

@ -3,6 +3,7 @@
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/misc/sg_dir.hxx>
#include <simgear/nasal/nasal.h>
#include <simgear/scene/model/modellib.hxx>
#include <simgear/xml/easyxml.hxx>
@ -24,7 +25,7 @@ public:
// Loads a nasal script from an external file and inserts it as a
// 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
// indicate successful execution. Does *not* return any Nasal
@ -53,7 +54,7 @@ public:
// Callbacks for command and timer bindings
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,
int argc=0, naRef*args=0);
@ -65,6 +66,7 @@ public:
private:
friend class FGNasalScript;
friend class FGNasalListener;
friend class FGNasalModuleListener;
//
// FGTimer subclass for handling Nasal timer callbacks.
@ -85,6 +87,9 @@ private:
static int _listenerId;
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 logError(naContext);
naRef parse(const char* filename, const char* buf, int len);

View file

@ -88,9 +88,11 @@ void TimeManager::init()
_warp->getIntValue());
globals->set_time_params(_impl);
// frame/update-rate counters
// frame-rate / worst-case latency / update-rate counters
_frameRate = fgGetNode("/sim/frame-rate", true);
_frameLatency = fgGetNode("/sim/frame-latency-max-ms", true);
_lastFrameTime = 0;
_frameLatencyMax = 0.0;
_frameCount = 0;
}
@ -160,7 +162,9 @@ void TimeManager::computeTimeDeltas(double& simDt, double& realDt)
SGTimeStamp currentStamp;
currentStamp.stamp();
double dt = (currentStamp - _lastStamp).toSecs();
if (dt > _frameLatencyMax)
_frameLatencyMax = dt;
// Limit the time we need to spend in simulation loops
// 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
@ -251,7 +255,9 @@ void TimeManager::computeFrameRate()
// Calculate frame rate average
if ((_impl->get_cur_time() != _lastFrameTime)) {
_frameRate->setIntValue(_frameCount);
_frameLatency->setDoubleValue(_frameLatencyMax*1000);
_frameCount = 0;
_frameLatencyMax = 0.0;
}
_lastFrameTime = _impl->get_cur_time();

View file

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

View file

@ -1,4 +1,4 @@
DIST_SUBDIRS = GPSsmooth TerraSync Modeller js_server fgadmin xmlgrep propmerge fgviewer
SUBDIRS = GPSsmooth TerraSync Modeller js_server propmerge fgviewer
SUBDIRS = GPSsmooth TerraSync Modeller js_server propmerge fgviewer fgpanel

7
utils/fgpanel/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
fgpanel
*.o
*.obj
.deps
*.Po
Makefile
Makefile.in

View file

@ -0,0 +1,31 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __APPLICATION_PROPERTIES
#define __APPLICATION_PROPERTIES
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
#include "FGFontCache.hxx"
class ApplicationProperties {
public:
static double getDouble( const char * name, double def = 0.0 );
static SGPath GetRootPath( const char * subDir = NULL );
static SGPropertyNode_ptr Properties;
static std::string root;
static FGFontCache fontCache;
};
#endif

View file

@ -0,0 +1,208 @@
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
using namespace std;
#include <map>
#include <algorithm>
#include "ApplicationProperties.hxx"
#include "FGFontCache.hxx"
////////////////////////////////////////////////////////////////////////
// FGFontCache class.
////////////////////////////////////////////////////////////////////////
//extern puFont FONT_HELVETICA_14;
//extern puFont FONT_SANS_12B;
namespace
{
struct GuiFont
{
const char *name;
puFont *font;
struct Predicate
: public std::unary_function<const GuiFont, bool>
{
Predicate(const char* name_) : name(name_) {}
bool operator() (const GuiFont& f1) const
{
return ::strcmp(f1.name, name) == 0;
}
const char* name;
};
};
const GuiFont guifonts[] = {
{ "default", &PUFONT_HELVETICA_12 },
{ "FIXED_8x13", &PUFONT_8_BY_13 },
{ "FIXED_9x15", &PUFONT_9_BY_15 },
{ "TIMES_10", &PUFONT_TIMES_ROMAN_10 },
{ "TIMES_24", &PUFONT_TIMES_ROMAN_24 },
{ "HELVETICA_10", &PUFONT_HELVETICA_10 },
{ "HELVETICA_12", &PUFONT_HELVETICA_12 },
// { "HELVETICA_14", &FONT_HELVETICA_14 },
{ "HELVETICA_18", &PUFONT_HELVETICA_18 }
// { "SANS_12B", &FONT_SANS_12B }
};
const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])];
}
FGFontCache::FGFontCache() :
_initialized(false)
{
}
FGFontCache::~FGFontCache()
{
PuFontMap::iterator it, end = _puFonts.end();
for (it = _puFonts.begin(); it != end; ++it)
delete it->second;
}
inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
const FntParams& f2) const
{
int comp = f1.name.compare(f2.name);
if (comp < 0)
return true;
else if (comp > 0)
return false;
if (f1.size < f2.size)
return true;
else if (f1.size > f2.size)
return false;
return f1.slant < f2.slant;
}
struct FGFontCache::fnt *
FGFontCache::getfnt(const char *name, float size, float slant)
{
string fontName(name);
FntParams fntParams(fontName, size, slant);
PuFontMap::iterator i = _puFonts.find(fntParams);
if (i != _puFonts.end())
return i->second;
// fntTexFont s are all preloaded into the _texFonts map
TexFontMap::iterator texi = _texFonts.find(fontName);
fntTexFont* texfont = 0;
puFont* pufont = 0;
if (texi != _texFonts.end()) {
texfont = texi->second;
} else {
const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
GuiFont::Predicate(name));
if (guifont != guifontsEnd) {
pufont = guifont->font;
}
}
fnt* f = new fnt;
if (pufont) {
f->pufont = pufont;
} else if (texfont) {
f->texfont = texfont;
f->pufont = new puFont;
f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
} else {
f->pufont = guifonts[0].font;
}
_puFonts[fntParams] = f;
return f;
}
puFont *
FGFontCache::get(const char *name, float size, float slant)
{
return getfnt(name, size, slant)->pufont;
}
fntTexFont *
FGFontCache::getTexFont(const char *name, float size, float slant)
{
init();
return getfnt(name, size, slant)->texfont;
}
puFont *
FGFontCache::get(SGPropertyNode *node)
{
if (!node)
return get("Helvetica.txf", 15.0, 0.0);
const char *name = node->getStringValue("name", "Helvetica.txf");
float size = node->getFloatValue("size", 15.0);
float slant = node->getFloatValue("slant", 0.0);
return get(name, size, slant);
}
void FGFontCache::init()
{
if (!_initialized) {
char *envp = ::getenv("FG_FONTS");
if (envp != NULL) {
_path.set(envp);
} else {
_path.set(ApplicationProperties::GetRootPath("Fonts").str());
}
_initialized = true;
}
}
SGPath
FGFontCache::getfntpath(const char *name)
{
init();
SGPath path(_path);
if (name && std::string(name) != "") {
path.append(name);
if (path.exists())
return path;
}
path = SGPath(_path);
path.append("Helvetica.txf");
return path;
}
bool FGFontCache::initializeFonts()
{
static string fontext("txf");
init();
ulDir* fontdir = ulOpenDir(_path.c_str());
if (!fontdir)
return false;
const ulDirEnt *dirEntry;
while ((dirEntry = ulReadDir(fontdir)) != 0) {
SGPath path(_path);
path.append(dirEntry->d_name);
if (path.extension() == fontext) {
fntTexFont* f = new fntTexFont;
if (f->load((char *)path.c_str()))
_texFonts[string(dirEntry->d_name)] = f;
else
delete f;
}
}
ulCloseDir(fontdir);
return true;
}
// end of new_gui.cxx

View file

@ -0,0 +1,86 @@
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __FGFONTCACHE_HXX
#define __FGFONTCACHE_HXX
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
#include <plib/pu.h>
/**
* A class to keep all fonts available for future use.
* This also assures a font isn't resident more than once.
*/
class FGFontCache {
private:
// The parameters of a request to the cache.
struct FntParams
{
const std::string name;
const float size;
const float slant;
FntParams() : size(0.0f), slant(0.0f) {}
FntParams(const FntParams& rhs)
: name(rhs.name), size(rhs.size), slant(rhs.slant)
{
}
FntParams(const std::string& name_, float size_, float slant_)
: name(name_), size(size_), slant(slant_)
{
}
};
struct FntParamsLess
: public std::binary_function<const FntParams, const FntParams, bool>
{
bool operator() (const FntParams& f1, const FntParams& f2) const;
};
struct fnt {
fnt(puFont *pu = 0) : pufont(pu), texfont(0) {}
~fnt() { if (texfont) { delete pufont; delete texfont; } }
// Font used by plib GUI code
puFont *pufont;
// TXF font
fntTexFont *texfont;
};
// Path to the font directory
SGPath _path;
typedef map<const string, fntTexFont*> TexFontMap;
typedef map<const FntParams, fnt*, FntParamsLess> PuFontMap;
TexFontMap _texFonts;
PuFontMap _puFonts;
bool _initialized;
struct fnt *getfnt(const char *name, float size, float slant);
void init();
public:
FGFontCache();
~FGFontCache();
puFont *get(const char *name, float size=15.0, float slant=0.0);
puFont *get(SGPropertyNode *node);
fntTexFont *getTexFont(const char *name, float size=15.0, float slant=0.0);
SGPath getfntpath(const char *name);
/**
* Preload all the fonts in the FlightGear font directory. It is
* important to load the font textures early, with the proper
* graphics context current, so that no plib (or our own) code
* tries to load a font from disk when there's no current graphics
* context.
*/
bool initializeFonts();
};
#endif

View file

@ -0,0 +1,94 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "FGGLApplication.hxx"
#include "GL/gl.h"
#include "GL/glut.h"
#include <iostream>
#include <exception>
#include <stdio.h>
FGGLApplication * FGGLApplication::application = NULL;
FGGLApplication::FGGLApplication( const char * aName, int argc, char ** argv ) :
gameMode(false),
name( aName )
{
if( application != NULL ) {
std::cerr << "Only one instance of FGGLApplication allowed!" << std::endl;
throw std::exception();
}
application = this;
glutInit( &argc, argv );
}
FGGLApplication::~FGGLApplication()
{
}
void FGGLApplication::DisplayCallback()
{
if( application ) application->Display();
}
void FGGLApplication::IdleCallback()
{
if( application ) application->Idle();
}
void FGGLApplication::KeyCallback( unsigned char key, int x, int y )
{
if( application ) application->Key( key, x, y );
}
void FGGLApplication::ReshapeCallback( int width, int height )
{
if( application ) application->Reshape( width, height );
}
void FGGLApplication::Run( int glutMode, bool gameMode, int width, int height, int bpp )
{
glutInitDisplayMode(glutMode);
if( gameMode ) {
width = glutGet(GLUT_SCREEN_WIDTH);
height = glutGet(GLUT_SCREEN_HEIGHT);
char game_mode_str[20];
snprintf(game_mode_str, 20, "%dx%d:%d", width, height, bpp );
glutGameModeString( game_mode_str );
glutEnterGameMode();
this->gameMode = gameMode;
} else {
if( width == -1 )
width = glutGet(GLUT_SCREEN_WIDTH);
if( height == -1 )
height = glutGet(GLUT_SCREEN_HEIGHT);
glutInitDisplayMode(glutMode);
// glutInitWindowSize(width, height);
windowId = glutCreateWindow(name);
}
Init();
glutKeyboardFunc(FGGLApplication::KeyCallback);
glutIdleFunc(FGGLApplication::IdleCallback);
glutDisplayFunc(FGGLApplication::DisplayCallback);
glutReshapeFunc(FGGLApplication::ReshapeCallback);
glutMainLoop();
}

View file

@ -0,0 +1,48 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __FGGLAPPLICATION_HXX
#define __FGGLAPPLICATION_HXX
class FGGLApplication {
public:
FGGLApplication( const char * name, int argc, char ** argv );
virtual ~FGGLApplication();
void Run( int glutMode, bool gameMode, int widht=-1, int height=-1, int bpp = 32 );
protected:
virtual void Key( unsigned char key, int x, int y ) {}
virtual void Idle() {}
virtual void Display() {}
virtual void Reshape( int width, int height ) {}
virtual void Init() {}
int windowId;
bool gameMode;
const char * name;
static FGGLApplication * application;
private:
static void KeyCallback( unsigned char key, int x, int y );
static void IdleCallback();
static void DisplayCallback();
static void ReshapeCallback( int width, int height );
};
#endif

View file

@ -0,0 +1,142 @@
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "FGPNGTextureLoader.hxx"
#include <GL/glu.h>
#include <png.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
GLuint FGPNGTextureLoader::loadTexture( const string & filename )
{
//header for testing if it is a png
png_byte header[8];
//open file as binary
FILE *fp = fopen(filename.c_str(), "rb");
if (!fp) {
return NOTEXTURE;
}
//read the header
fread(header, 1, 8, fp);
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png) {
fclose(fp);
return NOTEXTURE;
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL);
if (!png_ptr) {
fclose(fp);
return (NOTEXTURE);
}
//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
fclose(fp);
return (NOTEXTURE);
}
//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(fp);
return (NOTEXTURE);
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return (NOTEXTURE);
}
//init png reading
png_init_io(png_ptr, fp);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
// read all the info up to the image data
png_read_info(png_ptr, info_ptr);
//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;
// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
NULL, NULL, NULL);
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Row size in bytes.
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = new png_byte[rowbytes * theight];
if (!image_data) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return NOTEXTURE;
}
//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = new png_bytep[theight];
if (!row_pointers) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
fclose(fp);
return NOTEXTURE;
}
// set the individual row_pointers to point at the correct offsets of image_data
for (png_uint_32 i = 0; i < theight; ++i)
row_pointers[theight - 1 - i] = image_data + i * rowbytes;
//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);
//Now generate the OpenGL texture object
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
gluBuild2DMipmaps( GL_TEXTURE_2D, 4, twidth, theight, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image_data );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
// glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, twidth, theight, 0,
// GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
delete[] row_pointers;
fclose(fp);
return texture;
}

View file

@ -0,0 +1,26 @@
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __FGPNGTEXTURELOADER_HXX
#define __FGPNGTEXTURELOADER_HXX
#include "FGTextureLoaderInterface.hxx"
class FGPNGTextureLoader : public FGTextureLoaderInterface {
public:
virtual GLuint loadTexture( const std::string & filename );
const static GLuint NOTEXTURE = 0;
};
#endif

View file

@ -0,0 +1,279 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "FGPanelApplication.hxx"
#include <GL/gl.h>
#include <GL/glut.h>
#include <simgear/math/SGMisc.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
#include <iostream>
#include "panel_io.hxx"
#include "ApplicationProperties.hxx"
using namespace std;
inline static string ParseArgs( int argc, char ** argv, const string & token )
{
for( int i = 0; i < argc; i++ ) {
string arg = argv[i];
if( arg.find( token ) == 0 )
return arg.substr( token.length() );
}
return "";
}
inline static string ParseArgs( int argc, char ** argv, const char * token )
{
string s = token;
return ParseArgs( argc, argv, s );
}
#include "FGPNGTextureLoader.hxx"
#include "FGRGBTextureLoader.hxx"
static FGPNGTextureLoader pngTextureLoader;
static FGRGBTextureLoader rgbTextureLoader;
FGPanelApplication::FGPanelApplication( int argc, char ** argv ) :
FGGLApplication( "FlightGear Panel", argc, argv )
{
sglog().setLogLevels( SG_ALL, SG_WARN );
FGCroppedTexture::registerTextureLoader( "png", &pngTextureLoader );
FGCroppedTexture::registerTextureLoader( "rgb", &rgbTextureLoader );
string panelFilename;
string fgRoot;
for( int i = 1; i < argc; i++ ) {
panelFilename = ParseArgs( argc, argv, "--panel=" );
fgRoot = ParseArgs( argc, argv, "--fg-root=" );
}
if( fgRoot.length() > 0 )
ApplicationProperties::root = fgRoot;
if( panelFilename.length() == 0 ) {
cerr << "Need a panel filename. Use --panel=path_to_filename" << endl;
throw exception();
}
try {
SGPath tpath = ApplicationProperties::GetRootPath( panelFilename.c_str() );
readProperties( tpath.str(), ApplicationProperties::Properties );
}
catch( sg_io_exception & e ) {
cerr << e.getFormattedMessage() << endl;
throw;
}
for( int i = 1; i < argc; i++ ) {
string arg = argv[i];
if( arg.find( "--prop:" ) == 0 ) {
string s2 = arg.substr( 7 );
unsigned p = s2.find( "=" );
if( p != string::npos ) {
string propertyName = s2.substr( 0, p );
string propertyValue = s2.substr( p+1 );
ApplicationProperties::Properties->getNode( propertyName.c_str(), true )->setValue( propertyValue.c_str() );
}
}
}
SGPropertyNode_ptr n;
if( (n = ApplicationProperties::Properties->getNode( "panel" )) != NULL )
panel = FGReadablePanel::read( n );
protocol = new FGPanelProtocol( ApplicationProperties::Properties->getNode( "communication", true ) );
protocol->init();
}
FGPanelApplication::~FGPanelApplication()
{
}
void FGPanelApplication::Run()
{
int mode = GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE;
int w = panel == NULL ? 0 : panel->getWidth();
int h = panel == NULL ? 0 : panel->getHeight();
if( w == 0 && h == 0 ) {
w = 1024;
h = 768;
} else if( w == 0 ) {
w = h / 0.75;
} else if( h == 0 ) {
h = w * 0.75;
}
bool gameMode = ApplicationProperties::Properties->getNode( "game-mode", true )->getBoolValue();
FGGLApplication::Run( mode, gameMode, w, h );
}
void FGPanelApplication::Init()
{
glAlphaFunc(GL_GREATER, 0.1);
glutSetCursor( GLUT_CURSOR_NONE );
ApplicationProperties::fontCache.initializeFonts();
}
void FGPanelApplication::Reshape( int width, int height )
{
this->width = width;
this->height = height;
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
}
void FGPanelApplication::Idle()
{
double d = glutGet(GLUT_ELAPSED_TIME);
double dt = Sleep();
if( dt == 0 )
return;
if( panel != NULL )
panel->update( dt );
glutSwapBuffers();
if( protocol != NULL )
protocol->update( dt );
static double dsum = 0.0;
static unsigned cnt = 0;
dsum += glutGet(GLUT_ELAPSED_TIME)-d;
cnt++;
if( dsum > 1000.0 ) {
ApplicationProperties::Properties->getNode( "/sim/frame-rate", true )->setDoubleValue(cnt*1000.0/dsum );
dsum = 0.0;
cnt = 0;
}
}
void FGPanelApplication::Key( unsigned char key, int x, int y )
{
switch( key ) {
case 0x1b:
if( gameMode ) glutLeaveGameMode();
else glutDestroyWindow( windowId );
break;
}
}
double FGPanelApplication::Sleep()
{
SGTimeStamp current_time_stamp;
static SGTimeStamp last_time_stamp;
if ( last_time_stamp.get_seconds() == 0 )
last_time_stamp.stamp();
double model_hz = 60;
double throttle_hz = ApplicationProperties::getDouble("/sim/frame-rate-throttle-hz", 0.0);
if ( throttle_hz > 0.0 ) {
// optionally throttle the frame rate (to get consistent frame
// rates or reduce cpu usage.
double frame_us = 1.0e6 / throttle_hz;
// sleep based timing loop.
//
// Calling sleep, even usleep() on linux is less accurate than
// we like, but it does free up the cpu for other tasks during
// the sleep so it is desirable. Because of the way sleep()
// is implemented in consumer operating systems like windows
// and linux, you almost always sleep a little longer than the
// requested amount.
//
// To combat the problem of sleeping too long, we calculate the
// desired wait time and shorten it by 2000us (2ms) to avoid
// [hopefully] over-sleep'ing. The 2ms value was arrived at
// via experimentation. We follow this up at the end with a
// simple busy-wait loop to get the final pause timing exactly
// right.
//
// Assuming we don't oversleep by more than 2000us, this
// should be a reasonable compromise between sleep based
// waiting, and busy waiting.
// sleep() will always overshoot by a bit so undersleep by
// 2000us in the hopes of never oversleeping.
frame_us -= 2000.0;
if ( frame_us < 0.0 ) {
frame_us = 0.0;
}
current_time_stamp.stamp();
/* Convert to ms */
double elapsed_us = (current_time_stamp - last_time_stamp).toUSecs();
if ( elapsed_us < frame_us ) {
double requested_us = frame_us - elapsed_us;
usleep ( (useconds_t)(requested_us ) ) ;
}
// busy wait timing loop.
//
// This yields the most accurate timing. If the previous
// usleep() call is omitted this will peg the cpu
// (which is just fine if FG is the only app you care about.)
current_time_stamp.stamp();
SGTimeStamp next_time_stamp = last_time_stamp;
next_time_stamp += SGTimeStamp::fromSec(1e-6*frame_us);
while ( current_time_stamp < next_time_stamp ) {
current_time_stamp.stamp();
}
} else {
current_time_stamp.stamp();
}
double real_delta_time_sec = double(current_time_stamp.toUSecs() - last_time_stamp.toUSecs()) / 1000000.0;
last_time_stamp = current_time_stamp;
//fprintf(stdout,"\r%4.1lf ", 1/real_delta_time_sec );
//fflush(stdout);
// round the real time down to a multiple of 1/model-hz.
// this way all systems are updated the _same_ amount of dt.
static double reminder = 0.0;
static long global_multi_loop = 0;
real_delta_time_sec += reminder;
global_multi_loop = long(floor(real_delta_time_sec*model_hz));
global_multi_loop = SGMisc<long>::max(0, global_multi_loop);
reminder = real_delta_time_sec - double(global_multi_loop)/double(model_hz);
return double(global_multi_loop)/double(model_hz);
}
double ApplicationProperties::getDouble( const char * name, double def )
{
SGPropertyNode_ptr n = ApplicationProperties::Properties->getNode( name, false );
if( n == NULL ) return def;
return n->getDoubleValue();
}
SGPath ApplicationProperties::GetRootPath( const char * sub )
{
SGPath path( ApplicationProperties::root );
if( sub != NULL )
path.append( sub );
return path;
}
std::string ApplicationProperties::root = ".";
SGPropertyNode_ptr ApplicationProperties::Properties = new SGPropertyNode;
FGFontCache ApplicationProperties::fontCache;

View file

@ -0,0 +1,55 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __FGPANELAPPLICATION_HXX
#define __FGPANELAPPLICATION_HXX
#include "FGGLApplication.hxx"
#include "FGPanelProtocol.hxx"
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/props.hxx>
#include <string>
#include "panel.hxx"
class FGPanelApplication : public FGGLApplication {
public:
FGPanelApplication( int argc, char ** argv );
~FGPanelApplication();
void Run();
protected:
virtual void Key( unsigned char key, int x, int y );
virtual void Idle();
// virtual void Display();
virtual void Reshape( int width, int height );
virtual void Init();
double Sleep();
SGSharedPtr<FGPanel> panel;
SGSharedPtr<FGPanelProtocol> protocol;
int width;
int height;
};
#endif

View file

@ -0,0 +1,154 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "FGPanelProtocol.hxx"
#include "ApplicationProperties.hxx"
#include <simgear/io/sg_socket.hxx>
#include <simgear/misc/strutils.hxx>
class PropertySetter {
public:
PropertySetter( SGPropertyNode_ptr node ) : _node(node) {}
virtual void setValue( const char * value ) = 0;
protected:
SGPropertyNode_ptr _node;
};
class BoolPropertySetter : public PropertySetter {
public:
BoolPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
virtual void setValue( const char * value ) {
_node->setBoolValue( atoi( value ) != 0 );
}
};
class IntPropertySetter : public PropertySetter {
public:
IntPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
virtual void setValue( const char * value ) {
_node->setIntValue( atol( value ) );
}
};
class FloatPropertySetter : public PropertySetter {
public:
FloatPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
virtual void setValue( const char * value ) {
_node->setFloatValue( strtof( value, NULL ) );
}
};
class DoublePropertySetter : public PropertySetter {
public:
DoublePropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
virtual void setValue( const char * value ) {
_node->setDoubleValue( strtod( value, NULL ) );
}
};
class StringPropertySetter : public PropertySetter {
public:
StringPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
virtual void setValue( const char * value ) {
_node->setStringValue( value );
}
};
FGPanelProtocol::FGPanelProtocol( SGPropertyNode_ptr aRoot )
: SGSubsystem(),
root(aRoot),
io(NULL)
{
SGPropertyNode_ptr outputNode = root->getNode( "protocol/generic/output" );
if( outputNode ) {
vector<SGPropertyNode_ptr> chunks = outputNode->getChildren( "chunk" );
for( vector<SGPropertyNode_ptr>::size_type i = 0; i < chunks.size(); i++ ) {
SGPropertyNode_ptr chunk = chunks[i];
SGPropertyNode_ptr nodeNode = chunk->getNode("node", false );
if( nodeNode == NULL )
continue;
SGPropertyNode_ptr node = ApplicationProperties::Properties->getNode( nodeNode->getStringValue(), true );
string type = "";
SGPropertyNode_ptr typeNode = chunk->getNode( "type", false );
if( typeNode != NULL ) type = typeNode->getStringValue();
if( type == "float" ) {
propertySetterVector.push_back( new FloatPropertySetter( node ) );
} else if( type == "double" || type == "fixed" ) {
propertySetterVector.push_back( new DoublePropertySetter( node ) );
} else if( type == "bool" || type == "boolean" ) {
propertySetterVector.push_back( new BoolPropertySetter( node ) );
} else if( type == "string" ) {
propertySetterVector.push_back( new StringPropertySetter( node ) );
} else {
propertySetterVector.push_back( new IntPropertySetter( node ) );
}
}
}
}
FGPanelProtocol::~FGPanelProtocol()
{
for( PropertySetterVector::size_type i = 0; i < propertySetterVector.size(); i++ )
delete propertySetterVector[i];
}
void FGPanelProtocol::update( double dt )
{
char buf[8192];
if( io == NULL )
return;
int length = io->readline( buf, sizeof(buf)-1 );
buf[sizeof(buf)-1] = 0;
if ( length > 0 ) {
vector<string> tokens = simgear::strutils::split( buf, "," );
for( vector<string>::size_type i = 0; i < tokens.size(); i++ ) {
if( i < propertySetterVector.size() )
propertySetterVector[i]->setValue( tokens[i].c_str() );
}
}
}
void FGPanelProtocol::init()
{
SGPropertyNode_ptr listenNode = root->getNode( "listen" );
if( listenNode == NULL ) {
return;
}
string hostname = listenNode->getNode( "host", true )->getStringValue();
string port = listenNode->getNode( "port", true )->getStringValue();
string style = listenNode->getNode( "style", true )->getStringValue();
if( io != NULL )
delete io;
io = new SGSocket( hostname, port, style );
if( !io->open( SG_IO_IN ) ) {
cerr << "can't open socket " << style << ":" << hostname << ":" << port << endl;
}
}
void FGPanelProtocol::reinit()
{
init();
}

View file

@ -0,0 +1,41 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __FGPANELPROTOCOL_HXX
#define __FGPANELPROTOCOL_HXX
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/props.hxx>
#include <simgear/io/iochannel.hxx>
class PropertySetter;
typedef vector<PropertySetter*> PropertySetterVector;
class FGPanelProtocol : public SGSubsystem {
public:
FGPanelProtocol( SGPropertyNode_ptr root );
virtual ~FGPanelProtocol();
virtual void init();
virtual void reinit();
virtual void update( double dt );
protected:
private:
SGPropertyNode_ptr root;
SGIOChannel * io;
PropertySetterVector propertySetterVector;
};
#endif

View file

@ -0,0 +1,504 @@
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// From the OpenSceneGraph distribution ReaderWriterRGB.cpp
// Reader for sgi's .rgb format.
// specification can be found at http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
#include "FGRGBTextureLoader.hxx"
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <fstream>
typedef struct _rawImageRec
{
unsigned short imagic;
unsigned short type;
unsigned short dim;
unsigned short sizeX, sizeY, sizeZ;
unsigned long min, max;
unsigned long wasteBytes;
char name[80];
unsigned long colorMap;
std::istream *file;
unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
unsigned long rleEnd;
GLuint *rowStart;
GLint *rowSize;
GLenum swapFlag;
short bpc;
typedef unsigned char * BytePtr;
bool needsBytesSwapped()
{
union {
int testWord;
char testByte[sizeof(int)];
}endianTest;
endianTest.testWord = 1;
if( endianTest.testByte[0] == 1 )
return true;
else
return false;
}
template <class T>
inline void swapBytes( T &s )
{
if( sizeof( T ) == 1 )
return;
T d = s;
BytePtr sptr = (BytePtr)&s;
BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
for( unsigned int i = 0; i < sizeof(T); i++ )
*(sptr++) = *(dptr--);
}
void swapBytes()
{
swapBytes( imagic );
swapBytes( type );
swapBytes( dim );
swapBytes( sizeX );
swapBytes( sizeY );
swapBytes( sizeZ );
swapBytes( wasteBytes );
swapBytes( min );
swapBytes( max );
swapBytes( colorMap );
}
} rawImageRec;
static void ConvertShort(unsigned short *array, long length)
{
unsigned long b1, b2;
unsigned char *ptr;
ptr = (unsigned char *)array;
while (length--)
{
b1 = *ptr++;
b2 = *ptr++;
*array++ = (unsigned short) ((b1 << 8) | (b2));
}
}
static void ConvertLong(GLuint *array, long length)
{
unsigned long b1, b2, b3, b4;
unsigned char *ptr;
ptr = (unsigned char *)array;
while (length--)
{
b1 = *ptr++;
b2 = *ptr++;
b3 = *ptr++;
b4 = *ptr++;
*array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
}
}
static void RawImageClose(rawImageRec *raw)
{
if (raw)
{
if (raw->tmp) delete [] raw->tmp;
if (raw->tmpR) delete [] raw->tmpR;
if (raw->tmpG) delete [] raw->tmpG;
if (raw->tmpB) delete [] raw->tmpB;
if (raw->tmpA) delete [] raw->tmpA;
if (raw->rowStart) delete [] raw->rowStart;
if (raw->rowSize) delete [] raw->rowSize;
delete raw;
}
}
static rawImageRec *RawImageOpen(std::istream& fin)
{
union
{
int testWord;
char testByte[4];
} endianTest;
rawImageRec *raw;
int x;
raw = new rawImageRec;
if (raw == NULL)
{
// notify(WARN)<< "Out of memory!"<< std::endl;
return NULL;
}
//Set istream pointer
raw->file = &fin;
endianTest.testWord = 1;
if (endianTest.testByte[0] == 1)
{
raw->swapFlag = GL_TRUE;
}
else
{
raw->swapFlag = GL_FALSE;
}
fin.read((char*)raw,12);
if (!fin.good())
return NULL;
if (raw->swapFlag)
{
ConvertShort(&raw->imagic, 6);
}
raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
raw->rowStart = 0;
raw->rowSize = 0;
raw->bpc = (raw->type & 0x00FF);
raw->tmp = new unsigned char [raw->sizeX*256*raw->bpc];
if (raw->tmp == NULL )
{
// notify(FATAL)<< "Out of memory!"<< std::endl;
RawImageClose(raw);
return NULL;
}
if( raw->sizeZ >= 1 )
{
if( (raw->tmpR = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
{
// notify(FATAL)<< "Out of memory!"<< std::endl;
RawImageClose(raw);
return NULL;
}
}
if( raw->sizeZ >= 2 )
{
if( (raw->tmpG = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
{
// notify(FATAL)<< "Out of memory!"<< std::endl;
RawImageClose(raw);
return NULL;
}
}
if( raw->sizeZ >= 3 )
{
if( (raw->tmpB = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
{
// notify(FATAL)<< "Out of memory!"<< std::endl;
RawImageClose(raw);
return NULL;
}
}
if (raw->sizeZ >= 4)
{
if( (raw->tmpA = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
{
// notify(FATAL)<< "Out of memory!"<< std::endl;
RawImageClose(raw);
return NULL;
}
}
if ((raw->type & 0xFF00) == 0x0100)
{
unsigned int ybyz = raw->sizeY * raw->sizeZ;
if ( (raw->rowStart = new GLuint [ybyz]) == NULL )
{
// notify(FATAL)<< "Out of memory!"<< std::endl;
RawImageClose(raw);
return NULL;
}
if ( (raw->rowSize = new GLint [ybyz]) == NULL )
{
// notify(FATAL)<< "Out of memory!"<< std::endl;
RawImageClose(raw);
return NULL;
}
x = ybyz * sizeof(GLuint);
raw->rleEnd = 512 + (2 * x);
fin.seekg(512,std::ios::beg);
fin.read((char*)raw->rowStart,x);
fin.read((char*)raw->rowSize,x);
if (raw->swapFlag)
{
ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
}
}
return raw;
}
static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
{
unsigned char *iPtr, *oPtr;
unsigned short pixel;
int count, done = 0;
unsigned short *tempShort;
if ((raw->type & 0xFF00) == 0x0100)
{
raw->file->seekg((long) raw->rowStart[y+z*raw->sizeY], std::ios::beg);
raw->file->read((char*)raw->tmp, (unsigned int)raw->rowSize[y+z*raw->sizeY]);
iPtr = raw->tmp;
oPtr = buf;
while (!done)
{
if (raw->bpc == 1)
pixel = *iPtr++;
else
{
tempShort = reinterpret_cast<unsigned short*>(iPtr);
pixel = *tempShort;
tempShort++;
iPtr = reinterpret_cast<unsigned char *>(tempShort);
}
if(raw->bpc != 1)
ConvertShort(&pixel, 1);
count = (int)(pixel & 0x7F);
// limit the count value to the remiaing row size
if (oPtr + count*raw->bpc > buf + raw->sizeX*raw->bpc)
{
count = ( (buf + raw->sizeX*raw->bpc) - oPtr ) / raw->bpc;
}
if (count<=0)
{
done = 1;
return;
}
if (pixel & 0x80)
{
while (count--)
{
if(raw->bpc == 1)
*oPtr++ = *iPtr++;
else{
tempShort = reinterpret_cast<unsigned short*>(iPtr);
pixel = *tempShort;
tempShort++;
iPtr = reinterpret_cast<unsigned char *>(tempShort);
ConvertShort(&pixel, 1);
tempShort = reinterpret_cast<unsigned short*>(oPtr);
*tempShort = pixel;
tempShort++;
oPtr = reinterpret_cast<unsigned char *>(tempShort);
}
}
}
else
{
if (raw->bpc == 1)
{
pixel = *iPtr++;
}
else
{
tempShort = reinterpret_cast<unsigned short*>(iPtr);
pixel = *tempShort;
tempShort++;
iPtr = reinterpret_cast<unsigned char *>(tempShort);
}
if(raw->bpc != 1)
ConvertShort(&pixel, 1);
while (count--)
{
if(raw->bpc == 1)
*oPtr++ = pixel;
else
{
tempShort = reinterpret_cast<unsigned short*>(oPtr);
*tempShort = pixel;
tempShort++;
oPtr = reinterpret_cast<unsigned char *>(tempShort);
}
}
}
}
}
else
{
raw->file->seekg(512+(y*raw->sizeX*raw->bpc)+(z*raw->sizeX*raw->sizeY*raw->bpc),std::ios::beg);
raw->file->read((char*)buf, raw->sizeX*raw->bpc);
if(raw->swapFlag && raw->bpc != 1){
ConvertShort(reinterpret_cast<unsigned short*>(buf), raw->sizeX);
}
}
}
static void RawImageGetData(rawImageRec *raw, unsigned char **data )
{
unsigned char *ptr;
int i, j;
unsigned short *tempShort;
// // round the width to a factor 4
// int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f);
// if (width!=raw->sizeX) width += 4;
// byte aligned.
// osg::notify(osg::INFO)<<"raw->sizeX = "<<raw->sizeX<<std::endl;
// osg::notify(osg::INFO)<<"raw->sizeY = "<<raw->sizeY<<std::endl;
// osg::notify(osg::INFO)<<"raw->sizeZ = "<<raw->sizeZ<<std::endl;
// osg::notify(osg::INFO)<<"raw->bpc = "<<raw->bpc<<std::endl;
*data = new unsigned char [(raw->sizeX)*(raw->sizeY)*(raw->sizeZ)*(raw->bpc)];
ptr = *data;
for (i = 0; i < (int)(raw->sizeY); i++)
{
if( raw->sizeZ >= 1 )
RawImageGetRow(raw, raw->tmpR, i, 0);
if( raw->sizeZ >= 2 )
RawImageGetRow(raw, raw->tmpG, i, 1);
if( raw->sizeZ >= 3 )
RawImageGetRow(raw, raw->tmpB, i, 2);
if( raw->sizeZ >= 4 )
RawImageGetRow(raw, raw->tmpA, i, 3);
for (j = 0; j < (int)(raw->sizeX); j++)
{
if(raw->bpc == 1){
if( raw->sizeZ >= 1 )
*ptr++ = *(raw->tmpR + j);
if( raw->sizeZ >= 2 )
*ptr++ = *(raw->tmpG + j);
if( raw->sizeZ >= 3 )
*ptr++ = *(raw->tmpB + j);
if( raw->sizeZ >= 4 )
*ptr++ = *(raw->tmpA + j);
}else{
if( raw->sizeZ >= 1 )
{
tempShort = reinterpret_cast<unsigned short*>(ptr);
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpR) + j);
tempShort++;
ptr = reinterpret_cast<unsigned char *>(tempShort);
}
if( raw->sizeZ >= 2 )
{
tempShort = reinterpret_cast<unsigned short*>(ptr);
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpG) + j);
tempShort++;
ptr = reinterpret_cast<unsigned char *>(tempShort);
}
if( raw->sizeZ >= 3 )
{
tempShort = reinterpret_cast<unsigned short*>(ptr);
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpB) + j);
tempShort++;
ptr = reinterpret_cast<unsigned char *>(tempShort);
}
if( raw->sizeZ >= 4 )
{
tempShort = reinterpret_cast<unsigned short*>(ptr);
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpA) + j);
tempShort++;
ptr = reinterpret_cast<unsigned char *>(tempShort);
}
}
}
// // pad the image width with blanks to bring it up to the rounded width.
// for(;j<width;++j) *ptr++ = 0;
}
}
// supportsExtension("rgb","rgb image format");
// supportsExtension("rgba","rgba image format");
// supportsExtension("sgi","sgi image format");
// supportsExtension("int","int image format");
// supportsExtension("inta","inta image format");
// supportsExtension("bw","bw image format");
GLuint readRGBStream(std::istream& fin)
{
rawImageRec *raw;
if( (raw = RawImageOpen(fin)) == NULL )
{
return 0;
}
int s = raw->sizeX;
int t = raw->sizeY;
// int r = 1;
#if 0
int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
#else
// int internalFormat = raw->sizeZ;
#endif
unsigned int pixelFormat =
raw->sizeZ == 1 ? GL_LUMINANCE :
raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
raw->sizeZ == 3 ? GL_RGB :
raw->sizeZ == 4 ? GL_RGBA : (GLenum)-1;
GLint component = raw->sizeZ;
unsigned int dataType = raw->bpc == 1 ? GL_UNSIGNED_BYTE :
GL_UNSIGNED_SHORT;
unsigned char *data;
RawImageGetData(raw, &data);
RawImageClose(raw);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
gluBuild2DMipmaps( GL_TEXTURE_2D, component, s, t, pixelFormat, dataType, (GLvoid*)data );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
delete []data;
return texture;
}
GLuint FGRGBTextureLoader::loadTexture( const std::string & filename )
{
GLuint texture = NOTEXTURE;
std::ifstream istream(filename.c_str(), std::ios::in | std::ios::binary );
texture = readRGBStream(istream);
istream.close();
return texture;
}

View file

@ -0,0 +1,26 @@
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __FGRGBTEXTURELOADER_HXX
#define __FGRGBTEXTURELOADER_HXX
#include "FGTextureLoaderInterface.hxx"
class FGRGBTextureLoader : public FGTextureLoaderInterface {
public:
virtual GLuint loadTexture( const std::string & filename );
const static GLuint NOTEXTURE = 0;
};
#endif

View file

@ -0,0 +1,27 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef __FGTEXTURELOADERINTERFACE_HXX
#define __FGTEXTURELOADERINTERFACE_HXX
#include <GL/gl.h>
#include <string>
class FGTextureLoaderInterface {
public:
virtual GLuint loadTexture( const std::string & filename ) = 0;
};
#endif

22
utils/fgpanel/Makefile.am Normal file
View file

@ -0,0 +1,22 @@
if WITH_FGPANEL
AM_CXXFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\"
bin_PROGRAMS = fgpanel
fgpanel_SOURCES = main.cxx \
FGGLApplication.cxx FGGLApplication.hxx \
FGPanelApplication.cxx FGPanelApplication.hxx \
FGPNGTextureLoader.cxx FGPNGTextureLoader.hxx FGTextureLoaderInterface.hxx \
FGRGBTextureLoader.cxx FGRGBTextureLoader.hxx \
FGPanelProtocol.cxx \
FGFontCache.cxx \
panel.cxx panel.hxx \
panel_io.cxx panel_io.hxx
#LIBS =
fgpanel_LDADD = \
-lGLU -lglut -lsgmath -lsgprops -lsgio -lsgdebug -lsgmisc -lsgstructure -lsgxml -lsgtiming \
-lplibpu -lplibfnt -lplibul \
-lrt -lpng
endif

148
utils/fgpanel/README Normal file
View file

@ -0,0 +1,148 @@
=====================================================================
This is fgpanel - basically the stripped down 2D-Panel code from
FlightGear. It is designed as a standalone lightweight panel
rendering engine to draw 2d panels on a lowcost computer/graphic card
without 3d acceleration at reasonablel framerates.
=====================================================================
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
=====================================================================
Usage
start fgpanel with
fgpanel --fg-root=/path/to/fg/data --panel=Aircraft/MyAircraft/Panels/MyPanel.xml
with the command args set to
--fg-root shall point to the directory where your FGDATA lives
NOTE: you don't need a full copy of FGDATA, just the panel definition files for
your aircraft, e.g.
- Aircraft/MyAircraft/Panels/*
- Aircraft/Instruments/* (if referenced)
-panel shall point to a panel-configuration file, relative to FGDATA
start flightgear with
fgfs --generic=socket,out,10,239.24.10.64,5432,udp,../Aircraft/MyAircraft/Panels/SampleProtocol
=====================================================================
Sample:
Create the sample files within your aicraft directory, preferrable under Panels
MyPanel.xml
sample-2d-panel.xml
SampleProtocol.xml
=====================================================================
Sample panel configuration file (MyPanel.xml)
<PropertyList>
<!-- true: run full-screen, false; run in window -->
<game-mode type="bool">false</game-mode>
<!-- include the panel definitions (2d-panel syntax)-->
<panel include="sample-2d-panel.xml"/>
<!-- compose your property-tree here -->
<sim>
<panel>
<flip-x type="bool">false</flip-x>
</panel>
<instrument-options>
<omit-knobs type="bool">true</omit-knobs>
</instrument-options>
</sim>
<!-- network communication settings -->
<communication>
<listen>
<!-- interface to bind to,
leave empty for all interfaces -->
<host>239.24.10.64</host> <!-- multicast address! -->
<port>5432</port> <!-- tcp port to listen to -->
<style>udp</style> <!-- udp or tcp (forget about tcp!) -->
</listen>
<!-- the generic protocol definition
same as used for fgfs --generic=foobar option
-->
<protocol include="SampleProtocol.xml"/>
</communication>
</PropertyList>
=====================================================================
Sampe 2d-panel configuration file sample-2d-panel.xml
To be included from the panel configuration file
<?xml version="1.0"?>
<PropertyList>
<name>Sample Instrument Panel</name>
<w>375</w> <!-- screen width: 375mm -->
<h>305</h> <!-- screen height: 305mm -->
<instruments>
<!-- use FlightGear's c172 attitude indicator -->
<instrument include="../../Instruments/ati-c172s.xml">
<name>Attitude Gyro</name>
<x alias="../../../params/col-2"/>
<y alias="../../../params/row-1"/>
<w>80</w>
<h>80</h>
</instrument>
</instruments>
</PropertyList>
=====================================================================
Sample protocol configuration file to drive the AI (SampleProtocol.xml)
<?xml version="1.0"?>
<PropertyList>
<generic>
<output>
<line_separator>newline</line_separator>
<var_separator>,</var_separator>
<chunk>
<type>float</type>
<format>%.2f</format>
<node>/position/altitude-agl-ft</node>
</chunk>
<chunk>
<type>float</type>
<format>%.2f</format>
<node>/instrumentation/attitude-indicator/indicated-roll-deg</node>
</chunk>
<chunk>
<type>float</type>
<format>%.2f</format>
<node>/instrumentation/attitude-indicator/indicated-pitch-deg</node>
</chunk>
<chunk>
<type>float</type>
<format>%.2f</format>
<node>/instrumentation/attitude-indicator/horizon-offset-deg</node>
</chunk>
<chunk>
<type>float</type>
<format>%.4e</format>
<node>/instrumentation/attitude-indicator/spin</node>
</chunk>
</output>
</generic>
</PropertyList>
=====================================================================

30
utils/fgpanel/main.cxx Normal file
View file

@ -0,0 +1,30 @@
//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "FGPanelApplication.hxx"
int main( int argc, char ** argv )
{
try {
FGPanelApplication app(argc,argv);
app.Run();
return 0;
}
catch( ... ) {
cerr << "Sorry, your program terminated." << endl;
}
}

Some files were not shown because too many files have changed in this diff Show more