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 { 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; 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 dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
// run in standalone mode with no initialization file. // run in standalone mode with no initialization file.
AircraftPath = "aircraft";
EnginePath = "engine";
SystemsPath = "systems";
try { try {
char* num = getenv("JSBSIM_DEBUG"); char* num = getenv("JSBSIM_DEBUG");
if (num) debug_lvl = atoi(num); // set debug level if (num) debug_lvl = atoi(num); // set debug level
@ -154,12 +158,13 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
Constructing = true; Constructing = true;
typedef int (FGFDMExec::*iPMF)(void) const; typedef int (FGFDMExec::*iPMF)(void) const;
// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis); // instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim); instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions); instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
instance->Tie("simulation/terminate", (int *)&Terminate); instance->Tie("simulation/terminate", (int *)&Terminate);
instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime); instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel); instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
instance->Tie("simulation/frame", (int *)&Frame, false);
Constructing = false; Constructing = false;
} }
@ -350,6 +355,8 @@ bool FGFDMExec::RunIC(void)
void FGFDMExec::Initialize(FGInitialCondition *FGIC) void FGFDMExec::Initialize(FGInitialCondition *FGIC)
{ {
Setsim_time(0.0);
Propagate->SetInitialState( FGIC ); Propagate->SetInitialState( FGIC );
Atmosphere->Run(); Atmosphere->Run();
@ -358,6 +365,9 @@ void FGFDMExec::Initialize(FGInitialCondition *FGIC)
FGIC->GetWindDFpsIC() ); FGIC->GetWindDFpsIC() );
FGColumnVector3 vAeroUVW; FGColumnVector3 vAeroUVW;
//ToDo: move this to the Auxiliary class !?
vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED();
double alpha, beta; 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. // Process the output element[s]. This element is OPTIONAL, and there may be more than one.
unsigned int idx=0; 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"); element = document->FindElement("output");
while (element) { while (element) {
if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " "; if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " ";
@ -643,7 +655,8 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
} else { } else {
Outputs.push_back(Output); Outputs.push_back(Output);
string outputProp = CreateIndexedPropertyName("simulation/output",idx); 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++; idx++;
} }
element = document->FindNextElement("output"); element = document->FindNextElement("output");
@ -679,15 +692,6 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
<< fgdef << endl; << 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) { if (result) {
struct PropertyCatalogStructure masterPCS; struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = ""; 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 FGFDMExec::SetOutputDirectives(const string& fname)
{ {
bool result; bool result;
@ -930,9 +941,9 @@ bool FGFDMExec::SetOutputDirectives(const string& fname)
if (result) { if (result) {
Outputs.push_back(Output); Outputs.push_back(Output);
typedef int (FGOutput::*iOPMF)(void) const; typedef double (FGOutput::*iOPMF)(void) const;
string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1); 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; return result;

View file

@ -44,11 +44,9 @@ INCLUDES
#include <vector> #include <vector>
#include <string> #include <string>
//#include "models/FGModel.h"
#include "models/FGOutput.h" #include "models/FGOutput.h"
#include "models/FGInput.h" #include "models/FGInput.h"
#include "initialization/FGTrim.h" #include "initialization/FGTrim.h"
#include "initialization/FGInitialCondition.h"
#include "FGJSBBase.h" #include "FGJSBBase.h"
#include "input_output/FGPropertyManager.h" #include "input_output/FGPropertyManager.h"
#include "input_output/FGGroundCallback.h" #include "input_output/FGGroundCallback.h"
@ -60,7 +58,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -183,7 +181,7 @@ CLASS DOCUMENTATION
property actually maps toa function call of DoTrim(). property actually maps toa function call of DoTrim().
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.56 $ @version $Revision: 1.63 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -286,8 +284,11 @@ public:
/** Loads a script /** Loads a script
@param Script the full path name and file name for the script to be loaded. @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. */ @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. /** Sets the path to the engine config file directories.
@param path path to the directory under which engine config @param path path to the directory under which engine config
@ -401,6 +402,9 @@ public:
*/ */
bool SetOutputDirectives(const string& fname); 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 /** Sets (or overrides) the output filename
@param fname the name of the file to output data to @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 */ @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. */ @param rootDir the string containing the root directory. */
void SetRootDir(const string& rootDir) {RootDir = rootDir;} void SetRootDir(const string& rootDir) {RootDir = rootDir;}
/** Retrieves teh Root Directory. /** Retrieves the Root Directory.
@return the string representing the root (base) JSBSim directory. */ @return the string representing the root (base) JSBSim directory. */
const string& GetRootDir(void) const {return RootDir;} const string& GetRootDir(void) const {return RootDir;}

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_INITIALCONDITION;
//****************************************************************************** //******************************************************************************
@ -700,6 +700,8 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt)
case setve: case setve:
SetVtrueFpsIC(ve0 * sqrt(rho/rhoSL)); SetVtrueFpsIC(ve0 * sqrt(rho/rhoSL));
break; break;
default: // Make the compiler stop complaining about missing enums
break;
} }
position.SetRadius(alt + sea_level_radius); position.SetRadius(alt + sea_level_radius);
@ -998,6 +1000,18 @@ bool FGInitialCondition::Load_v1(void)
SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf")); 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; return result;
} }
@ -1032,7 +1046,7 @@ bool FGInitialCondition::Load_v2(void)
if (position_el->FindElement("radius")) { if (position_el->FindElement("radius")) {
position.SetRadius(position_el->FindElementValueAsNumberConvertTo("radius", "FT")); position.SetRadius(position_el->FindElementValueAsNumberConvertTo("radius", "FT"));
} else if (position_el->FindElement("altitudeAGL")) { } 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")) { } else if (position_el->FindElement("altitudeMSL")) {
position.SetRadius(sea_level_radius + position_el->FindElementValueAsNumberConvertTo("altitudeMSL", "FT")); position.SetRadius(sea_level_radius + position_el->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
} else { } else {
@ -1096,7 +1110,7 @@ bool FGInitialCondition::Load_v2(void)
// //
// Or, using quaternions (note reverse ordering compared to matrix representation): // 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); FGQuaternion QuatI2Body = FGQuaternion(vOrient);
QuatI2Body.Normalize(); QuatI2Body.Normalize();
@ -1196,6 +1210,9 @@ bool FGInitialCondition::Load_v2(void)
FGColumnVector3 vLocalRate; FGColumnVector3 vLocalRate;
Element* attrate_el = document->FindElement("attitude_rate"); 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(); double radInv = 1.0 / position.GetRadius();
FGColumnVector3 vOmegaLocal = FGColumnVector3( FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vUVW_NED(eEast), radInv*vUVW_NED(eEast),
@ -1209,11 +1226,11 @@ bool FGInitialCondition::Load_v2(void)
FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC"); FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC");
if (frame == "eci") { if (frame == "eci") {
vLocalRate = Tl2b * (position.GetTi2l() * (vAttRate - vOmegaEarth) - vOmegaLocal); vLocalRate = Tl2b * position.GetTi2l() * (vAttRate - vOmegaEarth);
} else if (frame == "ecef") { } else if (frame == "ecef") {
vLocalRate = Tl2b * (position.GetTec2l() * vAttRate - vOmegaLocal); vLocalRate = Tl2b * position.GetTec2l() * vAttRate;
} else if (frame == "local") { } else if (frame == "local") {
vLocalRate = vAttRate; vLocalRate = vAttRate + vOmegaLocal;
} else if (!frame.empty()) { // misspelling of frame } else if (!frame.empty()) { // misspelling of frame
cerr << endl << fgred << " Attitude rate frame type: \"" << frame cerr << endl << fgred << " Attitude rate frame type: \"" << frame
@ -1221,11 +1238,11 @@ bool FGInitialCondition::Load_v2(void)
result = false; result = false;
} else if (frame.empty()) { } else if (frame.empty()) {
vLocalRate = vOmegaLocal;
} }
} else { // Body frame attitude rate assumed 0 relative to local. } else { // Body frame attitude rate assumed 0 relative to local.
vLocalRate.InitMatrix(); vLocalRate = vOmegaLocal;
} }
p = vLocalRate(eP); p = vLocalRate(eP);

View file

@ -41,19 +41,10 @@ scheme. */
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <cstdlib>
#include <iomanip> #include <iomanip>
#include "FGTrim.h" #include "FGTrim.h"
#include "models/FGAtmosphere.h"
#include "FGInitialCondition.h"
#include "models/FGAircraft.h"
#include "models/FGMassBalance.h"
#include "models/FGGroundReactions.h" #include "models/FGGroundReactions.h"
#include "models/FGInertial.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 #if _MSC_VER
#pragma warning (disable : 4786 4788) #pragma warning (disable : 4786 4788)
@ -63,7 +54,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_TRIM;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -241,7 +232,7 @@ bool FGTrim::DoTrim(void) {
fdmex->DisableOutput(); fdmex->DisableOutput();
setEngineTrimMode(true); fdmex->SetTrimStatus(true);
fgic->SetPRadpsIC(0.0); fgic->SetPRadpsIC(0.0);
fgic->SetQRadpsIC(0.0); fgic->SetQRadpsIC(0.0);
@ -358,7 +349,7 @@ bool FGTrim::DoTrim(void) {
for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
} }
setEngineTrimMode(false); fdmex->SetTrimStatus(false);
fdmex->EnableOutput(); fdmex->EnableOutput();
return !trim_failed; 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) { void FGTrim::SetMode(TrimMode tt) {
ClearStates(); ClearStates();
mode=tt; mode=tt;

View file

@ -60,7 +60,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -120,7 +120,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Tony Peden @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 setupTurn(void);
void updateRates(void); void updateRates(void);
void setEngineTrimMode(bool mode);
void setDebug(void); void setDebug(void);
public: 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 { namespace JSBSim {
bool FGPropertyManager::suppress_warning = true; bool FGPropertyManager::suppress_warning = true;
std::vector<std::string> FGPropertyManager::tied_properties; std::vector<SGPropertyNode_ptr> FGPropertyManager::tied_properties;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Unbind(void) void FGPropertyManager::Unbind(void)
{ {
vector<string>::iterator it; vector<SGPropertyNode_ptr>::iterator it;
for (it = tied_properties.begin();it < tied_properties.end();it++) for (it = tied_properties.begin();it < tied_properties.end();it++)
{ (*it)->untie();
Untie(*it);
}
tied_properties.clear(); tied_properties.clear();
} }
@ -102,7 +102,6 @@ FGPropertyManager::GetNode (const string &relpath, int index, bool create)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::HasNode (const string &path) bool FGPropertyManager::HasNode (const string &path)
{ {
// Checking if a node exists shouldn't write a warning if it doesn't exist // 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) 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; cerr << "Failed to tie property " << name << " to a pointer" << endl;
else { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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, void FGPropertyManager::Tie (const string &name, int *pointer,
bool useDefault ) 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; cerr << "Failed to tie property " << name << " to a pointer" << endl;
else { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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, void FGPropertyManager::Tie (const string &name, long *pointer,
bool useDefault ) 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; cerr << "Failed to tie property " << name << " to a pointer" << endl;
else { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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, void FGPropertyManager::Tie (const string &name, float *pointer,
bool useDefault ) 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; cerr << "Failed to tie property " << name << " to a pointer" << endl;
else { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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) 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; cerr << "Failed to tie property " << name << " to a pointer" << endl;
else { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; if (debug_lvl & 0x20) cout << name << endl;
} }
} }

View file

@ -53,7 +53,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -77,7 +77,7 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
{ {
private: private:
static bool suppress_warning; static bool suppress_warning;
static std::vector<std::string> tied_properties; static std::vector<SGPropertyNode_ptr> tied_properties;
public: public:
/// Constructor /// Constructor
FGPropertyManager(void) {suppress_warning = false;} FGPropertyManager(void) {suppress_warning = false;}
@ -532,10 +532,16 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
template <class V> inline void template <class V> inline void
Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true) Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
{ {
if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter), useDefault)) SGPropertyNode* property = getNode(name.c_str(), true);
std::cout << "Failed to tie property " << name << " to functions" << std::endl; 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 { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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), template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true) void (*setter)(int, V) = 0, bool useDefault = true)
{ {
if (!tie(name.c_str(), SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault)) SGPropertyNode* property = getNode(name.c_str(), true);
std::cout << "Failed to tie property " << name << " to indexed functions" << std::endl; 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 { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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, Tie (const std::string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true) void (T::*setter)(V) = 0, bool useDefault = true)
{ {
if (!tie(name.c_str(), SGRawValueMethods<T,V>(*obj, getter, setter), useDefault)) SGPropertyNode* property = getNode(name.c_str(), true);
std::cout << "Failed to tie property " << name << " to object methods" << std::endl; 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 { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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, Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
void (T::*setter)(int, V) = 0, bool useDefault = true) void (T::*setter)(int, V) = 0, bool useDefault = true)
{ {
if (!tie(name.c_str(), SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault)) SGPropertyNode* property = getNode(name.c_str(), true);
std::cout << "Failed to tie property " << name << " to indexed object methods" << std::endl; 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 { else {
tied_properties.push_back(name); tied_properties.push_back(property);
if (debug_lvl & 0x20) std::cout << name << std::endl; 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 { 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; static const char *IdHdr = ID_FGSCRIPT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -78,12 +78,19 @@ FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
FGScript::~FGScript() 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(); 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(); Events.clear();
Debug(1); Debug(1);
@ -139,6 +146,8 @@ bool FGScript::LoadScript(string script, double deltaT)
StartTime = run_element->GetAttributeValueAsNumber("start"); StartTime = run_element->GetAttributeValueAsNumber("start");
FDMExec->Setsim_time(StartTime); FDMExec->Setsim_time(StartTime);
EndTime = run_element->GetAttributeValueAsNumber("end"); EndTime = run_element->GetAttributeValueAsNumber("end");
// Make sure that the desired time is reached and executed.
EndTime += 0.99*FDMExec->GetDeltaT();
if (deltaT == 0.0) if (deltaT == 0.0)
dt = run_element->GetAttributeValueAsNumber("dt"); dt = run_element->GetAttributeValueAsNumber("dt");
@ -240,11 +249,13 @@ bool FGScript::LoadScript(string script, double deltaT)
newCondition = new FGCondition(condition_element, PropertyManager); newCondition = new FGCondition(condition_element, PropertyManager);
} catch(string str) { } catch(string str) {
cout << endl << fgred << str << reset << endl << endl; cout << endl << fgred << str << reset << endl << endl;
delete newEvent;
return false; return false;
} }
newEvent->Condition = newCondition; newEvent->Condition = newCondition;
} else { } else {
cerr << "No condition specified in script event " << newEvent->Name << endl; cerr << "No condition specified in script event " << newEvent->Name << endl;
delete newEvent;
return false; return false;
} }
@ -258,16 +269,29 @@ bool FGScript::LoadScript(string script, double deltaT)
// Notify about when this event is triggered? // Notify about when this event is triggered?
if ((notify_element = event_element->FindElement("notify")) != 0) { if ((notify_element = event_element->FindElement("notify")) != 0) {
newEvent->Notify = true; 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"); notify_property_element = notify_element->FindElement("property");
while (notify_property_element) { while (notify_property_element) {
notifyPropertyName = notify_property_element->GetDataLine(); notifyPropertyName = notify_property_element->GetDataLine();
if (PropertyManager->GetNode(notifyPropertyName)) { if (PropertyManager->GetNode(notifyPropertyName)) {
newEvent->NotifyProperties.push_back( 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 { } else {
cout << endl << fgred << " Could not find the property named " cout << endl << fgred << " Could not find the property named "
<< notifyPropertyName << " in script" << endl << " \"" << notifyPropertyName << " in script" << endl << " \""
<< ScriptName << "\". Execution is aborted. Please recheck " << ScriptName << "\". Execution is aborted. Please recheck "
<< "your input files and scripts." << reset << endl; << "your input files and scripts." << reset << endl;
delete newEvent->Condition;
delete newEvent;
return false; return false;
} }
notify_property_element = notify_element->FindNextElement("property"); notify_property_element = notify_element->FindNextElement("property");
@ -339,7 +363,7 @@ bool FGScript::RunScript(void)
double currentTime = FDMExec->GetSimTime(); double currentTime = FDMExec->GetSimTime();
double newSetValue = 0; double newSetValue = 0;
if (currentTime > EndTime) return false; //Script done! if (currentTime > EndTime) return false;
// Iterate over all events. // Iterate over all events.
for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) { 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) { if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")" cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
<< " executed at time: " << currentTime << endl; << " 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++) { 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; << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
} }
cout << endl; cout << endl;

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -157,7 +157,7 @@ CLASS DOCUMENTATION
comes the &quot;run&quot; section, where the conditions are comes the &quot;run&quot; section, where the conditions are
described in &quot;event&quot; clauses.</p> described in &quot;event&quot; clauses.</p>
@author Jon S. Berndt @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- has been supplied on the command line, it will be override the script-
specified simulation step size. specified simulation step size.
@param script the filename (including path name, if any) for the script. @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 */ @return true if successful */
bool LoadScript(string script, double deltaT); bool LoadScript(string script, double deltaT);
@ -215,8 +215,10 @@ private:
double StartTime; double StartTime;
double TimeSpan; double TimeSpan;
string Name; string Name;
string Description;
vector <FGPropertyManager*> SetParam; vector <FGPropertyManager*> SetParam;
vector <FGPropertyManager*> NotifyProperties; vector <FGPropertyManager*> NotifyProperties;
vector <string> DisplayString;
vector <eAction> Action; vector <eAction> Action;
vector <eType> Type; vector <eType> Type;
vector <double> SetValue; 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 { 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; static const char *IdHdr = ID_XMLELEMENT;
bool Element::converterIsInitialized = false; bool Element::converterIsInitialized = false;
@ -64,6 +64,8 @@ Element::Element(const string& nm)
// Length // Length
convert["M"]["FT"] = 3.2808399; convert["M"]["FT"] = 3.2808399;
convert["FT"]["M"] = 1.0/convert["M"]["FT"]; 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["FT"]["IN"] = 12.0;
convert["IN"]["FT"] = 1.0/convert["FT"]["IN"]; convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"]; 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["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
convert["M/SEC"]["FT/SEC"] = 3.2808399; convert["M/SEC"]["FT/SEC"] = 3.2808399;
convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"]; 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 // Torque
convert["FT*LBS"]["N*M"] = 1.35581795; convert["FT*LBS"]["N*M"] = 1.35581795;
convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"]; convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
@ -153,6 +157,7 @@ Element::Element(const string& nm)
// Length // Length
convert["M"]["M"] = 1.00; convert["M"]["M"] = 1.00;
convert["KM"]["KM"] = 1.00;
convert["FT"]["FT"] = 1.00; convert["FT"]["FT"] = 1.00;
convert["IN"]["IN"] = 1.00; convert["IN"]["IN"] = 1.00;
// Area // Area
@ -195,6 +200,7 @@ Element::Element(const string& nm)
convert["KTS"]["KTS"] = 1.00; convert["KTS"]["KTS"] = 1.00;
convert["M/S"]["M/S"] = 1.0; convert["M/S"]["M/S"] = 1.0;
convert["M/SEC"]["M/SEC"] = 1.0; convert["M/SEC"]["M/SEC"] = 1.0;
convert["KM/SEC"]["KM/SEC"] = 1.0;
// Torque // Torque
convert["FT*LBS"]["FT*LBS"] = 1.00; convert["FT*LBS"]["FT*LBS"] = 1.00;
convert["N*M"]["N*M"] = 1.00; convert["N*M"]["N*M"] = 1.00;

View file

@ -35,6 +35,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGCondition.h" #include "FGCondition.h"
#include "FGPropertyValue.h"
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#include "input_output/FGPropertyManager.h" #include "input_output/FGPropertyManager.h"
#include <iostream> #include <iostream>
@ -44,7 +45,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_CONDITION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -122,12 +123,11 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
exit(-1); exit(-1);
} }
TestParam1 = PropertyManager->GetNode(property1, false); FGPropertyManager *node = PropertyManager->GetNode(property1, false);
if (!TestParam1) { if (node) {
cerr << fgred << " In condition: " << test << ". Unknown property " TestParam1 = new FGPropertyValue(node);
<< property1 << " referenced." << endl } else {
<< "Creating property. Check usage." << reset << endl; TestParam1 = new FGPropertyValue(property1, PropertyManager);
TestParam1 = PropertyManager->GetNode(property1, true);
} }
Comparison = mComparison[conditional]; Comparison = mComparison[conditional];
if (Comparison == ecUndef) { if (Comparison == ecUndef) {
@ -136,12 +136,11 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
if (is_number(property2)) { if (is_number(property2)) {
TestValue = atof(property2.c_str()); TestValue = atof(property2.c_str());
} else { } else {
TestParam2 = PropertyManager->GetNode(property2, false); node = PropertyManager->GetNode(property2, false);
if (!TestParam2) { if (node) {
cerr << fgred << " In condition: " << test << ". Unknown property " TestParam2 = new FGPropertyValue(node);
<< property2 << " referenced." << endl } else {
<< "Creating property. Check usage." << reset << endl; TestParam2 = new FGPropertyValue(property2, PropertyManager);
TestParam2 = PropertyManager->GetNode(property2, true);
} }
} }
} }
@ -267,11 +266,11 @@ void FGCondition::PrintCondition(void )
} else { } else {
if (TestParam2 != 0L) if (TestParam2 != 0L)
cout << " " << TestParam1->GetRelativeName() << " " cout << " " << TestParam1->GetName() << " "
<< conditional << " " << conditional << " "
<< TestParam2->GetRelativeName(); << TestParam2->GetName();
else else
cout << " " << TestParam1->GetRelativeName() << " " cout << " " << TestParam1->GetName() << " "
<< conditional << " " << TestValue; << conditional << " " << TestValue;
} }
} }

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -53,6 +53,7 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
class FGPropertyManager; class FGPropertyManager;
class FGPropertyValue;
class Element; class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -82,7 +83,8 @@ private:
std::map <std::string, eComparison> mComparison; std::map <std::string, eComparison> mComparison;
eLogic Logic; eLogic Logic;
FGPropertyManager *TestParam1, *TestParam2, *PropertyManager; FGPropertyManager *PropertyManager;
FGPropertyValue *TestParam1, *TestParam2;
double TestValue; double TestValue;
eComparison Comparison; eComparison Comparison;
bool isGroup; bool isGroup;

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

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_FUNCTION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -177,9 +177,10 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
newNode = PropertyManager->GetNode(property_name); newNode = PropertyManager->GetNode(property_name);
Parameters.push_back(new FGPropertyValue( newNode )); Parameters.push_back(new FGPropertyValue( newNode ));
} else { } else {
cerr << fgcyan << "The property " + property_name + " is initially undefined." cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined."
<< reset << endl; << 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) { } else if (operation == value_string || operation == v_string) {
Parameters.push_back(new FGRealValue(element->GetDataAsNumber())); Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
@ -252,16 +253,7 @@ double FGFunction::GetValue(void) const
if (cached) return cachedValue; if (cached) return cachedValue;
try { temp = Parameters[0]->GetValue();
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.");
}
}
switch (Type) { switch (Type) {
case eTopLevel: case eTopLevel:

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

@ -40,7 +40,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -65,6 +65,10 @@ class FGParameter : public FGJSBBase
public: public:
virtual ~FGParameter(void) {}; virtual ~FGParameter(void) {};
virtual double GetValue(void) const = 0; virtual double GetValue(void) const = 0;
virtual std::string GetName(void) const = 0;
// SGPropertyNode impersonation.
double getDoubleValue(void) const { return GetValue(); }
protected: 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 Purpose: Stores property values
------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) ------------- ------------- 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 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 the terms of the GNU Lesser General Public License as published by the Free Software
@ -32,36 +33,53 @@ INCLUDES
namespace JSBSim { 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; static const char *IdHdr = ID_PROPERTYVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION 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 FGPropertyValue::GetValue(void) const
{ {
double val; FGPropertyManager* node = PropertyNode;
try {
val = PropertyManager->getDoubleValue(); if (!PropertyNode) {
} catch (...) { // The node cannot be cached since this is a const method.
throw(PropertyName); 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 Date started: December 10 2004
------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) ------------- ------------- 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 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 the terms of the GNU Lesser General Public License as published by the Free Software
@ -41,7 +42,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -53,8 +54,8 @@ namespace JSBSim {
CLASS DOCUMENTATION CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Represents a property value /** Represents a property value which can use late binding.
@author Jon Berndt @author Jon Berndt, Anders Gidenstam
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -66,14 +67,17 @@ class FGPropertyValue : public FGParameter
public: public:
FGPropertyValue(FGPropertyManager* propNode); FGPropertyValue(FGPropertyManager* propNode);
FGPropertyValue(std::string propName); FGPropertyValue(std::string propName, FGPropertyManager* propertyManager);
~FGPropertyValue() {}; ~FGPropertyValue() {};
double GetValue(void) const; double GetValue(void) const;
void SetNode(FGPropertyManager* node) {PropertyManager = node;} void SetNode(FGPropertyManager* node) {PropertyNode = node;}
std::string GetName(void) const;
private: private:
FGPropertyManager* PropertyManager; FGPropertyManager* PropertyManager; // Property root used to do late binding.
FGPropertyManager* PropertyNode;
std::string PropertyName; std::string PropertyName;
}; };

View file

@ -40,7 +40,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -68,6 +68,7 @@ public:
~FGRealValue() {}; ~FGRealValue() {};
double GetValue(void) const; double GetValue(void) const;
std::string GetName(void) const {return "constant";}
private: private:
double Value; double Value;

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
@endcode @endcode
@author Jon S. Berndt @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); void Print(void);
std::string GetName(void) const {return Name;}
private: private:
enum type {tt1D, tt2D, tt3D} Type; enum type {tt1D, tt2D, tt3D} Type;
enum axis {eRow=0, eColumn, eTable}; enum axis {eRow=0, eColumn, eTable};

View file

@ -52,7 +52,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_AERODYNAMICS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -80,7 +80,7 @@ FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
axisType = atNone; axisType = atNone;
Coeff = new CoeffArray[6]; AeroFunctions = new AeroFunctionArray[6];
impending_stall = stall_hyst = 0.0; impending_stall = stall_hyst = 0.0;
alphaclmin = alphaclmax = 0.0; alphaclmin = alphaclmax = 0.0;
@ -103,10 +103,10 @@ FGAerodynamics::~FGAerodynamics()
unsigned int i,j; unsigned int i,j;
for (i=0; i<6; i++) for (i=0; i<6; i++)
for (j=0; j<Coeff[i].size(); j++) for (j=0; j<AeroFunctions[i].size(); j++)
delete Coeff[i][j]; delete AeroFunctions[i][j];
delete[] Coeff; delete[] AeroFunctions;
delete AeroRPShift; delete AeroRPShift;
@ -142,7 +142,7 @@ bool FGAerodynamics::Run(void)
const double alpha=FDMExec->GetAuxiliary()->Getalpha(); const double alpha=FDMExec->GetAuxiliary()->Getalpha();
const double twovel=2*FDMExec->GetAuxiliary()->GetVt(); const double twovel=2*FDMExec->GetAuxiliary()->GetVt();
const double qbar = FDMExec->GetAuxiliary()->Getqbar(); 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 wingspan = FDMExec->GetAircraft()->GetWingSpan();
const double wingchord = FDMExec->GetAircraft()->Getcbar(); const double wingchord = FDMExec->GetAircraft()->Getcbar();
const double wingincidence = FDMExec->GetAircraft()->GetWingIncidence(); const double wingincidence = FDMExec->GetAircraft()->GetWingIncidence();
@ -177,8 +177,8 @@ bool FGAerodynamics::Run(void)
vFnative.InitMatrix(); vFnative.InitMatrix();
for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) { for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) { for (ctr=0; ctr < AeroFunctions[axis_ctr].size(); ctr++) {
vFnative(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue(); vFnative(axis_ctr+1) += AeroFunctions[axis_ctr][ctr]->GetValue();
} }
} }
@ -224,8 +224,8 @@ bool FGAerodynamics::Run(void)
vMoments = vDXYZcg*vForces; // M = r X F vMoments = vDXYZcg*vForces; // M = r X F
for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) { for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) { for (ctr = 0; ctr < AeroFunctions[axis_ctr+3].size(); ctr++) {
vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->GetValue(); vMoments(axis_ctr+1) += AeroFunctions[axis_ctr+3][ctr]->GetValue();
} }
} }
@ -349,7 +349,7 @@ bool FGAerodynamics::Load(Element *element)
axis_element = document->FindElement("axis"); axis_element = document->FindElement("axis");
while (axis_element) { while (axis_element) {
CoeffArray ca; AeroFunctionArray ca;
axis = axis_element->GetAttributeValue("name"); axis = axis_element->GetAttributeValue("name");
function_element = axis_element->FindElement("function"); function_element = axis_element->FindElement("function");
while (function_element) { while (function_element) {
@ -363,7 +363,7 @@ bool FGAerodynamics::Load(Element *element)
} }
function_element = axis_element->FindNextElement("function"); function_element = axis_element->FindNextElement("function");
} }
Coeff[AxisIdx[axis]] = ca; AeroFunctions[AxisIdx[axis]] = ca;
axis_element = document->FindNextElement("axis"); 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; bool firstime = true;
unsigned int axis, sd; unsigned int axis, sd;
for (axis = 0; axis < 6; axis++) { for (axis = 0; axis < 6; axis++) {
for (sd = 0; sd < Coeff[axis].size(); sd++) { for (sd = 0; sd < AeroFunctions[axis].size(); sd++) {
if (firstime) { if (firstime) {
firstime = false; firstime = false;
} else { } 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; ostringstream buf;
for (unsigned int axis = 0; axis < 6; axis++) { 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; 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 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 FORWARD DECLARATIONS
@ -89,7 +89,7 @@ CLASS DOCUMENTATION
{function contents} {function contents}
</function> </function>
<axis name="{LIFT | DRAG | SIDE | ROLL | PITCH | YAW}"> <axis name="{LIFT | DRAG | SIDE | ROLL | PITCH | YAW}">
{force coefficient definitions} {force or moment definitions}
</axis> </axis>
{additional axis definitions} {additional axis definitions}
</aerodynamics> </aerodynamics>
@ -103,13 +103,13 @@ CLASS DOCUMENTATION
<br> <br>
2) Axial-Normal coordinate system: 2) Axial-Normal coordinate system:
@code @code
<axis name="{AXIAL | NORMAL}"> <axis name="{AXIAL | NORMAL | SIDE}">
@endcode @endcode
<br> <br>
Systems may NOT be combined, or a load error will occur. Systems may NOT be combined, or a load error will occur.
@author Jon S. Berndt, Tony Peden @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 SetAlphaCLMax(double tt) { alphaclmax=tt; }
void SetAlphaCLMin(double tt) { alphaclmin=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 @param delimeter either a tab or comma string depending on output type
@return a string containing the descriptive names for all coefficients */ @return a string containing the descriptive names for all aero functions */
std::string GetCoefficientStrings(const std::string& delimeter) const; 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 @param delimeter either a tab or comma string depending on output type
@return a string containing the numeric values for the current set of @return a string containing the numeric values for the current set of
coefficients */ aero functions */
std::string GetCoefficientValues(const std::string& delimeter) const; std::string GetAeroFunctionValues(const std::string& delimeter) const;
/** Calculates and returns the wind-to-body axis transformation matrix. /** Calculates and returns the wind-to-body axis transformation matrix.
@return a reference to the wind-to-body transformation matrix. @return a reference to the wind-to-body transformation matrix.
@ -207,15 +207,15 @@ public:
*/ */
FGMatrix33& GetTb2w(void); FGMatrix33& GetTb2w(void);
std::vector <FGFunction*> * GetCoeff(void) const { return Coeff; } std::vector <FGFunction*> * GetAeroFunctions(void) const { return AeroFunctions; }
private: private:
enum eAxisType {atNone, atLiftDrag, atAxialNormal, atBodyXYZ} axisType; enum eAxisType {atNone, atLiftDrag, atAxialNormal, atBodyXYZ} axisType;
typedef std::map<std::string,int> AxisIndex; typedef std::map<std::string,int> AxisIndex;
AxisIndex AxisIdx; AxisIndex AxisIdx;
FGFunction* AeroRPShift; FGFunction* AeroRPShift;
typedef vector <FGFunction*> CoeffArray; typedef vector <FGFunction*> AeroFunctionArray;
CoeffArray* Coeff; AeroFunctionArray* AeroFunctions;
FGColumnVector3 vFnative; FGColumnVector3 vFnative;
FGColumnVector3 vFw; FGColumnVector3 vFw;
FGColumnVector3 vForces; FGColumnVector3 vForces;

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -124,6 +124,7 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
FGAtmosphere::~FGAtmosphere() FGAtmosphere::~FGAtmosphere()
{ {
delete(POE_Table);
Debug(1); Debug(1);
} }

26
src/FDM/JSBSim/models/FGAuxiliary.cpp Normal file → Executable file
View file

@ -59,7 +59,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_AUXILIARY;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -180,33 +180,30 @@ bool FGAuxiliary::Run()
vAeroUVW = vUVW - wind; vAeroUVW = vUVW - wind;
Vt = vAeroUVW.Magnitude(); 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 ( Vt > 1.0 ) {
if (vAeroUVW(eW) != 0.0) if (vAeroUVW(eW) != 0.0)
alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
if (vAeroUVW(eV) != 0.0) if (vAeroUVW(eV) != 0.0)
beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), beta = mUW > 0.0 ? atan2(vAeroUVW(eV), sqrt(mUW)) : 0.0;
sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
double signU=1; double signU=1;
if (vAeroUVW(eU) < 0.0) signU=-1; if (vAeroUVW(eU) < 0.0) signU=-1;
if ( mUW < 1.0 ) { if ( mUW >= 1.0 ) {
adot = 0.0;
bdot = 0.0;
} else {
adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW; adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW;
bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU) bdot = (signU*mUW*vUVWdot(eV)
+ vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW)); - 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(); Re = Vt * FDMExec->GetAircraft()->Getcbar() / FDMExec->GetAtmosphere()->GetKinematicViscosity();
qbar = 0.5*density*Vt*Vt; qbar = 0.5*density*Vt2;
qbarUW = 0.5*density*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW)); qbarUW = 0.5*density*(mUW);
qbarUV = 0.5*density*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV)); qbarUV = 0.5*density*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
Mach = Vt / soundspeed; Mach = Vt / soundspeed;
MachU = vMachUVW(eU) = vAeroUVW(eU) / 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. // A positive headwind is blowing with you, a negative headwind is blowing against you.
// psi is the direction the wind is blowing *towards*. // 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 double FGAuxiliary::GetHeadWind(void) const
{ {

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_BUOYANTFORCES;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -213,13 +213,13 @@ string FGBuoyantForces::GetBuoyancyStrings(string delimeter)
} }
for (axis = 0; axis < 6; axis++) { for (axis = 0; axis < 6; axis++) {
for (sd = 0; sd < Coeff[axis].size(); sd++) { for (sd = 0; sd < AeroFunctions[axis].size(); sd++) {
if (firstime) { if (firstime) {
firstime = false; firstime = false;
} else { } else {
CoeffStrings += delimeter; 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 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) { if (firstime) {
firstime = false; firstime = false;
} else { } else {
SDValues += delimeter; 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) 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, 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, 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, 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, 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, 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, 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 { 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; static const char *IdHdr = ID_FCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -183,17 +183,6 @@ bool FGFCS::InitModel(void)
return true; 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 // Notes: In this logic the default engine commands are set. This is simply a
// sort of safe-mode method in case the user has not defined control laws for // sort of safe-mode method in case the user has not defined control laws for

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -168,7 +168,7 @@ CLASS DOCUMENTATION
@property gear/tailhook-pos-norm @property gear/tailhook-pos-norm
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.31 $ @version $Revision: 1.35 $
@see FGActuator @see FGActuator
@see FGDeadBand @see FGDeadBand
@see FGFCSFunction @see FGFCSFunction
@ -540,7 +540,7 @@ public:
FGPropertyManager* GetPropertyManager(void) { return PropertyManager; } FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
void LateBind(void); bool GetTrimStatus(void) const { return FDMExec->GetTrimStatus(); }
private: private:
double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd; double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd;

View file

@ -62,7 +62,7 @@ DEFINITIONS
GLOBAL DATA 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; static const char *IdHdr = ID_LGEAR;
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in // 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 // 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. // to allow the WOW flag to be used in terminating a scripted run.
if (WOW && lastWOW) CrashDetect(); if (WOW && lastWOW) CrashDetect();
lastWOW = WOW; lastWOW = WOW;
}
return FGForce::GetBodyForces(); return FGForce::GetBodyForces();
} }

View file

@ -57,7 +57,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_MODEL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -77,7 +77,7 @@ FGModel::FGModel(FGFDMExec* fdmex)
//must be brought up now. //must be brought up now.
PropertyManager = FDMExec->GetPropertyManager(); PropertyManager = FDMExec->GetPropertyManager();
exe_ctr = 1; exe_ctr = 0;
rate = 1; rate = 1;
if (debug_lvl & 2) cout << " FGModel Base Class" << endl; 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 (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; if (exe_ctr++ == 1) return false;
else return true; else return true;

View file

@ -74,7 +74,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_OUTPUT;
// (stolen from FGFS native_fdm.cxx) // (stolen from FGFS native_fdm.cxx)
@ -182,21 +182,9 @@ bool FGOutput::Run(void)
{ {
if (FGModel::Run()) return true; if (FGModel::Run()) return true;
if (enabled && !FDMExec->IntegrationSuspended()&& !FDMExec->Holding()) { if (enabled && !FDMExec->IntegrationSuspended() && !FDMExec->Holding()) {
RunPreFunctions(); RunPreFunctions();
if (Type == otSocket) { Print();
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
}
RunPostFunctions(); RunPostFunctions();
} }
return false; 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) void FGOutput::SetType(const string& type)
{ {
if (type == "CSV") { if (type == "CSV") {
@ -296,6 +303,7 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter; 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 << "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_{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)"; outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)";
} }
if (SubSystems & ssForces) { if (SubSystems & ssForces) {
@ -359,8 +367,8 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << "Distance AGL (ft)" + delimeter; outstream << "Distance AGL (ft)" + delimeter;
outstream << "Terrain Elevation (ft)"; outstream << "Terrain Elevation (ft)";
} }
if (SubSystems & ssCoefficients) { if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetCoefficientStrings(delimeter); scratch = Aerodynamics->GetAeroFunctionStrings(delimeter);
if (scratch.length() != 0) outstream << delimeter << scratch; if (scratch.length() != 0) outstream << delimeter << scratch;
} }
if (SubSystems & ssFCS) { if (SubSystems & ssFCS) {
@ -415,6 +423,7 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter; outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter; outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter; outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter;
outstream << Propagate->GetECEFVelocity().Dump(delimeter) << delimeter;
outstream << Propagate->GetVel().Dump(delimeter); outstream << Propagate->GetVel().Dump(delimeter);
outstream.precision(10); outstream.precision(10);
} }
@ -475,8 +484,8 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << Propagate->GetTerrainElevation(); outstream << Propagate->GetTerrainElevation();
outstream.precision(10); outstream.precision(10);
} }
if (SubSystems & ssCoefficients) { if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetCoefficientValues(delimeter); scratch = Aerodynamics->GetAeroFunctionValues(delimeter);
if (scratch.length() != 0) outstream << delimeter << scratch; if (scratch.length() != 0) outstream << delimeter << scratch;
} }
if (SubSystems & ssFCS) { if (SubSystems & ssFCS) {
@ -826,8 +835,8 @@ void FGOutput::SocketOutput(void)
socket->Append("Latitude (deg)"); socket->Append("Latitude (deg)");
socket->Append("Longitude (deg)"); socket->Append("Longitude (deg)");
} }
if (SubSystems & ssCoefficients) { if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetCoefficientStrings(","); scratch = Aerodynamics->GetAeroFunctionStrings(",");
if (scratch.length() != 0) socket->Append(scratch); if (scratch.length() != 0) socket->Append(scratch);
} }
if (SubSystems & ssFCS) { if (SubSystems & ssFCS) {
@ -932,8 +941,8 @@ void FGOutput::SocketOutput(void)
socket->Append(Propagate->GetLocation().GetLatitudeDeg()); socket->Append(Propagate->GetLocation().GetLatitudeDeg());
socket->Append(Propagate->GetLocation().GetLongitudeDeg()); socket->Append(Propagate->GetLocation().GetLongitudeDeg());
} }
if (SubSystems & ssCoefficients) { if (SubSystems & ssAeroFunctions) {
scratch = Aerodynamics->GetCoefficientValues(","); scratch = Aerodynamics->GetAeroFunctionValues(",");
if (scratch.length() != 0) socket->Append(scratch); if (scratch.length() != 0) socket->Append(scratch);
} }
if (SubSystems & ssFCS) { if (SubSystems & ssFCS) {
@ -974,7 +983,7 @@ bool FGOutput::Load(Element* element)
{ {
string parameter=""; string parameter="";
string name=""; string name="";
int OutRate = 0; double OutRate = 0.0;
unsigned int port; unsigned int port;
Element *property_element; Element *property_element;
@ -1003,7 +1012,7 @@ bool FGOutput::Load(Element* element)
BaseFilename = Filename = name; BaseFilename = Filename = name;
} }
if (!document->GetAttributeValue("rate").empty()) { if (!document->GetAttributeValue("rate").empty()) {
OutRate = (int)document->GetAttributeValueAsNumber("rate"); OutRate = document->GetAttributeValueAsNumber("rate");
} else { } else {
OutRate = 1; OutRate = 1;
} }
@ -1027,7 +1036,7 @@ bool FGOutput::Load(Element* element)
if (document->FindElementValue("position") == string("ON")) if (document->FindElementValue("position") == string("ON"))
SubSystems += ssPropagate; SubSystems += ssPropagate;
if (document->FindElementValue("coefficients") == string("ON")) if (document->FindElementValue("coefficients") == string("ON"))
SubSystems += ssCoefficients; SubSystems += ssAeroFunctions;
if (document->FindElementValue("ground_reactions") == string("ON")) if (document->FindElementValue("ground_reactions") == string("ON"))
SubSystems += ssGroundReactions; SubSystems += ssGroundReactions;
if (document->FindElementValue("fcs") == string("ON")) 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); rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz);
if (rtHz > 0) { if (rtHz > 0) {
@ -1128,7 +1137,7 @@ void FGOutput::Debug(int from)
if (SubSystems & ssMoments) cout << " Moments parameters logged" << endl; if (SubSystems & ssMoments) cout << " Moments parameters logged" << endl;
if (SubSystems & ssAtmosphere) cout << " Atmosphere parameters logged" << endl; if (SubSystems & ssAtmosphere) cout << " Atmosphere parameters logged" << endl;
if (SubSystems & ssMassProps) cout << " Mass 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 & ssPropagate) cout << " Propagate parameters logged" << endl;
if (SubSystems & ssGroundReactions) cout << " Ground parameters logged" << endl; if (SubSystems & ssGroundReactions) cout << " Ground parameters logged" << endl;
if (SubSystems & ssFCS) cout << " FCS parameters logged" << endl; if (SubSystems & ssFCS) cout << " FCS parameters logged" << endl;

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -124,7 +124,7 @@ CLASS DOCUMENTATION
propulsion ON|OFF propulsion ON|OFF
</pre> </pre>
NOTE that Time is always output with the data. 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 InitModel(void);
bool Run(void); bool Run(void);
void Print(void);
void DelimitedOutput(const std::string&); void DelimitedOutput(const std::string&);
void SocketOutput(void); void SocketOutput(void);
void FlightGearSocketOutput(void); void FlightGearSocketOutput(void);
@ -153,7 +154,7 @@ public:
void SetSubsystems(int tt) {SubSystems = tt;} void SetSubsystems(int tt) {SubSystems = tt;}
void SetOutputFileName(const std::string& fname) {Filename = fname;} void SetOutputFileName(const std::string& fname) {Filename = fname;}
void SetDirectivesFile(const std::string& fname) {DirectivesFile = fname;} void SetDirectivesFile(const std::string& fname) {DirectivesFile = fname;}
void SetRate(int rt); void SetRate(double rt);
void Enable(void) { enabled = true; } void Enable(void) { enabled = true; }
void Disable(void) { enabled = false; } void Disable(void) { enabled = false; }
bool Toggle(void) {enabled = !enabled; return enabled;} bool Toggle(void) {enabled = !enabled; return enabled;}
@ -171,7 +172,7 @@ public:
/** Subsystem: Moments (= 32) */ ssMoments = 32, /** Subsystem: Moments (= 32) */ ssMoments = 32,
/** Subsystem: Atmosphere (= 64) */ ssAtmosphere = 64, /** Subsystem: Atmosphere (= 64) */ ssAtmosphere = 64,
/** Subsystem: Mass Properties (= 128) */ ssMassProps = 128, /** Subsystem: Mass Properties (= 128) */ ssMassProps = 128,
/** Subsystem: Coefficients (= 256) */ ssCoefficients = 256, /** Subsystem: Coefficients (= 256) */ ssAeroFunctions = 256,
/** Subsystem: Propagate (= 512) */ ssPropagate = 512, /** Subsystem: Propagate (= 512) */ ssPropagate = 512,
/** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024, /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024,
/** Subsystem: FCS (= 2048) */ ssFCS = 2048, /** Subsystem: FCS (= 2048) */ ssFCS = 2048,

View file

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

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -102,7 +102,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Jon S. Berndt, Mathias Froehlich @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 */ units rad/sec */
FGColumnVector3 vPQRi; 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 /** The current orientation of the vehicle, that is, the orientation of the
body frame relative to the local, NED frame. */ body frame relative to the local, NED frame. */
FGQuaternion qAttitudeLocal; FGQuaternion qAttitudeLocal;
@ -338,6 +333,10 @@ public:
*/ */
const FGColumnVector3& GetInertialPosition(void) const { return VState.vInertialPosition; } 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. /** Returns the current altitude above sea level.
This function returns the altitude above sea level. This function returns the altitude above sea level.
units ft units ft
@ -581,8 +580,8 @@ public:
void RecomputeLocalTerrainRadius(void); void RecomputeLocalTerrainRadius(void);
void NudgeBodyLocation(FGColumnVector3 deltaLoc) { void NudgeBodyLocation(FGColumnVector3 deltaLoc) {
vDeltaXYZEC = Tb2ec*deltaLoc; VState.vInertialPosition -= Tb2i*deltaLoc;
VState.vLocation -= vDeltaXYZEC; VState.vLocation -= Tb2ec*deltaLoc;
} }
struct LagrangeMultiplier { struct LagrangeMultiplier {
@ -602,8 +601,7 @@ private:
struct VehicleState VState; struct VehicleState VState;
FGColumnVector3 vVel; FGColumnVector3 vVel;
FGColumnVector3 vPQRdot; FGColumnVector3 vPQRdot, vPQRidot;
FGColumnVector3 vPQRidot;
FGColumnVector3 vUVWdot, vUVWidot; FGColumnVector3 vUVWdot, vUVWidot;
FGColumnVector3 vInertialVelocity; FGColumnVector3 vInertialVelocity;
FGColumnVector3 vLocation; FGColumnVector3 vLocation;

View file

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

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_ACTUATOR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -114,10 +114,12 @@ bool FGActuator::Run(void )
// the Input will be further processed and the eventual Output // the Input will be further processed and the eventual Output
// will be overwritten from this perfect value. // will be overwritten from this perfect value.
if (lag != 0.0) Lag(); // models actuator lag if (!fcs->GetTrimStatus()) {
if (rate_limit != 0) RateLimit(); // limit the actuator rate if (lag != 0.0) Lag(); // models actuator lag
if (rate_limit != 0) RateLimit(); // limit the actuator rate
}
if (deadband_width != 0.0) Deadband(); 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 (bias != 0.0) Bias(); // models a finite bias
if (fail_stuck) Output = PreviousOutput; if (fail_stuck) Output = PreviousOutput;
@ -187,6 +189,18 @@ void FGActuator::RateLimit(void)
void FGActuator::Deadband(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 (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
if (InputSigns[0] < 0) if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl; cout << " INPUT: -" << InputNames[0] << endl;
else else
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNames[0] << endl;
if (IsOutput) { if (IsOutput) {
for (unsigned int i=0; i<OutputNodes.size(); i++) 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 (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->GetName() << endl;
if (WidthPropertyNode != 0) { if (WidthPropertyNode != 0) {
cout << " DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl; cout << " DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl;
} else { } else {

View file

@ -40,6 +40,7 @@ INCLUDES
#include "FGFCSComponent.h" #include "FGFCSComponent.h"
#include "input_output/FGPropertyManager.h" #include "input_output/FGPropertyManager.h"
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#include "math/FGPropertyValue.h"
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
@ -47,7 +48,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -111,8 +112,6 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
Name = element->GetAttributeValue("name"); Name = element->GetAttributeValue("name");
FGPropertyManager *tmp=0;
input_element = element->FindElement("input"); input_element = element->FindElement("input");
while (input_element) { while (input_element) {
input = input_element->GetDataLine(); input = input_element->GetDataLine();
@ -122,14 +121,14 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
} else { } else {
InputSigns.push_back( 1.0); InputSigns.push_back( 1.0);
} }
FGPropertyManager* node = 0L;
if (PropertyManager->HasNode(input)) { if (PropertyManager->HasNode(input)) {
tmp = PropertyManager->GetNode(input); node = PropertyManager->GetNode(input);
InputNodes.push_back(new FGPropertyValue( node ));
} else { } else {
tmp = 0L; InputNodes.push_back(new FGPropertyValue( input,
// cerr << fgcyan << "In component: " + Name + " property " PropertyManager ));
// + input + " is initially undefined." << reset << endl;
} }
InputNodes.push_back( tmp );
InputNames.push_back( input ); InputNames.push_back( input );
input_element = element->FindNextElement("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. // 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 "FGJSBBase.h"
#include "math/FGParameter.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -45,7 +46,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -80,7 +81,7 @@ CLASS DOCUMENTATION
- FGActuator - FGActuator
@author Jon S. Berndt @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 @see Documentation for the FGFCS class, and for the configuration file class
*/ */
@ -98,7 +99,6 @@ public:
virtual bool Run(void); virtual bool Run(void);
virtual void SetOutput(void); virtual void SetOutput(void);
void LateBind(void);
double GetOutput (void) const {return Output;} double GetOutput (void) const {return Output;}
std::string GetName(void) const {return Name;} std::string GetName(void) const {return Name;}
std::string GetType(void) const { return Type; } std::string GetType(void) const { return Type; }
@ -111,7 +111,7 @@ protected:
std::vector <FGPropertyManager*> OutputNodes; std::vector <FGPropertyManager*> OutputNodes;
FGPropertyManager* ClipMinPropertyNode; FGPropertyManager* ClipMinPropertyNode;
FGPropertyManager* ClipMaxPropertyNode; FGPropertyManager* ClipMaxPropertyNode;
std::vector <FGPropertyManager*> InputNodes; std::vector <FGParameter*> InputNodes;
std::vector <std::string> InputNames; std::vector <std::string> InputNames;
std::vector <float> InputSigns; std::vector <float> InputSigns;
std::vector <double> output_array; 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 (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
if (InputNodes.size()>0) if (InputNodes.size()>0)
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->GetName() << endl;
// cout << " Function: " << endl; // cout << " Function: " << endl;
if (IsOutput) { if (IsOutput) {
for (unsigned int i=0; i<OutputNodes.size(); i++) 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 (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->GetName() << endl;
switch (FilterType) { switch (FilterType) {
case eLag: case eLag:
if (PropertySign[1] < 0.0) sgn="-"; 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 (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
if (InputSigns[0] < 0) if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl; cout << " INPUT: -" << InputNodes[0]->GetName() << endl;
else else
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->GetName() << endl;
if (GainPropertyNode != 0) { if (GainPropertyNode != 0) {
cout << " GAIN: " << GainPropertyNode->GetName() << endl; 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 (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->GetName() << endl;
cout << " DETENTS: " << NumDetents << endl; cout << " DETENTS: " << NumDetents << endl;
for (int i=0;i<NumDetents;i++) { for (int i=0;i<NumDetents;i++) {
cout << " " << Detents[i] << " " << TransitionTimes[i] << endl; 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 (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
if (InputSigns[0] < 0) if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl; cout << " INPUT: -" << InputNodes[0]->GetName() << endl;
else else
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->GetName() << endl;
if (IsOutput) { if (IsOutput) {
for (unsigned int i=0; i<OutputNodes.size(); i++) 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 (from == 0) { // Constructor
if (InputSigns.size() > 0) { if (InputSigns.size() > 0) {
if (InputSigns[0] < 0) if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl; cout << " INPUT: -" << InputNodes[0]->GetName() << endl;
else else
cout << " INPUT: " << InputNodes[0]->getName() << endl; cout << " INPUT: " << InputNodes[0]->GetName() << endl;
} }
if (bits != 0) { if (bits != 0) {
if (quant_property.empty()) if (quant_property.empty())

View file

@ -69,7 +69,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_SWITCH;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -135,7 +135,13 @@ FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
} else { } else {
current_test->sign = 1.0; 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 i=0; i<tests.size(); i++) {
for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j]; for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j];
delete tests[i]->OutputProp;
delete tests[i]; delete tests[i];
} }

View file

@ -40,12 +40,13 @@ INCLUDES
#include "FGFCSComponent.h" #include "FGFCSComponent.h"
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#include "math/FGCondition.h" #include "math/FGCondition.h"
#include "math/FGPropertyValue.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS 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 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. whatever value fcs/roll-ap-error-summer is.
@author Jon S. Berndt @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; vector <FGCondition*> conditions;
eLogic Logic; eLogic Logic;
double OutputVal; double OutputVal;
FGPropertyManager *OutputProp; FGPropertyValue *OutputProp;
float sign; float sign;
double GetValue(void) { double GetValue(void) {
if (OutputProp == 0L) return OutputVal; if (OutputProp == 0L) return OutputVal;
else return OutputProp->getDoubleValue()*sign; else return OutputProp->GetValue()*sign;
} }
test(void) { // constructor for the test structure test(void) { // constructor for the test structure

View file

@ -50,7 +50,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_ELECTRIC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -93,15 +93,20 @@ void FGElectric::Calculate(void)
HP = PowerWatts * Throttle / hptowatts; HP = PowerWatts * Throttle / hptowatts;
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); Thruster->Calculate(HP * hptoftlbssec);
Thruster->Calculate(PowerAvailable);
RunPostFunctions(); RunPostFunctions();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGElectric::CalcFuelNeed(void)
{
return 0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGElectric::GetEngineLabels(const string& delimiter) string FGElectric::GetEngineLabels(const string& delimiter)
{ {
std::ostringstream buf; std::ostringstream buf;
@ -174,10 +179,4 @@ void FGElectric::Debug(int from)
} }
} }
double
FGElectric::CalcFuelNeed(void)
{
return 0;
}
} // namespace JSBSim } // namespace JSBSim

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -65,7 +65,7 @@ CLASS DOCUMENTATION
there is no battery model available, so this motor does not consume any there is no battery model available, so this motor does not consume any
energy. There is no internal friction. energy. There is no internal friction.
@author David Culp @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(); ~FGElectric();
void Calculate(void); void Calculate(void);
double GetPowerAvailable(void) {return PowerAvailable;} double GetPowerAvailable(void) {return (HP * hptoftlbssec);}
double getRPM(void) {return RPM;} double getRPM(void) {return RPM;}
std::string GetEngineLabels(const std::string& delimiter); std::string GetEngineLabels(const std::string& delimiter);
std::string GetEngineValues(const std::string& delimiter); std::string GetEngineValues(const std::string& delimiter);
@ -91,7 +91,6 @@ private:
double CalcFuelNeed(void); double CalcFuelNeed(void);
double BrakeHorsePower; double BrakeHorsePower;
double PowerAvailable;
// timestep // timestep
double dt; double dt;
@ -101,7 +100,7 @@ private:
double PowerWatts; // maximum engine power double PowerWatts; // maximum engine power
double RPM; // revolutions per minute double RPM; // revolutions per minute
double HP; double HP; // engine output, in horsepower
void Debug(int from); void Debug(int from);
}; };

View file

@ -54,7 +54,7 @@ using namespace std;
namespace JSBSim { 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; 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); PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust);
property_name = base_property_name + "/fuel-flow-rate-pps"; property_name = base_property_name + "/fuel-flow-rate-pps";
PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate); 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)); PostLoad(engine_element, PropertyManager, to_string(EngineNumber));
@ -177,11 +179,11 @@ void FGEngine::ResetToIC(void)
FuelExpended = 0.0; FuelExpended = 0.0;
Starved = Running = Cranking = false; Starved = Running = Cranking = false;
PctPower = 0.0; PctPower = 0.0;
TrimMode = false;
FuelFlow_gph = 0.0; FuelFlow_gph = 0.0;
FuelFlow_pph = 0.0; FuelFlow_pph = 0.0;
FuelFlowRate = 0.0; FuelFlowRate = 0.0;
FuelFreeze = false; FuelFreeze = false;
FuelUsedLbs = 0.0;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -194,7 +196,7 @@ void FGEngine::ResetToIC(void)
void FGEngine::ConsumeFuel(void) void FGEngine::ConsumeFuel(void)
{ {
if (FuelFreeze) return; if (FuelFreeze) return;
if (TrimMode) return; if (FDMExec->GetTrimStatus()) return;
unsigned int i; unsigned int i;
double Fshortage, FuelNeeded; double Fshortage, FuelNeeded;
@ -240,6 +242,7 @@ void FGEngine::ConsumeFuel(void)
Tank = Propulsion->GetTank(FeedList[i]); Tank = Propulsion->GetTank(FeedList[i]);
Tank->Drain(FuelNeeded); Tank->Drain(FuelNeeded);
} }
FuelUsedLbs += FuelToBurn;
} }

View file

@ -55,7 +55,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -118,7 +118,7 @@ CLASS DOCUMENTATION
documentation for engine and thruster classes. documentation for engine and thruster classes.
</pre> </pre>
@author Jon S. Berndt @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_gph () const {return FuelFlow_gph;}
virtual double getFuelFlow_pph () const {return FuelFlow_pph;} virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
virtual double GetFuelFlowRate(void) const {return FuelFlowRate;} virtual double GetFuelFlowRate(void) const {return FuelFlowRate;}
virtual double GetFuelUsedLbs(void) const {return FuelUsedLbs;}
virtual bool GetStarved(void) { return Starved; } virtual bool GetStarved(void) { return Starved; }
virtual bool GetRunning(void) const { return Running; } virtual bool GetRunning(void) const { return Running; }
virtual bool GetCranking(void) { return Cranking; } virtual bool GetCranking(void) { return Cranking; }
@ -173,9 +174,6 @@ public:
virtual double GetPowerAvailable(void) {return 0.0;}; 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& GetBodyForces(void);
virtual FGColumnVector3& GetMoments(void); virtual FGColumnVector3& GetMoments(void);
@ -219,12 +217,12 @@ protected:
bool Starved; bool Starved;
bool Running; bool Running;
bool Cranking; bool Cranking;
bool TrimMode;
bool FuelFreeze; bool FuelFreeze;
double FuelFlow_gph; double FuelFlow_gph;
double FuelFlow_pph; double FuelFlow_pph;
double FuelDensity; double FuelDensity;
double FuelUsedLbs;
FGFDMExec* FDMExec; FGFDMExec* FDMExec;
FGAtmosphere* Atmosphere; FGAtmosphere* Atmosphere;

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_FORCE;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -62,9 +62,20 @@ FGForce::FGForce(FGFDMExec *FDMExec) :
fdmex(FDMExec), fdmex(FDMExec),
ttype(tNone) ttype(tNone)
{ {
mT(1,1) = 1; //identity matrix vFn.InitMatrix();
mT(2,2) = 1; vMn.InitMatrix();
mT(3,3) = 1; 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); Debug(0);
} }

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_PISTON;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -442,8 +442,7 @@ void FGPiston::Calculate(void)
((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
} }
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); Thruster->Calculate(HP * hptoftlbssec);
Thruster->Calculate(PowerAvailable);
RunPostFunctions(); RunPostFunctions();
} }
@ -872,7 +871,7 @@ string FGPiston::GetEngineLabels(const string& delimiter)
{ {
std::ostringstream buf; 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 << " HP (engine " << EngineNumber << ")" << delimiter
<< Name << " equivalent ratio (engine " << EngineNumber << ")" << delimiter << Name << " equivalent ratio (engine " << EngineNumber << ")" << delimiter
<< Name << " MAP (engine " << EngineNumber << " in inHg)" << delimiter << Name << " MAP (engine " << EngineNumber << " in inHg)" << delimiter
@ -887,7 +886,7 @@ string FGPiston::GetEngineValues(const string& delimiter)
{ {
std::ostringstream buf; std::ostringstream buf;
buf << PowerAvailable << delimiter << HP << delimiter buf << (HP * hptoftlbssec) << delimiter << HP << delimiter
<< equivalence_ratio << delimiter << ManifoldPressure_inHg << delimiter << equivalence_ratio << delimiter << ManifoldPressure_inHg << delimiter
<< Thruster->GetThrusterValues(EngineNumber, delimiter); << Thruster->GetThrusterValues(EngineNumber, delimiter);

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS 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 #define FG_MAX_BOOST_SPEEDS 3
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -182,7 +182,7 @@ CLASS DOCUMENTATION
@author Dave Luff (engine operational code) @author Dave Luff (engine operational code)
@author David Megginson (initial porting and additional code) @author David Megginson (initial porting and additional code)
@author Ron Jensen (additional engine 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); std::string GetEngineValues(const std::string& delimiter);
void Calculate(void); void Calculate(void);
double GetPowerAvailable(void) const {return PowerAvailable;} double GetPowerAvailable(void) const {return (HP * hptoftlbssec);}
double CalcFuelNeed(void); double CalcFuelNeed(void);
void ResetToIC(void); void ResetToIC(void);
@ -227,7 +227,6 @@ private:
double FMEP; double FMEP;
double FMEPDynamic; double FMEPDynamic;
double FMEPStatic; double FMEPStatic;
double PowerAvailable;
// timestep // timestep
double dt; double dt;

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim { 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; 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 must be getting the aerodynamic velocity here, NOT the inertial velocity.
// We need the velocity with respect to the wind. // 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 // 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 // propeller and its acceleration to give a new RPM. The current RPM will be
// used to calculate thrust. // used to calculate thrust.
// //
// Because RPM could be zero, we need to be creative about what RPM is stated as. // 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 Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU);
double rho = fdmex->GetAtmosphere()->GetDensity(); double rho = fdmex->GetAtmosphere()->GetDensity();
double RPS = RPM/60.0; double RPS = RPM/60.0;
PowerAvailable = EnginePower - GetPowerRequired();
// Calculate helical tip Mach // Calculate helical tip Mach
double Area = 0.25*Diameter*Diameter*M_PI; double Area = 0.25*Diameter*Diameter*M_PI;
double Vtip = RPS * Diameter * M_PI; double Vtip = RPS * Diameter * M_PI;

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -141,7 +141,7 @@ CLASS DOCUMENTATION
<li>Various NACA Technical Notes and Reports</li> <li>Various NACA Technical Notes and Reports</li>
</ul> </ul>
@author Jon S. Berndt @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 FGEngine
@see FGThruster @see FGThruster
*/ */
@ -247,7 +247,7 @@ public:
accelerate the prop. It could be negative, dictating that the propeller accelerate the prop. It could be negative, dictating that the propeller
would be slowed. would be slowed.
@return the thrust in pounds */ @return the thrust in pounds */
double Calculate(double PowerAvailable); double Calculate(double EnginePower);
FGColumnVector3 GetPFactor(void); FGColumnVector3 GetPFactor(void);
string GetThrusterLabels(int id, string delimeter); string GetThrusterLabels(int id, string delimeter);
string GetThrusterValues(int id, string delimeter); string GetThrusterValues(int id, string delimeter);

View file

@ -49,7 +49,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_ROCKET;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -202,7 +202,7 @@ void FGRocket::ConsumeFuel(void)
double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0; double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0;
if (FuelFreeze) return; if (FuelFreeze) return;
if (TrimMode) return; if (FDMExec->GetTrimStatus()) return;
// Count how many assigned tanks have fuel for this engine at this time. // 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 // 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 11/15/10 T.Kreitler treated flow solver bug, flow and torque calculations
simplified, tiploss influence removed from flapping angles simplified, tiploss influence removed from flapping angles
01/10/11 T.Kreitler changed to single rotor model 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 INCLUDES
@ -56,7 +58,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_ROTOR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -109,7 +111,11 @@ FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num)
// control // control
ControlMap(eMainCtrl), 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); 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. // calculation would cause jumps too. 1Hz seems sufficient.
damp_hagl = Filter(1.0,dt); damp_hagl = Filter(1.0,dt);
// avoid too abrupt changes in power transmission
FreeWheelLag = Filter(200.0,dt);
// enable import-export // enable import-export
BindModel(); 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 // 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) void FGRotor::Configure(Element* rotor_element)
{ {
@ -279,22 +288,24 @@ void FGRotor::Configure(Element* rotor_element)
estimate = sqr(BladeChord) * sqr(Radius - HingeOffset) * 0.57; estimate = sqr(BladeChord) * sqr(Radius - HingeOffset) * 0.57;
BladeFlappingMoment = ConfigValueConv(rotor_element, "flappingmoment", estimate, "SLUG*FT2"); 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 // guess mass from moment of a thin stick, and multiply by the blades cg distance
estimate = ( 3.0 * BladeFlappingMoment / sqr(Radius) ) * (0.45 * Radius) ; estimate = ( 3.0 * BladeFlappingMoment / sqr(Radius) ) * (0.45 * Radius) ;
BladeMassMoment = ConfigValue(rotor_element, "massmoment", estimate); // unit is slug-ft BladeMassMoment = ConfigValue(rotor_element, "massmoment", estimate); // unit is slug-ft
BladeMassMoment = Constrain(0.001, BladeMassMoment, 1e9); BladeMassMoment = Constrain(0.001, BladeMassMoment, 1e9);
TipLossB = ConfigValue(rotor_element, "tiplossfactor", 1.0, silent);
estimate = 1.1 * BladeFlappingMoment * BladeNum; estimate = 1.1 * BladeFlappingMoment * BladeNum;
PolarMoment = ConfigValueConv(rotor_element, "polarmoment", estimate, "SLUG*FT2"); 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" is treated further down.
InflowLag = Constrain(1e-6, InflowLag, 2.0);
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 // ground effect
if (rotor_element->FindElement("cgroundeffect")) { if (rotor_element->FindElement("cgroundeffect")) {
@ -309,6 +320,17 @@ void FGRotor::Configure(Element* rotor_element)
GroundEffectExp = ConfigValue(rotor_element, "groundeffectexp", 0.0); GroundEffectExp = ConfigValue(rotor_element, "groundeffectexp", 0.0);
GroundEffectShift = ConfigValueConv(rotor_element, "groundeffectshift", 0.0, "FT"); 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 // 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]; 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]; 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; LockNumberByRho = LiftCurveSlope * BladeChord * R[4] / BladeFlappingMoment;
Solidity = BladeNum * BladeChord / (M_PI * Radius); 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; return;
} // Configure } // Configure
@ -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) 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; double t075 = theta_0 + 0.75 * BladeTwist;
H_drag = Thrust * a_dw; 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 // Simplified version of /SH79/ eqn(36). Uses an estimate for blade drag
// (a new config parameter to come...). // (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) void FGRotor::calc_torque(double theta_0)
{ {
@ -637,18 +666,52 @@ void FGRotor::CalcStatePart2(double PowerAvailable)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGRotor::GetPowerRequired(void) // Simulation of a free-wheeling-unit (FWU). Might need improvements.
{
CalcStatePart1(); void FGRotor::calc_freewheel_state(double p_source, double p_load) {
PowerRequired = Torque * Omega;
return PowerRequired; // 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; return Thrust;
} }
@ -725,6 +788,11 @@ bool FGRotor::BindModel(void)
PropertyManager->Tie( property_name.c_str(), this, &FGRotor::GetLongitudinalCtrl, &FGRotor::SetLongitudinalCtrl); 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 (ExternalRPM) {
if (RPMdefinition == -1) { if (RPMdefinition == -1) {
property_name = base_property_name + "/x-rpm-dict"; property_name = base_property_name + "/x-rpm-dict";
@ -826,6 +894,7 @@ void FGRotor::Debug(int from)
cout << " Tip Loss = " << TipLossB << endl; cout << " Tip Loss = " << TipLossB << endl;
cout << " Lock Number = " << LockNumberByRho * 0.002356 << " (SL)" << endl; cout << " Lock Number = " << LockNumberByRho * 0.002356 << " (SL)" << endl;
cout << " Solidity = " << Solidity << endl; cout << " Solidity = " << Solidity << endl;
cout << " Max Brake Power = " << MaxBrakePower/hptoftlbssec << " HP" << endl;
switch (ControlMap) { switch (ControlMap) {
case eTailCtrl: ControlMapName = "Tail Rotor"; break; case eTailCtrl: ControlMapName = "Tail Rotor"; break;
@ -834,6 +903,12 @@ void FGRotor::Debug(int from)
} }
cout << " Control Mapping = " << ControlMapName << endl; 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 if (debug_lvl & 2 ) { // Instantiation/Destruction notification

View file

@ -27,6 +27,7 @@ HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
01/01/10 T.Kreitler test implementation 01/01/10 T.Kreitler test implementation
01/10/11 T.Kreitler changed to single rotor model 01/10/11 T.Kreitler changed to single rotor model
03/06/11 T.Kreitler added brake, clutch, and experimental free-wheeling-unit
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY SENTRY
@ -45,7 +46,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -76,12 +77,15 @@ CLASS DOCUMENTATION
<polarmoment unit="{MOMENT}"> {number} </polarmoment> <polarmoment unit="{MOMENT}"> {number} </polarmoment>
<inflowlag> {number} </inflowlag> <inflowlag> {number} </inflowlag>
<tiplossfactor> {number} </tiplossfactor> <tiplossfactor> {number} </tiplossfactor>
<maxbrakepower unit="{POWER}"> {number} </maxbrakepower>
<controlmap> {MAIN|TAIL|TANDEM} </controlmap> <controlmap> {MAIN|TAIL|TANDEM} </controlmap>
<ExternalRPM> {number} </ExternalRPM> <ExternalRPM> {number} </ExternalRPM>
<groundeffectexp> {number} </groundeffectexp> <groundeffectexp> {number} </groundeffectexp>
<groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift> <groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>
<freewheelthresh> {number} </freewheelthresh>
</rotor> </rotor>
// LENGTH means any of the supported units, same for ANGLE and MOMENT. // 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 \<massmoment> - Blade mass moment. Mass of a single blade times the blade's
cg-distance from the hub, optional. cg-distance from the hub, optional.
\<polarmoment> - Moment of inertia for the whole rotor disk, optional. \<polarmoment> - Moment of inertia for the whole rotor disk, optional.
\<inflowlag> - Rotor inflow time constant, sec. Smaller values yield to \<inflowlag> - Rotor inflow time constant, sec. Smaller values yield to quicker
quicker responses to control input (defaults to 0.2). responses (typical values for main rotor: 0.1 - 0.2 s).
\<tiplossfactor> - Tip-loss factor. The Blade fraction that produces lift. \<tiplossfactor> - Tip-loss factor. The Blade fraction that produces lift.
Value usually ranges between 0.95 - 1.0, optional (B). 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). \<controlmap> - Defines the control inputs used (see notes).
\<ExternalRPM> - Links the rotor to another rotor, or an user controllable property. \<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. Omitting or setting to 0.0 disables the effect calculation.
\<groundeffectshift> - Further adjustment of ground effect, approx. hub height or slightly above. \<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> </pre>
<h3>Notes:</h3> <h3>Notes:</h3>
@ -165,8 +174,6 @@ CLASS DOCUMENTATION
<h4>- Engine issues -</h4> <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 In order to keep the rotor speed constant, use of a RPM-Governor system is
encouraged (see examples). encouraged (see examples).
@ -189,10 +196,12 @@ CLASS DOCUMENTATION
Comparison With Flight Measurements", NACA TN-2136, 1950.</dd> Comparison With Flight Measurements", NACA TN-2136, 1950.</dd>
<dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment <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> </dl>
@author Thomas Kreitler @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 /// Destructor for FGRotor
~FGRotor(); ~FGRotor();
/** Returns the power required by the rotor. Well, to achieve this the rotor /** Returns the power required by the rotor. */
is cycled through the whole machinery, yielding to a new state. double GetPowerRequired(void)const { return PowerRequired; }
(hmm, sort of a huge side effect)
*/
double GetPowerRequired(void);
/** Returns the scalar thrust of the rotor, and adjusts the RPM value. */ /** 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. /// Retrieves the RPMs of the rotor.
@ -257,6 +263,8 @@ public:
double GetCT(void) const { return C_T; } double GetCT(void) const { return C_T; }
/// Retrieves the torque /// Retrieves the torque
double GetTorque(void) const { return 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 /// Downwash angle - currently only valid for a rotor that spins horizontally
double GetThetaDW(void) const { return theta_downwash; } double GetThetaDW(void) const { return theta_downwash; }
@ -269,6 +277,8 @@ public:
double GetLateralCtrl(void) const { return LateralCtrl; } double GetLateralCtrl(void) const { return LateralCtrl; }
/// Retrieves the longitudinal control input in radians. /// Retrieves the longitudinal control input in radians.
double GetLongitudinalCtrl(void) const { return LongitudinalCtrl; } 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. /// Sets the collective control input in radians.
void SetCollectiveCtrl(double c) { CollectiveCtrl = c; } void SetCollectiveCtrl(double c) { CollectiveCtrl = c; }
@ -276,6 +286,8 @@ public:
void SetLateralCtrl(double c) { LateralCtrl = c; } void SetLateralCtrl(double c) { LateralCtrl = c; }
/// Sets the longitudinal control input in radians. /// Sets the longitudinal control input in radians.
void SetLongitudinalCtrl(double c) { LongitudinalCtrl = c; } 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 // Stubs. Only main rotor RPM is returned
string GetThrusterLabels(int id, string delimeter); string GetThrusterLabels(int id, string delimeter);
@ -303,6 +315,8 @@ private:
void calc_drag_and_side_forces(double theta_0); void calc_drag_and_side_forces(double theta_0);
void calc_torque(double theta_0); void calc_torque(double theta_0);
void calc_freewheel_state(double pwr_in, double pwr_out);
// transformations // transformations
FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr, FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr,
double a_ic = 0.0 , double b_ic = 0.0 ); double a_ic = 0.0 , double b_ic = 0.0 );
@ -380,6 +394,15 @@ private:
double LateralCtrl; double LateralCtrl;
double LongitudinalCtrl; 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 { 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; static const char *IdHdr = ID_THRUSTER;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -66,6 +66,7 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
GearRatio = 1.0; GearRatio = 1.0;
ReverserAngle = 0.0; ReverserAngle = 0.0;
ClutchCtrlNorm = 1.0;
EngineNum = num; EngineNum = num;
PropertyManager = FDMExec->GetPropertyManager(); PropertyManager = FDMExec->GetPropertyManager();
@ -98,6 +99,13 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
&FGThruster::SetReverserAngle); &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); Debug(0);
} }

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -74,7 +74,7 @@ CLASS DOCUMENTATION
1.57 (pi/2) results in no thrust at all. 1.57 (pi/2) results in no thrust at all.
@author Jon Berndt @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;} string GetName(void) {return Name;}
void SetReverserAngle(double angle) {ReverserAngle = angle;} void SetReverserAngle(double angle) {ReverserAngle = angle;}
double GetReverserAngle(void) const {return ReverserAngle;} 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; }; virtual double GetRPM(void) const { return 0.0; };
double GetGearRatio(void) {return GearRatio; } double GetGearRatio(void) {return GearRatio; }
virtual string GetThrusterLabels(int id, string delimeter); virtual string GetThrusterLabels(int id, string delimeter);
@ -119,6 +121,7 @@ protected:
double GearRatio; double GearRatio;
double ThrustCoeff; double ThrustCoeff;
double ReverserAngle; double ReverserAngle;
double ClutchCtrlNorm;
int EngineNum; int EngineNum;
FGPropertyManager* PropertyManager; FGPropertyManager* PropertyManager;
virtual void Debug(int from); virtual void Debug(int from);

View file

@ -51,7 +51,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_TURBINE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -74,6 +74,7 @@ FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number)
BypassRatio = BleedDemand = 0.0; BypassRatio = BleedDemand = 0.0;
IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0; IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0;
N1_spinup = 1.0; N2_spinup = 3.0; N1_spinup = 1.0; N2_spinup = 3.0;
EPR = 1.0;
ResetToIC(); ResetToIC();
@ -96,6 +97,9 @@ FGTurbine::~FGTurbine()
void FGTurbine::ResetToIC(void) void FGTurbine::ResetToIC(void)
{ {
FGEngine::ResetToIC();
N1 = N2 = 0.0; N1 = N2 = 0.0;
N2norm = 0.0; N2norm = 0.0;
correctedTSFC = TSFC; correctedTSFC = TSFC;
@ -534,6 +538,8 @@ void FGTurbine::bindmodel()
PropertyManager->Tie( property_name.c_str(), &Seized); PropertyManager->Tie( property_name.c_str(), &Seized);
property_name = base_property_name + "/stalled"; property_name = base_property_name + "/stalled";
PropertyManager->Tie( property_name.c_str(), &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);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

123
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 HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
05/14/2004 Created 05/14/2004 Created
02/08/2011 T. Kreitler, added rotor support
//JVK (mark) //JVK (mark)
@ -45,6 +46,7 @@ INCLUDES
#include <sstream> #include <sstream>
#include "FGTurboProp.h" #include "FGTurboProp.h"
#include "FGPropeller.h" #include "FGPropeller.h"
#include "FGRotor.h"
#include "models/FGPropulsion.h" #include "models/FGPropulsion.h"
#include "models/FGAuxiliary.h" #include "models/FGAuxiliary.h"
@ -52,7 +54,7 @@ using namespace std;
namespace JSBSim { 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; 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) ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL)
{ {
SetDefaults(); SetDefaults();
thrusterType = Thruster->GetType();
Load(exec, el); Load(exec, el);
bindmodel();
Debug(0); Debug(0);
} }
@ -101,6 +105,7 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
MaxN2 = el->FindElementValueAsNumber("maxn2"); MaxN2 = el->FindElementValueAsNumber("maxn2");
if (el->FindElement("betarangeend")) if (el->FindElement("betarangeend"))
BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0; BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0;
BetaRangeThrottleEnd = Constrain(0.0, BetaRangeThrottleEnd, 0.99999);
if (el->FindElement("reversemaxpower")) if (el->FindElement("reversemaxpower"))
ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0; ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0;
@ -146,10 +151,10 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
delay=1; delay=1;
N1_factor = MaxN1 - IdleN1; N1_factor = MaxN1 - IdleN1;
N2_factor = MaxN2 - IdleN2; 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 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; return true;
} }
@ -162,29 +167,29 @@ void FGTurboProp::Calculate(void)
{ {
RunPreFunctions(); RunPreFunctions();
TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; TAT = Auxiliary->GetTAT_C();
dt = FDMExec->GetDeltaT() * Propulsion->GetRate(); dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
ThrottleCmd = FCS->GetThrottleCmd(EngineNumber); Throttle = FCS->GetThrottlePos(EngineNumber);
Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
if (Thruster->GetType() == FGThruster::ttPropeller) { if (thrusterType == FGThruster::ttPropeller) {
((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
((FGPropeller*)Thruster)->SetReverse(Reversed); ((FGPropeller*)Thruster)->SetReverse(Reversed);
if (Reversed) { if (Reversed) {
((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd); ((FGPropeller*)Thruster)->SetReverseCoef(Throttle);
} else { } else {
((FGPropeller*)Thruster)->SetReverseCoef(0.0); ((FGPropeller*)Thruster)->SetReverseCoef(0.0);
} }
}
if (Reversed) { if (Reversed) {
if (ThrottleCmd < BetaRangeThrottleEnd) { if (Throttle < BetaRangeThrottleEnd) {
ThrottleCmd = 0.0; // idle when in Beta-range Throttle = 0.0; // idle when in Beta-range
} else { } else {
// when reversed: // when reversed:
ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower; Throttle = (Throttle-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
}
} }
} }
@ -223,36 +228,41 @@ void FGTurboProp::Calculate(void)
StartTime=-1; StartTime=-1;
} }
if (Condition < 1) { // limiter intervention wanted?
if (Ielu_max_torque > 0 if (Ielu_max_torque > 0.0) {
&& -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque() double torque = 0.0;
&& ThrottleCmd >= OldThrottle ) {
ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down if (thrusterType == FGThruster::ttPropeller) {
Ielu_intervent = true; torque = ((FGPropeller*)(Thruster))->GetTorque();
} else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) { } else if (thrusterType == FGThruster::ttRotor) {
ThrottleCmd = OldThrottle; torque = ((FGRotor*)(Thruster))->GetTorque();
ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up }
Ielu_intervent = true;
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 { } else {
Ielu_intervent = false; Ielu_intervent = false;
} }
} else { OldThrottle = Throttle;
Ielu_intervent = false;
} }
OldThrottle = ThrottleCmd;
switch (phase) { switch (phase) {
case tpOff: Eng_HP = Off(); break; case tpOff: HP = Off(); break;
case tpRun: Eng_HP = Run(); break; case tpRun: HP = Run(); break;
case tpSpinUp: Eng_HP = SpinUp(); break; case tpSpinUp: HP = SpinUp(); break;
case tpStart: Eng_HP = Start(); break; case tpStart: HP = Start(); break;
default: Eng_HP = 0; default: HP = 0;
} }
//printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power); Thruster->Calculate(HP * hptoftlbssec);
PowerAvailable = (Eng_HP * hptoftlbssec) - Thruster->GetPowerRequired();
Thruster->Calculate(PowerAvailable);
RunPostFunctions(); RunPostFunctions();
} }
@ -280,7 +290,7 @@ double FGTurboProp::Off(void)
ConsumeFuel(); // for possible setting Starved = false when fuel tank ConsumeFuel(); // for possible setting Starved = false when fuel tank
// is refilled (fuel crossfeed etc.) // 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; return 0.0;
} }
@ -293,9 +303,9 @@ double FGTurboProp::Run(void)
//--- //---
double old_N1 = N1; 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(); EngPower_HP *= EnginePowerVC->GetValue();
if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; 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 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; NozzlePosition = 1.0;
EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
EngPower_HP *= EnginePowerVC->GetValue(); EngPower_HP *= EnginePowerVC->GetValue();
if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
@ -366,13 +376,15 @@ double FGTurboProp::SpinUp(void)
double FGTurboProp::Start(void) double FGTurboProp::Start(void)
{ {
double EngPower_HP,eff_coef; double EngPower_HP = 0.0;
double eff_coef;
EngStarting = false; EngStarting = false;
if ((N1 > 15.0) && !Starved) { // minimum 15% N2 needed for start if ((N1 > 15.0) && !Starved) { // minimum 15% N2 needed for start
double old_N1 = N1; double old_N1 = N1;
Cranking = true; // provided for sound effects signal Cranking = true; // provided for sound effects signal
if (N1 < IdleN1) { if (N1 < IdleN1) {
EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
EngPower_HP *= EnginePowerVC->GetValue(); EngPower_HP *= EnginePowerVC->GetValue();
if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4); 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; Starter = false;
Cranking = false; Cranking = false;
FuelFlow_pph = 0; FuelFlow_pph = 0;
EngPower_HP=0.0;
} }
} else { // no start if N2 < 15% or Starved } else { // no start if N2 < 15% or Starved
phase = tpOff; phase = tpOff;
@ -449,13 +460,14 @@ void FGTurboProp::SetDefaults(void)
{ {
// Name = "Not defined"; // Name = "Not defined";
N1 = N2 = 0.0; N1 = N2 = 0.0;
HP = 0.0;
Type = etTurboprop; Type = etTurboprop;
MilThrust = 10000.0; MilThrust = 10000.0;
IdleN1 = 30.0; IdleN1 = 30.0;
IdleN2 = 60.0; IdleN2 = 60.0;
MaxN1 = 100.0; MaxN1 = 100.0;
MaxN2 = 100.0; MaxN2 = 100.0;
ThrottleCmd = 0.0; Throttle = 0.0;
InletPosition = 1.0; InletPosition = 1.0;
NozzlePosition = 1.0; NozzlePosition = 1.0;
Reversed = false; Reversed = false;
@ -472,6 +484,11 @@ void FGTurboProp::SetDefaults(void)
Ielu_intervent=false; Ielu_intervent=false;
Idle_Max_Delay = 1.0; 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; std::ostringstream buf;
buf << PowerAvailable << delimiter buf << N1 << delimiter
<< N1 << delimiter
<< N2 << delimiter << N2 << delimiter
<< HP << delimiter
<< Thruster->GetThrusterValues(EngineNumber,delimiter); << Thruster->GetThrusterValues(EngineNumber,delimiter);
return buf.str(); return buf.str();
@ -524,10 +541,18 @@ void FGTurboProp::bindmodel()
base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
property_name = base_property_name + "/n1"; property_name = base_property_name + "/n1";
PropertyManager->Tie( property_name.c_str(), &N1); PropertyManager->Tie( property_name.c_str(), &N1);
property_name = base_property_name + "/n2"; // property_name = base_property_name + "/n2";
PropertyManager->Tie( property_name.c_str(), &N2); // PropertyManager->Tie( property_name.c_str(), &N2);
property_name = base_property_name + "/reverser"; property_name = base_property_name + "/reverser";
PropertyManager->Tie( property_name.c_str(), &Reversed); 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 HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
05/14/2004 Created 05/14/2004 Created
02/08/2011 T. Kreitler, added rotor support
//JVK (mark) //JVK (mark)
@ -46,7 +47,7 @@ INCLUDES
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#include "math/FGTable.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 FORWARD DECLARATIONS
@ -107,11 +108,10 @@ public:
void Calculate(void); void Calculate(void);
double CalcFuelNeed(void); double CalcFuelNeed(void);
inline double GetPowerAvailable(void) const {return (Eng_HP * hptoftlbssec);} double GetPowerAvailable(void) const { return (HP * hptoftlbssec); }
inline double GetPowerAvailable_HP(void) const {return (Eng_HP);} double GetRPM(void) const { return (RPM); }
inline double GetPropRPM(void) const {return (Prop_RPM);} double GetIeluThrottle(void) const { return (Throttle); }
inline double GetThrottleCmd(void) const {return (ThrottleCmd);} bool GetIeluIntervent(void) const { return Ielu_intervent; }
inline bool GetIeluIntervent(void) const { return Ielu_intervent; }
double Seek(double* var, double target, double accel, double decel); double Seek(double* var, double target, double accel, double decel);
double ExpSeek(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 dt; ///< Simulator time slice
double N1_factor; ///< factor to tie N1 and throttle double N1_factor; ///< factor to tie N1 and throttle
double N2_factor; ///< factor to tie N2 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 TAT; ///< total air temperature (deg C)
double PowerAvailable;
bool Stalled; ///< true if engine is compressor-stalled bool Stalled; ///< true if engine is compressor-stalled
bool Seized; ///< true if inner spool is seized bool Seized; ///< true if inner spool is seized
bool Overtemp; ///< true if EGT exceeds limits bool Overtemp; ///< true if EGT exceeds limits
@ -189,26 +188,27 @@ private:
double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range
double ReverseMaxPower; // coef (0-1) multiplies max throttle on reverse 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 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 MaxStartingTime; // maximal time for start [s] (-1 means not used)
double Prop_RPM; // propeller RPM double RPM; // shaft RPM
double Velocity; double Velocity;
double rho; double rho;
double PSFC; // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency 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_ITT_degC;
double Eng_Temperature; // temperature inside engine double Eng_Temperature; // temperature inside engine
bool EngStarting; // logicaly output - TRUE if engine is starting bool EngStarting; // logicaly output - TRUE if engine is starting
bool GeneratorPower; bool GeneratorPower;
int Condition; int Condition;
int thrusterType; // the attached thruster
double Off(void); double Off(void);
double Run(void); double Run(void);