1
0
Fork 0

sync with JSBSim CVS

This commit is contained in:
Erik Hofman 2011-06-17 09:26:52 +02:00
parent bba9a768b3
commit ec454158fe
56 changed files with 1748 additions and 568 deletions

View file

@ -71,7 +71,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.91 2011/04/05 20:20:21 andgi Exp $"; static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.95 2011/05/20 10:35:25 jberndt Exp $";
static const char *IdHdr = ID_FDMEXEC; static const char *IdHdr = ID_FDMEXEC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -228,19 +228,19 @@ bool FGFDMExec::Allocate(void)
// 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.
Schedule(Input, 1); Schedule(Input, 1); // Input model is Models[0]
Schedule(Atmosphere, 1); Schedule(Atmosphere, 1); // Input model is Models[1]
Schedule(FCS, 1); Schedule(FCS, 1); // Input model is Models[2]
Schedule(Propulsion, 1); Schedule(Propulsion, 1); // Input model is Models[3]
Schedule(MassBalance, 1); Schedule(MassBalance, 1); // Input model is Models[4]
Schedule(Aerodynamics, 1); Schedule(Aerodynamics, 1); // Input model is Models[5]
Schedule(Inertial, 1); Schedule(Inertial, 1); // Input model is Models[6]
Schedule(GroundReactions, 1); Schedule(GroundReactions, 1); // Input model is Models[7]
Schedule(ExternalReactions, 1); Schedule(ExternalReactions, 1); // Input model is Models[8]
Schedule(BuoyantForces, 1); Schedule(BuoyantForces, 1); // Input model is Models[9]
Schedule(Aircraft, 1); Schedule(Aircraft, 1); // Input model is Models[10]
Schedule(Propagate, 1); Schedule(Propagate, 1); // Input model is Models[11]
Schedule(Auxiliary, 1); Schedule(Auxiliary, 1); // Input model is Models[12]
// Initialize models so they can communicate with each other // Initialize models so they can communicate with each other
@ -329,10 +329,9 @@ bool FGFDMExec::Run(void)
if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript(); if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript();
vector <FGModel*>::iterator it; vector <FGModel*>::iterator it;
for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run(); for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run(holding);
Frame++; IncrTime();
if (!Holding()) IncrTime();
if (Terminate) success = false; if (Terminate) success = false;
return (success); return (success);
@ -359,36 +358,12 @@ void FGFDMExec::Initialize(FGInitialCondition *FGIC)
Propagate->SetInitialState( FGIC ); Propagate->SetInitialState( FGIC );
Atmosphere->Run(); Atmosphere->Run(false);
Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(), Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(),
FGIC->GetWindEFpsIC(), FGIC->GetWindEFpsIC(),
FGIC->GetWindDFpsIC() ); FGIC->GetWindDFpsIC() );
FGColumnVector3 vAeroUVW; Auxiliary->Run(false);
//ToDo: move this to the Auxiliary class !?
vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED();
double alpha, beta;
if (vAeroUVW(eW) != 0.0)
alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
else
alpha = 0.0;
if (vAeroUVW(eV) != 0.0)
beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
else
beta = 0.0;
Auxiliary->SetAB(alpha, beta);
double Vt = vAeroUVW.Magnitude();
Auxiliary->SetVt(Vt);
Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed());
double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity();
Auxiliary->Setqbar(qbar);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -675,7 +650,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
modelLoaded = true; modelLoaded = true;
if (debug_lvl > 0) { if (debug_lvl > 0) {
MassBalance->Run(); // Update all mass properties for the report. MassBalance->Run(false); // Update all mass properties for the report.
MassBalance->GetMassPropertiesReport(); MassBalance->GetMassPropertiesReport();
cout << endl << fgblue << highint cout << endl << fgblue << highint
@ -968,38 +943,6 @@ void FGFDMExec::DoTrim(int mode)
sim_time = saved_time; sim_time = saved_time;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
void FGFDMExec::DoTrimAnalysis(int mode)
{
double saved_time;
if (Constructing) return;
if (mode < 0 || mode > JSBSim::taNone) {
cerr << endl << "Illegal trimming mode!" << endl << endl;
return;
}
saved_time = sim_time;
FGTrimAnalysis trimAnalysis(this, (JSBSim::TrimAnalysisMode)mode);
if ( !trimAnalysis.Load(IC->GetInitFile(), false) ) {
cerr << "A problem occurred with trim configuration file " << trimAnalysis.Load(IC->GetInitFile()) << endl;
exit(-1);
}
bool result = trimAnalysis.DoTrim();
if ( !result ) cerr << endl << "Trim Failed" << endl << endl;
trimAnalysis.Report();
Setsim_time(saved_time);
EnableOutput();
cout << "\nOutput: " << GetOutputFileName() << endl;
}
*/
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::UseAtmosphereMSIS(void) void FGFDMExec::UseAtmosphereMSIS(void)
@ -1010,6 +953,8 @@ void FGFDMExec::UseAtmosphereMSIS(void)
cerr << fgred << "MSIS Atmosphere model init failed" << fgdef << endl; cerr << fgred << "MSIS Atmosphere model init failed" << fgdef << endl;
Error+=1; Error+=1;
} }
Models[1] = Atmosphere; // Reassign the atmosphere model that has already been scheduled
// to the new atmosphere.
delete oldAtmosphere; delete oldAtmosphere;
} }
@ -1024,6 +969,8 @@ void FGFDMExec::UseAtmosphereMars(void)
cerr << fgred << "Mars Atmosphere model init failed" << fgdef << endl; cerr << fgred << "Mars Atmosphere model init failed" << fgdef << endl;
Error+=1; Error+=1;
} }
Models[1] = Atmosphere; // Reassign the atmosphere model that has already been scheduled
// to the new atmosphere.
delete oldAtmosphere; delete oldAtmosphere;
*/ */
} }

View file

@ -58,7 +58,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.63 2011/02/19 16:44:41 jberndt Exp $" #define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.64 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -181,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.63 $ @version $Revision: 1.64 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -432,7 +432,6 @@ public:
* - tTurn * - tTurn
* - tNone */ * - tNone */
void DoTrim(int mode); void DoTrim(int mode);
// void DoTrimAnalysis(int mode);
/// Disables data logging to all outputs. /// Disables data logging to all outputs.
void DisableOutput(void); void DisableOutput(void);
@ -522,10 +521,12 @@ public:
@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;}
/** Increments the simulation time. /** Increments the simulation time if not in Holding mode. The Frame counter
is also incremented.
@return the new simulation time. */ @return the new simulation time. */
double IncrTime(void) { double IncrTime(void) {
sim_time += dT; if (!holding) sim_time += dT;
Frame++;
return sim_time; return sim_time;
} }

View file

@ -44,7 +44,7 @@ INCLUDES
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.29 2010/03/18 13:19:21 jberndt Exp $"; static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.30 2011/06/13 11:47:04 jberndt Exp $";
static const char *IdHdr = ID_JSBBASE; static const char *IdHdr = ID_JSBBASE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -89,7 +89,9 @@ const double FGJSBBase::in3tom3 = 1.638706E-5;
const double FGJSBBase::m3toft3 = 1.0/(fttom*fttom*fttom); const double FGJSBBase::m3toft3 = 1.0/(fttom*fttom*fttom);
const double FGJSBBase::inhgtopa = 3386.38; const double FGJSBBase::inhgtopa = 3386.38;
const double FGJSBBase::fttom = 0.3048; const double FGJSBBase::fttom = 0.3048;
double FGJSBBase::Reng = 1716.0; double FGJSBBase::Reng = 1716.56; // Gas constant for Air (ft-lb/slug-R)
double FGJSBBase::Rstar = 1545.348; // Universal gas constant
double FGJSBBase::Mair = 28.9645; //
const double FGJSBBase::SHRatio = 1.40; const double FGJSBBase::SHRatio = 1.40;
// Note that definition of lbtoslug by the inverse of slugtolb and not // Note that definition of lbtoslug by the inverse of slugtolb and not

View file

@ -63,7 +63,7 @@ namespace std
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_JSBBASE "$Id: FGJSBBase.h,v 1.30 2010/07/01 23:13:19 jberndt Exp $" #define ID_JSBBASE "$Id: FGJSBBase.h,v 1.32 2011/06/13 11:47:04 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -79,7 +79,7 @@ CLASS DOCUMENTATION
* This class provides universal constants, utility functions, messaging * This class provides universal constants, utility functions, messaging
* functions, and enumerated constants to JSBSim. * functions, and enumerated constants to JSBSim.
@author Jon S. Berndt @author Jon S. Berndt
@version $Id: FGJSBBase.h,v 1.30 2010/07/01 23:13:19 jberndt Exp $ @version $Id: FGJSBBase.h,v 1.32 2011/06/13 11:47:04 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -92,7 +92,7 @@ public:
FGJSBBase() {}; FGJSBBase() {};
/// Destructor for FGJSBBase. /// Destructor for FGJSBBase.
~FGJSBBase() {}; virtual ~FGJSBBase() {};
/// JSBSim Message structure /// JSBSim Message structure
class Message { class Message {
@ -327,6 +327,8 @@ protected:
static const double inhgtopa; static const double inhgtopa;
static const double fttom; static const double fttom;
static double Reng; // Specific Gas Constant,ft^2/(sec^2*R) static double Reng; // Specific Gas Constant,ft^2/(sec^2*R)
static double Rstar;
static double Mair;
static const double SHRatio; static const double SHRatio;
static const double lbtoslug; static const double lbtoslug;
static const double slugtolb; static const double slugtolb;

View file

@ -140,7 +140,7 @@ FGJSBsim::FGJSBsim( double dt )
if( TURBULENCE_TYPE_NAMES.empty() ) { if( TURBULENCE_TYPE_NAMES.empty() ) {
TURBULENCE_TYPE_NAMES["ttNone"] = FGAtmosphere::ttNone; TURBULENCE_TYPE_NAMES["ttNone"] = FGAtmosphere::ttNone;
TURBULENCE_TYPE_NAMES["ttStandard"] = FGAtmosphere::ttStandard; TURBULENCE_TYPE_NAMES["ttStandard"] = FGAtmosphere::ttStandard;
TURBULENCE_TYPE_NAMES["ttBerndt"] = FGAtmosphere::ttBerndt; // TURBULENCE_TYPE_NAMES["ttBerndt"] = FGAtmosphere::ttBerndt;
TURBULENCE_TYPE_NAMES["ttCulp"] = FGAtmosphere::ttCulp; TURBULENCE_TYPE_NAMES["ttCulp"] = FGAtmosphere::ttCulp;
TURBULENCE_TYPE_NAMES["ttMilspec"] = FGAtmosphere::ttMilspec; TURBULENCE_TYPE_NAMES["ttMilspec"] = FGAtmosphere::ttMilspec;
TURBULENCE_TYPE_NAMES["ttTustin"] = FGAtmosphere::ttTustin; TURBULENCE_TYPE_NAMES["ttTustin"] = FGAtmosphere::ttTustin;
@ -672,9 +672,9 @@ bool FGJSBsim::copy_to_JSBsim()
Atmosphere->SetTurbType((FGAtmosphere::tType)TURBULENCE_TYPE_NAMES[turbulence_model->getStringValue()]); Atmosphere->SetTurbType((FGAtmosphere::tType)TURBULENCE_TYPE_NAMES[turbulence_model->getStringValue()]);
switch( Atmosphere->GetTurbType() ) { switch( Atmosphere->GetTurbType() ) {
// case FGAtmosphere::ttBerndt:
case FGAtmosphere::ttStandard: case FGAtmosphere::ttStandard:
case FGAtmosphere::ttCulp: case FGAtmosphere::ttCulp: {
case FGAtmosphere::ttBerndt: {
double tmp = turbulence_gain->getDoubleValue(); double tmp = turbulence_gain->getDoubleValue();
Atmosphere->SetTurbGain(tmp * tmp * 100.0); Atmosphere->SetTurbGain(tmp * tmp * 100.0);
Atmosphere->SetTurbRate(turbulence_rate->getDoubleValue()); Atmosphere->SetTurbRate(turbulence_rate->getDoubleValue());

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.61 2011/05/20 00:47:03 bcoconni Exp $"; static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.63 2011/06/13 10:30:22 bcoconni Exp $";
static const char *IdHdr = ID_INITIALCONDITION; static const char *IdHdr = ID_INITIALCONDITION;
//****************************************************************************** //******************************************************************************
@ -189,7 +189,7 @@ void FGInitialCondition::SetVequivalentKtsIC(double ve)
double altitudeASL = position.GetRadius() - sea_level_radius; double altitudeASL = position.GetRadius() - sea_level_radius;
double rho = fdmex->GetAtmosphere()->GetDensity(altitudeASL); double rho = fdmex->GetAtmosphere()->GetDensity(altitudeASL);
double rhoSL = fdmex->GetAtmosphere()->GetDensitySL(); double rhoSL = fdmex->GetAtmosphere()->GetDensitySL();
SetVtrueFpsIC(ve*ktstofps/sqrt(rho/rhoSL)); SetVtrueFpsIC(ve*ktstofps*sqrt(rhoSL/rho));
lastSpeedSet = setve; lastSpeedSet = setve;
} }
@ -324,7 +324,7 @@ void FGInitialCondition::SetClimbRateFpsIC(double hdot)
FGColumnVector3 _WIND_NED = _vt_NED - vUVW_NED; FGColumnVector3 _WIND_NED = _vt_NED - vUVW_NED;
double hdot0 = -_vt_NED(eW); double hdot0 = -_vt_NED(eW);
if (fabs(hdot0) < vt) { if (fabs(hdot0) < vt) { // Is this check really needed ?
double scale = sqrt((vt*vt-hdot*hdot)/(vt*vt-hdot0*hdot0)); double scale = sqrt((vt*vt-hdot*hdot)/(vt*vt-hdot0*hdot0));
_vt_NED(eU) *= scale; _vt_NED(eU) *= scale;
_vt_NED(eV) *= scale; _vt_NED(eV) *= scale;
@ -606,7 +606,7 @@ void FGInitialCondition::SetHeadWindKtsIC(double head)
FGColumnVector3 _vWIND_NED = _vt_NED - vUVW_NED; FGColumnVector3 _vWIND_NED = _vt_NED - vUVW_NED;
FGColumnVector3 _vHEAD(cos(psi), sin(psi), 0.); FGColumnVector3 _vHEAD(cos(psi), sin(psi), 0.);
// Gram-Schmidt process is used to remove the existing cross wind component // Gram-Schmidt process is used to remove the existing head wind component
_vWIND_NED -= DotProduct(_vWIND_NED, _vHEAD) * _vHEAD; _vWIND_NED -= DotProduct(_vWIND_NED, _vHEAD) * _vHEAD;
// which is now replaced by the new value. // which is now replaced by the new value.
_vWIND_NED += head * _vHEAD; _vWIND_NED += head * _vHEAD;
@ -707,7 +707,7 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt)
SetVtrueFpsIC(mach0 * soundSpeed); SetVtrueFpsIC(mach0 * soundSpeed);
break; break;
case setve: case setve:
SetVtrueFpsIC(ve0 * sqrt(rho/rhoSL)); SetVtrueFpsIC(ve0 * sqrt(rhoSL/rho));
break; break;
default: // Make the compiler stop complaining about missing enums default: // Make the compiler stop complaining about missing enums
break; break;
@ -1088,7 +1088,7 @@ bool FGInitialCondition::Load_v2(void)
// the given orientation and knowledge of the Earth position angle. // the given orientation and knowledge of the Earth position angle.
// This could be done using matrices (where in the subscript "b/a", // This could be done using matrices (where in the subscript "b/a",
// it is meant "b with respect to a", and where b=body frame, // it is meant "b with respect to a", and where b=body frame,
// i=inertial frame, and e=ecef frame) as: // i=inertial frame, l=local NED frame and e=ecef frame) as:
// //
// C_b/l = C_b/e * C_e/l // C_b/l = C_b/e * C_e/l
// //

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGTable.cpp,v 1.27 2010/10/21 11:09:56 jberndt Exp $"; static const char *IdSrc = "$Id: FGTable.cpp,v 1.28 2011/06/13 12:07:10 jberndt Exp $";
static const char *IdHdr = ID_TABLE; static const char *IdHdr = ID_TABLE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -559,6 +559,8 @@ void FGTable::operator<<(istream& in_stream)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Put some error handling in here if trying to access out of range row, col.
FGTable& FGTable::operator<<(const double n) FGTable& FGTable::operator<<(const double n)
{ {
Data[rowCounter][colCounter] = n; Data[rowCounter][colCounter] = n;

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TABLE "$Id: FGTable.h,v 1.13 2011/04/05 20:20:21 andgi Exp $" #define ID_TABLE "$Id: FGTable.h,v 1.14 2011/06/13 11:46:08 jberndt 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.13 2011/04/05 20:20:21 andgi Exp $ @version $Id: FGTable.h,v 1.14 2011/06/13 11:46:08 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -284,12 +284,17 @@ public:
FGTable& operator<<(const double n); FGTable& operator<<(const double n);
FGTable& operator<<(const int n); FGTable& operator<<(const int n);
inline double GetElement(int r, int c) {return Data[r][c];} inline double GetElement(int r, int c) const {return Data[r][c];}
inline double GetElement(int r, int c, int t); // inline double GetElement(int r, int c, int t);
double operator()(unsigned int r, unsigned int c) const {return GetElement(r, c);}
// double operator()(unsigned int r, unsigned int c, unsigned int t) {GetElement(r, c, t);}
void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;} void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;}
void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;} void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;}
unsigned int GetNumRows() const {return nRows;}
void Print(void); void Print(void);
std::string GetName(void) const {return Name;} std::string GetName(void) const {return Name;}

View file

@ -52,7 +52,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.37 2011/03/11 13:02:26 jberndt Exp $"; static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.38 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_AERODYNAMICS; static const char *IdHdr = ID_AERODYNAMICS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -132,11 +132,11 @@ bool FGAerodynamics::InitModel(void)
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAerodynamics::Run(void) bool FGAerodynamics::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; // if paused don't execute if (Holding) return false; // if paused don't execute
unsigned int axis_ctr, ctr; unsigned int axis_ctr, ctr;
const double alpha=FDMExec->GetAuxiliary()->Getalpha(); const double alpha=FDMExec->GetAuxiliary()->Getalpha();

View file

@ -52,7 +52,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $" #define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.23 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -109,7 +109,7 @@ CLASS DOCUMENTATION
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.22 $ @version $Revision: 1.23 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -129,8 +129,13 @@ public:
bool InitModel(void); bool InitModel(void);
/** Runs the Aerodynamics model; called by the Executive /** Runs the Aerodynamics model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
/** Loads the Aerodynamics model. /** Loads the Aerodynamics model.
The Load function for this class expects the XML parser to The Load function for this class expects the XML parser to

View file

@ -67,7 +67,7 @@ DEFINITIONS
GLOBAL DATA GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.30 2010/11/29 12:33:57 jberndt Exp $"; static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.31 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_AIRCRAFT; static const char *IdHdr = ID_AIRCRAFT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -101,17 +101,15 @@ FGAircraft::~FGAircraft()
bool FGAircraft::InitModel(void) bool FGAircraft::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAircraft::Run(void) bool FGAircraft::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AIRCRAFT "$Id: FGAircraft.h,v 1.16 2010/11/18 12:38:06 jberndt Exp $" #define ID_AIRCRAFT "$Id: FGAircraft.h,v 1.17 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -90,7 +90,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Id: FGAircraft.h,v 1.16 2010/11/18 12:38:06 jberndt Exp $ @version $Id: FGAircraft.h,v 1.17 2011/05/20 03:18:36 jberndt Exp $
@see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling @see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate
School, January 1994 School, January 1994
@ -118,9 +118,14 @@ public:
~FGAircraft(); ~FGAircraft();
/** Runs the Aircraft model; called by the Executive /** Runs the Aircraft model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@see JSBSim.cpp documentation @see JSBSim.cpp documentation
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
bool InitModel(void); bool InitModel(void);

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.42 2011/02/18 12:44:16 jberndt Exp $"; static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.45 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_ATMOSPHERE; static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -84,8 +84,7 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
htab[7]=278385.0; //ft. htab[7]=278385.0; //ft.
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0; MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
// SetTurbType( ttCulp ); SetTurbType( ttMilspec );
SetTurbType( ttNone );
TurbGain = 1.0; TurbGain = 1.0;
TurbRate = 10.0; TurbRate = 10.0;
Rhythmicity = 0.1; Rhythmicity = 0.1;
@ -132,8 +131,6 @@ FGAtmosphere::~FGAtmosphere()
bool FGAtmosphere::InitModel(void) bool FGAtmosphere::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
UseInternal(); // this is the default UseInternal(); // this is the default
Calculate(h); Calculate(h);
@ -151,10 +148,10 @@ bool FGAtmosphere::InitModel(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAtmosphere::Run(void) bool FGAtmosphere::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();
@ -483,45 +480,7 @@ void FGAtmosphere::Turbulence(void)
break; break;
} }
case ttBerndt: { // This is very experimental and incomplete at the moment.
vDirectiondAccelDt(eX) = GaussianRandomNumber();
vDirectiondAccelDt(eY) = GaussianRandomNumber();
vDirectiondAccelDt(eZ) = GaussianRandomNumber();
/*
MagnitudedAccelDt = GaussianRandomNumber();
MagnitudeAccel += MagnitudedAccelDt * DeltaT;
Magnitude += MagnitudeAccel * DeltaT;
*/
Magnitude += GaussianRandomNumber() * DeltaT;
vDirectiondAccelDt.Normalize();
vDirectionAccel += TurbRate * vDirectiondAccelDt * DeltaT;
vDirectionAccel.Normalize();
vDirection += vDirectionAccel*DeltaT;
// Diminish z-vector within two wingspans of the ground
if (HOverBMAC < 2.0) vDirection(eZ) *= HOverBMAC / 2.0;
vDirection.Normalize();
vTurbulenceNED = TurbGain*Magnitude * vDirection;
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
vBodyTurbGrad = Tl2b * vTurbulenceGrad;
vTurbPQR(eP) = vBodyTurbGrad(eY) / wingspan;
if (HTailArm > 0)
vTurbPQR(eQ) = vBodyTurbGrad(eZ) / HTailArm;
else
vTurbPQR(eQ) = vBodyTurbGrad(eZ) / 10.0;
if (VTailArm > 0)
vTurbPQR(eR) = vBodyTurbGrad(eX) / VTailArm;
else
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
break;
}
case ttCulp: { case ttCulp: {
vTurbPQR(eP) = wind_from_clockwise; vTurbPQR(eP) = wind_from_clockwise;

View file

@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.24 2010/11/18 12:38:06 jberndt Exp $" #define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.26 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -64,7 +64,7 @@ CLASS DOCUMENTATION
/** Models the 1976 Standard Atmosphere. /** Models the 1976 Standard Atmosphere.
@author Tony Peden, Jon Berndt @author Tony Peden, Jon Berndt
@version $Id: FGAtmosphere.h,v 1.24 2010/11/18 12:38:06 jberndt Exp $ @version $Id: FGAtmosphere.h,v 1.26 2011/05/20 03:18:36 jberndt Exp $
@see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill, @see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0 1989, ISBN 0-07-001641-0
@ -132,102 +132,107 @@ public:
/// Destructor /// Destructor
~FGAtmosphere(); ~FGAtmosphere();
/** Runs the Atmosphere model; called by the Executive /** Runs the Atmosphere model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
bool InitModel(void); bool InitModel(void);
enum tType {ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin} turbType; enum tType {ttNone, ttStandard, ttCulp, ttMilspec, ttTustin} turbType;
/// Returns the temperature in degrees Rankine. /// Returns the temperature in degrees Rankine.
double GetTemperature(void) const {return *temperature;} virtual double GetTemperature(void) const {return *temperature;}
/** Returns the density in slugs/ft^3. /** Returns the density in slugs/ft^3.
<i>This function may <b>only</b> be used if Run() is called first.</i> */ <i>This function may <b>only</b> be used if Run() is called first.</i> */
double GetDensity(void) const {return *density;} virtual double GetDensity(void) const {return *density;}
/// Returns the pressure in psf. /// Returns the pressure in psf.
double GetPressure(void) const {return *pressure;} virtual double GetPressure(void) const {return *pressure;}
/// Returns the standard pressure at a specified altitude /// Returns the standard pressure at a specified altitude
double GetPressure(double altitude); virtual double GetPressure(double altitude);
/// Returns the standard temperature at a specified altitude /// Returns the standard temperature at a specified altitude
double GetTemperature(double altitude); virtual double GetTemperature(double altitude);
/// Returns the standard density at a specified altitude /// Returns the standard density at a specified altitude
double GetDensity(double altitude); virtual double GetDensity(double altitude);
/// Returns the speed of sound in ft/sec. /// Returns the speed of sound in ft/sec.
double GetSoundSpeed(void) const {return soundspeed;} virtual double GetSoundSpeed(void) const {return soundspeed;}
/// Returns the absolute viscosity. /// Returns the absolute viscosity.
double GetAbsoluteViscosity(void) const {return intViscosity;} virtual double GetAbsoluteViscosity(void) const {return intViscosity;}
/// Returns the kinematic viscosity. /// Returns the kinematic viscosity.
double GetKinematicViscosity(void) const {return intKinematicViscosity;} virtual double GetKinematicViscosity(void) const {return intKinematicViscosity;}
/// Returns the sea level temperature in degrees Rankine. /// Returns the sea level temperature in degrees Rankine.
double GetTemperatureSL(void) const { return SLtemperature; } virtual double GetTemperatureSL(void) const { return SLtemperature; }
/// Returns the sea level density in slugs/ft^3 /// Returns the sea level density in slugs/ft^3
double GetDensitySL(void) const { return SLdensity; } virtual double GetDensitySL(void) const { return SLdensity; }
/// Returns the sea level pressure in psf. /// Returns the sea level pressure in psf.
double GetPressureSL(void) const { return SLpressure; } virtual double GetPressureSL(void) const { return SLpressure; }
/// Returns the sea level speed of sound in ft/sec. /// Returns the sea level speed of sound in ft/sec.
double GetSoundSpeedSL(void) const { return SLsoundspeed; } virtual double GetSoundSpeedSL(void) const { return SLsoundspeed; }
/// Returns the ratio of at-altitude temperature over the sea level value. /// Returns the ratio of at-altitude temperature over the sea level value.
double GetTemperatureRatio(void) const { return (*temperature)*rSLtemperature; } virtual double GetTemperatureRatio(void) const { return (*temperature)*rSLtemperature; }
/// Returns the ratio of at-altitude density over the sea level value. /// Returns the ratio of at-altitude density over the sea level value.
double GetDensityRatio(void) const { return (*density)*rSLdensity; } virtual double GetDensityRatio(void) const { return (*density)*rSLdensity; }
/// Returns the ratio of at-altitude pressure over the sea level value. /// Returns the ratio of at-altitude pressure over the sea level value.
double GetPressureRatio(void) const { return (*pressure)*rSLpressure; } virtual double GetPressureRatio(void) const { return (*pressure)*rSLpressure; }
/// Returns the ratio of at-altitude sound speed over the sea level value. /// Returns the ratio of at-altitude sound speed over the sea level value.
double GetSoundSpeedRatio(void) const { return soundspeed*rSLsoundspeed; } virtual double GetSoundSpeedRatio(void) const { return soundspeed*rSLsoundspeed; }
/// Tells the simulator to use an externally calculated atmosphere model. /// Tells the simulator to use an externally calculated atmosphere model.
void UseExternal(void); virtual void UseExternal(void);
/// Tells the simulator to use the internal atmosphere model. /// Tells the simulator to use the internal atmosphere model.
void UseInternal(void); //this is the default virtual void UseInternal(void); //this is the default
/// Gets the boolean that tells if the external atmosphere model is being used. /// Gets the boolean that tells if the external atmosphere model is being used.
bool External(void) { return useExternal; } virtual bool External(void) { return useExternal; }
/// Provides the external atmosphere model with an interface to set the temperature. /// Provides the external atmosphere model with an interface to set the temperature.
void SetExTemperature(double t) { exTemperature=t; } virtual void SetExTemperature(double t) { exTemperature=t; }
/// Provides the external atmosphere model with an interface to set the density. /// Provides the external atmosphere model with an interface to set the density.
void SetExDensity(double d) { exDensity=d; } virtual void SetExDensity(double d) { exDensity=d; }
/// Provides the external atmosphere model with an interface to set the pressure. /// Provides the external atmosphere model with an interface to set the pressure.
void SetExPressure(double p) { exPressure=p; } virtual void SetExPressure(double p) { exPressure=p; }
/// Sets the temperature deviation at sea-level in degrees Fahrenheit /// Sets the temperature deviation at sea-level in degrees Fahrenheit
void SetSLTempDev(double d) { T_dev_sl = d; } virtual void SetSLTempDev(double d) { T_dev_sl = d; }
/// Gets the temperature deviation at sea-level in degrees Fahrenheit /// Gets the temperature deviation at sea-level in degrees Fahrenheit
double GetSLTempDev(void) const { return T_dev_sl; } virtual double GetSLTempDev(void) const { return T_dev_sl; }
/// Sets the current delta-T in degrees Fahrenheit /// Sets the current delta-T in degrees Fahrenheit
void SetDeltaT(double d) { delta_T = d; } virtual void SetDeltaT(double d) { delta_T = d; }
/// Gets the current delta-T in degrees Fahrenheit /// Gets the current delta-T in degrees Fahrenheit
double GetDeltaT(void) const { return delta_T; } virtual double GetDeltaT(void) const { return delta_T; }
/// Gets the at-altitude temperature deviation in degrees Fahrenheit /// Gets the at-altitude temperature deviation in degrees Fahrenheit
double GetTempDev(void) const { return T_dev; } virtual double GetTempDev(void) const { return T_dev; }
/// Gets the density altitude in feet /// Gets the density altitude in feet
double GetDensityAltitude(void) const { return density_altitude; } virtual double GetDensityAltitude(void) const { return density_altitude; }
// TOTAL WIND access functions (wind + gust + turbulence) // TOTAL WIND access functions (wind + gust + turbulence)
/// Retrieves the total wind components in NED frame. /// Retrieves the total wind components in NED frame.
const FGColumnVector3& GetTotalWindNED(void) const { return vTotalWindNED; } virtual const FGColumnVector3& GetTotalWindNED(void) const { return vTotalWindNED; }
/// Retrieves a total wind component in NED frame. /// Retrieves a total wind component in NED frame.
double GetTotalWindNED(int idx) const {return vTotalWindNED(idx);} virtual double GetTotalWindNED(int idx) const {return vTotalWindNED(idx);}
// WIND access functions // WIND access functions
/// Sets the wind components in NED frame. /// Sets the wind components in NED frame.
void SetWindNED(double wN, double wE, double wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;} virtual void SetWindNED(double wN, double wE, double wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;}
/// Sets a wind component in NED frame. /// Sets a wind component in NED frame.
void SetWindNED(int idx, double wind) { vWindNED(idx)=wind;} virtual void SetWindNED(int idx, double wind) { vWindNED(idx)=wind;}
/// Retrieves the wind components in NED frame. /// Retrieves the wind components in NED frame.
FGColumnVector3& GetWindNED(void) { return vWindNED; } virtual FGColumnVector3& GetWindNED(void) { return vWindNED; }
/// Retrieves a wind component in NED frame. /// Retrieves a wind component in NED frame.
double GetWindNED(int idx) const {return vWindNED(idx);} virtual double GetWindNED(int idx) const {return vWindNED(idx);}
/** Retrieves the direction that the wind is coming from. /** Retrieves the direction that the wind is coming from.
The direction is defined as north=0 and increases counterclockwise. The direction is defined as north=0 and increases counterclockwise.
The wind heading is returned in radians.*/ The wind heading is returned in radians.*/
double GetWindPsi(void) const { return psiw; } virtual double GetWindPsi(void) const { return psiw; }
/** Sets the direction that the wind is coming from. /** Sets the direction that the wind is coming from.
The direction is defined as north=0 and increases counterclockwise to 2*pi (radians). The The direction is defined as north=0 and increases counterclockwise to 2*pi (radians). The
@ -235,56 +240,56 @@ public:
sets the vWindNED vector components based on the supplied direction. The magnitude of sets the vWindNED vector components based on the supplied direction. The magnitude of
the wind set in the vector is preserved (assuming the vertical component is non-zero). the wind set in the vector is preserved (assuming the vertical component is non-zero).
@param dir wind direction in the horizontal plane, in radians.*/ @param dir wind direction in the horizontal plane, in radians.*/
void SetWindPsi(double dir); virtual void SetWindPsi(double dir);
void SetWindspeed(double speed); virtual void SetWindspeed(double speed);
double GetWindspeed(void) const; virtual double GetWindspeed(void) const;
// GUST access functions // GUST access functions
/// Sets a gust component in NED frame. /// Sets a gust component in NED frame.
void SetGustNED(int idx, double gust) { vGustNED(idx)=gust;} virtual void SetGustNED(int idx, double gust) { vGustNED(idx)=gust;}
/// Sets a turbulence component in NED frame. /// Sets a turbulence component in NED frame.
void SetTurbNED(int idx, double turb) { vTurbulenceNED(idx)=turb;} virtual void SetTurbNED(int idx, double turb) { vTurbulenceNED(idx)=turb;}
/// Sets the gust components in NED frame. /// Sets the gust components in NED frame.
void SetGustNED(double gN, double gE, double gD) { vGustNED(eNorth)=gN; vGustNED(eEast)=gE; vGustNED(eDown)=gD;} virtual void SetGustNED(double gN, double gE, double gD) { vGustNED(eNorth)=gN; vGustNED(eEast)=gE; vGustNED(eDown)=gD;}
/// Retrieves a gust component in NED frame. /// Retrieves a gust component in NED frame.
double GetGustNED(int idx) const {return vGustNED(idx);} virtual double GetGustNED(int idx) const {return vGustNED(idx);}
/// Retrieves a turbulence component in NED frame. /// Retrieves a turbulence component in NED frame.
double GetTurbNED(int idx) const {return vTurbulenceNED(idx);} virtual double GetTurbNED(int idx) const {return vTurbulenceNED(idx);}
/// Retrieves the gust components in NED frame. /// Retrieves the gust components in NED frame.
FGColumnVector3& GetGustNED(void) {return vGustNED;} virtual FGColumnVector3& GetGustNED(void) {return vGustNED;}
/** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin */ /** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin */
void SetTurbType(tType tt) {turbType = tt;} virtual void SetTurbType(tType tt) {turbType = tt;}
tType GetTurbType() const {return turbType;} virtual tType GetTurbType() const {return turbType;}
void SetTurbGain(double tg) {TurbGain = tg;} virtual void SetTurbGain(double tg) {TurbGain = tg;}
double GetTurbGain() const {return TurbGain;} virtual double GetTurbGain() const {return TurbGain;}
void SetTurbRate(double tr) {TurbRate = tr;} virtual void SetTurbRate(double tr) {TurbRate = tr;}
double GetTurbRate() const {return TurbRate;} virtual double GetTurbRate() const {return TurbRate;}
void SetRhythmicity(double r) {Rhythmicity=r;} virtual void SetRhythmicity(double r) {Rhythmicity=r;}
double GetRhythmicity() const {return Rhythmicity;} virtual double GetRhythmicity() const {return Rhythmicity;}
double GetTurbPQR(int idx) const {return vTurbPQR(idx);} virtual double GetTurbPQR(int idx) const {return vTurbPQR(idx);}
double GetTurbMagnitude(void) const {return Magnitude;} virtual double GetTurbMagnitude(void) const {return Magnitude;}
const FGColumnVector3& GetTurbDirection(void) const {return vDirection;} virtual const FGColumnVector3& GetTurbDirection(void) const {return vDirection;}
const FGColumnVector3& GetTurbPQR(void) const {return vTurbPQR;} virtual const FGColumnVector3& GetTurbPQR(void) const {return vTurbPQR;}
void SetWindspeed20ft(double ws) { windspeed_at_20ft = ws;} virtual void SetWindspeed20ft(double ws) { windspeed_at_20ft = ws;}
double GetWindspeed20ft() const { return windspeed_at_20ft;} virtual double GetWindspeed20ft() const { return windspeed_at_20ft;}
/// allowable range: 0-7, 3=light, 4=moderate, 6=severe turbulence /// allowable range: 0-7, 3=light, 4=moderate, 6=severe turbulence
void SetProbabilityOfExceedence( int idx) {probability_of_exceedence_index = idx;} virtual void SetProbabilityOfExceedence( int idx) {probability_of_exceedence_index = idx;}
int GetProbabilityOfExceedence() const { return probability_of_exceedence_index;} virtual int GetProbabilityOfExceedence() const { return probability_of_exceedence_index;}
protected: protected:
double rho; double rho;
@ -338,7 +343,7 @@ protected:
/// Get T, P and rho for a standard atmosphere at the given altitude. /// Get T, P and rho for a standard atmosphere at the given altitude.
void GetStdAtmosphere(double altitude); void GetStdAtmosphere(double altitude);
void Turbulence(void); void Turbulence(void);
void bind(void); virtual void bind(void);
void Debug(int from); void Debug(int from);
}; };

54
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.47 2011/03/29 11:49:27 jberndt Exp $"; static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.49 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_AUXILIARY; static const char *IdHdr = ID_AUXILIARY;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -70,13 +70,14 @@ CLASS IMPLEMENTATION
FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex) FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
{ {
Name = "FGAuxiliary"; Name = "FGAuxiliary";
vcas = veas = pt = tat = 0; pt = p = psl = 1.0;
psl = rhosl = 1; rho = rhosl = 1.0;
qbar = 0; tat = sat = 1.0;
qbarUW = 0.0; tatc = RankineToCelsius(tat);
qbarUV = 0.0;
Re = 0.0; vcas = veas = 0.0;
Mach = 0.0; qbar = qbarUW = qbarUV = 0.0;
Mach = MachU = 0.0;
alpha = beta = 0.0; alpha = beta = 0.0;
adot = bdot = 0.0; adot = bdot = 0.0;
gamma = Vt = Vground = 0.0; gamma = Vt = Vground = 0.0;
@ -84,13 +85,19 @@ FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
day_of_year = 1; day_of_year = 1;
seconds_in_day = 0.0; seconds_in_day = 0.0;
hoverbmac = hoverbcg = 0.0; hoverbmac = hoverbcg = 0.0;
tatc = RankineToCelsius(tat); Re = 0.0;
Nz = 0.0;
lon_relative_position = lat_relative_position = relative_position = 0.0;
vPilotAccel.InitMatrix(); vPilotAccel.InitMatrix();
vPilotAccelN.InitMatrix(); vPilotAccelN.InitMatrix();
vToEyePt.InitMatrix(); vToEyePt.InitMatrix();
vAeroUVW.InitMatrix();
vAeroPQR.InitMatrix(); vAeroPQR.InitMatrix();
vMachUVW.InitMatrix();
vEuler.InitMatrix();
vEulerRates.InitMatrix(); vEulerRates.InitMatrix();
vAircraftAccel.InitMatrix();
bind(); bind();
@ -101,14 +108,16 @@ FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
bool FGAuxiliary::InitModel(void) bool FGAuxiliary::InitModel(void)
{ {
if (!FGModel::InitModel()) return false; pt = p = FDMExec->GetAtmosphere()->GetPressure();
rho = FDMExec->GetAtmosphere()->GetDensity();
rhosl = FDMExec->GetAtmosphere()->GetDensitySL();
psl = FDMExec->GetAtmosphere()->GetPressureSL();
tat = sat = FDMExec->GetAtmosphere()->GetTemperature();
tatc = RankineToCelsius(tat);
vcas = veas = pt = tat = 0; vcas = veas = 0.0;
psl = rhosl = 1; qbar = qbarUW = qbarUV = 0.0;
qbar = 0; Mach = MachU = 0.0;
qbarUW = 0.0;
qbarUV = 0.0;
Mach = 0.0;
alpha = beta = 0.0; alpha = beta = 0.0;
adot = bdot = 0.0; adot = bdot = 0.0;
gamma = Vt = Vground = 0.0; gamma = Vt = Vground = 0.0;
@ -116,12 +125,19 @@ bool FGAuxiliary::InitModel(void)
day_of_year = 1; day_of_year = 1;
seconds_in_day = 0.0; seconds_in_day = 0.0;
hoverbmac = hoverbcg = 0.0; hoverbmac = hoverbcg = 0.0;
Re = 0.0;
Nz = 0.0;
lon_relative_position = lat_relative_position = relative_position = 0.0;
vPilotAccel.InitMatrix(); vPilotAccel.InitMatrix();
vPilotAccelN.InitMatrix(); vPilotAccelN.InitMatrix();
vToEyePt.InitMatrix(); vToEyePt.InitMatrix();
vAeroUVW.InitMatrix();
vAeroPQR.InitMatrix(); vAeroPQR.InitMatrix();
vMachUVW.InitMatrix();
vEuler.InitMatrix();
vEulerRates.InitMatrix(); vEulerRates.InitMatrix();
vAircraftAccel.InitMatrix();
return true; return true;
} }
@ -135,12 +151,12 @@ FGAuxiliary::~FGAuxiliary()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAuxiliary::Run() bool FGAuxiliary::Run(bool Holding)
{ {
double A,B,D; double A,B,D;
if (FGModel::Run()) return true; // return true if error returned from base class if (FGModel::Run(Holding)) return true; // return true if error returned from base class
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.19 2010/11/18 12:38:06 jberndt Exp $" #define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.20 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -99,7 +99,7 @@ CLASS DOCUMENTATION
The radius R is calculated below in the vector vToEyePt. The radius R is calculated below in the vector vToEyePt.
@author Tony Peden, Jon Berndt @author Tony Peden, Jon Berndt
@version $Id: FGAuxiliary.h,v 1.19 2010/11/18 12:38:06 jberndt Exp $ @version $Id: FGAuxiliary.h,v 1.20 2011/05/20 03:18:36 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -118,8 +118,13 @@ public:
bool InitModel(void); bool InitModel(void);
/** Runs the Auxiliary routines; called by the Executive /** Runs the Auxiliary routines; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
// GET functions // GET functions

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.16 2011/03/23 11:58:29 jberndt Exp $"; static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.17 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_BUOYANTFORCES; static const char *IdHdr = ID_BUOYANTFORCES;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -80,17 +80,15 @@ FGBuoyantForces::~FGBuoyantForces()
bool FGBuoyantForces::InitModel(void) bool FGBuoyantForces::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGBuoyantForces::Run(void) bool FGBuoyantForces::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; // if paused don't execute if (Holding) return false; // if paused don't execute
if (NoneDefined) return true; if (NoneDefined) return true;
RunPreFunctions(); RunPreFunctions();

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_BUOYANTFORCES "$Id: FGBuoyantForces.h,v 1.11 2010/05/07 20:38:34 andgi Exp $" #define ID_BUOYANTFORCES "$Id: FGBuoyantForces.h,v 1.12 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -96,7 +96,7 @@ CLASS DOCUMENTATION
See FGGasCell for the full configuration file format for gas cells. See FGGasCell for the full configuration file format for gas cells.
@author Anders Gidenstam, Jon S. Berndt @author Anders Gidenstam, Jon S. Berndt
@version $Id: FGBuoyantForces.h,v 1.11 2010/05/07 20:38:34 andgi Exp $ @version $Id: FGBuoyantForces.h,v 1.12 2011/05/20 03:18:36 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -116,8 +116,13 @@ public:
bool InitModel(void); bool InitModel(void);
/** Runs the Buoyant forces model; called by the Executive /** Runs the Buoyant forces model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
/** Loads the Buoyant forces model. /** Loads the Buoyant forces model.
The Load function for this class expects the XML parser to The Load function for this class expects the XML parser to

10
src/FDM/JSBSim/models/FGExternalReactions.cpp Normal file → Executable file
View file

@ -53,7 +53,7 @@ DEFINITIONS
GLOBAL DATA GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.9 2010/09/07 00:40:03 jberndt Exp $"; static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.10 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_EXTERNALREACTIONS; static const char *IdHdr = ID_EXTERNALREACTIONS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -104,17 +104,15 @@ FGExternalReactions::~FGExternalReactions()
bool FGExternalReactions::InitModel(void) bool FGExternalReactions::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGExternalReactions::Run() bool FGExternalReactions::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; // if paused don't execute if (Holding) return false; // if paused don't execute
if (NoneDefined) return true; if (NoneDefined) return true;
RunPreFunctions(); RunPreFunctions();

12
src/FDM/JSBSim/models/FGExternalReactions.h Normal file → Executable file
View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_EXTERNALREACTIONS "$Id: FGExternalReactions.h,v 1.10 2010/11/18 12:38:06 jberndt Exp $" #define ID_EXTERNALREACTIONS "$Id: FGExternalReactions.h,v 1.11 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -132,9 +132,13 @@ public:
bool InitModel(void); bool InitModel(void);
/** Sum all the constituent forces for this cycle. /** Sum all the constituent forces for this cycle.
@return true always. Can pass in a value indicating if the executive is directing the simulation to Hold.
*/ @param Holding if true, the executive has been directed to hold the sim from
bool Run(void); advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return true always. */
bool Run(bool Holding);
/** Loads the external forces from the XML configuration file. /** Loads the external forces from the XML configuration file.
If the external_reactions section is encountered in the vehicle configuration If the external_reactions section is encountered in the vehicle configuration

View file

@ -63,7 +63,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.73 2011/04/05 20:20:21 andgi Exp $"; static const char *IdSrc = "$Id: FGFCS.cpp,v 1.74 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_FCS; static const char *IdHdr = ID_FCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -123,8 +123,6 @@ bool FGFCS::InitModel(void)
{ {
unsigned int i; unsigned int i;
if (!FGModel::InitModel()) return false;
for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = 0.0; for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = 0.0;
for (i=0; i<MixturePos.size(); i++) MixturePos[i] = 0.0; for (i=0; i<MixturePos.size(); i++) MixturePos[i] = 0.0;
for (i=0; i<ThrottleCmd.size(); i++) ThrottleCmd[i] = 0.0; for (i=0; i<ThrottleCmd.size(); i++) ThrottleCmd[i] = 0.0;
@ -191,12 +189,12 @@ bool FGFCS::InitModel(void)
// actually present in the flight_control or autopilot section will override // actually present in the flight_control or autopilot section will override
// these simple assignments. // these simple assignments.
bool FGFCS::Run(void) bool FGFCS::Run(bool Holding)
{ {
unsigned int i; unsigned int i;
if (FGModel::Run()) return true; // fast exit if nothing to do if (FGModel::Run(Holding)) return true; // fast exit if nothing to do
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCS "$Id: FGFCS.h,v 1.35 2011/04/05 20:20:21 andgi Exp $" #define ID_FCS "$Id: FGFCS.h,v 1.36 2011/05/20 03:18:36 jberndt 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.35 $ @version $Revision: 1.36 $
@see FGActuator @see FGActuator
@see FGDeadBand @see FGDeadBand
@see FGFCSFunction @see FGFCSFunction
@ -200,8 +200,13 @@ public:
bool InitModel(void); bool InitModel(void);
/** Runs the Flight Controls model; called by the Executive /** Runs the Flight Controls model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
/// @name Pilot input command retrieval /// @name Pilot input command retrieval
//@{ //@{

View file

@ -46,7 +46,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.31 2010/11/18 12:38:06 jberndt Exp $"; static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.32 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_GROUNDREACTIONS; static const char *IdHdr = ID_GROUNDREACTIONS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -116,17 +116,15 @@ FGGroundReactions::~FGGroundReactions(void)
bool FGGroundReactions::InitModel(void) bool FGGroundReactions::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGGroundReactions::Run(void) bool FGGroundReactions::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();

View file

@ -45,7 +45,7 @@ INCLUDES
#include "math/FGColumnVector3.h" #include "math/FGColumnVector3.h"
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.19 2010/11/18 12:38:06 jberndt Exp $" #define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.20 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -98,7 +98,14 @@ public:
~FGGroundReactions(void); ~FGGroundReactions(void);
bool InitModel(void); bool InitModel(void);
bool Run(void); /** Runs the Ground Reactions model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */
bool Run(bool Holding);
bool Load(Element* el); bool Load(Element* el);
const FGColumnVector3& GetForces(void) const {return vForces;} const FGColumnVector3& GetForces(void) const {return vForces;}
double GetForces(int idx) const {return vForces(idx);} double GetForces(int idx) const {return vForces(idx);}

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGInertial.cpp,v 1.20 2010/11/18 12:38:06 jberndt Exp $"; static const char *IdSrc = "$Id: FGInertial.cpp,v 1.21 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_INERTIAL; static const char *IdHdr = ID_INERTIAL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -98,8 +98,6 @@ FGInertial::~FGInertial(void)
bool FGInertial::InitModel(void) bool FGInertial::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
earthPosAngle = 0.0; earthPosAngle = 0.0;
return true; return true;
@ -107,11 +105,11 @@ bool FGInertial::InitModel(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGInertial::Run(void) bool FGInertial::Run(bool Holding)
{ {
// Fast return if we have nothing to do ... // Fast return if we have nothing to do ...
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INERTIAL "$Id: FGInertial.h,v 1.15 2010/01/27 04:01:09 jberndt Exp $" #define ID_INERTIAL "$Id: FGInertial.h,v 1.16 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -75,7 +75,14 @@ public:
bool InitModel(void); bool InitModel(void);
bool Run(void); /** Runs the Inertial model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */
bool Run(bool Holding);
double SLgravity(void) const {return gAccelReference;} double SLgravity(void) const {return gAccelReference;}
double gravity(void) const {return gAccel;} double gravity(void) const {return gAccel;}
double omega(void) const {return RotationRate;} double omega(void) const {return RotationRate;}

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGInput.cpp,v 1.20 2010/11/18 12:38:06 jberndt Exp $"; static const char *IdSrc = "$Id: FGInput.cpp,v 1.21 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_INPUT; static const char *IdHdr = ID_INPUT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -83,8 +83,6 @@ FGInput::~FGInput()
bool FGInput::InitModel(void) bool FGInput::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
return true; return true;
} }
@ -93,14 +91,14 @@ bool FGInput::InitModel(void)
// This function handles accepting input commands from the socket interface. // This function handles accepting input commands from the socket interface.
// //
bool FGInput::Run(void) bool FGInput::Run(bool Holding)
{ {
string line, token; string line, token;
size_t start=0, string_start=0, string_end=0; size_t start=0, string_start=0, string_end=0;
double value=0; double value=0;
FGPropertyManager* node=0; FGPropertyManager* node=0;
if (FGModel::Run()) return true; // fast exit if nothing to do if (FGModel::Run(Holding)) return true; // fast exit if nothing to do
if (port == 0) return false; // Do nothing here if port not defined if (port == 0) return false; // Do nothing here if port not defined
// return false if no error // return false if no error
// This model DOES execute if "Exec->Holding" // This model DOES execute if "Exec->Holding"
@ -157,7 +155,7 @@ bool FGInput::Run(void)
break; break;
} }
if (node == 0) { if (node == 0) {
if (FDMExec->Holding()) { // if holding can query property list if (Holding) { // if holding can query property list
string query = FDMExec->QueryPropertyCatalog(argument); string query = FDMExec->QueryPropertyCatalog(argument);
socket->Reply(query); socket->Reply(query);
} else { } else {

11
src/FDM/JSBSim/models/FGInput.h Normal file → Executable file
View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INPUT "$Id: FGInput.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $" #define ID_INPUT "$Id: FGInput.h,v 1.9 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -76,7 +76,14 @@ public:
~FGInput(); ~FGInput();
bool InitModel(void); bool InitModel(void);
bool Run(void); /** Runs the Input model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */
bool Run(bool Holding);
inline void Enable(void) { enabled = true; } inline void Enable(void) { enabled = true; }
inline void Disable(void) { enabled = false; } inline void Disable(void) { enabled = false; }

View file

@ -51,7 +51,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.34 2010/11/18 12:38:06 jberndt Exp $"; static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.35 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_MASSBALANCE; static const char *IdHdr = ID_MASSBALANCE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -92,8 +92,6 @@ FGMassBalance::~FGMassBalance()
bool FGMassBalance::InitModel(void) bool FGMassBalance::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
vLastXYZcg.InitMatrix(0.0); vLastXYZcg.InitMatrix(0.0);
vDeltaXYZcg.InitMatrix(0.0); vDeltaXYZcg.InitMatrix(0.0);
@ -164,13 +162,13 @@ bool FGMassBalance::Load(Element* el)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGMassBalance::Run(void) bool FGMassBalance::Run(bool Holding)
{ {
double denom, k1, k2, k3, k4, k5, k6; double denom, k1, k2, k3, k4, k5, k6;
double Ixx, Iyy, Izz, Ixy, Ixz, Iyz; double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MASSBALANCE "$Id: FGMassBalance.h,v 1.22 2010/11/18 12:38:06 jberndt Exp $" #define ID_MASSBALANCE "$Id: FGMassBalance.h,v 1.23 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONSS FORWARD DECLARATIONSS
@ -116,7 +116,14 @@ public:
bool Load(Element* el); bool Load(Element* el);
bool InitModel(void); bool InitModel(void);
bool Run(void); /** Runs the Mass Balance model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */
bool Run(bool Holding);
double GetMass(void) const {return Mass;} double GetMass(void) const {return Mass;}
double GetWeight(void) const {return Weight;} double GetWeight(void) const {return Weight;}

View file

@ -38,26 +38,15 @@ HISTORY
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <iostream>
#include "FGModel.h" #include "FGModel.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGAtmosphere.h"
#include "FGFCS.h"
#include "FGPropulsion.h"
#include "FGMassBalance.h"
#include "FGAerodynamics.h"
#include "FGInertial.h"
#include "FGGroundReactions.h"
#include "FGExternalReactions.h"
#include "FGAircraft.h"
#include "FGPropagate.h"
#include "FGAuxiliary.h"
#include <iostream>
using namespace std; using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGModel.cpp,v 1.17 2011/02/16 12:30:53 jberndt Exp $"; static const char *IdSrc = "$Id: FGModel.cpp,v 1.19 2011/05/22 12:44:30 jberndt Exp $";
static const char *IdHdr = ID_MODEL; static const char *IdHdr = ID_MODEL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -99,7 +88,7 @@ bool FGModel::InitModel(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGModel::Run() bool FGModel::Run(bool Holding)
{ {
if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MODEL "$Id: FGModel.h,v 1.18 2010/11/18 12:38:06 jberndt Exp $" #define ID_MODEL "$Id: FGModel.h,v 1.19 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -83,10 +83,17 @@ public:
std::string Name; std::string Name;
/** Runs the model; called by the Executive /** Runs the model; called by the Executive.
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given. The Holding flag is not used in the base
FGModel class.
@see JSBSim.cpp documentation @see JSBSim.cpp documentation
@return false if no error */ @return false if no error */
virtual bool Run(void); virtual bool Run(bool Holding);
virtual bool InitModel(void); virtual bool InitModel(void);
virtual void SetRate(int tt) {rate = tt;} virtual void SetRate(int tt) {rate = tt;}
virtual int GetRate(void) {return rate;} virtual int GetRate(void) {return rate;}

View file

@ -74,7 +74,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGOutput.cpp,v 1.54 2011/03/11 13:02:26 jberndt Exp $"; static const char *IdSrc = "$Id: FGOutput.cpp,v 1.55 2011/05/20 03:18:36 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)
@ -157,8 +157,6 @@ FGOutput::~FGOutput()
bool FGOutput::InitModel(void) bool FGOutput::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
if (Filename.size() > 0 && StartNewFile) { if (Filename.size() > 0 && StartNewFile) {
ostringstream buf; ostringstream buf;
string::size_type dot = BaseFilename.find_last_of('.'); string::size_type dot = BaseFilename.find_last_of('.');
@ -178,11 +176,11 @@ bool FGOutput::InitModel(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGOutput::Run(void) bool FGOutput::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (enabled && !FDMExec->IntegrationSuspended() && !FDMExec->Holding()) { if (enabled && !FDMExec->IntegrationSuspended() && !Holding) {
RunPreFunctions(); RunPreFunctions();
Print(); Print();
RunPostFunctions(); RunPostFunctions();

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_OUTPUT "$Id: FGOutput.h,v 1.22 2011/03/11 13:02:26 jberndt Exp $" #define ID_OUTPUT "$Id: FGOutput.h,v 1.23 2011/05/20 03:18:36 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.22 2011/03/11 13:02:26 jberndt Exp $ @version $Id: FGOutput.h,v 1.23 2011/05/20 03:18:36 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -138,7 +138,14 @@ public:
~FGOutput(); ~FGOutput();
bool InitModel(void); bool InitModel(void);
bool Run(void); /** Runs the Output model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */
bool Run(bool Holding);
void Print(void); void Print(void);
void DelimitedOutput(const std::string&); void DelimitedOutput(const std::string&);

View file

@ -71,7 +71,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.86 2011/04/17 11:27:14 bcoconni Exp $"; static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.88 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_PROPAGATE; static const char *IdHdr = ID_PROPAGATE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -121,8 +121,6 @@ FGPropagate::~FGPropagate(void)
bool FGPropagate::InitModel(void) bool FGPropagate::InitModel(void)
{ {
if (!FGModel::InitModel()) return false;
// For initialization ONLY: // For initialization ONLY:
SeaLevelRadius = LocalTerrainRadius = FDMExec->GetInertial()->GetRefRadius(); SeaLevelRadius = LocalTerrainRadius = FDMExec->GetInertial()->GetRefRadius();
@ -140,10 +138,10 @@ bool FGPropagate::InitModel(void)
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0)); VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0)); VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
integrator_rotational_rate = eAdamsBashforth2; integrator_rotational_rate = eRectEuler;
integrator_translational_rate = eTrapezoidal; integrator_translational_rate = eAdamsBashforth2;
integrator_rotational_position = eAdamsBashforth2; integrator_rotational_position = eRectEuler;
integrator_translational_position = eTrapezoidal; integrator_translational_position = eAdamsBashforth3;
return true; return true;
} }
@ -226,10 +224,10 @@ Inertial.
*/ */
bool FGPropagate::Run(void) bool FGPropagate::Run(bool Holding)
{ {
if (FGModel::Run()) return true; // Fast return if we have nothing to do ... if (FGModel::Run(Holding)) return true; // Fast return if we have nothing to do ...
if (FDMExec->Holding()) return false; if (Holding) return false;
double dt = FDMExec->GetDeltaT()*rate; // The 'stepsize' double dt = FDMExec->GetDeltaT()*rate; // The 'stepsize'

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.58 2011/04/03 19:24:58 jberndt Exp $" #define ID_PROPAGATE "$Id: FGPropagate.h,v 1.59 2011/05/20 03:18:36 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.58 2011/04/03 19:24:58 jberndt Exp $ @version $Id: FGPropagate.h,v 1.59 2011/05/20 03:18:36 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -177,9 +177,14 @@ public:
other FGModel objects (and others). */ other FGModel objects (and others). */
bool InitModel(void); bool InitModel(void);
/** Runs the Propagate model; called by the Executive. /** Runs the state propagation model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
const FGQuaternion& GetQuaterniondot(void) const {return vQtrndot;} const FGQuaternion& GetQuaterniondot(void) const {return vQtrndot;}

View file

@ -65,7 +65,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.45 2011/02/13 00:42:45 jberndt Exp $"; static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.46 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_PROPULSION; static const char *IdHdr = ID_PROPULSION;
extern short debug_lvl; extern short debug_lvl;
@ -117,8 +117,6 @@ bool FGPropulsion::InitModel(void)
{ {
bool result = true; bool result = true;
if (!FGModel::InitModel()) return false;
for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC(); for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
for (unsigned int i=0; i<numEngines; i++) { for (unsigned int i=0; i<numEngines; i++) {
@ -151,12 +149,12 @@ bool FGPropulsion::InitModel(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropulsion::Run(void) bool FGPropulsion::Run(bool Holding)
{ {
unsigned int i; unsigned int i;
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();
@ -199,7 +197,7 @@ bool FGPropulsion::GetSteadyState(void)
vForces.InitMatrix(); vForces.InitMatrix();
vMoments.InitMatrix(); vMoments.InitMatrix();
if (!FGModel::Run()) { if (!FGModel::Run(false)) {
FDMExec->SetTrimStatus(true); FDMExec->SetTrimStatus(true);
for (unsigned int i=0; i<numEngines; i++) { for (unsigned int i=0; i<numEngines; i++) {

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.26 2010/11/18 12:38:06 jberndt Exp $" #define ID_PROPULSION "$Id: FGPropulsion.h,v 1.27 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -91,7 +91,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Id: FGPropulsion.h,v 1.26 2010/11/18 12:38:06 jberndt Exp $ @version $Id: FGPropulsion.h,v 1.27 2011/05/20 03:18:36 jberndt Exp $
@see @see
FGEngine FGEngine
FGTank FGTank
@ -112,9 +112,13 @@ public:
/** Executes the propulsion model. /** Executes the propulsion model.
The initial plan for the FGPropulsion class calls for Run() to be executed, The initial plan for the FGPropulsion class calls for Run() to be executed,
calculating the power available from the engine. calculating the power available from the engine.
Can pass in a value indicating if the executive is directing the simulation to Hold.
[Note: Should we be checking the Starved flag here?] */ @param Holding if true, the executive has been directed to hold the sim from
bool Run(void); advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */
bool Run(bool Holding);
bool InitModel(void); bool InitModel(void);

166
src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp Normal file → Executable file
View file

@ -66,7 +66,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGMSIS.cpp,v 1.14 2010/11/18 12:38:06 jberndt Exp $"; static const char *IdSrc = "$Id: FGMSIS.cpp,v 1.17 2011/05/20 03:18:36 jberndt Exp $";
static const char *IdHdr = ID_MSIS; static const char *IdHdr = ID_MSIS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -95,7 +95,19 @@ CLASS IMPLEMENTATION
MSIS::MSIS(FGFDMExec* fdmex) : FGAtmosphere(fdmex) MSIS::MSIS(FGFDMExec* fdmex) : FGAtmosphere(fdmex)
{ {
Name = "MSIS"; Name = "MSIS";
bind();
for (int i=0; i<9; i++) output.d[i] = 0.0;
for (int i=0; i<2; i++) output.t[i] = 0.0;
dm04 = dm16 = dm28 = dm32 = dm40 = dm01 = dm14 = dfa = 0.0;
for (int i=0; i<5; i++) meso_tn1[i] = 0.0;
for (int i=0; i<4; i++) meso_tn2[i] = 0.0;
for (int i=0; i<5; i++) meso_tn3[i] = 0.0;
for (int i=0; i<2; i++) meso_tgn1[i] = 0.0;
for (int i=0; i<2; i++) meso_tgn2[i] = 0.0;
for (int i=0; i<2; i++) meso_tgn3[i] = 0.0;
Debug(0); Debug(0);
} }
@ -110,12 +122,16 @@ MSIS::~MSIS()
bool MSIS::InitModel(void) bool MSIS::InitModel(void)
{ {
FGModel::InitModel();
unsigned int i; unsigned int i;
flags.switches[0] = 0; flags.switches[0] = 0;
for (i=1;i<24;i++) flags.switches[i] = 1; flags.sw[0] = 0;
flags.swc[0] = 0;
for (i=1;i<24;i++) {
flags.switches[i] = 1;
flags.sw[i] = 1;
flags.swc[i] = 1;
}
for (i=0;i<7;i++) aph.a[i] = 100.0; for (i=0;i<7;i++) aph.a[i] = 100.0;
@ -124,6 +140,8 @@ bool MSIS::InitModel(void)
input.f107 = 150.0; input.f107 = 150.0;
input.ap = 4.0; input.ap = 4.0;
UseInternal();
SLtemperature = intTemperature = 518.0; SLtemperature = intTemperature = 518.0;
SLpressure = intPressure = 2116.7; SLpressure = intPressure = 2116.7;
SLdensity = intDensity = 0.002378; SLdensity = intDensity = 0.002378;
@ -132,24 +150,21 @@ bool MSIS::InitModel(void)
rSLpressure = 1.0/intPressure; rSLpressure = 1.0/intPressure;
rSLdensity = 1.0/intDensity; rSLdensity = 1.0/intDensity;
rSLsoundspeed = 1.0/SLsoundspeed; rSLsoundspeed = 1.0/SLsoundspeed;
temperature = &intTemperature;
pressure = &intPressure;
density = &intDensity;
UseInternal();
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool MSIS::Run(void) bool MSIS::Run(bool Holding)
{ {
if (FGModel::Run()) return true; if (FGModel::Run(Holding)) return true;
if (FDMExec->Holding()) return false; if (Holding) return false;
RunPreFunctions(); RunPreFunctions();
h = FDMExec->GetPropagate()->GetAltitudeASL();
//do temp, pressure, and density first //do temp, pressure, and density first
if (!useExternal) { if (!useExternal) {
// get sea-level values // get sea-level values
@ -170,7 +185,7 @@ bool MSIS::Run(void)
// get at-altitude values // get at-altitude values
Calculate(FDMExec->GetAuxiliary()->GetDayOfYear(), Calculate(FDMExec->GetAuxiliary()->GetDayOfYear(),
FDMExec->GetAuxiliary()->GetSecondsInDay(), FDMExec->GetAuxiliary()->GetSecondsInDay(),
FDMExec->GetPropagate()->GetAltitudeASL(), h,
FDMExec->GetPropagate()->GetLocation().GetLatitudeDeg(), FDMExec->GetPropagate()->GetLocation().GetLatitudeDeg(),
FDMExec->GetPropagate()->GetLocation().GetLongitudeDeg()); FDMExec->GetPropagate()->GetLocation().GetLongitudeDeg());
intTemperature = output.t[1] * 1.8; intTemperature = output.t[1] * 1.8;
@ -357,7 +372,7 @@ void MSIS::splini (double *xa, double *ya, double *y2a, int n, double x, double
double yi=0; double yi=0;
int klo=0; int klo=0;
int khi=1; int khi=1;
double xx, h, a, b, a2, b2; double xx=0.0, h=0.0, a=0.0, b=0.0, a2=0.0, b2=0.0;
while ((x>xa[klo]) && (khi<n)) { while ((x>xa[klo]) && (khi<n)) {
xx=x; xx=x;
if (khi<(n-1)) { if (khi<(n-1)) {
@ -472,15 +487,17 @@ double MSIS::densm(double alt, double d0, double xm, double *tz, int mn3,
double *tn2, double *tgn2) double *tn2, double *tgn2)
{ {
/* Calculate Temperature and Density Profiles for lower atmos. */ /* Calculate Temperature and Density Profiles for lower atmos. */
double xs[10], ys[10], y2out[10]; double xs[10] = {0,0,0,0,0,0,0,0,0,0};
double ys[10] = {0,0,0,0,0,0,0,0,0,0};
double y2out[10] = {0,0,0,0,0,0,0,0,0,0};
double rgas = 831.4; double rgas = 831.4;
double z, z1, z2, t1, t2, zg, zgdif; double z=0, z1=0, z2=0, t1=0, t2=0, zg=0, zgdif=0;
double yd1, yd2; double yd1=0, yd2=0;
double x, y, yi; double x=0, y=0, yi=0;
double expl, gamm, glb; double expl=0, gamm=0, glb=0;
double densm_tmp; double densm_tmp=0;
int mn; int mn=0;
int k; int k=0;
densm_tmp=d0; densm_tmp=d0;
if (alt>zn2[0]) { if (alt>zn2[0]) {
if (xm==0.0) if (xm==0.0)
@ -593,19 +610,19 @@ double MSIS::densu(double alt, double dlb, double tinf, double tlb, double xm,
/* Calculate Temperature and Density Profiles for MSIS models /* Calculate Temperature and Density Profiles for MSIS models
* New lower thermo polynomial * New lower thermo polynomial
*/ */
double yd2, yd1, x=0.0, y=0.0; double yd2=0.0, yd1=0.0, x=0.0, y=0.0;
double rgas=831.4; double rgas=831.4;
double densu_temp=1.0; double densu_temp=1.0;
double za, z, zg2, tt, ta=0.0; double za=0.0, z=0.0, zg2=0.0, tt=0.0, ta=0.0;
double dta, z1=0.0, z2, t1=0.0, t2, zg, zgdif=0.0; double dta=0.0, z1=0.0, z2=0.0, t1=0.0, t2=0.0, zg=0.0, zgdif=0.0;
int mn=0; int mn=0;
int k; int k=0;
double glb; double glb=0.0;
double expl; double expl=0.0;
double yi; double yi=0.0;
double densa; double densa=0.0;
double gamma, gamm; double gamma=0.0, gamm=0.0;
double xs[5], ys[5], y2out[5]; double xs[5]={0.0,0.0,0.0,0.0,0.0}, ys[5]={0.0,0.0,0.0,0.0,0.0}, y2out[5]={0.0,0.0,0.0,0.0,0.0};
/* joining altitudes of Bates and spline */ /* joining altitudes of Bates and spline */
za=zn1[0]; za=zn1[0];
if (alt>za) if (alt>za)
@ -739,7 +756,7 @@ double MSIS::globe7(double *p, struct nrlmsise_input *input,
double hr = 0.2618; double hr = 0.2618;
double cd32, cd18, cd14, cd39; double cd32, cd18, cd14, cd39;
double p32, p18, p14, p39; double p32, p18, p14, p39;
double df, dfa; double df;
double f1, f2; double f1, f2;
double tinf; double tinf;
struct ap_array *ap; struct ap_array *ap;
@ -957,11 +974,11 @@ double MSIS::glob7s(double *p, struct nrlmsise_input *input,
/* VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99 /* VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99
*/ */
double pset=2.0; double pset=2.0;
double t[14]; double t[14] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,};
double tt; double tt=0.0;
double cd32, cd18, cd14, cd39; double cd32=0.0, cd18=0.0, cd14=0.0, cd39=0.0;
double p32, p18, p14, p39; double p32=0.0, p18=0.0, p14=0.0, p39=0.0;
int i,j; int i=0,j=0;
double dr=1.72142E-2; double dr=1.72142E-2;
double dgtr=1.74533E-2; double dgtr=1.74533E-2;
/* confirm parameter set */ /* confirm parameter set */
@ -1053,23 +1070,26 @@ double MSIS::glob7s(double *p, struct nrlmsise_input *input,
void MSIS::gtd7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, void MSIS::gtd7(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
struct nrlmsise_output *output) struct nrlmsise_output *output)
{ {
double xlat; double xlat=0.0;
double xmm; double xmm=0.0;
int mn3 = 5; int mn3 = 5;
double zn3[5]={32.5,20.0,15.0,10.0,0.0}; double zn3[5]={32.5,20.0,15.0,10.0,0.0};
int mn2 = 4; int mn2 = 4;
double zn2[4]={72.5,55.0,45.0,32.5}; double zn2[4]={72.5,55.0,45.0,32.5};
double altt; double altt=0.0;
double zmix=62.5; double zmix=62.5;
double tmp; double tmp=0.0;
double dm28m; double dm28m=0.0;
double tz; double tz=0.0;
double dmc; double dmc=0.0;
double dmr; double dmr=0.0;
double dz28; double dz28=0.0;
struct nrlmsise_output soutput; struct nrlmsise_output soutput;
int i; int i;
for (int i=0; i<9; i++) soutput.d[i] = 0.0;
for (int i=0; i<2; i++) soutput.t[i] = 0.0;
tselec(flags); tselec(flags);
/* Latitude variation of gravity (none for sw[2]=0) */ /* Latitude variation of gravity (none for sw[2]=0) */
@ -1186,6 +1206,8 @@ void MSIS::gtd7d(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] + output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] +
28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4] 28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4]
+ output->d[6] + 14.0 * output->d[7] + 16.0 * output->d[8]); + output->d[6] + 14.0 * output->d[7] + 16.0 * output->d[8]);
if (flags->sw[0])
output->d[5]=output->d[5]/1000;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -1277,36 +1299,36 @@ void MSIS::gts7(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
* See GTD7 for more extensive comments * See GTD7 for more extensive comments
* alt > 72.5 km! * alt > 72.5 km!
*/ */
double za; double za=0.0;
int i, j; int i, j;
double ddum, z; double ddum=0.0, z=0.0;
double zn1[5] = {120.0, 110.0, 100.0, 90.0, 72.5}; double zn1[5] = {120.0, 110.0, 100.0, 90.0, 72.5};
double tinf; double tinf=0.0;
int mn1 = 5; int mn1 = 5;
double g0; double g0=0.0;
double tlb; double tlb=0.0;
double s, z0, t0, tr12; double s=0.0, z0=0.0, t0=0.0, tr12=0.0;
double db01, db04, db14, db16, db28, db32, db40, db48; double db01=0.0, db04=0.0, db14=0.0, db16=0.0, db28=0.0, db32=0.0, db40=0.0, db48=0.0;
double zh28, zh04, zh16, zh32, zh40, zh01, zh14; double zh28=0.0, zh04=0.0, zh16=0.0, zh32=0.0, zh40=0.0, zh01=0.0, zh14=0.0;
double zhm28, zhm04, zhm16, zhm32, zhm40, zhm01, zhm14; double zhm28=0.0, zhm04=0.0, zhm16=0.0, zhm32=0.0, zhm40=0.0, zhm01=0.0, zhm14=0.0;
double xmd; double xmd=0.0;
double b28, b04, b16, b32, b40, b01, b14; double b28=0.0, b04=0.0, b16=0.0, b32=0.0, b40=0.0, b01=0.0, b14=0.0;
double tz; double tz=0.0;
double g28, g4, g16, g32, g40, g1, g14; double g28=0.0, g4=0.0, g16=0.0, g32=0.0, g40=0.0, g1=0.0, g14=0.0;
double zhf, xmm; double zhf=0.0, xmm=0.0;
double zc04, zc16, zc32, zc40, zc01, zc14; double zc04=0.0, zc16=0.0, zc32=0.0, zc40=0.0, zc01=0.0, zc14=0.0;
double hc04, hc16, hc32, hc40, hc01, hc14; double hc04=0.0, hc16=0.0, hc32=0.0, hc40=0.0, hc01=0.0, hc14=0.0;
double hcc16, hcc32, hcc01, hcc14; double hcc16=0.0, hcc32=0.0, hcc01=0.0, hcc14=0.0;
double zcc16, zcc32, zcc01, zcc14; double zcc16=0.0, zcc32=0.0, zcc01=0.0, zcc14=0.0;
double rc16, rc32, rc01, rc14; double rc16=0.0, rc32=0.0, rc01=0.0, rc14=0.0;
double rl; double rl=0.0;
double g16h, db16h, tho, zsht, zmho, zsho; double g16h=0.0, db16h=0.0, tho=0.0, zsht=0.0, zmho=0.0, zsho=0.0;
double dgtr=1.74533E-2; double dgtr=1.74533E-2;
double dr=1.72142E-2; double dr=1.72142E-2;
double alpha[9]={-0.38, 0.0, 0.0, 0.0, 0.17, 0.0, -0.38, 0.0, 0.0}; double alpha[9]={-0.38, 0.0, 0.0, 0.0, 0.17, 0.0, -0.38, 0.0, 0.0};
double altl[8]={200.0, 300.0, 160.0, 250.0, 240.0, 450.0, 320.0, 450.0}; double altl[8]={200.0, 300.0, 160.0, 250.0, 240.0, 450.0, 320.0, 450.0};
double dd; double dd=0.0;
double hc216, hcc232; double hc216=0.0, hcc232=0.0;
za = pdl[1][15]; za = pdl[1][15];
zn1[0] = za; zn1[0] = za;
for (j=0;j<9;j++) for (j=0;j<9;j++)
@ -1480,7 +1502,7 @@ void MSIS::gts7(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
/**** AR DENSITY ****/ /**** AR DENSITY ****/
/* Density variation factor at Zlb */ /* Density variation factor at Zlb */
g40= flags->sw[20]*globe7(pd[5],input,flags); g40= flags->sw[21]*globe7(pd[5],input,flags);
/* Diffusive density at Zlb */ /* Diffusive density at Zlb */
db40 = pdm[4][0]*exp(g40)*pd[5][0]; db40 = pdm[4][0]*exp(g40)*pd[5][0];
/* Diffusive density at Alt */ /* Diffusive density at Alt */

137
src/FDM/JSBSim/models/atmosphere/FGMSIS.h Normal file → Executable file
View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MSIS "$Id: FGMSIS.h,v 1.7 2010/02/25 05:21:36 jberndt Exp $" #define ID_MSIS "$Id: FGMSIS.h,v 1.9 2011/05/20 03:18:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -75,7 +75,7 @@ CLASS DOCUMENTATION
and check http://www.brodo.de/english/pub/nrlmsise/index.html for and check http://www.brodo.de/english/pub/nrlmsise/index.html for
updated releases of this package. updated releases of this package.
@author David Culp @author David Culp
@version $Id: FGMSIS.h,v 1.7 2010/02/25 05:21:36 jberndt Exp $ @version $Id: FGMSIS.h,v 1.9 2011/05/20 03:18:36 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -87,10 +87,60 @@ struct nrlmsise_flags {
double sw[24]; double sw[24];
double swc[24]; double swc[24];
}; };
/*
* Switches: to turn on and off particular variations use these switches.
* 0 is off, 1 is on, and 2 is main effects off but cross terms on.
*
* Standard values are 0 for switch 0 and 1 for switches 1 to 23. The
* array "switches" needs to be set accordingly by the calling program.
* The arrays sw and swc are set internally.
*
* switches[i]:
* i - explanation
* -----------------
* 0 - output in centimeters instead of meters
* 1 - F10.7 effect on mean
* 2 - time independent
* 3 - symmetrical annual
* 4 - symmetrical semiannual
* 5 - asymmetrical annual
* 6 - asymmetrical semiannual
* 7 - diurnal
* 8 - semidiurnal
* 9 - daily ap [when this is set to -1 (!) the pointer
* ap_a in struct nrlmsise_input must
* point to a struct ap_array]
* 10 - all UT/long effects
* 11 - longitudinal
* 12 - UT and mixed UT/long
* 13 - mixed AP/UT/LONG
* 14 - terdiurnal
* 15 - departures from diffusive equilibrium
* 16 - all TINF var
* 17 - all TLB var
* 18 - all TN1 var
* 19 - all S var
* 20 - all TN2 var
* 21 - all NLB var
* 22 - all TN3 var
* 23 - turbo scale height var
*/
struct ap_array { struct ap_array {
double a[7]; double a[7];
}; };
/* Array containing the following magnetic values:
* 0 : daily AP
* 1 : 3 hr AP index for current time
* 2 : 3 hr AP index for 3 hrs before current time
* 3 : 3 hr AP index for 6 hrs before current time
* 4 : 3 hr AP index for 9 hrs before current time
* 5 : Average of eight 3 hr AP indicies from 12 to 33 hrs
* prior to current time
* 6 : Average of eight 3 hr AP indicies from 36 to 57 hrs
* prior to current time
*/
struct nrlmsise_input { struct nrlmsise_input {
int year; /* year, currently ignored */ int year; /* year, currently ignored */
@ -105,11 +155,71 @@ struct nrlmsise_input {
double ap; /* magnetic index(daily) */ double ap; /* magnetic index(daily) */
struct ap_array *ap_a; /* see above */ struct ap_array *ap_a; /* see above */
}; };
/*
* NOTES ON INPUT VARIABLES:
* UT, Local Time, and Longitude are used independently in the
* model and are not of equal importance for every situation.
* For the most physically realistic calculation these three
* variables should be consistent (lst=sec/3600 + g_long/15).
* The Equation of Time departures from the above formula
* for apparent local time can be included if available but
* are of minor importance.
*
* f107 and f107A values used to generate the model correspond
* to the 10.7 cm radio flux at the actual distance of the Earth
* from the Sun rather than the radio flux at 1 AU. The following
* site provides both classes of values:
* ftp://ftp.ngdc.noaa.gov/STP/SOLAR_DATA/SOLAR_RADIO/FLUX/
*
* f107, f107A, and ap effects are neither large nor well
* established below 80 km and these parameters should be set to
* 150., 150., and 4. respectively.
*/
/* ------------------------------------------------------------------- */
/* ------------------------------ OUTPUT ----------------------------- */
/* ------------------------------------------------------------------- */
struct nrlmsise_output { struct nrlmsise_output {
double d[9]; /* densities */ double d[9]; /* densities */
double t[2]; /* temperatures */ double t[2]; /* temperatures */
}; };
/*
* OUTPUT VARIABLES:
* d[0] - HE NUMBER DENSITY(CM-3)
* d[1] - O NUMBER DENSITY(CM-3)
* d[2] - N2 NUMBER DENSITY(CM-3)
* d[3] - O2 NUMBER DENSITY(CM-3)
* d[4] - AR NUMBER DENSITY(CM-3)
* d[5] - TOTAL MASS DENSITY(GM/CM3) [includes d[8] in td7d]
* d[6] - H NUMBER DENSITY(CM-3)
* d[7] - N NUMBER DENSITY(CM-3)
* d[8] - Anomalous oxygen NUMBER DENSITY(CM-3)
* t[0] - EXOSPHERIC TEMPERATURE
* t[1] - TEMPERATURE AT ALT
*
*
* O, H, and N are set to zero below 72.5 km
*
* t[0], Exospheric temperature, is set to global average for
* altitudes below 120 km. The 120 km gradient is left at global
* average value for altitudes below 72 km.
*
* d[5], TOTAL MASS DENSITY, is NOT the same for subroutines GTD7
* and GTD7D
*
* SUBROUTINE GTD7 -- d[5] is the sum of the mass densities of the
* species labeled by indices 0-4 and 6-7 in output variable d.
* This includes He, O, N2, O2, Ar, H, and N but does NOT include
* anomalous oxygen (species index 8).
*
* SUBROUTINE GTD7D -- d[5] is the "effective total mass density
* for drag" and is the sum of the mass densities of all species
* in this model, INCLUDING anomalous oxygen.
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -125,8 +235,13 @@ public:
/// Destructor /// Destructor
~MSIS(); ~MSIS();
/** Runs the MSIS-00 atmosphere model; called by the Executive /** Runs the MSIS-00 atmosphere model; called by the Executive
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */ @return false if no error */
bool Run(void); bool Run(bool Holding);
bool InitModel(void); bool InitModel(void);
@ -196,9 +311,25 @@ private:
double sg0(double ex, double *p, double *ap); double sg0(double ex, double *p, double *ap);
double globe7(double *p, nrlmsise_input *input, nrlmsise_flags *flags); double globe7(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
double glob7s(double *p, nrlmsise_input *input, nrlmsise_flags *flags); double glob7s(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
// GTD7
// Neutral Atmosphere Empirical Model from the surface to lower exosphere.
void gtd7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); void gtd7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
// GTD7D
// This subroutine provides Effective Total Mass Density for output
// d[5] which includes contributions from "anomalous oxygen" which can
// affect satellite drag above 500 km. See the section "output" for
// additional details.
void gtd7d(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); void gtd7d(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
// GHP7
// To specify outputs at a pressure level (press) rather than at
// an altitude.
void ghp7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output, double press); void ghp7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output, double press);
// GTS7
// Thermospheric portion of NRLMSISE-00
void gts7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); void gts7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
}; };

View file

@ -0,0 +1,568 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGStandardAtmosphere.cpp
Author: Jon Berndt, Tony Peden
Date started: 5/2011
Purpose: Models the 1976 U.S. Standard Atmosphere
Called by: FGFDMExec
------------- Copyright (C) 2011 Jon S. Berndt (jon@jsbsim.org) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1] Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include "FGFDMExec.h"
#include "FGStandardAtmosphere.h"
namespace JSBSim {
static const char *IdSrc = "$Id: FGStandardAtmosphere.cpp,v 1.9 2011/06/13 12:06:29 jberndt Exp $";
static const char *IdHdr = ID_STANDARDATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGStandardAtmosphere::FGStandardAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex),
TemperatureDeltaGradient(0.0),
TemperatureBias(0.0),
PressureAltitude(0.0), // ft
DensityAltitude(0.0), // ft
SutherlandConstant(198.72), // deg Rankine
Beta(2.269690E-08) // slug/(sec ft R^0.5)
{
Name = "FGStandardAtmosphere";
StdAtmosTemperatureTable = new FGTable(9);
// This is the U.S. Standard Atmosphere table for temperature in degrees
// Rankine, based on geometric altitude. The table values are often given
// in literature relative to geopotential altitude.
//
// GeoMet Alt Temp GeoPot Alt GeoMet Alt
// (ft) (deg R) (km) (km)
// -------- -------- ---------- ----------
*StdAtmosTemperatureTable << 0.0 << 518.67 // 0.000 0.000
<< 36151.6 << 390.0 // 11.000 11.019
<< 65823.5 << 390.0 // 20.000 20.063
<< 105518.4 << 411.6 // 32.000 32.162
<< 155347.8 << 487.2 // 47.000 47.350
<< 168677.8 << 487.2 // 51.000 51.413
<< 235570.9 << 386.4 // 71.000 71.802
<< 282152.2 << 336.5 // 84.852 86.000
<< 298556.4 << 336.5; // 91.000 - First layer in high altitude regime
LapseRateVector.resize(StdAtmosTemperatureTable->GetNumRows()-1);
PressureBreakpointVector.resize(StdAtmosTemperatureTable->GetNumRows());
// Assume the altitude to fade out the gradient at is at the highest
// altitude in the table. Above that, other functions are used to
// calculate temperature.
GradientFadeoutAltitude = (*StdAtmosTemperatureTable)(StdAtmosTemperatureTable->GetNumRows(),0);
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGStandardAtmosphere::~FGStandardAtmosphere()
{
LapseRateVector.clear();
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGStandardAtmosphere::InitModel(void)
{
PressureBreakpointVector[0] = StdSLpressure = 2116.22; // psf
TemperatureDeltaGradient = 0.0;
TemperatureBias = 0.0;
CalculateLapseRates();
CalculatePressureBreakpoints();
Calculate(0.0);
StdSLtemperature = SLtemperature = Temperature;
SLpressure = Pressure;
StdSLdensity = SLdensity = Density;
StdSLsoundspeed = SLsoundspeed = Soundspeed;
rSLtemperature = 1/SLtemperature ;
rSLpressure = 1/SLpressure ;
rSLdensity = 1/SLdensity ;
rSLsoundspeed = 1/SLsoundspeed ;
// PrintStandardAtmosphereTable();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGStandardAtmosphere::Run(bool Holding)
{
if (FGModel::Run(Holding)) return true;
if (Holding) return false;
RunPreFunctions();
double altitude = FDMExec->GetPropagate()->GetAltitudeASL();
Calculate(altitude);
RunPostFunctions();
Debug(2);
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::Calculate(double altitude)
{
Temperature = GetTemperature(altitude);
Pressure = GetPressure(altitude);
Density = Pressure/(Reng*Temperature);
Soundspeed = sqrt(SHRatio*Reng*(Temperature));
Viscosity = Beta * pow(Temperature, 1.5) / (SutherlandConstant + Temperature);
KinematicViscosity = Viscosity / Density;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the actual pressure as modeled at a specified altitude
// These calculations are from equations 33a and 33b in the U.S. Standard Atmosphere
// document referenced in the documentation for this code.
double FGStandardAtmosphere::GetPressure(double altitude) const
{
unsigned int b=0;
double pressure = 0.0;
double Lmb, Exp, Tmb, deltaH, factor;
// Iterate through the altitudes to find the current Base Altitude
// in the table. That is, if the current altitude (the argument passed in)
// is 20000 ft, then the base altitude from the table is 0.0. If the
// passed-in altitude is 40000 ft, the base altitude is 36151.6 ft (and
// the index "b" is 2 - the second entry in the table).
double testAlt = (*StdAtmosTemperatureTable)(b+1,0);
while (altitude >= testAlt) {
b++;
if (b+1 > StdAtmosTemperatureTable->GetNumRows()) break;
testAlt = (*StdAtmosTemperatureTable)(b+1,0);
}
if (b>0) b--;
double BaseAlt = (*StdAtmosTemperatureTable)(b+1,0);
Tmb = GetTemperature(BaseAlt);
deltaH = altitude - BaseAlt;
if (LapseRateVector[b] != 0.00) {
Lmb = LapseRateVector[b];
Exp = Mair/(Rstar*Lmb);
factor = Tmb/(Tmb + Lmb*deltaH);
pressure = PressureBreakpointVector[b]*pow(factor, Exp);
} else {
pressure = PressureBreakpointVector[b]*exp(-Mair*deltaH/(Rstar*Tmb));
}
return pressure;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::SetSeaLevelPressure(double pressure, ePressure unit)
{
double press = ConvertToPSF(pressure, unit);
PressureBreakpointVector[0] = press;
CalculatePressureBreakpoints();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the modeled temperature at a specified altitude, including any bias or gradient
// effects.
double FGStandardAtmosphere::GetTemperature(double altitude) const
{
double T = StdAtmosTemperatureTable->GetValue(altitude) + TemperatureBias;
if (altitude <= GradientFadeoutAltitude)
T += TemperatureDeltaGradient * (GradientFadeoutAltitude - altitude);
return T;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Retrieves the standard temperature at a particular altitude.
double FGStandardAtmosphere::GetStdTemperature(double altitude) const
{
double Lk9 = 0.00658368; // deg R per foot
double Tinf = 1800.0; // Same as 1000 Kelvin
double temp = Tinf;
if (altitude < 298556.4) { // 91 km - station 8
temp = StdAtmosTemperatureTable->GetValue(altitude);
} else if (altitude < 360892.4) { // 110 km - station 9
temp = 473.7429 - 137.38176 * sqrt(1.0 - pow((altitude - 298556.4)/65429.462, 2.0));
} else if (altitude < 393700.8) { // 120 km - station 10
temp = 432 + Lk9 * (altitude - 360892.4);
} else if (altitude < 3280839.9) { // 1000 km station 12
double lambda = 0.00001870364;
double eps = (altitude - 393700.8) * (20855531.5 + 393700.8) / (20855531.5 + altitude);
temp = Tinf - (Tinf - 648.0) * exp(-lambda*eps);
}
return temp;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGStandardAtmosphere::GetStdPressure(double altitude) const
{
double press=0;
if (TemperatureBias == 0.0 && TemperatureDeltaGradient == 0.0 && PressureBreakpointVector[0] == StdSLpressure) {
press = GetPressure(altitude);
} else if (altitude <= 100000.0) {
GetStdPressure100K(altitude);
} else {
// Cannot currently retrieve the standard pressure
}
return press;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This function calculates an approximation of the standard atmospheric pressure
// up to an altitude of about 100,000 ft. If the temperature and pressure are not
// altered for local conditions, the GetPressure(h) function should be used,
// as that is valid to a much higher altitude. This function is accurate to within
// a couple of psf up to 100K ft. This polynomial fit was determined using Excel.
double FGStandardAtmosphere::GetStdPressure100K(double altitude) const
{
// Limit this equation to input altitudes of 100000 ft.
if (altitude > 100000.0) altitude = 100000.0;
double alt[6];
double coef[6] = { 2116.22,
-7.583514352598E-02,
1.045494405501E-06,
-5.881341527124E-12,
3.482031690718E-18,
5.683922549284E-23 };
alt[0] = 1;
for (int pwr=1; pwr<=5; pwr++) alt[pwr] = alt[pwr-1]*altitude;
double press = 0.0;
for (int ctr=0; ctr<=5; ctr++) press += coef[ctr]*alt[ctr];
return press;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the modeled density at a specified altitude
double FGStandardAtmosphere::GetDensity(double altitude) const
{
return GetPressure(altitude)/(Reng * GetTemperature(altitude));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the standard density at a specified altitude
double FGStandardAtmosphere::GetStdDensity(double altitude) const
{
return GetStdPressure(altitude)/(Reng * GetStdTemperature(altitude));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::SetTemperatureBias(double t, eTemperature unit)
{
TemperatureBias = ConvertToRankine(t, unit);
CalculatePressureBreakpoints();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This function calculates a bias based on the supplied temperature for sea
// level. The bias is applied to the entire temperature profile at all altitudes.
// Internally, the Rankine scale is used for calculations, so any temperature
// supplied must be converted to that unit.
void FGStandardAtmosphere::SetSLTemperature(double t, eTemperature unit)
{
double targetSLtemp = ConvertToRankine(t, unit);
TemperatureBias = targetSLtemp - GetStdTemperatureSL();
CalculatePressureBreakpoints();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Sets a Sea Level temperature delta that is ramped out by 86 km (282,152 ft).
void FGStandardAtmosphere::SetSLTemperatureGradedDelta(double deltemp, eTemperature unit)
{
SetTemperatureGradedDelta(deltemp, 0.0, unit);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Sets a temperature delta at the supplied altitude that is ramped out by 86 km.
// After this calculation is performed, the lapse rates and pressure breakpoints
// must be recalculated. Since we are calculating a delta here and not an actual
// temperature, we only need to be concerned about a scale factor and not
// the actual temperature itself.
void FGStandardAtmosphere::SetTemperatureGradedDelta(double deltemp, double h, eTemperature unit)
{
switch(unit) {
case eCelsius:
case eKelvin:
deltemp *= 9.0/5.0; // If temp delta is given in metric, scale up to English
break;
}
TemperatureDeltaGradient = deltemp/(GradientFadeoutAltitude - h);
CalculateLapseRates();
CalculatePressureBreakpoints();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::PrintStandardAtmosphereTable()
{
std::cout << "Altitude (ft) Temp (F) Pressure (psf) Density (sl/ft3)" << std::endl;
std::cout << "------------- -------- -------------- ----------------" << std::endl;
for (int i=0; i<280000; i+=1000) {
Calculate(i);
std::cout << std::setw(12) << std::setprecision(2) << i
<< " " << std::setw(9) << std::setprecision(2) << Temperature-459.67
<< " " << std::setw(13) << std::setprecision(4) << Pressure
<< " " << std::setw(18) << std::setprecision(8) << Density
<< std::endl;
}
// Re-execute the Run() method to reset the calculated values
Run(false);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This function calculates (or recalculates) the lapse rate over an altitude range
// where the "bh" in this case refers to the index of the base height in the
// StdAtmosTemperatureTable table. This function should be called anytime the
// temperature table is altered, such as when a gradient is applied across the
// temperature table for a range of altitudes.
void FGStandardAtmosphere::CalculateLapseRates()
{
for (unsigned int bh=0; bh<LapseRateVector.size(); bh++)
{
double t0 = (*StdAtmosTemperatureTable)(bh+1,1);
double t1 = (*StdAtmosTemperatureTable)(bh+2,1);
double h0 = (*StdAtmosTemperatureTable)(bh+1,0);
double h1 = (*StdAtmosTemperatureTable)(bh+2,0);
LapseRateVector[bh] = (t1 - t0) / (h1 - h0) + TemperatureDeltaGradient;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::CalculatePressureBreakpoints()
{
for (unsigned int b=0; b<PressureBreakpointVector.size()-1; b++) {
double BaseTemp = (*StdAtmosTemperatureTable)(b+1,1);
double BaseAlt = (*StdAtmosTemperatureTable)(b+1,0);
double UpperAlt = (*StdAtmosTemperatureTable)(b+2,0);
double deltaH = UpperAlt - BaseAlt;
double Tmb = BaseTemp
+ TemperatureBias
+ (GradientFadeoutAltitude - BaseAlt)*TemperatureDeltaGradient;
if (LapseRateVector[b] != 0.00) {
double Lmb = LapseRateVector[b];
double Exp = Mair/(Rstar*Lmb);
double factor = Tmb/(Tmb + Lmb*deltaH);
PressureBreakpointVector[b+1] = PressureBreakpointVector[b]*pow(factor, Exp);
} else {
PressureBreakpointVector[b+1] = PressureBreakpointVector[b]*exp(-Mair*deltaH/(Rstar*Tmb));
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::ResetSLTemperature()
{
TemperatureBias = TemperatureDeltaGradient = 0.0;
CalculateLapseRates();
CalculatePressureBreakpoints();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::ResetSLPressure()
{
PressureBreakpointVector[0] = StdSLpressure; // psf
CalculatePressureBreakpoints();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGStandardAtmosphere::ConvertToRankine(double t, eTemperature unit) const
{
double targetTemp=0; // in degrees Rankine
switch(unit) {
case eFahrenheit:
targetTemp = t + 459.67;
break;
case eCelsius:
targetTemp = t*9.0/5.0 + 32.0 + 459.67;
break;
case eRankine:
targetTemp = t;
break;
case eKelvin:
targetTemp = t*9.0/5.0;
}
return targetTemp;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGStandardAtmosphere::ConvertToPSF(double p, ePressure unit) const
{
double targetPressure=0; // Pressure in PSF
switch(unit) {
case ePSF:
targetPressure = p;
break;
case eMillibars:
targetPressure = p*2.08854342;
break;
case ePascals:
targetPressure = p*0.0208854342;
break;
case eInchesHg:
targetPressure = p*70.7180803;
break;
default:
throw("Undefined pressure unit given");
}
return targetPressure;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGStandardAtmosphere::bind(void)
{
typedef double (FGStandardAtmosphere::*PMFi)(int) const;
typedef void (FGStandardAtmosphere::*PMF)(int, double);
PropertyManager->Tie("stdatmosphere/T-R", this, &FGStandardAtmosphere::GetTemperature);
PropertyManager->Tie("stdatmosphere/rho-slugs_ft3", this, &FGStandardAtmosphere::GetDensity);
PropertyManager->Tie("stdatmosphere/P-psf", this, &FGStandardAtmosphere::GetPressure);
PropertyManager->Tie("stdatmosphere/a-fps", this, &FGStandardAtmosphere::GetSoundSpeed);
PropertyManager->Tie("stdatmosphere/T-sl-R", this, &FGStandardAtmosphere::GetTemperatureSL);
PropertyManager->Tie("stdatmosphere/rho-sl-slugs_ft3", this, &FGStandardAtmosphere::GetDensitySL);
PropertyManager->Tie("stdatmosphere/P-sl-psf", this, &FGStandardAtmosphere::GetPressureSL);
PropertyManager->Tie("stdatmosphere/a-sl-fps", this, &FGStandardAtmosphere::GetSoundSpeedSL);
PropertyManager->Tie("stdatmosphere/theta", this, &FGStandardAtmosphere::GetTemperatureRatio);
PropertyManager->Tie("stdatmosphere/sigma", this, &FGStandardAtmosphere::GetDensityRatio);
PropertyManager->Tie("stdatmosphere/delta", this, &FGStandardAtmosphere::GetPressureRatio);
PropertyManager->Tie("stdatmosphere/a-ratio", this, &FGStandardAtmosphere::GetSoundSpeedRatio);
PropertyManager->Tie("stdatmosphere/delta-T", this, eRankine,
(PMFi)&FGStandardAtmosphere::GetTemperatureBias,
(PMF)&FGStandardAtmosphere::SetTemperatureBias);
// PropertyManager->Tie("atmosphere/density-altitude", this, &FGStandardAtmosphere::GetDensityAltitude);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGStandardAtmosphere::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) std::cout << "Instantiated: FGStandardAtmosphere" << std::endl;
if (from == 1) std::cout << "Destroyed: FGStandardAtmosphere" << std::endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 128) { //
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
std::cout << IdSrc << std::endl;
std::cout << IdHdr << std::endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,379 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGStandardAtmosphere.h
Author: Jon Berndt
Date started: 5/2011
------------- Copyright (C) 2011 Jon S. Berndt (jon@jsbsim.org) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
HISTORY
--------------------------------------------------------------------------------
5/2011 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGSTANDARDATMOSPHERE_H
#define FGSTANDARDATMOSPHERE_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <vector>
#include "models/FGModel.h"
#include "math/FGTable.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_STANDARDATMOSPHERE "$Id: FGStandardAtmosphere.h,v 1.9 2011/06/13 12:06:21 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models the 1976 U.S. Standard Atmosphere, with the ability to modify the
temperature and pressure. A base feature of the model is the temperature
profile that is stored as an FGTable object with this data:
@code
GeoMet Alt Temp GeoPot Alt GeoMet Alt
(ft) (deg R) (km) (km)
--------- -------- ---------- ----------
0.0 518.67 // 0.000 0.000
36151.6 390.0 // 11.000 11.019
65823.5 390.0 // 20.000 20.063
105518.4 411.6 // 32.000 32.162
155347.8 487.2 // 47.000 47.350
168677.8 487.2 // 51.000 51.413
235570.9 386.4 // 71.000 71.802
282152.2 336.5; // 84.852 86.000
@endcode
The pressure is calculated at lower altitudes through the use of two equations
that are presented in the U.S. Standard Atmosphere document (see references).
Density, kinematic viscosity, speed of sound, etc., are all calculated based
on various constants and temperature and pressure. At higher altitudes (above
86 km (282152 ft) a different and more complicated method of calculating
pressure is used.
The temperature may be modified through the use of several methods. Ultimately,
these access methods allow the user to modify the sea level standard temperature,
and/or the sea level standard pressure, so that the entire profile will be
consistently and accurately calculated.
<h2> Properties </h2>
@property atmosphere/T-R The current modeled temperature in degrees Rankine.
@property atmosphere/rho-slugs_ft3
@property atmosphere/P-psf
@property atmosphere/a-fps
@property atmosphere/T-sl-R
@property atmosphere/rho-sl-slugs_ft3
@property atmosphere/P-sl-psf
@property atmosphere/a-sl-fps
@property atmosphere/theta
@property atmosphere/sigma
@property atmosphere/delta
@property atmosphere/a-ratio
@property atmosphere/delta-T
@property atmosphere/T-sl-dev-F
@author Jon Berndt
@see "U.S. Standard Atmosphere, 1976", NASA TM-X-74335
@version $Id: FGStandardAtmosphere.h,v 1.9 2011/06/13 12:06:21 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGStandardAtmosphere : public FGModel {
public:
/// Enums for specifying temperature units.
enum eTemperature {eNoTempUnit=0, eFahrenheit, eCelsius, eRankine, eKelvin};
/// Enums for specifying pressure units.
enum ePressure {eNoPressUnit=0, ePSF, eMillibars, ePascals, eInchesHg};
/// Constructor
FGStandardAtmosphere(FGFDMExec*);
/// Destructor
~FGStandardAtmosphere();
/** Runs the standard atmosphere forces model; called by the Executive.
Can pass in a value indicating if the executive is directing the simulation to Hold.
@param Holding if true, the executive has been directed to hold the sim from
advancing time. Some models may ignore this flag, such as the Input
model, which may need to be active to listen on a socket for the
"Resume" command to be given.
@return false if no error */
bool Run(bool Holding);
bool InitModel(void);
// *************************************************************************
/// @name Temperature access functions.
/// There are several ways to get the temperature, and several modeled temperature
/// values that can be retrieved. The U.S. Standard Atmosphere temperature either
/// at a specified altitude, or at sea level can be retrieved. These two temperatures
/// do NOT include the effects of any bias or delta gradient that may have been
/// supplied by the user. The modeled temperature and the modeled temperature
/// at sea level can also be retrieved. These two temperatures DO include the
/// effects of an optionally user-supplied bias or delta gradient.
// @{
/// Returns the actual, modeled temperature at the current altitude in degrees Rankine.
/// @return Modeled temperature in degrees Rankine.
virtual double GetTemperature() const {return Temperature;}
/// Returns the actual modeled temperature in degrees Rankine at a specified altitude.
/// @param altitude The altitude above sea level (ASL) in feet.
/// @return Modeled temperature in degrees Rankine at the specified altitude.
virtual double GetTemperature(double altitude) const;
/// Returns the actual, modeled sea level temperature in degrees Rankine.
/// @return The modeled temperature in degrees Rankine at sea level.
virtual double GetTemperatureSL() const { return GetTemperature(0.0); }
/// Returns the standard temperature in degrees Rankine at a specified altitude.
/// @param altitude The altitude in feet above sea level (ASL) to get the temperature at.
/// @return The STANDARD temperature in degrees Rankine at the specified altitude.
virtual double GetStdTemperature(double altitude) const;
/// Returns the standard sea level temperature in degrees Rankine.
/// @return The STANDARD temperature at sea level in degrees Rankine.
virtual double GetStdTemperatureSL() const { return GetStdTemperature(0.0); }
/// Returns the ratio of the at-current-altitude temperature as modeled
/// over the standard sea level value.
virtual double GetTemperatureRatio() const { return GetTemperature()*rSLtemperature; }
/// Returns the ratio of the temperature as modeled at the supplied altitude
/// over the standard sea level value.
virtual double GetTemperatureRatio(double h) const { return GetTemperature(h)*rSLtemperature; }
/// Returns the ratio of the standard temperature at the supplied altitude
/// over the standard sea level temperature.
virtual double GetStdTemperatureRatio(double h) const { return GetStdTemperature(h)*rSLtemperature; }
/// Returns the temperature bias over the sea level value in degrees Rankine.
virtual double GetTemperatureBias(eTemperature to) const {return TemperatureBias;}
/// Returns the temperature gradient to be applied on top of the standard
/// temperature gradient.
virtual double GetTemperatureDeltaGradient() { return TemperatureDeltaGradient;}
/// Sets the Sea Level temperature, if it is to be different than the standard.
/// This function will calculate a bias - a difference - from the standard
/// atmosphere temperature and will apply that bias to the entire
/// temperature profile. This is one way to set the temperature bias. Using
/// the SetTemperatureBias function will replace the value calculated by
/// this function.
/// @param t the temperature value in the unit provided.
/// @param unit the unit of the temperature.
virtual void SetSLTemperature(double t, eTemperature unit=eFahrenheit);
/// Sets the temperature at the supplied altitude, if it is to be different
/// than the standard temperature.
/// This function will calculate a bias - a difference - from the standard
/// atmosphere temperature at the supplied altitude and will apply that
/// calculated bias to the entire temperature profile.
/// @param t The temperature value in the unit provided.
/// @param h The altitude in feet above sea level.
/// @param unit The unit of the temperature.
virtual void SetTemperature(double t, double h, eTemperature unit=eFahrenheit) {};
/// Sets the temperature bias to be added to the standard temperature at all altitudes.
/// This function sets the bias - the difference - from the standard
/// atmosphere temperature. This bias applies to the entire
/// temperature profile. Another way to set the temperature bias is to use the
/// SetSLTemperature function, which replaces the value calculated by
/// this function with a calculated bias.
/// @param t the temperature value in the unit provided.
/// @param unit the unit of the temperature.
virtual void SetTemperatureBias(double t, eTemperature unit=eFahrenheit);
/// Sets a Sea Level temperature delta that is ramped out by 86 km.
/// The value of the delta is used to calculate a delta gradient that is
/// applied to the temperature at all altitudes below 86 km (282152 ft).
/// For instance, if a temperature of 20 degrees F is supplied, the delta
/// gradient would be 20/282152 - or, about 7.09E-5 degrees/ft. At sea level,
/// the full 20 degrees would be added to the standard temperature,
/// but that 20 degree delta would be reduced by 7.09E-5 degrees for every
/// foot of altitude above sea level, so that by 86 km, there would be no
/// further delta added to the standard temperature.
/// The graded delta can be used along with the a bias to tailor the
/// temperature profile as desired.
/// @param t the sea level temperature delta value in the unit provided.
/// @param unit the unit of the temperature.
virtual void SetSLTemperatureGradedDelta(double t, eTemperature unit=eFahrenheit);
/// Sets the temperature delta value at the supplied altitude/elevation above
/// sea level, to be added to the standard temperature and ramped out by
/// 86 km.
/// This function computes the sea level delta from the standard atmosphere
/// temperature at sea level.
/// @param t the temperature skew value in the unit provided.
/// @param unit the unit of the temperature.
virtual void SetTemperatureGradedDelta(double t, double h, eTemperature unit=eFahrenheit);
/// This function resets the model to apply no bias or delta gradient to the
/// temperature.
/// The delta gradient and bias values are reset to 0.0, and the standard
/// temperature is used for the entire temperature profile at all altitudes.
virtual void ResetSLTemperature();
//@}
// *************************************************************************
/// @name Pressure access functions.
//@{
/// Returns the pressure in psf.
virtual double GetPressure(void) const {return Pressure;}
/// Returns the pressure at a specified altitude in psf.
virtual double GetPressure(double altitude) const;
/// Returns the standard pressure at a specified altitude in psf
virtual double GetStdPressure100K(double altitude) const;
/// Returns the standard pressure at the specified altitude.
virtual double GetStdPressure(double altitude) const;
/// Returns the sea level pressure in psf.
virtual double GetPressureSL(void) const { return SLpressure; }
/// Returns the ratio of at-altitude pressure over the sea level value.
virtual double GetPressureRatio(void) const { return Pressure*rSLpressure; }
/** Sets the sea level pressure for modeling an off-standard pressure
profile. This could be useful in the case where the pressure at an
airfield is known or set for a particular simulation run.
@param pressure The pressure in the units specified (PSF by default).
@param unit the unit of measure that the specified pressure is
supplied in.*/
virtual void SetSeaLevelPressure(double pressure, ePressure unit=ePSF);
/** Resets the sea level to the Standard sea level pressure, and recalculates
dependent parameters so that the pressure calculations are standard. */
virtual void ResetSLPressure();
//@}
// *************************************************************************
/// @name Density access functions.
//@{
/** Returns the density in slugs/ft^3.
This function may only be used if Run() is called first. */
virtual double GetDensity(void) const {return Density;}
/** Returns the density in slugs/ft^3 at a given altitude in ft. */
virtual double GetDensity(double altitude) const;
/// Returns the standard density at a specified altitude
virtual double GetStdDensity(double altitude) const;
/// Returns the sea level density in slugs/ft^3
virtual double GetDensitySL(void) const { return SLdensity; }
/// Returns the ratio of at-altitude density over the sea level value.
virtual double GetDensityRatio(void) const { return Density*rSLdensity; }
//@}
// *************************************************************************
/// @name Speed of sound access functions.
//@{
/// Returns the speed of sound in ft/sec.
virtual double GetSoundSpeed(void) const {return Soundspeed;}
/// Returns the sea level speed of sound in ft/sec.
virtual double GetSoundSpeedSL(void) const { return SLsoundspeed; }
/// Returns the ratio of at-altitude sound speed over the sea level value.
virtual double GetSoundSpeedRatio(void) const { return Soundspeed*rSLsoundspeed; }
//@}
// *************************************************************************
/// @name Viscosity access functions.
//@{
/// Returns the absolute viscosity.
virtual double GetAbsoluteViscosity(void) const {return Viscosity;}
/// Returns the kinematic viscosity.
virtual double GetKinematicViscosity(void) const {return KinematicViscosity;}
//@}
/* /// Gets the density altitude in feet */
// virtual double GetDensityAltitude(void) const { return density_altitude; }
/// Prints the U.S. Standard Atmosphere table.
virtual void PrintStandardAtmosphereTable();
protected:
double StdSLtemperature, StdSLdensity, StdSLpressure, StdSLsoundspeed; // Standard sea level conditions
double SLtemperature, SLdensity, SLpressure, SLsoundspeed; // Sea level conditions
double Temperature, Density, Pressure, Soundspeed; // Current actual conditions at altitude
double rSLtemperature, rSLdensity, rSLpressure, rSLsoundspeed; // Reciprocal of sea level conditions
double PressureAltitude;
double DensityAltitude;
double TemperatureBias;
double TemperatureDeltaGradient;
double GradientFadeoutAltitude;
FGTable* StdAtmosTemperatureTable;
std::vector<double> LapseRateVector;
std::vector<double> PressureBreakpointVector;
const double SutherlandConstant, Beta;
double Viscosity, KinematicViscosity;
/// Calculate the atmosphere for the given altitude, including effects of temperature deviation.
void Calculate(double altitude);
/// Recalculate the lapse rate vectors when the temperature profile is altered
/// in a way that would change the lapse rates, such as when a gradient is applied.
/// This function is also called to initialize the lapse rate vector.
void CalculateLapseRates();
/// Calculate (or recalculate) the atmospheric pressure breakpoints at the
/// altitudes in the standard temperature table.
void CalculatePressureBreakpoints();
// Converts to Rankine from one of several unit systems.
virtual double ConvertToRankine(double t, eTemperature unit) const;
// Converts to PSF (pounds per square foot) from one of several unit systems.
virtual double ConvertToPSF(double t, ePressure unit=ePSF) const;
virtual void bind(void);
void Debug(int from);
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGActuator.cpp,v 1.17 2011/02/13 00:42:45 jberndt Exp $"; static const char *IdSrc = "$Id: FGActuator.cpp,v 1.18 2011/05/13 17:14:47 bcoconni Exp $";
static const char *IdHdr = ID_ACTUATOR; static const char *IdHdr = ID_ACTUATOR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -125,6 +125,13 @@ bool FGActuator::Run(void )
if (fail_stuck) Output = PreviousOutput; if (fail_stuck) Output = PreviousOutput;
PreviousOutput = Output; // previous value needed for "stuck" malfunction PreviousOutput = Output; // previous value needed for "stuck" malfunction
if (fcs->GetTrimStatus()) {
PreviousHystOutput = Output;
PreviousRateLimOutput = Output;
PreviousLagInput = Output;
PreviousLagOutput = Output;
}
Clip(); Clip();
if (IsOutput) SetOutput(); if (IsOutput) SetOutput();

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.30 2011/04/05 20:20:21 andgi Exp $"; static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.32 2011/06/16 03:39:38 jberndt Exp $";
static const char *IdHdr = ID_FCSCOMPONENT; static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -58,7 +58,7 @@ CLASS IMPLEMENTATION
FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs) FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
{ {
Element *input_element, *clip_el; Element *input_element, *clip_el;
Input = Output = clipmin = clipmax = 0.0; Input = Output = clipmin = clipmax = delay_time = 0.0;
treenode = 0; treenode = 0;
delay = index = 0; delay = index = 0;
ClipMinPropertyNode = ClipMaxPropertyNode = 0; ClipMinPropertyNode = ClipMaxPropertyNode = 0;
@ -149,18 +149,18 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
Element* delay_elem = element->FindElement("delay"); Element* delay_elem = element->FindElement("delay");
if ( delay_elem ) { if ( delay_elem ) {
delay = (unsigned int)delay_elem->GetDataAsNumber(); delay_time = delay_elem->GetDataAsNumber();
string delayType = delay_elem->GetAttributeValue("type"); string delayType = delay_elem->GetAttributeValue("type");
if (delayType.length() > 0) { if (delayType.length() > 0) {
if (delayType == "time") { if (delayType == "time") {
delay = (int)(delay / dt); delay = (unsigned int)(delay_time / dt);
} else if (delayType == "frames") { } else if (delayType == "frames") {
// no op. the delay type of "frames" is assumed and is the default. delay = (unsigned int)delay_time;
} else { } else {
cerr << "Unallowed delay type" << endl; cerr << "Unallowed delay type" << endl;
} }
} else { } else {
delay = (int)(delay / dt); delay = (unsigned int)(delay_time / dt);
} }
output_array.resize(delay); output_array.resize(delay);
for (int i=0; i<delay; i++) output_array[i] = 0.0; for (int i=0; i<delay; i++) output_array[i] = 0.0;

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.18 2011/04/05 20:20:21 andgi Exp $" #define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.20 2011/06/16 03:39:38 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -81,7 +81,7 @@ CLASS DOCUMENTATION
- FGActuator - FGActuator
@author Jon S. Berndt @author Jon S. Berndt
@version $Id: FGFCSComponent.h,v 1.18 2011/04/05 20:20:21 andgi Exp $ @version $Id: FGFCSComponent.h,v 1.20 2011/06/16 03:39:38 jberndt 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
*/ */
@ -120,7 +120,8 @@ protected:
double Input; double Input;
double Output; double Output;
double clipmax, clipmin; double clipmax, clipmin;
int delay; double delay_time;
unsigned int delay;
int index; int index;
float clipMinSign, clipMaxSign; float clipMinSign, clipMaxSign;
double dt; double dt;

10
src/FDM/JSBSim/models/flight_control/FGPID.cpp Normal file → Executable file
View file

@ -44,7 +44,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGPID.cpp,v 1.16 2009/10/24 22:59:30 jberndt Exp $"; static const char *IdSrc = "$Id: FGPID.cpp,v 1.19 2011/05/05 11:44:11 jberndt Exp $";
static const char *IdHdr = ID_PID; static const char *IdHdr = ID_PID;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -144,10 +144,14 @@ bool FGPID::Run(void )
if (Trigger != 0) { if (Trigger != 0) {
double test = Trigger->getDoubleValue(); double test = Trigger->getDoubleValue();
if (fabs(test) < 0.000001) I_out_delta = Ki * dt * Input; // Normal if (fabs(test) < 0.000001) {
// I_out_delta = Ki * dt * Input; // Normal rectangular integrator
I_out_delta = Ki * dt * (1.5*Input - 0.5*Input_prev); // 2nd order Adams Bashforth integrator
}
if (test < 0.0) I_out_total = 0.0; // Reset integrator to 0.0 if (test < 0.0) I_out_total = 0.0; // Reset integrator to 0.0
} else { // no anti-wind-up trigger defined } else { // no anti-wind-up trigger defined
I_out_delta = Ki * dt * Input; // I_out_delta = Ki * dt * Input;
I_out_delta = Ki * dt * (1.5*Input - 0.5*Input_prev); // 2nd order Adams Bashforth integrator
} }
I_out_total += I_out_delta; I_out_total += I_out_delta;

View file

@ -69,7 +69,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.20 2011/04/05 20:20:21 andgi Exp $"; static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.21 2011/06/16 03:39:38 jberndt Exp $";
static const char *IdHdr = ID_SWITCH; static const char *IdHdr = ID_SWITCH;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -196,6 +196,7 @@ bool FGSwitch::Run(void )
if (!pass) Output = default_output; if (!pass) Output = default_output;
if (delay != 0) Delay();
Clip(); Clip();
if (IsOutput) SetOutput(); if (IsOutput) SetOutput();

View file

@ -42,6 +42,7 @@ INCLUDES
#include "FGElectric.h" #include "FGElectric.h"
#include "models/FGPropulsion.h" #include "models/FGPropulsion.h"
#include "models/propulsion/FGThruster.h" #include "models/propulsion/FGThruster.h"
#include "FGPropeller.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -50,7 +51,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGElectric.cpp,v 1.10 2011/03/10 01:35:25 dpculp Exp $"; static const char *IdSrc = "$Id: FGElectric.cpp,v 1.11 2011/06/06 22:35:08 jentron Exp $";
static const char *IdHdr = ID_ELECTRIC; static const char *IdHdr = ID_ELECTRIC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -71,6 +72,11 @@ FGElectric::FGElectric(FGFDMExec* exec, Element *el, int engine_number)
if (el->FindElement("power")) if (el->FindElement("power"))
PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS"); PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS");
string property_name, base_property_name;
base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
property_name = base_property_name + "/power-hp";
PropertyManager->Tie(property_name, &HP);
Debug(0); // Call Debug() routine from constructor if needed Debug(0); // Call Debug() routine from constructor if needed
} }
@ -89,6 +95,11 @@ void FGElectric::Calculate(void)
Throttle = FCS->GetThrottlePos(EngineNumber); Throttle = FCS->GetThrottlePos(EngineNumber);
if (Thruster->GetType() == FGThruster::ttPropeller) {
((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
}
RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
HP = PowerWatts * Throttle / hptowatts; HP = PowerWatts * Throttle / hptowatts;

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGPiston.cpp,v 1.55 2011/03/10 01:35:25 dpculp Exp $"; static const char *IdSrc = "$Id: FGPiston.cpp,v 1.58 2011/06/13 15:23:09 jentron Exp $";
static const char *IdHdr = ID_PISTON; static const char *IdHdr = ID_PISTON;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -64,7 +64,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
: FGEngine(exec, el, engine_number), : FGEngine(exec, el, engine_number),
R_air(287.3), // Gas constant for air J/Kg/K R_air(287.3), // Gas constant for air J/Kg/K
rho_fuel(800), // estimate rho_fuel(800), // estimate
calorific_value_fuel(47.3e6), calorific_value_fuel(47.3e6), // J/Kg
Cp_air(1005), // Specific heat (constant pressure) J/Kg/K Cp_air(1005), // Specific heat (constant pressure) J/Kg/K
Cp_fuel(1700), Cp_fuel(1700),
standard_pressure(101320.73) standard_pressure(101320.73)
@ -100,6 +100,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
FMEPDynamic= 18400; FMEPDynamic= 18400;
FMEPStatic = 46500; FMEPStatic = 46500;
Cooling_Factor = 0.5144444; Cooling_Factor = 0.5144444;
StaticFriction_HP = 1.5;
// These are internal program variables // These are internal program variables
@ -177,6 +178,8 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3"); Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3");
if (el->FindElement("maxhp")) if (el->FindElement("maxhp"))
MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP"); MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP");
if (el->FindElement("static-friction"))
StaticFriction_HP = el->FindElementValueAsNumberConvertTo("static-friction","HP");
if (el->FindElement("sparkfaildrop")) if (el->FindElement("sparkfaildrop"))
SparkFailDrop = Constrain(0, 1 - el->FindElementValueAsNumber("sparkfaildrop"), 1); SparkFailDrop = Constrain(0, 1 - el->FindElementValueAsNumber("sparkfaildrop"), 1);
if (el->FindElement("cycles")) if (el->FindElement("cycles"))
@ -259,7 +262,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
pmep *= inhgtopa * volumetric_efficiency; pmep *= inhgtopa * volumetric_efficiency;
double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic); double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic);
double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371); double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371);
ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss)); ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss-StaticFriction_HP));
// cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl; // cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl;
} }
if ( MaxManifoldPressure_inHg > 29.9 ) { // Don't allow boosting with a bogus number if ( MaxManifoldPressure_inHg > 29.9 ) { // Don't allow boosting with a bogus number
@ -314,6 +317,14 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
PropertyManager->Tie(property_name, &BoostSpeed); PropertyManager->Tie(property_name, &BoostSpeed);
property_name = base_property_name + "/cht-degF"; property_name = base_property_name + "/cht-degF";
PropertyManager->Tie(property_name, this, &FGPiston::getCylinderHeadTemp_degF); PropertyManager->Tie(property_name, this, &FGPiston::getCylinderHeadTemp_degF);
property_name = base_property_name + "/engine-rpm";
PropertyManager->Tie(property_name, this, &FGPiston::getRPM);
property_name = base_property_name + "/oil-temperature-degF";
PropertyManager->Tie(property_name, this, &FGPiston::getOilTemp_degF);
property_name = base_property_name + "/oil-pressure-psi";
PropertyManager->Tie(property_name, this, &FGPiston::getOilPressure_psi);
property_name = base_property_name + "/egt-degF";
PropertyManager->Tie(property_name, this, &FGPiston::getExhaustGasTemp_degF);
// Set up and sanity-check the turbo/supercharging configuration based on the input values. // Set up and sanity-check the turbo/supercharging configuration based on the input values.
if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true; if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true;
@ -730,7 +741,7 @@ void FGPiston::doEnginePower(void)
// (1/2) convert cycles, 60 minutes to seconds, 745.7 watts to hp. // (1/2) convert cycles, 60 minutes to seconds, 745.7 watts to hp.
double pumping_hp = ((PMEP + FMEP) * displacement_SI * RPM)/(Cycles*22371); double pumping_hp = ((PMEP + FMEP) * displacement_SI * RPM)/(Cycles*22371);
HP = IndicatedHorsePower + pumping_hp - 1.5; //FIXME 1.5 static friction should depend on oil temp and configuration HP = IndicatedHorsePower + pumping_hp - StaticFriction_HP; //FIXME static friction should depend on oil temp and configuration
// cout << "pumping_hp " <<pumping_hp << FMEP << PMEP <<endl; // cout << "pumping_hp " <<pumping_hp << FMEP << PMEP <<endl;
PctPower = HP / MaxHP ; PctPower = HP / MaxHP ;
// cout << "Power = " << HP << " RPM = " << RPM << " Running = " << Running << " Cranking = " << Cranking << endl; // cout << "Power = " << HP << " RPM = " << RPM << " Running = " << Running << " Cranking = " << Cranking << endl;
@ -756,11 +767,10 @@ void FGPiston::doEGT(void)
if ((Running) && (m_dot_air > 0.0)) { // do the energy balance if ((Running) && (m_dot_air > 0.0)) { // do the energy balance
combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio); combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio);
enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * enthalpy_exhaust = m_dot_fuel * calorific_value_fuel *
combustion_efficiency * 0.33; combustion_efficiency * 0.30;
heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel); heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel);
delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust; delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust;
ExhaustGasTemp_degK = T_amb + delta_T_exhaust; ExhaustGasTemp_degK = T_amb + delta_T_exhaust;
ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * PctPower);
} else { // Drop towards ambient - guess an appropriate time constant for now } else { // Drop towards ambient - guess an appropriate time constant for now
combustion_efficiency = 0; combustion_efficiency = 0;
dEGTdt = (RankineToKelvin(Atmosphere->GetTemperature()) - ExhaustGasTemp_degK) / 100.0; dEGTdt = (RankineToKelvin(Atmosphere->GetTemperature()) - ExhaustGasTemp_degK) / 100.0;

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PISTON "$Id: FGPiston.h,v 1.26 2011/03/10 01:35:25 dpculp Exp $"; #define ID_PISTON "$Id: FGPiston.h,v 1.29 2011/06/16 16:32:10 jentron Exp $";
#define FG_MAX_BOOST_SPEEDS 3 #define FG_MAX_BOOST_SPEEDS 3
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -59,7 +59,7 @@ namespace JSBSim {
CLASS DOCUMENTATION CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models Dave Luff's Turbo/Supercharged Piston engine model. /** Models a Supercharged Piston engine. Based on Dave Luff's model.
<h3>Configuration File Format:</h3> <h3>Configuration File Format:</h3>
@ -67,19 +67,21 @@ CLASS DOCUMENTATION
<piston_engine name="{string}"> <piston_engine name="{string}">
<minmp unit="{INHG | PA | ATM}"> {number} </minmp> <minmp unit="{INHG | PA | ATM}"> {number} </minmp>
<maxmp unit="{INHG | PA | ATM}"> {number} </maxmp> <maxmp unit="{INHG | PA | ATM}"> {number} </maxmp>
<idlerpm> {number} </idlerpm>
<maxrpm> {number} </maxrpm>
<maxhp unit="{HP | WATTS}"> {number} </maxhp>
<displacement unit="{IN3 | LTR | CC}"> {number} </displacement> <displacement unit="{IN3 | LTR | CC}"> {number} </displacement>
<cycles> {number} </cycles>
<bore unit="{IN | M}"> {number} </bore> <bore unit="{IN | M}"> {number} </bore>
<stroke unit="{IN | M}"> {number} </stroke> <stroke unit="{IN | M}"> {number} </stroke>
<cylinders> {number} </cylinders> <cylinders> {number} </cylinders>
<cylinder-head-mass unit="{KG | LBS}"> {number} </cylinder-head-mass>
<compression-ratio> {number} </compression-ratio> <compression-ratio> {number} </compression-ratio>
<sparkfaildrop> {number} </sparkfaildrop> <sparkfaildrop> {number} </sparkfaildrop>
<maxhp unit="{HP | WATTS}"> {number} </maxhp> <static-friction unit="{HP | WATTS}"> {number} </static-friction>
<cycles> {number} </cycles> <air-intake-impedance-factor> {number} </air-intake-impedance-factor>
<idlerpm> {number} </idlerpm> <ram-air-factor> {number} </ram-air-factor>
<maxrpm> {number} </maxrpm> <cooling-factor> {number} </cooling-factor>
<maxthrottle> {number} </maxthrottle> <cylinder-head-mass unit="{KG | LBS}"> {number} </cylinder-head-mass>
<minthrottle> {number} </minthrottle>
<bsfc unit="{LBS/HP*HR | "KG/KW*HR"}"> {number} </bsfc> <bsfc unit="{LBS/HP*HR | "KG/KW*HR"}"> {number} </bsfc>
<volumetric-efficiency> {number} </volumetric-efficiency> <volumetric-efficiency> {number} </volumetric-efficiency>
<dynamic-fmep unit="{INHG | PA | ATM}"> {number} </dynamic-fmep> <dynamic-fmep unit="{INHG | PA | ATM}"> {number} </dynamic-fmep>
@ -100,89 +102,103 @@ CLASS DOCUMENTATION
<ratedrpm3> {number} </ratedrpm3> <ratedrpm3> {number} </ratedrpm3>
<ratedaltitude3 unit="{FT | M}"> {number} </ratedaltitude3> <ratedaltitude3 unit="{FT | M}"> {number} </ratedaltitude3>
<takeoffboost unit="{INHG | PA | ATM}"> {number} </takeoffboost> <takeoffboost unit="{INHG | PA | ATM}"> {number} </takeoffboost>
<air-intake-impedance-factor> {number} </air-intake-impedance-factor>
<ram-air-factor> {number} </ram-air-factor>
<cooling-factor> {number} </cooling-factor>
</piston_engine> </piston_engine>
@endcode @endcode
<pre> <h3>Definition of the piston engine configuration file parameters:</h3>
Additional elements are required for a supercharged engine. These can be Basic parameters:
left off a non-supercharged engine, ie. the changes are all backward - \b minmp - this value is the nominal idle manifold pressure at sea-level
compatible at present. without boost. Along with idlerpm, it determines throttle response slope.
- \b maxmp - this value is the nominal maximum manifold pressure at sea-level
without boost. Along with maxrpm it determines the resistance of the
aircraft intake system. Overridden by air-intake-impedance-factor
- \b idlerpm - this value affects the throttle fall off and the engine stops
running if it is slowed below 80% of this value. The engine starts
running when it reaches 80% of this value.
- \b maxrpm - this value is used to calculate air-box resistance and BSFC. It
also affects oil pressure among other things.
- \b maxhp - this value is the nominal power the engine creates at maxrpm. It
will determine bsfc if that tag is not input. It also determines the
starter motor power.
- \b displacement - this value is used to determine mass air and fuel flow
which impacts engine power and cooling.
- \b cycles - Designate a 2 or 4 stroke engine. Currently only the 4 stroke
engine is supported.
- \b bore - cylinder bore is currently unused.
- \b stroke - piston stroke is used to determine the mean piston speed. Longer
strokes result in an engine that does not work as well at higher RPMs.
- \b compression-ratio - the compression ratio affects the change in volumetric
efficiency with altitude.
- \b sparkfaildrop - this is the percentage drop in horsepower for single
magneto operation.
- \b static-friction - this value is the power required to turn an engine that
is not running. Used to control and slow a windmilling propeller. Choose
a small percentage of maxhp.
- NUMBOOSTSPEEDS - zero (or not present) for a naturally-aspirated engine, Advanced parameters
- \b bsfc - Indicated Specific Fuel Consumption. The power produced per unit of
fuel. Higher numbers give worse fuel economy. This number may need to be
lowered slightly from actual BSFC numbers because some internal engine
losses are modeled separately. Typically between 0.3 and 0.5
- \b volumetric-efficiency - the nominal volumetric efficiency of the engine.
This is the primary way to control fuel flow Boosted engines may require
values above 1. Typical engines are 0.80 to 0.82
- \b air-intake-impedance-factor - this number is the pressure drop across the
intake system. Increasing it reduces available manifold pressure. Also a
property for run-time adjustment.
- \b ram-air-factor - this number creates increases manifold pressure with an
increase in dynamic pressure (aircraft speed).
Also a property for run-time adjustment.
Cooling control:
- \b cylinders - number of cylinders scales the cylinder head mass.
- \b cylinder-head-mass - the nominal mass of a cylinder head. A larger value
slows changes in engine temperature
- \b cooling-factor - this number models the efficiency of the aircraft cooling
system. Also a property for run-time adjustment.
Supercharge parameters:
- \b numboostspeed - zero (or not present) for a naturally-aspirated engine,
either 1, 2 or 3 for a boosted engine. This corresponds to the number of either 1, 2 or 3 for a boosted engine. This corresponds to the number of
supercharger speeds. Merlin XII had 1 speed, Merlin 61 had 2, a late supercharger speeds. Merlin XII had 1 speed, Merlin 61 had 2, a late
Griffon engine apparently had 3. No known engine more than 3, although Griffon engine apparently had 3. No known engine more than 3, although
some German engines apparently had a continuously variable-speed some German engines had continuously variable-speed superchargers.
supercharger. - \b boostoverride - unused
- \b boostmanual - whether a multispeed supercharger will manually or
automatically shift boost speeds. On manual shifting the boost speeds is
accomplished by controlling the property propulsion/engine/boostspeed.
- \b takeoffboost - boost in psi above sea level ambient. Typically used for
takeoff, and emergency situations, generally for not more than five
minutes. This is a change in the boost control setting, not the actual
supercharger speed, and so would only give extra power below the rated altitude.
A typical takeoff boost for an early Merlin was about 12psi, compared
with a rated boost of 9psi.
- BOOSTOVERRIDE - whether the boost pressure control system (either a boost When TAKEOFFBOOST is specified in the config file (and is above RATEDBOOST1),
control valve for superchargers or wastegate for turbochargers) can be the throttle position is interpreted as:
overriden by the pilot. During wartime this was commonly possible, and - 0 to 0.98 : idle manifold pressure to rated boost (where attainable)
known as "War Emergency Power" by the Brits. 1 or 0 in the config file. - 0.99, 1.0 : takeoff boost (where attainable).
This isn't implemented in the model yet though, there would need to be
some way of getting the boost control cutout lever position (on or off)
from FlightGear first.
- BOOSTMANUAL - whether a multispeed supercharger will manually or The next items are all appended with either 1, 2 or 3 depending on which
automatically shift boost speeds. On manual shifting the boost speeds boostspeed they refer to:
is accomplished by controling propulsion/engine/boostspeed - \b ratedboost[123] - the absolute rated boost above sea level ambient
(14.7 PSI, 29.92 inHg) for a given boost speed.
- The next items are all appended with either 1, 2 or 3 depending on which - \b ratedpower[123] - unused
boost speed they refer to, eg RATEDBOOST1. The rated values seems to have - \b ratedrpm[123] - The rpm at which rated boost is developed
been a common convention at the time to express the maximum continuously - \b ratedaltitude[123] - The altitude up to which the rated boost can be
available power, and the conditions to attain that power. maintained. Up to this altitude the boost is clipped to rated boost or
takeoffboost. Beyond this altitude the manifold pressure must drop,
- RATEDBOOST[123] - the absolute rated boost above sea level ambient for a since the supercharger is now at maximum unregulated output. The actual
given boost speed, in psi. Eg the Merlin XII had a rated boost of 9psi, pressure multiplier of the supercharger system is calculated at
giving approximately 42inHg manifold pressure up to the rated altitude. initialization from this value.
- RATEDALTITUDE[123] - The altitude up to which rated boost can be
maintained. Up to this altitude the boost is maintained constant for a
given throttle position by the BCV or wastegate. Beyond this altitude the
manifold pressure must drop, since the supercharger is now at maximum
unregulated output. The actual pressure multiplier of the supercharger
system is calculated at initialisation from this value.
- RATEDPOWER[123] - The power developed at rated boost at rated altitude at
rated rpm.
- RATEDRPM[123] - The rpm at which rated power is developed.
- TAKEOFFBOOST - Takeoff boost in psi above ambient. Many aircraft had an
extra boost setting beyond rated boost, but not totally uncontrolled as in
the already mentioned boost-control-cutout, typically attained by pushing
the throttle past a mechanical 'gate' preventing its inadvertant use. This
was typically used for takeoff, and emergency situations, generally for
not more than five minutes. This is a change in the boost control
setting, not the actual supercharger speed, and so would only give extra
power below the rated altitude. When TAKEOFFBOOST is specified in the
config file (and is above RATEDBOOST1), then the throttle position is
interpreted as:
- 0 to 0.98 : idle manifold pressure to rated boost (where attainable)
- 0.99, 1.0 : takeoff boost (where attainable).
A typical takeoff boost for an earlyish Merlin was about 12psi, compared
with a rated boost of 9psi.
It is quite possible that other boost control settings could have been used
on some aircraft, or that takeoff/extra boost could have activated by other
means than pushing the throttle full forward through a gate, but this will
suffice for now.
Note that MAXMP is still the non-boosted max manifold pressure even for
boosted engines - effectively this is simply a measure of the pressure drop
through the fully open throttle.
</pre>
@author Jon S. Berndt (Engine framework code and framework-related mods) @author Jon S. Berndt (Engine framework code and framework-related mods)
@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.26 2011/03/10 01:35:25 dpculp Exp $ @see Taylor, Charles Fayette, "The Internal Combustion Engine in Theory and Practice"
@version $Id: FGPiston.h,v 1.29 2011/06/16 16:32:10 jentron Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -250,7 +266,7 @@ private:
const double R_air; const double R_air;
const double rho_fuel; // kg/m^3 const double rho_fuel; // kg/m^3
const double calorific_value_fuel; // W/Kg (approximate) const double calorific_value_fuel; // J/Kg (approximate)
const double Cp_air; // J/KgK const double Cp_air; // J/KgK
const double Cp_fuel; // J/KgK const double Cp_fuel; // J/KgK
const double standard_pressure; //Pa const double standard_pressure; //Pa
@ -268,6 +284,7 @@ private:
double Displacement; // cubic inches double Displacement; // cubic inches
double displacement_SI; // cubic meters double displacement_SI; // cubic meters
double MaxHP; // horsepower double MaxHP; // horsepower
double StaticFriction_HP; // horsepower: amount subtracted from final engine power
double SparkFailDrop; // drop of power due to spark failure double SparkFailDrop; // drop of power due to spark failure
double Cycles; // cycles/power stroke double Cycles; // cycles/power stroke
double IdleRPM; // revolutions per minute double IdleRPM; // revolutions per minute
@ -284,29 +301,29 @@ private:
double Ram_Air_Factor; // number double Ram_Air_Factor; // number
double StarterHP; // initial horsepower of starter motor double StarterHP; // initial horsepower of starter motor
int BoostSpeeds; // Number of super/turbocharger boost speeds - zero implies no turbo/supercharging. int BoostSpeeds; // Number of super/turbocharger boost speeds - zero implies no turbo/supercharging.
int BoostSpeed; // The current boost-speed (zero-based). int BoostSpeed; // The current boost-speed (zero-based).
bool Boosted; // Set true for boosted engine. bool Boosted; // Set true for boosted engine.
int BoostManual; // The raw value read in from the config file - should be 1 or 0 - see description below. int BoostManual; // The raw value read in from the config file - should be 1 or 0 - see description below.
bool bBoostManual; // Set true if pilot must manually control the boost speed. bool bBoostManual; // Set true if pilot must manually control the boost speed.
int BoostOverride; // The raw value read in from the config file - should be 1 or 0 - see description below. int BoostOverride; // The raw value read in from the config file - should be 1 or 0 - see description below.
bool bBoostOverride; // Set true if pilot override of the boost regulator was fitted. bool bBoostOverride; // Set true if pilot override of the boost regulator was fitted.
// (Typically called 'war emergency power'). // (Typically called 'war emergency power').
bool bTakeoffBoost; // Set true if extra takeoff / emergency boost above rated boost could be attained. bool bTakeoffBoost; // Set true if extra takeoff / emergency boost above rated boost could be attained.
// (Typically by extra throttle movement past a mechanical 'gate'). // (Typically by extra throttle movement past a mechanical 'gate').
double TakeoffBoost; // Sea-level takeoff boost in psi. (if fitted). double TakeoffBoost; // Sea-level takeoff boost in psi. (if fitted).
double RatedBoost[FG_MAX_BOOST_SPEEDS]; // Sea-level rated boost in psi. double RatedBoost[FG_MAX_BOOST_SPEEDS]; // Sea-level rated boost in psi.
double RatedAltitude[FG_MAX_BOOST_SPEEDS]; // Altitude at which full boost is reached (boost regulation ends) double RatedAltitude[FG_MAX_BOOST_SPEEDS]; // Altitude at which full boost is reached (boost regulation ends)
// and at which power starts to fall with altitude [ft]. // and at which power starts to fall with altitude [ft].
double RatedRPM[FG_MAX_BOOST_SPEEDS]; // Engine speed at which the rated power for each boost speed is delivered [rpm]. double RatedRPM[FG_MAX_BOOST_SPEEDS]; // Engine speed at which the rated power for each boost speed is delivered [rpm].
double RatedPower[FG_MAX_BOOST_SPEEDS]; // Power at rated throttle position at rated altitude [HP]. double RatedPower[FG_MAX_BOOST_SPEEDS]; // Power at rated throttle position at rated altitude [HP].
double BoostSwitchAltitude[FG_MAX_BOOST_SPEEDS - 1]; // Altitude at which switchover (currently assumed automatic) double BoostSwitchAltitude[FG_MAX_BOOST_SPEEDS - 1]; // Altitude at which switchover (currently assumed automatic)
// from one boost speed to next occurs [ft]. // from one boost speed to next occurs [ft].
double BoostSwitchPressure[FG_MAX_BOOST_SPEEDS - 1]; // Pressure at which boost speed switchover occurs [Pa] double BoostSwitchPressure[FG_MAX_BOOST_SPEEDS - 1]; // Pressure at which boost speed switchover occurs [Pa]
double BoostMul[FG_MAX_BOOST_SPEEDS]; // Pressure multipier of unregulated supercharger double BoostMul[FG_MAX_BOOST_SPEEDS]; // Pressure multipier of unregulated supercharger
double RatedMAP[FG_MAX_BOOST_SPEEDS]; // Rated manifold absolute pressure [Pa] (BCV clamp) double RatedMAP[FG_MAX_BOOST_SPEEDS]; // Rated manifold absolute pressure [Pa] (BCV clamp)
double TakeoffMAP[FG_MAX_BOOST_SPEEDS]; // Takeoff setting manifold absolute pressure [Pa] (BCV clamp) double TakeoffMAP[FG_MAX_BOOST_SPEEDS]; // Takeoff setting manifold absolute pressure [Pa] (BCV clamp)
double BoostSwitchHysteresis; // Pa. double BoostSwitchHysteresis; // Pa.
double minMAP; // Pa double minMAP; // Pa
double maxMAP; // Pa double maxMAP; // Pa

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.33 2011/03/10 01:35:25 dpculp Exp $"; static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.34 2011/06/16 14:54:06 jentron Exp $";
static const char *IdHdr = ID_PROPELLER; static const char *IdHdr = ID_PROPELLER;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -102,8 +102,7 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
ConstantSpeed = (int)prop_element->FindElementValueAsNumber("constspeed"); ConstantSpeed = (int)prop_element->FindElementValueAsNumber("constspeed");
if (prop_element->FindElement("reversepitch")) if (prop_element->FindElement("reversepitch"))
ReversePitch = prop_element->FindElementValueAsNumber("reversepitch"); ReversePitch = prop_element->FindElementValueAsNumber("reversepitch");
for (int i=0; i<2; i++) { while(table_element = prop_element->FindNextElement("table")) {
table_element = prop_element->FindNextElement("table");
name = table_element->GetAttributeValue("name"); name = table_element->GetAttributeValue("name");
try { try {
if (name == "C_THRUST") { if (name == "C_THRUST") {
@ -121,6 +120,9 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
throw("Error loading propeller table:" + name + ". " + str); throw("Error loading propeller table:" + name + ". " + str);
} }
} }
if( (cPower == 0) || (cThrust == 0)){
cerr << "Propeller configuration must contain C_THRUST and C_POWER tables!" << endl;
}
local_element = prop_element->GetParent()->FindElement("sense"); local_element = prop_element->GetParent()->FindElement("sense");
if (local_element) { if (local_element) {
@ -132,7 +134,7 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
P_Factor = local_element->GetDataAsNumber(); P_Factor = local_element->GetDataAsNumber();
} }
if (P_Factor < 0) { if (P_Factor < 0) {
cerr << "P-Factor value in config file must be greater than zero" << endl; cerr << "P-Factor value in propeller configuration file must be greater than zero" << endl;
} }
if (prop_element->FindElement("ct_factor")) if (prop_element->FindElement("ct_factor"))
SetCtFactor( prop_element->FindElementValueAsNumber("ct_factor") ); SetCtFactor( prop_element->FindElementValueAsNumber("ct_factor") );
@ -424,10 +426,25 @@ void FGPropeller::Debug(int from)
cout << " Maximum Pitch = " << MaxPitch << endl; cout << " Maximum Pitch = " << MaxPitch << endl;
cout << " Minimum RPM = " << MinRPM << endl; cout << " Minimum RPM = " << MinRPM << endl;
cout << " Maximum RPM = " << MaxRPM << endl; cout << " Maximum RPM = " << MaxRPM << endl;
// Tables are being printed elsewhere...
// cout << " Thrust Coefficient: " << endl; // cout << " Thrust Coefficient: " << endl;
// cThrust->Print(); // cThrust->Print();
// cout << " Power Coefficient: " << endl; // cout << " Power Coefficient: " << endl;
// cPower->Print(); // cPower->Print();
// cout << " Mach Thrust Coefficient: " << endl;
// if(CtMach)
// {
// CtMach->Print();
// } else {
// cout << " NONE" << endl;
// }
// cout << " Mach Power Coefficient: " << endl;
// if(CpMach)
// {
// CpMach->Print();
// } else {
// cout << " NONE" << endl;
// }
} }
} }
if (debug_lvl & 2 ) { // Instantiation/Destruction notification if (debug_lvl & 2 ) { // Instantiation/Destruction notification

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPELLER "$Id: FGPropeller.h,v 1.17 2011/03/10 01:35:25 dpculp Exp $" #define ID_PROPELLER "$Id: FGPropeller.h,v 1.18 2011/06/06 22:39:52 jentron Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -62,6 +62,7 @@ CLASS DOCUMENTATION
<h3>Configuration File Format:</h3> <h3>Configuration File Format:</h3>
@code @code
<sense> {1 | -1} </sense>
<propeller name="{string}"> <propeller name="{string}">
<ixx> {number} </ixx> <ixx> {number} </ixx>
<diameter unit="IN"> {number} </diameter> <diameter unit="IN"> {number} </diameter>
@ -73,7 +74,6 @@ CLASS DOCUMENTATION
<maxrpm> {number} </maxrpm> <maxrpm> {number} </maxrpm>
<constspeed> {number} </constspeed> <constspeed> {number} </constspeed>
<reversepitch> {number} </reversepitch> <reversepitch> {number} </reversepitch>
<sense> {1 | -1} </sense>
<p_factor> {number} </p_factor> <p_factor> {number} </p_factor>
<ct_factor> {number} </ct_factor> <ct_factor> {number} </ct_factor>
<cp_factor> {number} </cp_factor> <cp_factor> {number} </cp_factor>
@ -119,7 +119,8 @@ CLASS DOCUMENTATION
\<constspeed> - 1 = constant speed mode, 0 = manual pitch mode. \<constspeed> - 1 = constant speed mode, 0 = manual pitch mode.
\<reversepitch> - Blade pitch angle for reverse. \<reversepitch> - Blade pitch angle for reverse.
\<sense> - Direction of rotation (1=clockwise as viewed from cockpit, \<sense> - Direction of rotation (1=clockwise as viewed from cockpit,
-1=anti-clockwise as viewed from cockpit). -1=anti-clockwise as viewed from cockpit). Sense is
specified in the parent tag of the propeller.
\<p_factor> - P factor. \<p_factor> - P factor.
\<ct_factor> - A multiplier for the coefficients of thrust. \<ct_factor> - A multiplier for the coefficients of thrust.
\<cp_factor> - A multiplier for the coefficients of power. \<cp_factor> - A multiplier for the coefficients of power.
@ -141,7 +142,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.17 2011/03/10 01:35:25 dpculp Exp $ @version $Id: FGPropeller.h,v 1.18 2011/06/06 22:39:52 jentron Exp $
@see FGEngine @see FGEngine
@see FGThruster @see FGThruster
*/ */

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGTank.cpp,v 1.28 2010/01/24 19:26:04 jberndt Exp $"; static const char *IdSrc = "$Id: FGTank.cpp,v 1.29 2011/06/06 22:39:52 jentron Exp $";
static const char *IdHdr = ID_TANK; static const char *IdHdr = ID_TANK;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -66,6 +66,7 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
InitialTemperature = Temperature = -9999.0; InitialTemperature = Temperature = -9999.0;
Ixx = Iyy = Izz = 0.0; Ixx = Iyy = Izz = 0.0;
Radius = Contents = Standpipe = Length = InnerRadius = 0.0; Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
ExternalFlow = 0.0;
InitialStandpipe = 0.0; InitialStandpipe = 0.0;
Capacity = 0.00001; Capacity = 0.00001;
Priority = InitialPriority = 1; Priority = InitialPriority = 1;
@ -162,6 +163,9 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
property_name = base_property_name + "/priority"; property_name = base_property_name + "/priority";
PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority, PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
&FGTank::SetPriority ); &FGTank::SetPriority );
property_name = base_property_name + "/external-flow-rate-pps";
PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
&FGTank::SetExternalFlow );
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);
@ -269,6 +273,9 @@ void FGTank::SetContentsGallons(double gallons)
double FGTank::Calculate(double dt) double FGTank::Calculate(double dt)
{ {
if(ExternalFlow < 0.) Drain( -ExternalFlow *dt);
else Fill(ExternalFlow * dt);
if (Temperature == -9999.0) return 0.0; if (Temperature == -9999.0) return 0.0;
double HeatCapacity = 900.0; // Joules/lbm/C double HeatCapacity = 900.0; // Joules/lbm/C
double TempFlowFactor = 1.115; // Watts/sqft/C double TempFlowFactor = 1.115; // Watts/sqft/C
@ -278,6 +285,7 @@ double FGTank::Calculate(double dt)
if (fabs(Tdiff) > 0.1) { if (fabs(Tdiff) > 0.1) {
dTemp = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity); dTemp = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity);
} }
return Temperature += (dTemp + dTemp); // For now, assume upper/lower the same return Temperature += (dTemp + dTemp); // For now, assume upper/lower the same
} }

View file

@ -52,7 +52,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TANK "$Id: FGTank.h,v 1.21 2010/02/05 05:53:00 jberndt Exp $" #define ID_TANK "$Id: FGTank.h,v 1.23 2011/06/13 15:23:09 jentron Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -100,7 +100,16 @@ CLASS DOCUMENTATION
tree at <tt>propulsion/tank[i]/contents-lbs</tt>, where i is the tank number (Tanks tree at <tt>propulsion/tank[i]/contents-lbs</tt>, where i is the tank number (Tanks
are automatically numbered, starting at zero, in the order in which they are read in are automatically numbered, starting at zero, in the order in which they are read in
the aircraft configuration file). The latter method allows one to use a system of FCS the aircraft configuration file). The latter method allows one to use a system of FCS
components to control tank contents. components to control tank contents.
There is also a property <tt>propulsion/tank[i]/external-flow-rate-pps</tt>. Setting
this property to a positive value causes the tank to fill at the rate specified.
Setting a negative number causes the tank to drain. The value is the rate in pounds
of fuel per second. The tank will not fill past 100% full and will not drain below 0%.
Fuel may be transfered between two tanks by setting the source tank's external flow rate
to a negative value and the destination's external flow rate to the same positive value.
Care must be taken to stop fuel flow before the source tank becomes empty to prevent
phantom fuel being created.
<h3>Configuration File Format:</h3> <h3>Configuration File Format:</h3>
@ -275,6 +284,9 @@ public:
double GetDensity(void) const {return Density;} double GetDensity(void) const {return Density;}
void SetDensity(double d) { Density = d; } void SetDensity(double d) { Density = d; }
double GetExternalFlow(void) const {return ExternalFlow;}
void SetExternalFlow(double f) { ExternalFlow = f; }
const FGColumnVector3 GetXYZ(void); const FGColumnVector3 GetXYZ(void);
const double GetXYZ(int idx); const double GetXYZ(int idx);
@ -309,6 +321,7 @@ private:
double Area; double Area;
double Temperature, InitialTemperature; double Temperature, InitialTemperature;
double Standpipe, InitialStandpipe; double Standpipe, InitialStandpipe;
double ExternalFlow;
bool Selected; bool Selected;
int Priority, InitialPriority; int Priority, InitialPriority;
FGFDMExec* Exec; FGFDMExec* Exec;

View file

@ -51,7 +51,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.31 2011/03/03 12:16:26 jberndt Exp $"; static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.32 2011/06/07 00:28:03 jentron Exp $";
static const char *IdHdr = ID_TURBINE; static const char *IdHdr = ID_TURBINE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -360,7 +360,7 @@ double FGTurbine::Seize(void)
double FGTurbine::Trim() double FGTurbine::Trim()
{ {
double idlethrust, milthrust, thrust, tdiff; double idlethrust, milthrust, thrust, tdiff, N2, N2norm;
idlethrust = MilThrust * IdleThrustLookup->GetValue(); idlethrust = MilThrust * IdleThrustLookup->GetValue();
milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue(); milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
N2 = IdleN2 + ThrottlePos * N2_factor; N2 = IdleN2 + ThrottlePos * N2_factor;

View file

@ -42,7 +42,7 @@ INCLUDES
#include "FGEngine.h" #include "FGEngine.h"
#define ID_TURBINE "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $" #define ID_TURBINE "$Id: FGTurbine.h,v 1.20 2011/06/07 00:28:03 jentron Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -93,6 +93,8 @@ CLASS DOCUMENTATION
<atsfc> {number} </atsfc> <atsfc> {number} </atsfc>
<idlen1> {number} </idlen1> <idlen1> {number} </idlen1>
<idlen2> {number} </idlen2> <idlen2> {number} </idlen2>
<n1spinup> {number} </n1spinup>
<n2spinup> {number} </n2spinup>
<maxn1> {number} </maxn1> <maxn1> {number} </maxn1>
<maxn2> {number} </maxn2> <maxn2> {number} </maxn2>
<augmented> {0 | 1} </augmented> <augmented> {0 | 1} </augmented>
@ -113,6 +115,8 @@ CLASS DOCUMENTATION
atsfc - Afterburning TSFC, lbm/hr/lbf atsfc - Afterburning TSFC, lbm/hr/lbf
idlen1 - Fan rotor rpm (% of max) at idle idlen1 - Fan rotor rpm (% of max) at idle
idlen2 - Core rotor rpm (% of max) at idle idlen2 - Core rotor rpm (% of max) at idle
n1spinup - Fan rotor rpm starter acceleration (default 1.0)
n2spinup - Core rotor rpm starter acceleration (default 3.0)
maxn1 - Fan rotor rpm (% of max) at full throttle maxn1 - Fan rotor rpm (% of max) at full throttle
maxn2 - Core rotor rpm (% of max) at full throttle maxn2 - Core rotor rpm (% of max) at full throttle
augmented augmented
@ -146,7 +150,7 @@ CLASS DOCUMENTATION
/engine/direct.xml /engine/direct.xml
</pre> </pre>
@author David P. Culp @author David P. Culp
@version "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $" @version "$Id: FGTurbine.h,v 1.20 2011/06/07 00:28:03 jentron Exp $"
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%