Sync. withn JSBSim CVS
This commit is contained in:
parent
b1eebb21a6
commit
30e535bc7b
29 changed files with 383 additions and 135 deletions
|
@ -94,7 +94,8 @@ void checkTied ( FGPropertyManager *node )
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
if (node->getChild(i)->nChildren() ) {
|
if (node->getChild(i)->nChildren() ) {
|
||||||
checkTied( (FGPropertyManager*)node->getChild(i) );
|
checkTied( (FGPropertyManager*)node->getChild(i) );
|
||||||
} else if ( node->getChild(i)->isTied() ) {
|
}
|
||||||
|
if ( node->getChild(i)->isTied() ) {
|
||||||
name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName();
|
name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName();
|
||||||
node->Untie(name);
|
node->Untie(name);
|
||||||
}
|
}
|
||||||
|
@ -108,7 +109,6 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
|
||||||
{
|
{
|
||||||
|
|
||||||
Frame = 0;
|
Frame = 0;
|
||||||
FirstModel = 0;
|
|
||||||
Error = 0;
|
Error = 0;
|
||||||
GroundCallback = 0;
|
GroundCallback = 0;
|
||||||
State = 0;
|
State = 0;
|
||||||
|
@ -221,30 +221,11 @@ bool FGFDMExec::Allocate(void)
|
||||||
// class needs valid pointers to the above
|
// class needs valid pointers to the above
|
||||||
// model classes
|
// model classes
|
||||||
|
|
||||||
// Initialize models so they can communicate with each other
|
|
||||||
|
|
||||||
Atmosphere->InitModel();
|
|
||||||
FCS->InitModel();
|
|
||||||
Propulsion->InitModel();
|
|
||||||
MassBalance->InitModel();
|
|
||||||
Aerodynamics->InitModel();
|
|
||||||
Inertial->InitModel();
|
|
||||||
GroundReactions->InitModel();
|
|
||||||
ExternalReactions->InitModel();
|
|
||||||
BuoyantForces->InitModel();
|
|
||||||
Aircraft->InitModel();
|
|
||||||
Propagate->InitModel();
|
|
||||||
Auxiliary->InitModel();
|
|
||||||
Input->InitModel();
|
|
||||||
|
|
||||||
IC = new FGInitialCondition(this);
|
|
||||||
|
|
||||||
// Schedule a model. The second arg (the integer) is the pass number. For
|
// Schedule a model. The second arg (the integer) is the pass number. For
|
||||||
// instance, the atmosphere model could get executed every fifth pass it is called
|
// instance, the atmosphere model could get executed every fifth pass it is called.
|
||||||
// by the executive. IC and Trim objects are NOT scheduled.
|
|
||||||
|
|
||||||
Schedule(Input, 1);
|
Schedule(Input, 1);
|
||||||
Schedule(Atmosphere, 1);
|
Schedule(Atmosphere, 30);
|
||||||
Schedule(FCS, 1);
|
Schedule(FCS, 1);
|
||||||
Schedule(Propulsion, 1);
|
Schedule(Propulsion, 1);
|
||||||
Schedule(MassBalance, 1);
|
Schedule(MassBalance, 1);
|
||||||
|
@ -257,6 +238,13 @@ bool FGFDMExec::Allocate(void)
|
||||||
Schedule(Propagate, 1);
|
Schedule(Propagate, 1);
|
||||||
Schedule(Auxiliary, 1);
|
Schedule(Auxiliary, 1);
|
||||||
|
|
||||||
|
// Initialize models so they can communicate with each other
|
||||||
|
|
||||||
|
vector <FGModel*>::iterator it;
|
||||||
|
for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel();
|
||||||
|
|
||||||
|
IC = new FGInitialCondition(this);
|
||||||
|
|
||||||
modelLoaded = false;
|
modelLoaded = false;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -290,7 +278,6 @@ bool FGFDMExec::DeAllocate(void)
|
||||||
|
|
||||||
delete GroundCallback;
|
delete GroundCallback;
|
||||||
|
|
||||||
FirstModel = 0L;
|
|
||||||
Error = 0;
|
Error = 0;
|
||||||
|
|
||||||
State = 0;
|
State = 0;
|
||||||
|
@ -309,35 +296,18 @@ bool FGFDMExec::DeAllocate(void)
|
||||||
Auxiliary = 0;
|
Auxiliary = 0;
|
||||||
Script = 0;
|
Script = 0;
|
||||||
|
|
||||||
|
Models.clear();
|
||||||
|
|
||||||
modelLoaded = false;
|
modelLoaded = false;
|
||||||
return modelLoaded;
|
return modelLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
int FGFDMExec::Schedule(FGModel* model, int rate)
|
void FGFDMExec::Schedule(FGModel* model, int rate)
|
||||||
{
|
{
|
||||||
FGModel* model_iterator;
|
model->SetRate(rate);
|
||||||
|
Models.push_back(model);
|
||||||
model_iterator = FirstModel;
|
|
||||||
|
|
||||||
if (model_iterator == 0L) { // this is the first model
|
|
||||||
|
|
||||||
FirstModel = model;
|
|
||||||
FirstModel->NextModel = 0L;
|
|
||||||
FirstModel->SetRate(rate);
|
|
||||||
|
|
||||||
} else { // subsequent model
|
|
||||||
|
|
||||||
while (model_iterator->NextModel != 0L) {
|
|
||||||
model_iterator = model_iterator->NextModel;
|
|
||||||
}
|
|
||||||
model_iterator->NextModel = model;
|
|
||||||
model_iterator->NextModel->SetRate(rate);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
@ -345,10 +315,6 @@ int FGFDMExec::Schedule(FGModel* model, int rate)
|
||||||
bool FGFDMExec::Run(void)
|
bool FGFDMExec::Run(void)
|
||||||
{
|
{
|
||||||
bool success=true;
|
bool success=true;
|
||||||
FGModel* model_iterator;
|
|
||||||
|
|
||||||
model_iterator = FirstModel;
|
|
||||||
if (model_iterator == 0L) return false;
|
|
||||||
|
|
||||||
Debug(2);
|
Debug(2);
|
||||||
|
|
||||||
|
@ -357,14 +323,11 @@ bool FGFDMExec::Run(void)
|
||||||
ChildFDMList[i]->Run();
|
ChildFDMList[i]->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if success
|
// returns true if success, false if complete
|
||||||
// false if complete
|
|
||||||
if (Script != 0 && !State->IntegrationSuspended()) success = Script->RunScript();
|
if (Script != 0 && !State->IntegrationSuspended()) success = Script->RunScript();
|
||||||
|
|
||||||
while (model_iterator != 0L) {
|
vector <FGModel*>::iterator it;
|
||||||
model_iterator->Run();
|
for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run();
|
||||||
model_iterator = model_iterator->NextModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame++;
|
Frame++;
|
||||||
if (!Holding()) State->IncrTime();
|
if (!Holding()) State->IncrTime();
|
||||||
|
@ -406,15 +369,10 @@ void FGFDMExec::ResetToInitialConditions(int mode)
|
||||||
|
|
||||||
void FGFDMExec::ResetToInitialConditions(void)
|
void FGFDMExec::ResetToInitialConditions(void)
|
||||||
{
|
{
|
||||||
FGModel* model_iterator;
|
if (Constructing) return;
|
||||||
|
|
||||||
model_iterator = FirstModel;
|
vector <FGModel*>::iterator it;
|
||||||
if (model_iterator == 0L || Constructing) return;
|
for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel();
|
||||||
|
|
||||||
while (model_iterator != 0L) {
|
|
||||||
model_iterator->InitModel();
|
|
||||||
model_iterator = model_iterator->NextModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
RunIC();
|
RunIC();
|
||||||
if (Script) Script->ResetEvents();
|
if (Script) Script->ResetEvents();
|
||||||
|
|
|
@ -222,7 +222,7 @@ public:
|
||||||
@param model A pointer to the model being scheduled.
|
@param model A pointer to the model being scheduled.
|
||||||
@param rate The rate at which to execute the model as described above.
|
@param rate The rate at which to execute the model as described above.
|
||||||
@return Currently returns 0 always. */
|
@return Currently returns 0 always. */
|
||||||
int Schedule(FGModel* model, int rate);
|
void Schedule(FGModel* model, int rate);
|
||||||
|
|
||||||
/** This function executes each scheduled model in succession.
|
/** This function executes each scheduled model in succession.
|
||||||
@return true if successful, false if sim should be ended */
|
@return true if successful, false if sim should be ended */
|
||||||
|
@ -488,7 +488,6 @@ private:
|
||||||
|
|
||||||
static FGPropertyManager *master;
|
static FGPropertyManager *master;
|
||||||
|
|
||||||
FGModel* FirstModel;
|
|
||||||
FGGroundCallback* GroundCallback;
|
FGGroundCallback* GroundCallback;
|
||||||
FGState* State;
|
FGState* State;
|
||||||
FGAtmosphere* Atmosphere;
|
FGAtmosphere* Atmosphere;
|
||||||
|
@ -514,6 +513,7 @@ private:
|
||||||
vector <string> PropertyCatalog;
|
vector <string> PropertyCatalog;
|
||||||
vector <FGOutput*> Outputs;
|
vector <FGOutput*> Outputs;
|
||||||
vector <childData*> ChildFDMList;
|
vector <childData*> ChildFDMList;
|
||||||
|
vector <FGModel*> Models;
|
||||||
|
|
||||||
bool ReadFileHeader(Element*);
|
bool ReadFileHeader(Element*);
|
||||||
bool ReadChild(Element*);
|
bool ReadChild(Element*);
|
||||||
|
|
|
@ -31,6 +31,7 @@ INCLUDES
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
#include "FGFunction.h"
|
#include "FGFunction.h"
|
||||||
#include "FGTable.h"
|
#include "FGTable.h"
|
||||||
#include "FGPropertyValue.h"
|
#include "FGPropertyValue.h"
|
||||||
|
@ -56,6 +57,7 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
|
||||||
string operation, property_name;
|
string operation, property_name;
|
||||||
cached = false;
|
cached = false;
|
||||||
cachedValue = -HUGE_VAL;
|
cachedValue = -HUGE_VAL;
|
||||||
|
invlog2val = 1.0/log10(2.0);
|
||||||
|
|
||||||
property_string = "property";
|
property_string = "property";
|
||||||
value_string = "value";
|
value_string = "value";
|
||||||
|
@ -72,6 +74,9 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
|
||||||
quotient_string = "quotient";
|
quotient_string = "quotient";
|
||||||
pow_string = "pow";
|
pow_string = "pow";
|
||||||
exp_string = "exp";
|
exp_string = "exp";
|
||||||
|
log2_string = "log2";
|
||||||
|
ln_string = "ln";
|
||||||
|
log10_string = "log10";
|
||||||
abs_string = "abs";
|
abs_string = "abs";
|
||||||
sin_string = "sin";
|
sin_string = "sin";
|
||||||
cos_string = "cos";
|
cos_string = "cos";
|
||||||
|
@ -103,6 +108,12 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
|
||||||
Type = eQuotient;
|
Type = eQuotient;
|
||||||
} else if (operation == pow_string) {
|
} else if (operation == pow_string) {
|
||||||
Type = ePow;
|
Type = ePow;
|
||||||
|
} else if (operation == log2_string) {
|
||||||
|
Type = eLog2;
|
||||||
|
} else if (operation == ln_string) {
|
||||||
|
Type = eLn;
|
||||||
|
} else if (operation == log10_string) {
|
||||||
|
Type = eLog10;
|
||||||
} else if (operation == abs_string) {
|
} else if (operation == abs_string) {
|
||||||
Type = eAbs;
|
Type = eAbs;
|
||||||
} else if (operation == sin_string) {
|
} else if (operation == sin_string) {
|
||||||
|
@ -174,6 +185,9 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
|
||||||
operation == quotient_string ||
|
operation == quotient_string ||
|
||||||
operation == pow_string ||
|
operation == pow_string ||
|
||||||
operation == exp_string ||
|
operation == exp_string ||
|
||||||
|
operation == log2_string ||
|
||||||
|
operation == ln_string ||
|
||||||
|
operation == log10_string ||
|
||||||
operation == abs_string ||
|
operation == abs_string ||
|
||||||
operation == sin_string ||
|
operation == sin_string ||
|
||||||
operation == cos_string ||
|
operation == cos_string ||
|
||||||
|
@ -259,6 +273,18 @@ double FGFunction::GetValue(void) const
|
||||||
case eExp:
|
case eExp:
|
||||||
temp = exp(temp);
|
temp = exp(temp);
|
||||||
break;
|
break;
|
||||||
|
case eLog2:
|
||||||
|
if (temp > 0.00) temp = log10(temp)*invlog2val;
|
||||||
|
else temp = -HUGE_VAL;
|
||||||
|
break;
|
||||||
|
case eLn:
|
||||||
|
if (temp > 0.00) temp = log(temp);
|
||||||
|
else temp = -HUGE_VAL;
|
||||||
|
break;
|
||||||
|
case eLog10:
|
||||||
|
if (temp > 0.00) temp = log10(temp);
|
||||||
|
else temp = -HUGE_VAL;
|
||||||
|
break;
|
||||||
case eAbs:
|
case eAbs:
|
||||||
temp = fabs(temp);
|
temp = fabs(temp);
|
||||||
break;
|
break;
|
||||||
|
@ -335,7 +361,12 @@ string FGFunction::GetValueAsString(void) const
|
||||||
void FGFunction::bind(void)
|
void FGFunction::bind(void)
|
||||||
{
|
{
|
||||||
if ( !Name.empty() ) {
|
if ( !Name.empty() ) {
|
||||||
string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
|
string tmp;
|
||||||
|
if (Prefix.empty())
|
||||||
|
tmp = PropertyManager->mkPropertyName(Name, false); // Allow upper case
|
||||||
|
else
|
||||||
|
tmp = PropertyManager->mkPropertyName(Prefix + "/" + Name, false); // Allow upper case
|
||||||
|
|
||||||
PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
|
PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,9 @@ A function definition consists of an operation, a value, a table, or a property
|
||||||
- quotient (takes 2 args)
|
- quotient (takes 2 args)
|
||||||
- pow (takes 2 args)
|
- pow (takes 2 args)
|
||||||
- exp (takes 2 args)
|
- exp (takes 2 args)
|
||||||
|
- log2 (takes 1 arg)
|
||||||
|
- ln (takes 1 arg)
|
||||||
|
- log10 (takes 1 arg)
|
||||||
- abs (takes n args)
|
- abs (takes n args)
|
||||||
- sin (takes 1 arg)
|
- sin (takes 1 arg)
|
||||||
- cos (takes 1 arg)
|
- cos (takes 1 arg)
|
||||||
|
@ -193,6 +196,7 @@ private:
|
||||||
std::vector <FGParameter*> Parameters;
|
std::vector <FGParameter*> Parameters;
|
||||||
FGPropertyManager* const PropertyManager;
|
FGPropertyManager* const PropertyManager;
|
||||||
bool cached;
|
bool cached;
|
||||||
|
double invlog2val;
|
||||||
std::string Prefix;
|
std::string Prefix;
|
||||||
std::string description_string;
|
std::string description_string;
|
||||||
std::string property_string;
|
std::string property_string;
|
||||||
|
@ -208,6 +212,9 @@ private:
|
||||||
std::string quotient_string;
|
std::string quotient_string;
|
||||||
std::string pow_string;
|
std::string pow_string;
|
||||||
std::string exp_string;
|
std::string exp_string;
|
||||||
|
std::string log2_string;
|
||||||
|
std::string ln_string;
|
||||||
|
std::string log10_string;
|
||||||
std::string abs_string;
|
std::string abs_string;
|
||||||
std::string sin_string;
|
std::string sin_string;
|
||||||
std::string cos_string;
|
std::string cos_string;
|
||||||
|
@ -226,7 +233,7 @@ private:
|
||||||
double cachedValue;
|
double cachedValue;
|
||||||
enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow,
|
enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow,
|
||||||
eExp, eAbs, eSin, eCos, eTan, eASin, eACos, eATan, eATan2,
|
eExp, eAbs, eSin, eCos, eTan, eASin, eACos, eATan, eATan2,
|
||||||
eMin, eMax, eAvg, eFrac, eInteger, eMod, eRandom} Type;
|
eMin, eMax, eAvg, eFrac, eInteger, eMod, eRandom, eLog2, eLn, eLog10} Type;
|
||||||
std::string Name;
|
std::string Name;
|
||||||
void bind(void);
|
void bind(void);
|
||||||
void Debug(int from);
|
void Debug(int from);
|
||||||
|
|
|
@ -39,6 +39,8 @@ INCLUDES
|
||||||
|
|
||||||
#include "FGMatrix33.h"
|
#include "FGMatrix33.h"
|
||||||
#include "FGColumnVector3.h"
|
#include "FGColumnVector3.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -65,6 +67,23 @@ FGMatrix33::FGMatrix33(void)
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
string FGMatrix33::Dump(const string& delimiter) const
|
||||||
|
{
|
||||||
|
ostringstream buffer;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(1,1) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(1,2) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(1,3) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(2,1) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(2,2) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(2,3) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(3,1) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(3,2) << delimiter;
|
||||||
|
buffer << std::setw(18) << std::setprecision(16) << Entry(3,3);
|
||||||
|
return buffer.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
ostream& operator<<(ostream& os, const FGMatrix33& M)
|
ostream& operator<<(ostream& os, const FGMatrix33& M)
|
||||||
{
|
{
|
||||||
for (unsigned int i=1; i<=M.Rows(); i++) {
|
for (unsigned int i=1; i<=M.Rows(); i++) {
|
||||||
|
|
|
@ -158,6 +158,11 @@ public:
|
||||||
*/
|
*/
|
||||||
~FGMatrix33(void) { Debug(1); }
|
~FGMatrix33(void) { Debug(1); }
|
||||||
|
|
||||||
|
/** Prints the contents of the matrix.
|
||||||
|
@param delimeter the item separator (tab or comma)
|
||||||
|
@return a string with the delimeter-separated contents of the matrix */
|
||||||
|
std::string Dump(const std::string& delimeter) const;
|
||||||
|
|
||||||
/** Read access the entries of the matrix.
|
/** Read access the entries of the matrix.
|
||||||
@param row Row index.
|
@param row Row index.
|
||||||
@param col Column index.
|
@param col Column index.
|
||||||
|
|
|
@ -108,9 +108,6 @@ FGAerodynamics::~FGAerodynamics()
|
||||||
|
|
||||||
delete[] Coeff;
|
delete[] Coeff;
|
||||||
|
|
||||||
for (i=0; i<variables.size(); i++)
|
|
||||||
delete variables[i];
|
|
||||||
|
|
||||||
delete AeroRPShift;
|
delete AeroRPShift;
|
||||||
|
|
||||||
Debug(1);
|
Debug(1);
|
||||||
|
@ -137,12 +134,14 @@ bool FGAerodynamics::InitModel(void)
|
||||||
|
|
||||||
bool FGAerodynamics::Run(void)
|
bool FGAerodynamics::Run(void)
|
||||||
{
|
{
|
||||||
unsigned int axis_ctr, ctr, i;
|
unsigned int axis_ctr, ctr;
|
||||||
double alpha, twovel;
|
double alpha, twovel;
|
||||||
|
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false; // if paused don't execute
|
if (FDMExec->Holding()) return false; // if paused don't execute
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
// calculate some oft-used quantities for speed
|
// calculate some oft-used quantities for speed
|
||||||
|
|
||||||
twovel = 2*Auxiliary->GetVt();
|
twovel = 2*Auxiliary->GetVt();
|
||||||
|
@ -173,13 +172,6 @@ bool FGAerodynamics::Run(void)
|
||||||
vFw.InitMatrix();
|
vFw.InitMatrix();
|
||||||
vFnative.InitMatrix();
|
vFnative.InitMatrix();
|
||||||
|
|
||||||
// Tell the variable functions to cache their values, so while the aerodynamic
|
|
||||||
// functions are being calculated for each axis, these functions do not get
|
|
||||||
// calculated each time, but instead use the values that have already
|
|
||||||
// been calculated for this frame.
|
|
||||||
|
|
||||||
for (i=0; i<variables.size(); i++) variables[i]->cacheValue(true);
|
|
||||||
|
|
||||||
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 < Coeff[axis_ctr].size(); ctr++) {
|
||||||
vFnative(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue();
|
vFnative(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue();
|
||||||
|
@ -233,6 +225,8 @@ bool FGAerodynamics::Run(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +318,7 @@ bool FGAerodynamics::Load(Element *element)
|
||||||
document = element;
|
document = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGModel::Load(element); // Perform base class Load
|
FGModel::Load(element); // Perform base class Pre-Load
|
||||||
|
|
||||||
DetermineAxisSystem(); // Detemine if Lift/Side/Drag, etc. is used.
|
DetermineAxisSystem(); // Detemine if Lift/Side/Drag, etc. is used.
|
||||||
|
|
||||||
|
@ -349,12 +343,6 @@ bool FGAerodynamics::Load(Element *element)
|
||||||
AeroRPShift = new FGFunction(PropertyManager, function_element);
|
AeroRPShift = new FGFunction(PropertyManager, function_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_element = document->FindElement("function");
|
|
||||||
while (function_element) {
|
|
||||||
variables.push_back( new FGFunction(PropertyManager, function_element) );
|
|
||||||
function_element = document->FindNextElement("function");
|
|
||||||
}
|
|
||||||
|
|
||||||
axis_element = document->FindElement("axis");
|
axis_element = document->FindElement("axis");
|
||||||
while (axis_element) {
|
while (axis_element) {
|
||||||
CoeffArray ca;
|
CoeffArray ca;
|
||||||
|
@ -368,6 +356,8 @@ bool FGAerodynamics::Load(Element *element)
|
||||||
axis_element = document->FindNextElement("axis");
|
axis_element = document->FindNextElement("axis");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FGModel::PostLoad(element); // Perform base class Post-Load
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,15 +417,6 @@ string FGAerodynamics::GetCoefficientStrings(const string& delimeter) const
|
||||||
bool firstime = true;
|
bool firstime = true;
|
||||||
unsigned int axis, sd;
|
unsigned int axis, sd;
|
||||||
|
|
||||||
for (sd = 0; sd < variables.size(); sd++) {
|
|
||||||
if (firstime) {
|
|
||||||
firstime = false;
|
|
||||||
} else {
|
|
||||||
CoeffStrings += delimeter;
|
|
||||||
}
|
|
||||||
CoeffStrings += variables[sd]->GetName();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (axis = 0; axis < 6; axis++) {
|
for (axis = 0; axis < 6; axis++) {
|
||||||
for (sd = 0; sd < Coeff[axis].size(); sd++) {
|
for (sd = 0; sd < Coeff[axis].size(); sd++) {
|
||||||
if (firstime) {
|
if (firstime) {
|
||||||
|
@ -455,12 +436,6 @@ string FGAerodynamics::GetCoefficientValues(const string& delimeter) const
|
||||||
{
|
{
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
|
|
||||||
buf.precision(6);
|
|
||||||
for (unsigned int sd = 0; sd < variables.size(); sd++) {
|
|
||||||
if (buf.tellp() > 0) buf << delimeter;
|
|
||||||
buf << setw(9) << variables[sd]->GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 < Coeff[axis].size(); sd++) {
|
||||||
if (buf.tellp() > 0) buf << delimeter;
|
if (buf.tellp() > 0) buf << delimeter;
|
||||||
|
|
|
@ -114,6 +114,8 @@ bool FGAircraft::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
vForces.InitMatrix();
|
vForces.InitMatrix();
|
||||||
if (!HoldDown) {
|
if (!HoldDown) {
|
||||||
vForces += Aerodynamics->GetForces();
|
vForces += Aerodynamics->GetForces();
|
||||||
|
@ -139,6 +141,8 @@ bool FGAircraft::Run(void)
|
||||||
vNwcg = Aerodynamics->GetTb2w() * vNcg;
|
vNwcg = Aerodynamics->GetTb2w() * vNcg;
|
||||||
vNwcg(3) = -1*vNwcg(3) + 1;
|
vNwcg(3) = -1*vNwcg(3) + 1;
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +203,8 @@ bool FGAircraft::Load(Element* el)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FGModel::PostLoad(el);
|
||||||
|
|
||||||
Debug(2);
|
Debug(2);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -139,6 +139,8 @@ bool FGAtmosphere::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
T_dev = 0.0;
|
T_dev = 0.0;
|
||||||
h = Propagate->GetAltitudeASL();
|
h = Propagate->GetAltitudeASL();
|
||||||
|
|
||||||
|
@ -149,6 +151,8 @@ bool FGAtmosphere::Run(void)
|
||||||
CalculateDerived();
|
CalculateDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
Debug(2);
|
Debug(2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,8 @@ bool FGAuxiliary::Run()
|
||||||
if (FGModel::Run()) return true; // return true if error returned from base class
|
if (FGModel::Run()) return true; // return true if error returned from base class
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
const FGColumnVector3& vPQR = Propagate->GetPQR();
|
const FGColumnVector3& vPQR = Propagate->GetPQR();
|
||||||
const FGColumnVector3& vUVW = Propagate->GetUVW();
|
const FGColumnVector3& vUVW = Propagate->GetUVW();
|
||||||
const FGColumnVector3& vUVWdot = Propagate->GetUVWdot();
|
const FGColumnVector3& vUVWdot = Propagate->GetUVWdot();
|
||||||
|
@ -290,6 +292,8 @@ bool FGAuxiliary::Run()
|
||||||
|
|
||||||
CalculateRelativePosition();
|
CalculateRelativePosition();
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,8 @@ bool FGBuoyantForces::Run(void)
|
||||||
if (FDMExec->Holding()) return false; // if paused don't execute
|
if (FDMExec->Holding()) return false; // if paused don't execute
|
||||||
if (NoneDefined) return true;
|
if (NoneDefined) return true;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
vTotalForces.InitMatrix();
|
vTotalForces.InitMatrix();
|
||||||
vTotalMoments.InitMatrix();
|
vTotalMoments.InitMatrix();
|
||||||
|
|
||||||
|
@ -104,6 +106,8 @@ bool FGBuoyantForces::Run(void)
|
||||||
vTotalMoments += Cells[i]->GetMoments();
|
vTotalMoments += Cells[i]->GetMoments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +139,8 @@ bool FGBuoyantForces::Load(Element *element)
|
||||||
gas_cell_element = document->FindNextElement("gas_cell");
|
gas_cell_element = document->FindNextElement("gas_cell");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FGModel::PostLoad(element);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,8 @@ bool FGExternalReactions::Load(Element* el)
|
||||||
force_element = el->FindNextElement("force");
|
force_element = el->FindNextElement("force");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FGModel::PostLoad(el);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +117,8 @@ bool FGExternalReactions::Run()
|
||||||
if (FDMExec->Holding()) return false; // if paused don't execute
|
if (FDMExec->Holding()) return false; // if paused don't execute
|
||||||
if (NoneDefined) return true;
|
if (NoneDefined) return true;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
vTotalForces.InitMatrix();
|
vTotalForces.InitMatrix();
|
||||||
vTotalMoments.InitMatrix();
|
vTotalMoments.InitMatrix();
|
||||||
|
|
||||||
|
@ -123,6 +127,8 @@ bool FGExternalReactions::Run()
|
||||||
vTotalMoments += Forces[i]->GetMoments();
|
vTotalMoments += Forces[i]->GetMoments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,6 +198,8 @@ bool FGFCS::Run(void)
|
||||||
if (FGModel::Run()) return true; // fast exit if nothing to do
|
if (FGModel::Run()) return true; // fast exit if nothing to do
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
|
for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
|
||||||
for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
|
for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
|
||||||
for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
|
for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
|
||||||
|
@ -218,6 +220,8 @@ bool FGFCS::Run(void)
|
||||||
// Execute Flight Control System
|
// Execute Flight Control System
|
||||||
for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run();
|
for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run();
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,8 @@ bool FGGroundReactions::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
vForces.InitMatrix();
|
vForces.InitMatrix();
|
||||||
vMoments.InitMatrix();
|
vMoments.InitMatrix();
|
||||||
|
|
||||||
|
@ -102,6 +104,8 @@ bool FGGroundReactions::Run(void)
|
||||||
vMoments += lGear[i]->GetMoments();
|
vMoments += lGear[i]->GetMoments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +142,8 @@ bool FGGroundReactions::Load(Element* el)
|
||||||
|
|
||||||
for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();
|
for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();
|
||||||
|
|
||||||
|
FGModel::PostLoad(el);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +191,7 @@ string FGGroundReactions::GetGroundReactionValues(string delimeter)
|
||||||
for (unsigned int i=0;i<lGear.size();i++) {
|
for (unsigned int i=0;i<lGear.size();i++) {
|
||||||
if (lGear[i]->IsBogey()) {
|
if (lGear[i]->IsBogey()) {
|
||||||
FGLGear *gear = lGear[i];
|
FGLGear *gear = lGear[i];
|
||||||
buf << (gear->GetWOW() ? "1, " : "0, ")
|
buf << (gear->GetWOW() ? "1" : "0") << delimeter
|
||||||
<< setprecision(5) << gear->GetCompLen() << delimeter
|
<< setprecision(5) << gear->GetCompLen() << delimeter
|
||||||
<< setprecision(6) << gear->GetCompVel() << delimeter
|
<< setprecision(6) << gear->GetCompVel() << delimeter
|
||||||
<< setprecision(10) << gear->GetCompForce() << delimeter
|
<< setprecision(10) << gear->GetCompForce() << delimeter
|
||||||
|
|
|
@ -114,11 +114,15 @@ bool FGInertial::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
// Gravitation accel
|
// Gravitation accel
|
||||||
double r = Propagate->GetRadius();
|
double r = Propagate->GetRadius();
|
||||||
gAccel = GetGAccel(r);
|
gAccel = GetGAccel(r);
|
||||||
earthPosAngle += State->Getdt()*RotationRate;
|
earthPosAngle += State->Getdt()*RotationRate;
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,8 @@ bool FGInput::Run(void)
|
||||||
// return false if no error
|
// return false if no error
|
||||||
// This model DOES execute if "Exec->Holding"
|
// This model DOES execute if "Exec->Holding"
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
data = socket->Receive(); // get socket transmission if present
|
data = socket->Receive(); // get socket transmission if present
|
||||||
|
|
||||||
if (data.size() > 0) {
|
if (data.size() > 0) {
|
||||||
|
@ -213,6 +215,8 @@ bool FGInput::Run(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,8 @@ bool FGMassBalance::Load(Element* el)
|
||||||
|
|
||||||
Mass = lbtoslug*Weight;
|
Mass = lbtoslug*Weight;
|
||||||
|
|
||||||
|
FGModel::PostLoad(el);
|
||||||
|
|
||||||
Debug(2);
|
Debug(2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -166,6 +168,8 @@ bool FGMassBalance::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
double ChildFDMWeight = 0.0;
|
double ChildFDMWeight = 0.0;
|
||||||
for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
|
for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
|
||||||
if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
|
if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
|
||||||
|
@ -226,6 +230,8 @@ bool FGMassBalance::Run(void)
|
||||||
k2, k4, k5,
|
k2, k4, k5,
|
||||||
k3, k5, k6 );
|
k3, k5, k6 );
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
Debug(0);
|
Debug(0);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -105,6 +105,9 @@ FGModel::~FGModel()
|
||||||
for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
|
for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
|
||||||
interface_properties.clear();
|
interface_properties.clear();
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<PreFunctions.size(); i++) delete PreFunctions[i];
|
||||||
|
for (unsigned int i=0; i<PostFunctions.size(); i++) delete PostFunctions[i];
|
||||||
|
|
||||||
if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl;
|
if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,15 +149,16 @@ bool FGModel::InitModel(void)
|
||||||
bool FGModel::Load(Element* el)
|
bool FGModel::Load(Element* el)
|
||||||
{
|
{
|
||||||
// Interface properties are all stored in the interface properties array.
|
// Interface properties are all stored in the interface properties array.
|
||||||
|
|
||||||
string interface_property_string = "";
|
string interface_property_string = "";
|
||||||
|
|
||||||
Element *property_element = el->FindElement("property");
|
Element *property_element = el->FindElement("property");
|
||||||
if (property_element && debug_lvl > 0) cout << endl << " Declared properties" << endl << endl;
|
if (property_element && debug_lvl > 0) cout << endl << " Declared properties"
|
||||||
|
<< endl << endl;
|
||||||
while (property_element) {
|
while (property_element) {
|
||||||
interface_property_string = property_element->GetDataLine();
|
interface_property_string = property_element->GetDataLine();
|
||||||
if (PropertyManager->HasNode(interface_property_string)) {
|
if (PropertyManager->HasNode(interface_property_string)) {
|
||||||
cerr << " Property " << interface_property_string << " is already defined." << endl;
|
cerr << " Property " << interface_property_string
|
||||||
|
<< " is already defined." << endl;
|
||||||
} else {
|
} else {
|
||||||
double value=0.0;
|
double value=0.0;
|
||||||
if ( ! property_element->GetAttributeValue("value").empty())
|
if ( ! property_element->GetAttributeValue("value").empty())
|
||||||
|
@ -162,23 +166,82 @@ bool FGModel::Load(Element* el)
|
||||||
interface_properties.push_back(new double(value));
|
interface_properties.push_back(new double(value));
|
||||||
PropertyManager->Tie(interface_property_string, interface_properties.back());
|
PropertyManager->Tie(interface_property_string, interface_properties.back());
|
||||||
if (debug_lvl > 0)
|
if (debug_lvl > 0)
|
||||||
cout << " " << interface_property_string << " (initial value: " << value << ")" << endl;
|
cout << " " << interface_property_string << " (initial value: "
|
||||||
|
<< value << ")" << endl << endl;
|
||||||
}
|
}
|
||||||
property_element = el->FindNextElement("property");
|
property_element = el->FindNextElement("property");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// End of interface property loading logic
|
||||||
|
|
||||||
|
// Load model pre-functions, if any
|
||||||
|
|
||||||
|
Element *function = el->FindElement("function");
|
||||||
|
while (function) {
|
||||||
|
if (function->GetAttributeValue("type") == "pre") {
|
||||||
|
PreFunctions.push_back(new FGFunction(PropertyManager, function));
|
||||||
|
} else if (function->GetAttributeValue("type").empty()) { // Assume pre-function
|
||||||
|
string funcname = function->GetAttributeValue("name");
|
||||||
|
PreFunctions.push_back(new FGFunction(PropertyManager, function));
|
||||||
|
}
|
||||||
|
function = el->FindNextElement("function");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
void FGModel::PostLoad(Element* el)
|
||||||
|
{
|
||||||
|
// Load model post-functions, if any
|
||||||
|
|
||||||
|
Element *function = el->FindElement("function");
|
||||||
|
while (function) {
|
||||||
|
if (function->GetAttributeValue("type") == "post") {
|
||||||
|
PostFunctions.push_back(new FGFunction(PropertyManager, function));
|
||||||
|
}
|
||||||
|
function = el->FindNextElement("function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
// Tell the Functions to cache values, so when the function values
|
||||||
|
// are being used in the model, the functions do not get
|
||||||
|
// calculated each time, but instead use the values that have already
|
||||||
|
// been calculated for this frame.
|
||||||
|
|
||||||
|
void FGModel::RunPreFunctions(void)
|
||||||
|
{
|
||||||
|
vector <FGFunction*>::iterator it;
|
||||||
|
for (it = PreFunctions.begin(); it != PreFunctions.end(); it++)
|
||||||
|
(*it)->GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
// Tell the Functions to cache values, so when the function values
|
||||||
|
// are being used in the model, the functions do not get
|
||||||
|
// calculated each time, but instead use the values that have already
|
||||||
|
// been calculated for this frame.
|
||||||
|
|
||||||
|
void FGModel::RunPostFunctions(void)
|
||||||
|
{
|
||||||
|
vector <FGFunction*>::iterator it;
|
||||||
|
for (it = PostFunctions.begin(); it != PostFunctions.end(); it++)
|
||||||
|
(*it)->GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
bool FGModel::Run()
|
bool FGModel::Run()
|
||||||
{
|
{
|
||||||
if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;
|
if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;
|
||||||
|
|
||||||
if (exe_ctr++ >= rate) exe_ctr = 1;
|
if (rate == 1) return false; // Fast exit if nothing to do
|
||||||
|
|
||||||
if (exe_ctr == 1) return false;
|
if (exe_ctr >= rate) exe_ctr = 1;
|
||||||
|
|
||||||
|
if (exe_ctr++ == 1) return false;
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ INCLUDES
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||||
|
|
||||||
#include "FGJSBBase.h"
|
#include "FGJSBBase.h"
|
||||||
|
#include "math/FGFunction.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -93,11 +94,6 @@ public:
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~FGModel();
|
~FGModel();
|
||||||
|
|
||||||
/** Loads this model.
|
|
||||||
@param el a pointer to the element
|
|
||||||
@return true if model is successfully loaded*/
|
|
||||||
virtual bool Load(Element* el);
|
|
||||||
|
|
||||||
FGModel* NextModel;
|
FGModel* NextModel;
|
||||||
std::string Name;
|
std::string Name;
|
||||||
|
|
||||||
|
@ -116,6 +112,16 @@ protected:
|
||||||
int exe_ctr;
|
int exe_ctr;
|
||||||
int rate;
|
int rate;
|
||||||
|
|
||||||
|
void RunPreFunctions(void);
|
||||||
|
void RunPostFunctions(void);
|
||||||
|
|
||||||
|
/** Loads this model.
|
||||||
|
@param el a pointer to the element
|
||||||
|
@return true if model is successfully loaded*/
|
||||||
|
virtual bool Load(Element* el);
|
||||||
|
|
||||||
|
void PostLoad(Element* el);
|
||||||
|
|
||||||
virtual void Debug(int from);
|
virtual void Debug(int from);
|
||||||
|
|
||||||
FGFDMExec* FDMExec;
|
FGFDMExec* FDMExec;
|
||||||
|
@ -133,6 +139,8 @@ protected:
|
||||||
FGPropagate* Propagate;
|
FGPropagate* Propagate;
|
||||||
FGAuxiliary* Auxiliary;
|
FGAuxiliary* Auxiliary;
|
||||||
FGPropertyManager* PropertyManager;
|
FGPropertyManager* PropertyManager;
|
||||||
|
std::vector <FGFunction*> PreFunctions;
|
||||||
|
std::vector <FGFunction*> PostFunctions;
|
||||||
|
|
||||||
std::vector <double*> interface_properties;
|
std::vector <double*> interface_properties;
|
||||||
};
|
};
|
||||||
|
|
|
@ -188,6 +188,7 @@ bool FGOutput::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
|
|
||||||
if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) {
|
if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) {
|
||||||
|
RunPreFunctions();
|
||||||
if (Type == otSocket) {
|
if (Type == otSocket) {
|
||||||
SocketOutput();
|
SocketOutput();
|
||||||
} else if (Type == otFlightGear) {
|
} else if (Type == otFlightGear) {
|
||||||
|
@ -201,6 +202,7 @@ bool FGOutput::Run(void)
|
||||||
} else {
|
} else {
|
||||||
// Not a valid type of output
|
// Not a valid type of output
|
||||||
}
|
}
|
||||||
|
RunPostFunctions();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -396,22 +398,22 @@ void FGOutput::DelimitedOutput(const string& fname)
|
||||||
}
|
}
|
||||||
if (SubSystems & ssForces) {
|
if (SubSystems & ssForces) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << Aerodynamics->GetvFw() << delimeter;
|
outstream << Aerodynamics->GetvFw().Dump(delimeter) << delimeter;
|
||||||
outstream << Aerodynamics->GetLoD() << delimeter;
|
outstream << Aerodynamics->GetLoD() << delimeter;
|
||||||
outstream << Aerodynamics->GetForces() << delimeter;
|
outstream << Aerodynamics->GetForces().Dump(delimeter) << delimeter;
|
||||||
outstream << Propulsion->GetForces() << delimeter;
|
outstream << Propulsion->GetForces().Dump(delimeter) << delimeter;
|
||||||
outstream << GroundReactions->GetForces() << delimeter;
|
outstream << GroundReactions->GetForces().Dump(delimeter) << delimeter;
|
||||||
outstream << ExternalReactions->GetForces() << delimeter;
|
outstream << ExternalReactions->GetForces().Dump(delimeter) << delimeter;
|
||||||
outstream << BuoyantForces->GetForces() << delimeter;
|
outstream << BuoyantForces->GetForces().Dump(delimeter) << delimeter;
|
||||||
outstream << Aircraft->GetForces().Dump(delimeter);
|
outstream << Aircraft->GetForces().Dump(delimeter);
|
||||||
}
|
}
|
||||||
if (SubSystems & ssMoments) {
|
if (SubSystems & ssMoments) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << Aerodynamics->GetMoments() << delimeter;
|
outstream << Aerodynamics->GetMoments().Dump(delimeter) << delimeter;
|
||||||
outstream << Propulsion->GetMoments() << delimeter;
|
outstream << Propulsion->GetMoments().Dump(delimeter) << delimeter;
|
||||||
outstream << GroundReactions->GetMoments() << delimeter;
|
outstream << GroundReactions->GetMoments().Dump(delimeter) << delimeter;
|
||||||
outstream << ExternalReactions->GetMoments() << delimeter;
|
outstream << ExternalReactions->GetMoments().Dump(delimeter) << delimeter;
|
||||||
outstream << BuoyantForces->GetMoments() << delimeter;
|
outstream << BuoyantForces->GetMoments().Dump(delimeter) << delimeter;
|
||||||
outstream << Aircraft->GetMoments().Dump(delimeter);
|
outstream << Aircraft->GetMoments().Dump(delimeter);
|
||||||
}
|
}
|
||||||
if (SubSystems & ssAtmosphere) {
|
if (SubSystems & ssAtmosphere) {
|
||||||
|
@ -428,9 +430,9 @@ void FGOutput::DelimitedOutput(const string& fname)
|
||||||
}
|
}
|
||||||
if (SubSystems & ssMassProps) {
|
if (SubSystems & ssMassProps) {
|
||||||
outstream << delimeter;
|
outstream << delimeter;
|
||||||
outstream << MassBalance->GetJ() << delimeter;
|
outstream << MassBalance->GetJ().Dump(delimeter) << delimeter;
|
||||||
outstream << MassBalance->GetMass() << delimeter;
|
outstream << MassBalance->GetMass() << delimeter;
|
||||||
outstream << MassBalance->GetXYZcg();
|
outstream << MassBalance->GetXYZcg().Dump(delimeter);
|
||||||
}
|
}
|
||||||
if (SubSystems & ssPropagate) {
|
if (SubSystems & ssPropagate) {
|
||||||
outstream.precision(14);
|
outstream.precision(14);
|
||||||
|
|
|
@ -233,6 +233,8 @@ bool FGPropagate::Run(void)
|
||||||
if (FGModel::Run()) return true; // Fast return if we have nothing to do ...
|
if (FGModel::Run()) return true; // Fast return if we have nothing to do ...
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
RecomputeLocalTerrainRadius();
|
RecomputeLocalTerrainRadius();
|
||||||
|
|
||||||
// Calculate current aircraft radius from center of planet
|
// Calculate current aircraft radius from center of planet
|
||||||
|
@ -344,6 +346,8 @@ bool FGPropagate::Run(void)
|
||||||
last2_vLocationDot = last_vLocationDot;
|
last2_vLocationDot = last_vLocationDot;
|
||||||
last_vLocationDot = vLocationDot;
|
last_vLocationDot = vLocationDot;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
Debug(2);
|
Debug(2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,8 @@ bool FGPropulsion::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
double dt = State->Getdt();
|
double dt = State->Getdt();
|
||||||
|
|
||||||
vForces.InitMatrix();
|
vForces.InitMatrix();
|
||||||
|
@ -169,6 +171,8 @@ bool FGPropulsion::Run(void)
|
||||||
if (refuel) DoRefuel( dt * rate );
|
if (refuel) DoRefuel( dt * rate );
|
||||||
if (dump) DumpFuel( dt * rate );
|
if (dump) DumpFuel( dt * rate );
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +337,7 @@ bool FGPropulsion::Load(Element* el)
|
||||||
if (el->FindElement("dump-rate"))
|
if (el->FindElement("dump-rate"))
|
||||||
DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
|
DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
|
||||||
|
|
||||||
|
FGModel::PostLoad(el);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,8 @@ bool MSIS::Run(void)
|
||||||
if (FGModel::Run()) return true;
|
if (FGModel::Run()) return true;
|
||||||
if (FDMExec->Holding()) return false;
|
if (FDMExec->Holding()) return false;
|
||||||
|
|
||||||
|
RunPreFunctions();
|
||||||
|
|
||||||
//do temp, pressure, and density first
|
//do temp, pressure, and density first
|
||||||
if (!useExternal) {
|
if (!useExternal) {
|
||||||
// get sea-level values
|
// get sea-level values
|
||||||
|
@ -180,6 +182,8 @@ bool MSIS::Run(void)
|
||||||
|
|
||||||
CalculateDerived();
|
CalculateDerived();
|
||||||
|
|
||||||
|
RunPostFunctions();
|
||||||
|
|
||||||
Debug(2);
|
Debug(2);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -74,6 +74,7 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
|
||||||
SLFuelFlowMax = 0.0;
|
SLFuelFlowMax = 0.0;
|
||||||
MaxThrottle = 1.0;
|
MaxThrottle = 1.0;
|
||||||
MinThrottle = 0.0;
|
MinThrottle = 0.0;
|
||||||
|
FuelDensity = 6.0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
ResetToIC(); // initialize dynamic terms
|
ResetToIC(); // initialize dynamic terms
|
||||||
|
@ -122,7 +123,9 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
|
||||||
if (local_element) {
|
if (local_element) {
|
||||||
while (local_element) {
|
while (local_element) {
|
||||||
int tankID = (int)local_element->GetDataAsNumber();
|
int tankID = (int)local_element->GetDataAsNumber();
|
||||||
AddFeedTank( tankID , Propulsion->GetTank(tankID)->GetPriority());
|
FGTank* tank = Propulsion->GetTank(tankID);
|
||||||
|
AddFeedTank( tankID , tank->GetPriority());
|
||||||
|
FuelDensity = tank->GetDensity();
|
||||||
local_element = engine_element->GetParent()->FindNextElement("feed");
|
local_element = engine_element->GetParent()->FindNextElement("feed");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -139,6 +142,8 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
|
||||||
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);
|
||||||
|
|
||||||
|
//cout << "Engine[" << EngineNumber << "] using fuel density: " << FuelDensity << endl;
|
||||||
|
|
||||||
Debug(0);
|
Debug(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,7 @@ CLASS DOCUMENTATION
|
||||||
@endcode
|
@endcode
|
||||||
<pre>
|
<pre>
|
||||||
NOTES:
|
NOTES:
|
||||||
Engines feed from all tanks equally.
|
|
||||||
|
|
||||||
Not all thruster types can be matched with a given engine type. See the class
|
Not all thruster types can be matched with a given engine type. See the class
|
||||||
documentation for engine and thruster classes.
|
documentation for engine and thruster classes.
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -226,6 +225,7 @@ protected:
|
||||||
|
|
||||||
double FuelFlow_gph;
|
double FuelFlow_gph;
|
||||||
double FuelFlow_pph;
|
double FuelFlow_pph;
|
||||||
|
double FuelDensity;
|
||||||
|
|
||||||
FGFDMExec* FDMExec;
|
FGFDMExec* FDMExec;
|
||||||
FGState* State;
|
FGState* State;
|
||||||
|
|
|
@ -71,6 +71,8 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
|
||||||
SLOxiFlowMax = 0.0;
|
SLOxiFlowMax = 0.0;
|
||||||
BuildupTime = 0.0;
|
BuildupTime = 0.0;
|
||||||
It = 0.0;
|
It = 0.0;
|
||||||
|
ThrustVariation = 0.0;
|
||||||
|
TotalIspVariation = 0.0;
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
MinThrottle = 0.0;
|
MinThrottle = 0.0;
|
||||||
|
@ -89,9 +91,19 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
|
||||||
if (el->FindElement("sloxiflowmax"))
|
if (el->FindElement("sloxiflowmax"))
|
||||||
SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC");
|
SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC");
|
||||||
|
|
||||||
|
// If there is a thrust table element, this is a solid propellant engine.
|
||||||
thrust_table_element = el->FindElement("thrust_table");
|
thrust_table_element = el->FindElement("thrust_table");
|
||||||
if (thrust_table_element) {
|
if (thrust_table_element) {
|
||||||
ThrustTable = new FGTable(PropertyManager, thrust_table_element);
|
ThrustTable = new FGTable(PropertyManager, thrust_table_element);
|
||||||
|
Element* variation_element = el->FindElement("variation");
|
||||||
|
if (variation_element) {
|
||||||
|
if (variation_element->FindElement("thrust")) {
|
||||||
|
ThrustVariation = variation_element->FindElementValueAsNumber("thrust");
|
||||||
|
}
|
||||||
|
if (variation_element->FindElement("total_isp")) {
|
||||||
|
TotalIspVariation = variation_element->FindElementValueAsNumber("total_isp");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindmodel();
|
bindmodel();
|
||||||
|
@ -138,7 +150,9 @@ double FGRocket::Calculate(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VacThrust = ThrustTable->GetValue(TotalEngineFuelBurned);
|
VacThrust = ThrustTable->GetValue(TotalEngineFuelBurned)
|
||||||
|
* (ThrustVariation + 1)
|
||||||
|
* (TotalIspVariation + 1);
|
||||||
if (BurnTime <= BuildupTime && BuildupTime > 0.0) {
|
if (BurnTime <= BuildupTime && BuildupTime > 0.0) {
|
||||||
VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0);
|
VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0);
|
||||||
// VacThrust *= (1-cos((BurnTime/BuildupTime)*M_PI))/2.0; // 1 - cos approach
|
// VacThrust *= (1-cos((BurnTime/BuildupTime)*M_PI))/2.0; // 1 - cos approach
|
||||||
|
@ -241,6 +255,11 @@ void FGRocket::ConsumeFuel(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
//
|
||||||
|
// The FuelFlowRate can be affected by the TotalIspVariation value (settable
|
||||||
|
// in a config file or via properties). The TotalIspVariation parameter affects
|
||||||
|
// thrust, but the thrust determines fuel flow rate, so it must be adjusted
|
||||||
|
// for Total Isp Variation.
|
||||||
|
|
||||||
double FGRocket::CalcFuelNeed(void)
|
double FGRocket::CalcFuelNeed(void)
|
||||||
{
|
{
|
||||||
|
@ -248,6 +267,7 @@ double FGRocket::CalcFuelNeed(void)
|
||||||
|
|
||||||
if (ThrustTable != 0L) { // Thrust table given - infers solid fuel
|
if (ThrustTable != 0L) { // Thrust table given - infers solid fuel
|
||||||
FuelFlowRate = VacThrust/Isp; // This calculates wdot (weight flow rate in lbs/sec)
|
FuelFlowRate = VacThrust/Isp; // This calculates wdot (weight flow rate in lbs/sec)
|
||||||
|
FuelFlowRate /= (1 + TotalIspVariation);
|
||||||
} else {
|
} else {
|
||||||
FuelFlowRate = SLFuelFlowMax*PctPower;
|
FuelFlowRate = SLFuelFlowMax*PctPower;
|
||||||
}
|
}
|
||||||
|
@ -290,7 +310,7 @@ string FGRocket::GetEngineValues(const string& delimiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
// This funciton should tie properties to rocket engine specific properties
|
// This function should tie properties to rocket engine specific properties
|
||||||
// that are not bound in the base class (FGEngine) code.
|
// that are not bound in the base class (FGEngine) code.
|
||||||
//
|
//
|
||||||
void FGRocket::bindmodel()
|
void FGRocket::bindmodel()
|
||||||
|
@ -300,10 +320,20 @@ void FGRocket::bindmodel()
|
||||||
|
|
||||||
property_name = base_property_name + "/total-impulse";
|
property_name = base_property_name + "/total-impulse";
|
||||||
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse);
|
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse);
|
||||||
property_name = base_property_name + "/oxi-flow-rate-pps";
|
|
||||||
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate);
|
|
||||||
property_name = base_property_name + "/vacuum-thrust_lbs";
|
property_name = base_property_name + "/vacuum-thrust_lbs";
|
||||||
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust);
|
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust);
|
||||||
|
|
||||||
|
if (ThrustTable) { // Solid rocket motor
|
||||||
|
property_name = base_property_name + "/thrust-variation_pct";
|
||||||
|
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetThrustVariation,
|
||||||
|
&FGRocket::SetThrustVariation);
|
||||||
|
property_name = base_property_name + "/total-isp-variation_pct";
|
||||||
|
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalIspVariation,
|
||||||
|
&FGRocket::SetTotalIspVariation);
|
||||||
|
} else { // Liquid rocket motor
|
||||||
|
property_name = base_property_name + "/oxi-flow-rate-pps";
|
||||||
|
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
|
@ -162,6 +162,32 @@ public:
|
||||||
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);
|
||||||
|
|
||||||
|
/** Sets the thrust variation for a solid rocket engine.
|
||||||
|
Solid propellant rocket motor thrust characteristics are typically
|
||||||
|
defined at 70 degrees F temperature. At any other temperature,
|
||||||
|
performance will be different. Warmer propellant grain will
|
||||||
|
burn quicker and at higher thrust. Total motor impulse is
|
||||||
|
not changed for change in thrust.
|
||||||
|
@param var the variation in percent. That is, a 2 percent
|
||||||
|
variation would be specified as 0.02. A positive 2% variation
|
||||||
|
in thrust would increase the thrust by 2%, and shorten the burn time. */
|
||||||
|
void SetThrustVariation(double var) {ThrustVariation = var;}
|
||||||
|
|
||||||
|
/** Sets the variation in total motor energy.
|
||||||
|
The total energy present in a solid rocket motor can be modified
|
||||||
|
(such as might happen with manufacturing variations) by setting
|
||||||
|
the total Isp variation.
|
||||||
|
@param var the variation in percent. That is, a 2 percent
|
||||||
|
variation would be specified as 0.02. This variation will
|
||||||
|
affect the total thrust, but not the burn time.*/
|
||||||
|
void SetTotalIspVariation(double var) {TotalIspVariation = var;}
|
||||||
|
|
||||||
|
/** Returns the thrust variation, if any. */
|
||||||
|
double GetThrustVariation(void) const {return ThrustVariation;}
|
||||||
|
|
||||||
|
/** Returns the Total Isp variation, if any. */
|
||||||
|
double GetTotalIspVariation(void) const {return TotalIspVariation;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Reduces the fuel in the active tanks by the amount required.
|
/** Reduces the fuel in the active tanks by the amount required.
|
||||||
This function should be called from within the
|
This function should be called from within the
|
||||||
|
@ -192,6 +218,8 @@ private:
|
||||||
double It;
|
double It;
|
||||||
double MxR; // Mixture Ratio
|
double MxR; // Mixture Ratio
|
||||||
double BurnTime;
|
double BurnTime;
|
||||||
|
double ThrustVariation;
|
||||||
|
double TotalIspVariation;
|
||||||
double VacThrust;
|
double VacThrust;
|
||||||
double previousFuelNeedPerTank;
|
double previousFuelNeedPerTank;
|
||||||
double previousOxiNeedPerTank;
|
double previousOxiNeedPerTank;
|
||||||
|
|
|
@ -58,7 +58,7 @@ CLASS IMPLEMENTATION
|
||||||
FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
|
FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
|
||||||
: TankNumber(tank_number), Exec(exec)
|
: TankNumber(tank_number), Exec(exec)
|
||||||
{
|
{
|
||||||
string token;
|
string token, strFuelName;
|
||||||
Element* element;
|
Element* element;
|
||||||
Element* element_Grain;
|
Element* element_Grain;
|
||||||
Area = 1.0;
|
Area = 1.0;
|
||||||
|
@ -102,6 +102,9 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
|
||||||
InitialPriority = Priority = el->FindElementValueAsNumber("priority");
|
InitialPriority = Priority = el->FindElementValueAsNumber("priority");
|
||||||
if (el->FindElement("density"))
|
if (el->FindElement("density"))
|
||||||
Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL");
|
Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL");
|
||||||
|
if (el->FindElement("type"))
|
||||||
|
strFuelName = el->FindElementValue("type");
|
||||||
|
|
||||||
|
|
||||||
SetPriority( InitialPriority ); // this will also set the Selected flag
|
SetPriority( InitialPriority ); // this will also set the Selected flag
|
||||||
|
|
||||||
|
@ -162,6 +165,9 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
|
||||||
if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
|
if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
|
||||||
Area = 40.0 * pow(Capacity/1975, 0.666666667);
|
Area = 40.0 * pow(Capacity/1975, 0.666666667);
|
||||||
|
|
||||||
|
// A named fuel type will override a previous density value
|
||||||
|
if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName);
|
||||||
|
|
||||||
Debug(0);
|
Debug(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,6 +319,43 @@ void FGTank::CalculateInertias(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
double FGTank::ProcessFuelName(std::string const& name)
|
||||||
|
{
|
||||||
|
if (name == "AVGAS") return 6.02;
|
||||||
|
else if (name == "JET-A") return 6.74;
|
||||||
|
else if (name == "JET-A1") return 6.74;
|
||||||
|
else if (name == "JET-B") return 6.48;
|
||||||
|
else if (name == "JP-1") return 6.76;
|
||||||
|
else if (name == "JP-2") return 6.38;
|
||||||
|
else if (name == "JP-3") return 6.34;
|
||||||
|
else if (name == "JP-4") return 6.48;
|
||||||
|
else if (name == "JP-5") return 6.81;
|
||||||
|
else if (name == "JP-6") return 6.55;
|
||||||
|
else if (name == "JP-7") return 6.61;
|
||||||
|
else if (name == "JP-8") return 6.66;
|
||||||
|
else if (name == "JP-8+100") return 6.66;
|
||||||
|
//else if (name == "JP-9") return 6.74;
|
||||||
|
//else if (name == "JPTS") return 6.74;
|
||||||
|
else if (name == "RP-1") return 6.73;
|
||||||
|
else if (name == "T-1") return 6.88;
|
||||||
|
else if (name == "ETHANOL") return 6.58;
|
||||||
|
else if (name == "HYDRAZINE")return 8.61;
|
||||||
|
else if (name == "F-34") return 6.66;
|
||||||
|
else if (name == "F-35") return 6.74;
|
||||||
|
else if (name == "F-40") return 6.48;
|
||||||
|
else if (name == "F-44") return 6.81;
|
||||||
|
else if (name == "AVTAG") return 6.48;
|
||||||
|
else if (name == "AVCAT") return 6.81;
|
||||||
|
else {
|
||||||
|
cerr << "Unknown fuel type specified: "<< name << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 6.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
// The bitmasked value choices are as follows:
|
// The bitmasked value choices are as follows:
|
||||||
// unset: In this case (the default) JSBSim would only print
|
// unset: In this case (the default) JSBSim would only print
|
||||||
|
|
|
@ -126,6 +126,7 @@ CLASS DOCUMENTATION
|
||||||
<standpipe unit="{LBS | KG"}> {number} </standpipe>
|
<standpipe unit="{LBS | KG"}> {number} </standpipe>
|
||||||
<priority> {integer} </priority>
|
<priority> {integer} </priority>
|
||||||
<density unit="{KG/L | LBS/GAL}"> {number} </density>
|
<density unit="{KG/L | LBS/GAL}"> {number} </density>
|
||||||
|
<type> {string} </type> <!-- will override previous density setting -->
|
||||||
</tank>
|
</tank>
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
|
@ -141,6 +142,9 @@ CLASS DOCUMENTATION
|
||||||
- \b standpipe - Minimum contents to which tank can dump, defaults to pounds.
|
- \b standpipe - Minimum contents to which tank can dump, defaults to pounds.
|
||||||
- \b priority - Establishes feed sequence of tank. "1" is the highest priority.
|
- \b priority - Establishes feed sequence of tank. "1" is the highest priority.
|
||||||
- \b density - Density of liquid tank contents.
|
- \b density - Density of liquid tank contents.
|
||||||
|
- \b type - Named fuel type. One of AVGAS, JET-A, JET-A1, JET-B, JP-1, JP-2, JP-3,
|
||||||
|
- \b JP-4, JP-5, JP-6, JP-7, JP-8, JP-8+100, RP-1, T-1, ETHANOL, HYDRAZINE,
|
||||||
|
- \b F-34, F-35, F-40, F-44, AVTAG, AVCAT
|
||||||
|
|
||||||
location:
|
location:
|
||||||
- \b x - Location of tank on aircraft's x-axis, defaults to inches.
|
- \b x - Location of tank on aircraft's x-axis, defaults to inches.
|
||||||
|
@ -252,6 +256,10 @@ public:
|
||||||
is given, otherwise 32 degrees F is returned. */
|
is given, otherwise 32 degrees F is returned. */
|
||||||
double GetTemperature(void) {return CelsiusToFahrenheit(Temperature);}
|
double GetTemperature(void) {return CelsiusToFahrenheit(Temperature);}
|
||||||
|
|
||||||
|
/** Returns the density of a named fuel type.
|
||||||
|
@return the density, in lbs/gal, or 6.6 if name cannot be resolved. */
|
||||||
|
double ProcessFuelName(std::string const& name);
|
||||||
|
|
||||||
double GetIxx(void) {return Ixx;}
|
double GetIxx(void) {return Ixx;}
|
||||||
double GetIyy(void) {return Iyy;}
|
double GetIyy(void) {return Iyy;}
|
||||||
double GetIzz(void) {return Izz;}
|
double GetIzz(void) {return Izz;}
|
||||||
|
@ -261,6 +269,9 @@ public:
|
||||||
int GetPriority(void) const {return Priority;}
|
int GetPriority(void) const {return Priority;}
|
||||||
void SetPriority(int p) { Priority = p; Selected = p>0 ? true:false; }
|
void SetPriority(int p) { Priority = p; Selected = p>0 ? true:false; }
|
||||||
|
|
||||||
|
double GetDensity(void) const {return Density;}
|
||||||
|
void SetDensity(double d) { Density = d; }
|
||||||
|
|
||||||
const FGColumnVector3 GetXYZ(void);
|
const FGColumnVector3 GetXYZ(void);
|
||||||
const double GetXYZ(int idx);
|
const double GetXYZ(int idx);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue