1
0
Fork 0

Merge branch 'next' into durk-atc

This commit is contained in:
Durk Talsma 2011-04-11 20:51:16 +02:00
commit 416ba93a41
61 changed files with 796 additions and 526 deletions

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);
}
}
}
@ -267,11 +266,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);
}

26
src/FDM/JSBSim/models/FGAuxiliary.cpp Normal file → Executable file
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");
@ -238,24 +237,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/FGParameter.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 <FGParameter*> 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);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

125
src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp Normal file → Executable file
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);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

28
src/FDM/JSBSim/models/propulsion/FGTurboProp.h Normal file → Executable file
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);