1
0
Fork 0

Syncing with the very latest JSBSim development code.

This commit is contained in:
curt 2001-10-05 20:19:59 +00:00
parent 2297c706e8
commit ba10c133fc
84 changed files with 2972 additions and 1876 deletions

View file

@ -43,8 +43,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_AERODYNAMICS; static const char *IdHdr = ID_AERODYNAMICS;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -109,16 +107,14 @@ bool FGAerodynamics::Run(void)
vForces = State->GetTs2b(alpha, beta)*vFs; vForces = State->GetTs2b(alpha, beta)*vFs;
// see http://home.earthlink.net/~apeden/jsbsim_moments_due_to_forces.txt vDXYZcg(eX) = -(Aircraft->GetXYZrp(eX)
// for details on this - MassBalance->GetXYZcg(eX))*INCHTOFT;
vDXYZcg(eY) = (Aircraft->GetXYZrp(eY)
- MassBalance->GetXYZcg(eY))*INCHTOFT;
vDXYZcg(eZ) = -(Aircraft->GetXYZrp(eZ)
- MassBalance->GetXYZcg(eZ))*INCHTOFT;
vDXYZcg(eX) = -(Aircraft->GetXYZrp(eX) - MassBalance->GetXYZcg(eX))/12.0; vMoments = vDXYZcg*vForces; // M = r X F
vDXYZcg(eY) = (Aircraft->GetXYZrp(eY) - MassBalance->GetXYZcg(eY))/12.0;
vDXYZcg(eZ) = -(Aircraft->GetXYZrp(eZ) - MassBalance->GetXYZcg(eZ))/12.0;
vMoments(eL) = vForces(eZ)*vDXYZcg(eY) - vForces(eY)*vDXYZcg(eZ);
vMoments(eM) = vForces(eX)*vDXYZcg(eZ) - vForces(eZ)*vDXYZcg(eX);
vMoments(eN) = vForces(eY)*vDXYZcg(eX) - vForces(eX)*vDXYZcg(eY);
for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) { for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) { for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) {

View file

@ -111,15 +111,17 @@ public:
/** Gets the total aerodynamic force vector. /** Gets the total aerodynamic force vector.
@return a force vector reference. */ @return a force vector reference. */
FGColumnVector& GetForces(void) {return vForces;} FGColumnVector3& GetForces(void) {return vForces;}
inline float GetForces(int n) {return vForces(n);}
/** Gets the total aerodynamic moment vector. /** Gets the total aerodynamic moment vector.
@return a moment vector reference. */ @return a moment vector reference. */
FGColumnVector& GetMoments(void) {return vMoments;} FGColumnVector3& GetMoments(void) {return vMoments;}
inline float GetMoments(int n) {return vMoments(n);}
inline FGColumnVector GetvLastFs(void) { return vLastFs; } inline FGColumnVector3& GetvLastFs(void) { return vLastFs; }
inline float GetvLastFs(int axis) { return vLastFs(axis); } inline float GetvLastFs(int axis) { return vLastFs(axis); }
inline FGColumnVector GetvFs(void) { return vFs; } inline FGColumnVector3& GetvFs(void) { return vFs; }
inline float GetvFs(int axis) { return vFs(axis); } inline float GetvFs(int axis) { return vFs(axis); }
float GetLoD(void); float GetLoD(void);
@ -140,11 +142,11 @@ private:
AxisIndex AxisIdx; AxisIndex AxisIdx;
typedef vector<FGCoefficient*> CoeffArray; typedef vector<FGCoefficient*> CoeffArray;
CoeffArray* Coeff; CoeffArray* Coeff;
FGColumnVector vFs; FGColumnVector3 vFs;
FGColumnVector vForces; FGColumnVector3 vForces;
FGColumnVector vMoments; FGColumnVector3 vMoments;
FGColumnVector vLastFs; FGColumnVector3 vLastFs;
FGColumnVector vDXYZcg; FGColumnVector3 vDXYZcg;
void Debug(void); void Debug(void);
}; };

View file

@ -43,59 +43,6 @@ HISTORY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate
School, January 1994
[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
JSC 12960, July 1977
[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
NASA-Ames", NASA CR-2497, January 1975
[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
Wiley & Sons, 1979 ISBN 0-471-03032-5
[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
1982 ISBN 0-471-08936-2
The aerodynamic coefficients used in this model are:
Longitudinal
CL0 - Reference lift at zero alpha
CD0 - Reference drag at zero alpha
CDM - Drag due to Mach
CLa - Lift curve slope (w.r.t. alpha)
CDa - Drag curve slope (w.r.t. alpha)
CLq - Lift due to pitch rate
CLM - Lift due to Mach
CLadt - Lift due to alpha rate
Cmadt - Pitching Moment due to alpha rate
Cm0 - Reference Pitching moment at zero alpha
Cma - Pitching moment slope (w.r.t. alpha)
Cmq - Pitch damping (pitch moment due to pitch rate)
CmM - Pitch Moment due to Mach
Lateral
Cyb - Side force due to sideslip
Cyr - Side force due to yaw rate
Clb - Dihedral effect (roll moment due to sideslip)
Clp - Roll damping (roll moment due to roll rate)
Clr - Roll moment due to yaw rate
Cnb - Weathercocking stability (yaw moment due to sideslip)
Cnp - Rudder adverse yaw (yaw moment due to roll rate)
Cnr - Yaw damping (yaw moment due to yaw rate)
Control
CLDe - Lift due to elevator
CDDe - Drag due to elevator
CyDr - Side force due to rudder
CyDa - Side force due to aileron
CmDe - Pitch moment due to elevator
ClDa - Roll moment due to aileron
ClDr - Roll moment due to rudder
CnDr - Yaw moment due to rudder
CnDa - Yaw moment due to aileron
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES INCLUDES
@ -114,12 +61,17 @@ INCLUDES
# include <math.h> # include <math.h>
# endif # endif
#else #else
# include <cmath> # if defined (sgi) && !defined(__GNUC__)
# include <math.h>
# else
# include <cmath>
# endif
#endif #endif
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "FGInertial.h" #include "FGInertial.h"
#include "FGGroundReactions.h"
#include "FGAerodynamics.h" #include "FGAerodynamics.h"
#include "FGTranslation.h" #include "FGTranslation.h"
#include "FGRotation.h" #include "FGRotation.h"
@ -142,20 +94,6 @@ GLOBAL DATA
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_AIRCRAFT; static const char *IdHdr = ID_AIRCRAFT;
extern char highint[5];
extern char halfint[5];
extern char normint[6];
extern char reset[5];
extern char underon[5];
extern char underoff[6];
extern char fgblue[6];
extern char fgcyan[6];
extern char fgred[6];
extern char fggreen[6];
extern char fgdef[6];
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -165,15 +103,15 @@ FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex),
vForces(3), vForces(3),
vXYZrp(3), vXYZrp(3),
vXYZep(3), vXYZep(3),
vEuler(3),
vDXYZcg(3), vDXYZcg(3),
vAeroBodyForces(3) vBodyAccel(3)
{ {
Name = "FGAircraft"; Name = "FGAircraft";
GearUp = false; GearUp = false;
alphaclmin = alphaclmax = 0; alphaclmin = alphaclmax = 0;
HTailArea = VTailArea = HTailArm = VTailArm = 0.0;
lbarh = lbarv = vbarh = vbarv = 0.0;
WingIncidence=0;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
} }
@ -217,7 +155,7 @@ bool FGAircraft::Load(FGConfigFile* AC_cfg)
ReadOutput(AC_cfg); ReadOutput(AC_cfg);
} }
} }
return true; return true;
} }
@ -226,16 +164,19 @@ bool FGAircraft::Load(FGConfigFile* AC_cfg)
bool FGAircraft::Run(void) bool FGAircraft::Run(void)
{ {
if (!FGModel::Run()) { // if false then execute this Run() if (!FGModel::Run()) { // if false then execute this Run()
GetState();
vForces.InitMatrix(); vForces.InitMatrix();
vForces += Aerodynamics->GetForces();
vForces += Inertial->GetForces();
vForces += Propulsion->GetForces();
vForces += GroundReactions->GetForces();
vMoments.InitMatrix(); vMoments.InitMatrix();
vMoments += Aerodynamics->GetMoments();
FMProp(); vMoments += Propulsion->GetMoments();
FMAero(); vMoments += GroundReactions->GetMoments();
FMMass();
FMGear(); vBodyAccel = vForces/MassBalance->GetMass();
return false; return false;
} else { // skip Run() execution this time } else { // skip Run() execution this time
return true; return true;
@ -244,62 +185,12 @@ bool FGAircraft::Run(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::FMAero(void)
{
vForces += Aerodynamics->GetForces();
vMoments += Aerodynamics->GetMoments();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::FMGear(void)
{
if ( !GearUp ) {
vector <FGLGear>::iterator iGear = lGear.begin();
while (iGear != lGear.end()) {
vForces += iGear->Force();
vMoments += iGear->Moment();
iGear++;
}
} else {
// Crash Routine
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::FMMass(void)
{
vForces += Inertial->GetForces();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::FMProp(void)
{
vForces += Propulsion->GetForces();
vMoments += Propulsion->GetMoments();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::GetState(void)
{
dt = State->Getdt();
alpha = Translation->Getalpha();
beta = Translation->Getbeta();
vEuler = Rotation->GetEuler();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::ReadMetrics(FGConfigFile* AC_cfg) void FGAircraft::ReadMetrics(FGConfigFile* AC_cfg)
{ {
string token = ""; string token = "";
string parameter; string parameter;
float EW, bixx, biyy, bizz, bixz, biyz; float EW, bixx, biyy, bizz, bixz, biyz;
FGColumnVector vbaseXYZcg(3); FGColumnVector3 vbaseXYZcg(3);
AC_cfg->GetNextConfigLine(); AC_cfg->GetNextConfigLine();
@ -311,9 +202,24 @@ void FGAircraft::ReadMetrics(FGConfigFile* AC_cfg)
} else if (parameter == "AC_WINGSPAN") { } else if (parameter == "AC_WINGSPAN") {
*AC_cfg >> WingSpan; *AC_cfg >> WingSpan;
if (debug_lvl > 0) cout << " WingSpan: " << WingSpan << endl; if (debug_lvl > 0) cout << " WingSpan: " << WingSpan << endl;
} else if (parameter == "AC_WINGINCIDENCE") {
*AC_cfg >> WingIncidence;
if (debug_lvl > 0) cout << " Chord: " << cbar << endl;
} else if (parameter == "AC_CHORD") { } else if (parameter == "AC_CHORD") {
*AC_cfg >> cbar; *AC_cfg >> cbar;
if (debug_lvl > 0) cout << " Chord: " << cbar << endl; if (debug_lvl > 0) cout << " Chord: " << cbar << endl;
} else if (parameter == "AC_HTAILAREA") {
*AC_cfg >> HTailArea;
if (debug_lvl > 0) cout << " H. Tail Area: " << HTailArea << endl;
} else if (parameter == "AC_HTAILARM") {
*AC_cfg >> HTailArm;
if (debug_lvl > 0) cout << " H. Tail Arm: " << HTailArm << endl;
} else if (parameter == "AC_VTAILAREA") {
*AC_cfg >> VTailArea;
if (debug_lvl > 0) cout << " V. Tail Area: " << VTailArea << endl;
} else if (parameter == "AC_VTAILARM") {
*AC_cfg >> VTailArm;
if (debug_lvl > 0) cout << " V. Tail Arm: " << VTailArm << endl;
} else if (parameter == "AC_IXX") { } else if (parameter == "AC_IXX") {
*AC_cfg >> bixx; *AC_cfg >> bixx;
if (debug_lvl > 0) cout << " baseIxx: " << bixx << endl; if (debug_lvl > 0) cout << " baseIxx: " << bixx << endl;
@ -355,11 +261,23 @@ void FGAircraft::ReadMetrics(FGConfigFile* AC_cfg)
<< endl; << endl;
} }
} }
// calculate some derived parameters
if (cbar != 0.0) {
lbarh = HTailArm/cbar;
lbarv = VTailArm/cbar;
if (WingArea != 0.0) {
vbarh = HTailArm*HTailArea / (cbar*WingArea);
vbarv = VTailArm*VTailArea / (cbar*WingArea);
}
}
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::ReadPropulsion(FGConfigFile* AC_cfg) { void FGAircraft::ReadPropulsion(FGConfigFile* AC_cfg)
{
if (!Propulsion->Load(AC_cfg)) { if (!Propulsion->Load(AC_cfg)) {
cerr << "Propulsion not successfully loaded" << endl; cerr << "Propulsion not successfully loaded" << endl;
} }
@ -367,7 +285,8 @@ void FGAircraft::ReadPropulsion(FGConfigFile* AC_cfg) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::ReadFlightControls(FGConfigFile* AC_cfg) { void FGAircraft::ReadFlightControls(FGConfigFile* AC_cfg)
{
if (!FCS->Load(AC_cfg)) { if (!FCS->Load(AC_cfg)) {
cerr << "Flight Controls not successfully loaded" << endl; cerr << "Flight Controls not successfully loaded" << endl;
} }
@ -380,24 +299,21 @@ void FGAircraft::ReadAerodynamics(FGConfigFile* AC_cfg)
if (!Aerodynamics->Load(AC_cfg)) { if (!Aerodynamics->Load(AC_cfg)) {
cerr << "Aerodynamics not successfully loaded" << endl; cerr << "Aerodynamics not successfully loaded" << endl;
} }
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::ReadUndercarriage(FGConfigFile* AC_cfg) { void FGAircraft::ReadUndercarriage(FGConfigFile* AC_cfg)
string token; {
if (!GroundReactions->Load(AC_cfg)) {
AC_cfg->GetNextConfigLine(); cerr << "Ground Reactions not successfully loaded" << endl;
while ((token = AC_cfg->GetValue()) != "/UNDERCARRIAGE") {
lGear.push_back(FGLGear(AC_cfg, FDMExec));
} }
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::ReadOutput(FGConfigFile* AC_cfg) { void FGAircraft::ReadOutput(FGConfigFile* AC_cfg)
{
string token, parameter; string token, parameter;
int OutRate = 0; int OutRate = 0;
int subsystems = 0; int subsystems = 0;
@ -473,7 +389,8 @@ void FGAircraft::ReadOutput(FGConfigFile* AC_cfg) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg) { void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg)
{
string token = AC_cfg->GetValue(); string token = AC_cfg->GetValue();
string scratch; string scratch;
AircraftName = AC_cfg->GetValue("NAME"); AircraftName = AC_cfg->GetValue("NAME");
@ -496,46 +413,6 @@ void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGAircraft::GetGroundReactionStrings(void) {
string GroundReactionStrings = "";
bool firstime = true;
for (unsigned int i=0;i<lGear.size();i++) {
if (!firstime) GroundReactionStrings += ", ";
GroundReactionStrings += (lGear[i].GetName() + "_WOW, ");
GroundReactionStrings += (lGear[i].GetName() + "_compressLength, ");
GroundReactionStrings += (lGear[i].GetName() + "_compressSpeed, ");
GroundReactionStrings += (lGear[i].GetName() + "_Force");
firstime = false;
}
return GroundReactionStrings;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGAircraft::GetGroundReactionValues(void) {
char buff[20];
string GroundReactionValues = "";
bool firstime = true;
for (unsigned int i=0;i<lGear.size();i++) {
if (!firstime) GroundReactionValues += ", ";
GroundReactionValues += string( lGear[i].GetWOW()?"1":"0" ) + ", ";
GroundReactionValues += (string(gcvt(lGear[i].GetCompLen(), 5, buff)) + ", ");
GroundReactionValues += (string(gcvt(lGear[i].GetCompVel(), 6, buff)) + ", ");
GroundReactionValues += (string(gcvt(lGear[i].GetCompForce(), 10, buff)));
firstime = false;
}
return GroundReactionValues;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::Debug(void) void FGAircraft::Debug(void)
{ {
//TODO: Add your source code here //TODO: Add your source code here

View file

@ -55,7 +55,9 @@ INCLUDES
#include "FGModel.h" #include "FGModel.h"
#include "FGPropulsion.h" #include "FGPropulsion.h"
#include "FGConfigFile.h" #include "FGConfigFile.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
#include "FGLGear.h" #include "FGLGear.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -70,9 +72,48 @@ FORWARD DECLARATIONS
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Longitudinal
CL0 - Reference lift at zero alpha
CD0 - Reference drag at zero alpha
CDM - Drag due to Mach
CLa - Lift curve slope (w.r.t. alpha)
CDa - Drag curve slope (w.r.t. alpha)
CLq - Lift due to pitch rate
CLM - Lift due to Mach
CLadt - Lift due to alpha rate
Cmadt - Pitching Moment due to alpha rate
Cm0 - Reference Pitching moment at zero alpha
Cma - Pitching moment slope (w.r.t. alpha)
Cmq - Pitch damping (pitch moment due to pitch rate)
CmM - Pitch Moment due to Mach
Lateral
Cyb - Side force due to sideslip
Cyr - Side force due to yaw rate
Clb - Dihedral effect (roll moment due to sideslip)
Clp - Roll damping (roll moment due to roll rate)
Clr - Roll moment due to yaw rate
Cnb - Weathercocking stability (yaw moment due to sideslip)
Cnp - Rudder adverse yaw (yaw moment due to roll rate)
Cnr - Yaw damping (yaw moment due to yaw rate)
Control
CLDe - Lift due to elevator
CDDe - Drag due to elevator
CyDr - Side force due to rudder
CyDa - Side force due to aileron
CmDe - Pitch moment due to elevator
ClDa - Roll moment due to aileron
ClDr - Roll moment due to rudder
CnDr - Yaw moment due to rudder
CnDa - Yaw moment due to aileron
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -107,11 +148,6 @@ CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGAircraft : public FGModel { class FGAircraft : public FGModel {
enum {eL=1, eM, eN};
enum {eX=1, eY, eZ};
enum {eP=1, eQ, eR};
enum {ePhi=1, eTht, ePsi};
public: public:
/** Constructor /** Constructor
@param Executive a pointer to the parent executive object */ @param Executive a pointer to the parent executive object */
@ -151,12 +187,20 @@ public:
inline float GetWingSpan(void) { return WingSpan; } inline float GetWingSpan(void) { return WingSpan; }
/// Gets the average wing chord /// Gets the average wing chord
inline float Getcbar(void) { return cbar; } inline float Getcbar(void) { return cbar; }
inline FGColumnVector GetMoments(void) { return vMoments; } inline float GetWingIncidence(void) { return WingIncidence; }
inline FGColumnVector GetForces(void) { return vForces; } inline float GetHTailArea(void) { return HTailArea; }
inline FGColumnVector GetAeroBodyForces(void) { return vAeroBodyForces; } inline float GetHTailArm(void) { return HTailArm; }
inline float GetAeroBodyForces(int axis) { return vAeroBodyForces(axis); } inline float GetVTailArea(void) { return VTailArea; }
inline FGColumnVector GetXYZrp(void) { return vXYZrp; } inline float GetVTailArm(void) { return VTailArm; }
inline FGColumnVector GetXYZep(void) { return vXYZep; } inline float Getlbarh(void) { return lbarh; } // HTailArm / cbar
inline float Getlbarv(void) { return lbarv; } // VTailArm / cbar
inline float Getvbarh(void) { return vbarh; } // H. Tail Volume
inline float Getvbarv(void) { return vbarv; } // V. Tail Volume
inline FGColumnVector3& GetMoments(void) { return vMoments; }
inline FGColumnVector3& GetForces(void) { return vForces; }
inline FGColumnVector3& GetBodyAccel(void) { return vBodyAccel; }
inline FGColumnVector3& GetXYZrp(void) { return vXYZrp; }
inline FGColumnVector3& GetXYZep(void) { return vXYZep; }
inline float GetXYZrp(int idx) { return vXYZrp(idx); } inline float GetXYZrp(int idx) { return vXYZrp(idx); }
inline float GetXYZep(int idx) { return vXYZep(idx); } inline float GetXYZep(int idx) { return vXYZep(idx); }
inline float GetAlphaCLMax(void) { return alphaclmax; } inline float GetAlphaCLMax(void) { return alphaclmax; }
@ -168,9 +212,6 @@ public:
inline void SetAlphaCLMax(float tt) { alphaclmax=tt; } inline void SetAlphaCLMax(float tt) { alphaclmax=tt; }
inline void SetAlphaCLMin(float tt) { alphaclmin=tt; } inline void SetAlphaCLMin(float tt) { alphaclmin=tt; }
string GetGroundReactionStrings(void);
string GetGroundReactionValues(void);
/// Subsystem types for specifying which will be output in the FDM data logging /// Subsystem types for specifying which will be output in the FDM data logging
enum SubSystems { enum SubSystems {
/** Subsystem: Simulation (= 1) */ ssSimulation = 1, /** Subsystem: Simulation (= 1) */ ssSimulation = 1,
@ -189,22 +230,17 @@ public:
} subsystems; } subsystems;
private: private:
void GetState(void); FGColumnVector3 vMoments;
void FMAero(void); FGColumnVector3 vForces;
void FMGear(void); FGColumnVector3 vXYZrp;
void FMMass(void); FGColumnVector3 vXYZep;
void FMProp(void); FGColumnVector3 vEuler;
FGColumnVector vMoments; FGColumnVector3 vDXYZcg;
FGColumnVector vForces; FGColumnVector3 vBodyAccel;
FGColumnVector vXYZrp; float WingArea, WingSpan, cbar, WingIncidence;
FGColumnVector vXYZep; float HTailArea, VTailArea, HTailArm, VTailArm;
FGColumnVector vEuler; float lbarh,lbarv,vbarh,vbarv;
FGColumnVector vDXYZcg;
FGColumnVector vAeroBodyForces;
float alpha, beta;
float WingArea, WingSpan, cbar;
float alphaclmax,alphaclmin; float alphaclmax,alphaclmin;
float dt;
string CFGVersion; string CFGVersion;
string AircraftName; string AircraftName;

View file

@ -57,13 +57,13 @@ INCLUDES
#include "FGAuxiliary.h" #include "FGAuxiliary.h"
#include "FGOutput.h" #include "FGOutput.h"
#include "FGDefs.h" #include "FGDefs.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ATMOSPHERE; static const char *IdHdr = ID_ATMOSPHERE;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -73,12 +73,26 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex),
vWindNED(3) vWindNED(3)
{ {
Name = "FGAtmosphere"; Name = "FGAtmosphere";
lastIndex=0;
h = 0; h = 0;
htab[0]=0;
htab[1]=36089.239;
htab[2]=65616.798;
htab[3]=104986.878;
htab[4]=154199.475;
htab[5]=170603.675;
htab[6]=200131.234;
htab[7]=259186.352; //ft.
Calculate(h); Calculate(h);
SLtemperature = temperature; SLtemperature = temperature;
SLpressure = pressure; SLpressure = pressure;
SLdensity = density; SLdensity = density;
SLsoundspeed = sqrt(SHRATIO*Reng*temperature); SLsoundspeed = sqrt(SHRATIO*Reng*temperature);
rSLtemperature = 1.0/temperature;
rSLpressure = 1.0/pressure;
rSLdensity = 1.0/density;
rSLsoundspeed = 1.0/SLsoundspeed;
useExternal=false; useExternal=false;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
@ -95,13 +109,10 @@ FGAtmosphere::~FGAtmosphere()
bool FGAtmosphere::Run(void) bool FGAtmosphere::Run(void)
{ {
//cout << "In FGAtmosphere::Run(void)" << endl;
if (!FGModel::Run()) { // if false then execute this Run() if (!FGModel::Run()) { // if false then execute this Run()
//do temp, pressure, and density first //do temp, pressure, and density first
if (!useExternal) { if (!useExternal) {
//cout << "Atmosphere: Using internal model, altitude= ";
h = Position->Geth(); h = Position->Geth();
Calculate(h); Calculate(h);
} else { } else {
density = exDensity; density = exDensity;
@ -114,7 +125,7 @@ bool FGAtmosphere::Run(void)
if (psiw < 0) psiw += 2*M_PI; if (psiw < 0) psiw += 2*M_PI;
soundspeed = sqrt(SHRATIO*Reng*temperature); soundspeed = sqrt(SHRATIO*Reng*temperature);
//cout << "Atmosphere: soundspeed: " << soundspeed << endl;
State->Seta(soundspeed); State->Seta(soundspeed);
} else { // skip Run() execution this time } else { // skip Run() execution this time
@ -128,84 +139,90 @@ void FGAtmosphere::Calculate(float altitude)
{ {
//see reference [1] //see reference [1]
float slope,reftemp,refpress,refdens; float slope,reftemp,refpress;
int i=0; int i=0; bool lookup = false;
float htab[]={0,36089,82020,154198,173882,259183,295272,344484}; //ft.
// cout << "Atmosphere: h=" << altitude << " rho= " << density << endl; // cout << "Atmosphere: h=" << altitude << " rho= " << density << endl;
if (altitude <= htab[0]) { i=lastIndex;
altitude=0; if(altitude < htab[lastIndex]) {
} else if (altitude >= htab[7]){ if (altitude <= 0) {
i = 7; i=0; altitude=0;
altitude = htab[7]; } else {
} else { i=lastIndex-1;
while (htab[i+1] < altitude) { while (htab[i] > altitude) { i--; }
i++; }
} } else if (altitude > htab[lastIndex+1]){
} if (altitude >= htab[7]){
i = 7; altitude = htab[7];
} else {
i=lastIndex+1;
while(htab[i+1] < altitude) { i++; }
}
}
switch(i) { switch(i) {
case 0: // sea level case 0: // sea level
slope = -0.0035662; // R/ft. slope = -0.00356616; // R/ft.
reftemp = 518.688; // R reftemp = 518.67; // R
refpress = 2116.17; // psf refpress = 2116.22; // psf
refdens = 0.0023765; // slugs/cubic ft. //refdens = 0.00237767; // slugs/cubic ft.
break; break;
case 1: // 36089 ft. case 1: // 36089 ft.
slope = 0; slope = 0;
reftemp = 389.988; reftemp = 389.97;
refpress = 474.1; refpress = 472.452;
refdens = 0.0007078; //refdens = 0.000706032;
break; break;
case 2: // 82020 ft. case 2: // 65616 ft.
slope = 0.00164594; slope = 0.00054864;
reftemp = 389.988; reftemp = 389.97;
refpress = 52.7838; refpress = 114.636;
refdens = 7.8849E-5; //refdens = 0.000171306;
break; break;
case 3: // 154198 ft. case 3: // 104986 ft.
slope = 0.00153619;
reftemp = 411.57;
refpress = 8.36364;
//refdens = 1.18422e-05;
break;
case 4: // 154199 ft.
slope = 0; slope = 0;
reftemp = 508.788; reftemp = 487.17;
refpress = 2.62274; refpress = 0.334882;
refdens = 3.01379E-6; //refdens = 4.00585e-7;
break; break;
case 4: // 173882 ft. case 5: // 170603 ft.
slope = -0.00246891; slope = -0.00109728;
reftemp = 508.788; reftemp = 487.17;
refpress = 1.28428; refpress = 0.683084;
refdens = 1.47035e-06; //refdens = 8.17102e-7;
break; break;
case 5: // 259183 ft. case 6: // 200131 ft.
slope = -0.00219456;
reftemp = 454.17;
refpress = 0.00684986;
//refdens = 8.77702e-9;
break;
case 7: // 259186 ft.
slope = 0; slope = 0;
reftemp = 298.188; reftemp = 325.17;
refpress = 0.0222008; refpress = 0.000122276;
refdens = 4.33396e-08; //refdens = 2.19541e-10;
break;
case 6: // 295272 ft.
slope = 0.00219459;
reftemp = 298.188;
refpress = 0.00215742;
refdens = 4.21368e-09;
break;
case 7: // 344484 ft.
slope = 0;
reftemp = 406.188;
refpress = 0.000153755;
refdens = 2.20384e-10;
break; break;
} }
if (slope == 0) { if (slope == 0) {
temperature = reftemp; temperature = reftemp;
pressure = refpress*exp(-GRAVITY/(reftemp*Reng)*(altitude-htab[i])); pressure = refpress*exp(-GRAVITY/(reftemp*Reng)*(altitude-htab[i]));
density = refdens*exp(-GRAVITY/(reftemp*Reng)*(altitude-htab[i])); //density = refdens*exp(-GRAVITY/(reftemp*Reng)*(altitude-htab[i]));
density = pressure/(Reng*temperature);
} else { } else {
temperature = reftemp+slope*(altitude-htab[i]); temperature = reftemp+slope*(altitude-htab[i]);
pressure = refpress*pow(temperature/reftemp,-GRAVITY/(slope*Reng)); pressure = refpress*pow(temperature/reftemp,-GRAVITY/(slope*Reng));
density = refdens*pow(temperature/reftemp,-(GRAVITY/(slope*Reng)+1)); //density = refdens*pow(temperature/reftemp,-(GRAVITY/(slope*Reng)+1));
density = pressure/(Reng*temperature);
} }
lastIndex=i;
//cout << "Atmosphere: h=" << altitude << " rho= " << density << endl; //cout << "Atmosphere: h=" << altitude << " rho= " << density << endl;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -43,69 +43,116 @@ INCLUDES
*******************************************************************************/ *******************************************************************************/
#include "FGModel.h" #include "FGModel.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ATMOSPHERE "$Id$" #define ID_ATMOSPHERE "$Id$"
/******************************************************************************* /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES FORWARD DECLARATIONS
******************************************************************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1] Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill, [1] Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0 1989, ISBN 0-07-001641-0
******************************************************************************* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models the standard atmosphere.
@author Tony Peden, Jon Berndt
@version $Id$
*/
/******************************************************************************
CLASS DECLARATION CLASS DECLARATION
*******************************************************************************/ *******************************************************************************/
class FGAtmosphere : public FGModel { class FGAtmosphere : public FGModel {
public: public:
/// Constructor
FGAtmosphere(FGFDMExec*); FGAtmosphere(FGFDMExec*);
/// Destructor
~FGAtmosphere(); ~FGAtmosphere();
/** Runs the Atmosphere model; called by the Executive
@return false if no error */
bool Run(void); bool Run(void);
/// Returns the temperature in degrees Rankine.
inline float GetTemperature(void) {return temperature;} inline float GetTemperature(void) {return temperature;}
inline float GetDensity(void) {return density;} // use only after Run() has been called /** Returns the density in slugs/ft^3.
<i>This function may <b>only</b> be used if Run() is called first.</i> */
inline float GetDensity(void) {return density;}
/// Returns the pressure in psf.
inline float GetPressure(void) {return pressure;} inline float GetPressure(void) {return pressure;}
/// Returns the speed of sound in ft/sec.
inline float GetSoundSpeed(void) {return soundspeed;} inline float GetSoundSpeed(void) {return soundspeed;}
inline float GetTemperatureSL(void) { return SLtemperature; } //Rankine, altitude in feet /// Returns the sea level temperature in degrees Rankine.
inline float GetDensitySL(void) { return SLdensity; } //slugs/ft^3 inline float GetTemperatureSL(void) { return SLtemperature; }
inline float GetPressureSL(void) { return SLpressure; } //lbs/ft^2 /// Returns the sea level density in slugs/ft^3
inline float GetSoundSpeedSL(void) { return SLsoundspeed; } //ft/s inline float GetDensitySL(void) { return SLdensity; }
/// Returns the sea level pressure in psf.
inline float GetPressureSL(void) { return SLpressure; }
/// Returns the sea level speed of sound in ft/sec.
inline float GetSoundSpeedSL(void) { return SLsoundspeed; }
inline float GetTemperatureRatio(void) { return temperature/SLtemperature; } /// Returns the ratio of at-altitude temperature over the sea level value.
inline float GetDensityRatio(void) { return density/SLdensity; } inline float GetTemperatureRatio(void) { return temperature*rSLtemperature; }
inline float GetPressureRatio(void) { return pressure/SLpressure; } /// Returns the ratio of at-altitude density over the sea level value.
inline float GetSoundSpeedRatio(void) { return soundspeed/SLsoundspeed; } inline float GetDensityRatio(void) { return density*rSLdensity; }
/// Returns the ratio of at-altitude pressure over the sea level value.
inline float GetPressureRatio(void) { return pressure*rSLpressure; }
/// Returns the ratio of at-altitude sound speed over the sea level value.
inline float GetSoundSpeedRatio(void) { return soundspeed*rSLsoundspeed; }
/// Tells the simulator to use an externally calculated atmosphere model.
inline void UseExternal(void) { useExternal=true; } inline void UseExternal(void) { useExternal=true; }
/// Tells the simulator to use the internal atmosphere model.
inline void UseInternal(void) { useExternal=false; } //this is the default inline void UseInternal(void) { useExternal=false; } //this is the default
/// Gets the boolean that tells if the external atmosphere model is being used.
bool External(void) { return useExternal; } bool External(void) { return useExternal; }
/// Provides the external atmosphere model with an interface to set the temperature.
inline void SetExTemperature(float t) { exTemperature=t; } inline void SetExTemperature(float t) { exTemperature=t; }
/// Provides the external atmosphere model with an interface to set the density.
inline void SetExDensity(float d) { exDensity=d; } inline void SetExDensity(float d) { exDensity=d; }
/// Provides the external atmosphere model with an interface to set the pressure.
inline void SetExPressure(float p) { exPressure=p; } inline void SetExPressure(float p) { exPressure=p; }
/// Sets the wind components in NED frame.
inline void SetWindNED(float wN, float wE, float wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;} inline void SetWindNED(float wN, float wE, float wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;}
inline FGColumnVector GetWindNED(void) { return vWindNED; } /// Retrieves the wind components in NED frame.
inline FGColumnVector3& GetWindNED(void) { return vWindNED; }
/** Retrieves the wind direction. The direction is defined as north=0 and
increases counterclockwise. The wind heading is returned in radians.*/
inline float GetWindPsi(void) { return psiw; } inline float GetWindPsi(void) { return psiw; }
protected:
private: private:
float rho; float rho;
int lastIndex;
float h; float h;
float htab[8];
float SLtemperature,SLdensity,SLpressure,SLsoundspeed; float SLtemperature,SLdensity,SLpressure,SLsoundspeed;
float rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
float temperature,density,pressure,soundspeed; float temperature,density,pressure,soundspeed;
bool useExternal; bool useExternal;
float exTemperature,exDensity,exPressure; float exTemperature,exDensity,exPressure;
FGColumnVector vWindNED; FGColumnVector3 vWindNED;
float psiw; float psiw;
void Calculate(float altitude); void Calculate(float altitude);

View file

@ -50,13 +50,14 @@ INCLUDES
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGPosition.h" #include "FGPosition.h"
#include "FGOutput.h" #include "FGOutput.h"
#include "FGMatrix.h" #include "FGInertial.h"
#include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_AUXILIARY; static const char *IdHdr = ID_AUXILIARY;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -109,12 +110,50 @@ bool FGAuxiliary::Run()
vcas = sqrt(7*psl/rhosl*(A-1)); vcas = sqrt(7*psl/rhosl*(A-1));
veas = sqrt(2*qbar/rhosl); veas = sqrt(2*qbar/rhosl);
// vPilotAccel = Translation->GetUVWdot() + Aircraft->GetXYZep() * Rotation->GetPQRdot(); // Pilot sensed accelerations are calculated here. This is used
// for the coordinated turn ball instrument. Motion base platforms sometimes
// use the derivative of pilot sensed accelerations as the driving parameter,
// rather than straight accelerations.
//
// The theory behind pilot-sensed calculations is presented:
//
// For purposes of discussion and calculation, assume for a minute that the
// pilot is in space and motionless in inertial space. She will feel
// no accelerations. If the aircraft begins to accelerate along any axis or
// axes (without rotating), the pilot will sense those accelerations. If
// any rotational moment is applied, the pilot will sense an acceleration
// due to that motion in the amount:
//
// [wdot X R] + [w X (w X R)]
// Term I Term II
//
// where:
//
// wdot = omegadot, the rotational acceleration rate vector
// w = omega, the rotational rate vector
// R = the vector from the aircraft CG to the pilot eyepoint
//
// The sum total of these two terms plus the acceleration of the aircraft
// body axis gives the acceleration the pilot senses in inertial space.
// In the presence of a large body such as a planet, a gravity field also
// provides an accelerating attraction. This acceleration can be transformed
// from the reference frame of the planet so as to be expressed in the frame
// of reference of the aircraft. This gravity field accelerating attraction
// is felt by the pilot as a force on her tushie as she sits in her aircraft
// on the runway awaiting takeoff clearance.
//
// In JSBSim the acceleration of the body frame in inertial space is given
// by the F = ma relation. If the vForces vector is divided by the aircraft
// mass, the acceleration vector is calculated. The term wdot is equivalent
// to the JSBSim vPQRdot vector, and the w parameter is equivalent to vPQR.
// The radius R is calculated below in the vector vToEyePt.
vToEyePt = Aircraft->GetXYZep() - MassBalance->GetXYZcg(); vToEyePt = Aircraft->GetXYZep() - MassBalance->GetXYZcg();
vPilotAccel = Translation->GetUVWdot()
+ Rotation->GetPQRdot() * vToEyePt vPilotAccel = Aircraft->GetBodyAccel()
+ Rotation->GetPQR() * (Rotation->GetPQR() * vToEyePt); + Rotation->GetPQRdot() * vToEyePt
+ Rotation->GetPQR() * (Rotation->GetPQR() * vToEyePt)
+ Inertial->GetGravity();
earthPosAngle += State->Getdt()*OMEGA_EARTH; earthPosAngle += State->Getdt()*OMEGA_EARTH;
return false; return false;
@ -133,7 +172,7 @@ float FGAuxiliary::GetHeadWind(void)
psi = Rotation->Getpsi(); psi = Rotation->Getpsi();
vw = Atmosphere->GetWindNED().Magnitude(); vw = Atmosphere->GetWindNED().Magnitude();
return -vw*cos(psiw - psi); return vw*cos(psiw - psi);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -40,7 +40,9 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h" #include "FGModel.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -88,9 +90,9 @@ public:
inline float GetVequivalentFPS(void) { return veas; } inline float GetVequivalentFPS(void) { return veas; }
inline float GetVequivalentKTS(void) { return veas*FPSTOKTS; } inline float GetVequivalentKTS(void) { return veas*FPSTOKTS; }
inline FGColumnVector GetPilotAccel(void) { return vPilotAccel; } inline FGColumnVector3& GetPilotAccel(void) { return vPilotAccel; }
inline float GetPilotAccel(int idx) { return vPilotAccel(idx); } inline float GetPilotAccel(int idx) { return vPilotAccel(idx); }
inline FGColumnVector GetNpilot(void) { return vPilotAccel*INVGRAVITY; } inline FGColumnVector3 GetNpilot(void) { return vPilotAccel*INVGRAVITY; }
inline float GetNpilot(int idx) { return (vPilotAccel*INVGRAVITY)(idx); } inline float GetNpilot(int idx) { return (vPilotAccel*INVGRAVITY)(idx); }
inline float GetEarthPositionAngle(void) { return earthPosAngle; } inline float GetEarthPositionAngle(void) { return earthPosAngle; }
@ -111,8 +113,8 @@ private:
// (apeden@earthlink.net) or you can add it your self using the // (apeden@earthlink.net) or you can add it your self using the
// isentropic flow equations // isentropic flow equations
FGColumnVector vPilotAccel; FGColumnVector3 vPilotAccel;
FGColumnVector vToEyePt; FGColumnVector3 vToEyePt;
float earthPosAngle; float earthPosAngle;

View file

@ -44,12 +44,17 @@ HISTORY
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGDefs.h"
#include "FGCoefficient.h" #include "FGCoefficient.h"
#include "FGState.h" #include "FGState.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#ifndef FGFS #ifndef FGFS
# include <iomanip> # if defined(sgi) && !defined(__GNUC__)
# include <iomanip.h>
# else
# include <iomanip>
# endif
#else #else
# include STL_IOMANIP # include STL_IOMANIP
#endif #endif
@ -57,20 +62,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_COEFFICIENT; static const char *IdHdr = ID_COEFFICIENT;
extern char highint[5];
extern char halfint[5];
extern char normint[6];
extern char reset[5];
extern char underon[5];
extern char underoff[6];
extern char fgblue[6];
extern char fgcyan[6];
extern char fgred[6];
extern char fggreen[6];
extern char fgdef[6];
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -286,10 +277,11 @@ void FGCoefficient::DisplayCoeffFactors(void)
string FGCoefficient::GetCoefficientValues(void) { string FGCoefficient::GetCoefficientValues(void) {
char buffer[10]; char buffer[10];
string value; string value;
//value = ", ";
snprintf(buffer,10,"%9.6f",SD); sprintf(buffer,"%9.6f",SD);
value += string(buffer); value = string(buffer);
return value; return value;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -47,6 +47,7 @@ INCLUDES
#include "FGConfigFile.h" #include "FGConfigFile.h"
#include "FGDefs.h" #include "FGDefs.h"
#include "FGTable.h" #include "FGTable.h"
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -95,11 +96,11 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGCoefficient class FGCoefficient : public FGJSBBase
{ {
public: public:
FGCoefficient(FGFDMExec*); FGCoefficient(FGFDMExec*);
~FGCoefficient(); virtual ~FGCoefficient();
virtual bool Load(FGConfigFile* AC_cfg); virtual bool Load(FGConfigFile* AC_cfg);

View file

@ -24,8 +24,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_CONFIGFILE; static const char *IdHdr = ID_CONFIGFILE;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -54,20 +54,26 @@ INCLUDES
SG_USING_STD(cout); SG_USING_STD(cout);
# endif # endif
#else #else
# include <fstream>
# include <iostream>
# include <string> # include <string>
using std::string; # if defined(sgi) && !defined(__GNUC__)
using std::ostream; # include <fstream.h>
using std::istream; # include <iostream.h>
using std::ifstream; # else
using std::ios; # include <fstream>
using std::cerr; # include <iostream>
using std::endl; using std::ostream;
using std::cout; using std::istream;
using std::ifstream;
using std::ios;
using std::cerr;
using std::endl;
using std::cout;
# endif
using std::string;
#endif #endif
#include "FGDefs.h" #include "FGDefs.h"
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -98,7 +104,7 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGConfigFile class FGConfigFile : public FGJSBBase
{ {
public: public:
/** Constructor /** Constructor

View file

@ -34,17 +34,11 @@ SENTRY
#ifndef FGDEFS_H #ifndef FGDEFS_H
#define FGDEFS_H #define FGDEFS_H
#define MAX_ENGINES 10
#define MAX_TANKS 30
#define GRAVITY 32.174 #define GRAVITY 32.174
#define INVGRAVITY 0.031081 #define INVGRAVITY 0.031081
#define EARTHRAD 20925650.00 // feet, equatorial #define EARTHRAD 20925650.00 // feet, equatorial
#define EARTHRADSQRD 437882827922500.0 #define EARTHRADSQRD 437882827922500.0
#define ONESECOND 4.848136811E-6 #define ONESECOND 4.848136811E-6
#define ECCENT 0.996647186
#define ECCENTSQRD 0.99330561
#define INVECCENTSQRD 1.0067395
#define INVECCENTSQRDM1 0.0067395
#define Reng 1716 //Specific Gas Constant,ft^2/(sec^2*R) #define Reng 1716 //Specific Gas Constant,ft^2/(sec^2*R)
#define SHRATIO 1.4 //Specific Heat Ratio #define SHRATIO 1.4 //Specific Heat Ratio
#define RADTODEG 57.29578 #define RADTODEG 57.29578
@ -54,7 +48,7 @@ SENTRY
#define INCHTOFT 0.08333333 #define INCHTOFT 0.08333333
#define OMEGA_EARTH .00007272205217 #define OMEGA_EARTH .00007272205217
#define NEEDED_CFG_VERSION "1.40" #define NEEDED_CFG_VERSION "1.40"
#define JSBSIM_VERSION "0.8.6" #define JSBSIM_VERSION "0.8.7"
#define HPTOFTLBSSEC 550 #define HPTOFTLBSSEC 550
#define METERS_TO_FEET 3.2808 #define METERS_TO_FEET 3.2808
@ -99,13 +93,23 @@ enum eParam {
FG_FLAPS_CMD, FG_FLAPS_CMD,
FG_THROTTLE_CMD, FG_THROTTLE_CMD,
FG_THROTTLE_POS, FG_THROTTLE_POS,
FG_MIXTURE_CMD,
FG_MIXTURE_POS,
FG_ACTIVE_ENGINE, FG_ACTIVE_ENGINE,
FG_HOVERB, FG_HOVERB,
FG_PITCH_TRIM_CMD, FG_PITCH_TRIM_CMD,
FG_LEFT_BRAKE_CMD, FG_LEFT_BRAKE_CMD,
FG_CENTER_BRAKE_CMD, FG_CENTER_BRAKE_CMD,
FG_RIGHT_BRAKE_CMD, FG_RIGHT_BRAKE_CMD,
FG_SET_LOGGING FG_SET_LOGGING,
FG_ALPHAH,
FG_ALPHAW,
FG_LBARH, //normalized horizontal tail arm
FG_LBARV, //normalized vertical tail arm
FG_HTAILAREA,
FG_VTAILAREA,
FG_VBARH, //horizontal tail volume
FG_VBARV //vertical tail volume
}; };
enum eAction { enum eAction {

View file

@ -46,7 +46,11 @@ INCLUDES
# include <fstream.h> # include <fstream.h>
# endif # endif
#else #else
# include <fstream> # if defined(sgi) && !defined(__GNUC__)
# include <fstream.h>
# else
# include <fstream>
# endif
#endif #endif
#include "FGEngine.h" #include "FGEngine.h"
@ -55,8 +59,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ENGINE; static const char *IdHdr = ID_ENGINE;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -75,6 +77,7 @@ FGEngine::FGEngine(FGFDMExec* exec) {
Auxiliary = FDMExec->GetAuxiliary(); Auxiliary = FDMExec->GetAuxiliary();
Output = FDMExec->GetOutput(); Output = FDMExec->GetOutput();
Mixture = 1.0; // FIXME: get actual value
Thrust = PctPower = 0.0; Thrust = PctPower = 0.0;
Starved = Flameout = false; Starved = Flameout = false;
Running = true; Running = true;

View file

@ -1,216 +1,243 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGEngine.h Header: FGEngine.h
Author: Jon S. Berndt Author: Jon S. Berndt
Date started: 01/21/99 Date started: 01/21/99
------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) ------------- ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later Foundation; either version 2 of the License, or (at your option) any later
version. version.
This program is distributed in the hope that it will be useful, but WITHOUT 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 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details. details.
You should have received a copy of the GNU General Public License along with You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA. Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU General Public License can also be found on Further information about the GNU General Public License can also be found on
the world wide web at http://www.gnu.org. the world wide web at http://www.gnu.org.
FUNCTIONAL DESCRIPTION FUNCTIONAL DESCRIPTION
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Based on Flightgear code, which is based on LaRCSim. This class simulates Based on Flightgear code, which is based on LaRCSim. This class simulates
a generic engine. a generic engine.
HISTORY HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
01/21/99 JSB Created 01/21/99 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGENGINE_H #ifndef FGENGINE_H
#define FGENGINE_H #define FGENGINE_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS #ifdef FGFS
# include <simgear/compiler.h> # include <simgear/compiler.h>
# include STL_STRING # include STL_STRING
SG_USING_STD(string); SG_USING_STD(string);
# ifdef SG_HAVE_STD_INCLUDES # ifdef SG_HAVE_STD_INCLUDES
# include <vector> # include <vector>
# else # else
# include <vector.h> # include <vector.h>
# endif # endif
#else #else
# include <vector> # include <vector>
# include <string> # include <string>
#endif #endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #include "FGJSBBase.h"
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
#define ID_ENGINE "$Id$" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
using std::string; #define ID_ENGINE "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% using std::string;
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
class FGFDMExec; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGState;
class FGAtmosphere; class FGFDMExec;
class FGFCS; class FGState;
class FGAircraft; class FGAtmosphere;
class FGTranslation; class FGFCS;
class FGRotation; class FGAircraft;
class FGPropulsion; class FGTranslation;
class FGPosition; class FGRotation;
class FGAuxiliary; class FGPropulsion;
class FGOutput; class FGPosition;
class FGAuxiliary;
using std::vector; class FGOutput;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% using std::vector;
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
/** Base class for all engines. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
This base class contains methods and members common to all engines, such as
logic to drain fuel from the appropriate tank, etc. /** Base class for all engines.
@author Jon S. Berndt This base class contains methods and members common to all engines, such as
@version $Id$ logic to drain fuel from the appropriate tank, etc.
*/ @author Jon S. Berndt
@version $Id$
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
class FGEngine { %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
public:
FGEngine(FGFDMExec* exec); class FGEngine : public FGJSBBase
virtual ~FGEngine(); {
public:
enum EngineType {etUnknown, etRocket, etPiston, etTurboProp, etTurboJet, etTurboShaft}; FGEngine(FGFDMExec* exec);
virtual ~FGEngine();
virtual float GetThrottleMin(void) { return MinThrottle; }
virtual float GetThrottleMax(void) { return MaxThrottle; } enum EngineType {etUnknown, etRocket, etPiston, etTurboProp, etTurboJet, etTurboShaft};
float GetThrottle(void) { return Throttle; }
float GetThrust(void) { return Thrust; } virtual float GetThrottleMin(void) { return MinThrottle; }
bool GetStarved(void) { return Starved; } virtual float GetThrottleMax(void) { return MaxThrottle; }
bool GetFlameout(void) { return Flameout; } float GetThrottle(void) { return Throttle; }
bool GetRunning(void) { return Running; } float GetMixture(void) { return Mixture; }
int GetType(void) { return Type; } float GetThrust(void) { return Thrust; }
string GetName(void) { return Name; } bool GetStarved(void) { return Starved; }
bool GetFlameout(void) { return Flameout; }
void SetStarved(bool tt) {Starved = tt;} bool GetRunning(void) { return Running; }
void SetStarved(void) {Starved = true;} int GetType(void) { return Type; }
string GetName(void) { return Name; }
void SetRunning(bool bb) { Running=bb; }
void SetName(string name) {Name = name;} virtual float getManifoldPressure_inHg () const {
void AddFeedTank(int tkID); return ManifoldPressure_inHg;
}
/** Calculates the thrust of the engine, and other engine functions. virtual float getExhaustGasTemp_degF () const {
@param PowerRequired this is the power required to run the thrusting device return (ExhaustGasTemp_degK - 273) * (9.0 / 5.0) + 32.0;
such as a propeller. This resisting effect must be provided to the }
engine model. virtual float getCylinderHeadTemp_degF () const {
@return Thrust in pounds */ return (CylinderHeadTemp_degK - 273) * (9.0 / 5.0) + 32.0;
virtual float Calculate(float PowerRequired) {return 0.0;}; }
virtual float getOilPressure_psi () const {
/** Reduces the fuel in the active tanks by the amount required. return OilPressure_psi;
This function should be called from within the }
derived class' Calculate() function before any other calculations are virtual float getOilTemp_degF () const {
done. This base class method removes fuel from the fuel tanks as return (OilTemp_degK - 273.0) * (9.0 / 5.0) + 32.0;
appropriate, and sets the starved flag if necessary. */ }
void ConsumeFuel(void);
void SetStarved(bool tt) {Starved = tt;}
/** The fuel need is calculated based on power levels and flow rate for that void SetStarved(void) {Starved = true;}
power level. It is also turned from a rate into an actual amount (pounds)
by multiplying it by the delta T and the rate. void SetRunning(bool bb) { Running=bb; }
@return Total fuel requirement for this engine in pounds. */ void SetName(string name) {Name = name;}
float CalcFuelNeed(void); void AddFeedTank(int tkID);
/** The oxidizer need is calculated based on power levels and flow rate for that /** Calculates the thrust of the engine, and other engine functions.
power level. It is also turned from a rate into an actual amount (pounds) @param PowerRequired this is the power required to run the thrusting device
by multiplying it by the delta T and the rate. such as a propeller. This resisting effect must be provided to the
@return Total oxidizer requirement for this engine in pounds. */ engine model.
float CalcOxidizerNeed(void); @return Thrust in pounds */
virtual float Calculate(float PowerRequired) {return 0.0;};
/// Sets engine placement information
void SetPlacement(float x, float y, float z, float pitch, float yaw); /** Reduces the fuel in the active tanks by the amount required.
This function should be called from within the
virtual float GetPowerAvailable(void) {return 0.0;}; derived class' Calculate() function before any other calculations are
done. This base class method removes fuel from the fuel tanks as
bool GetTrimMode(void) {return TrimMode;} appropriate, and sets the starved flag if necessary. */
void SetTrimMode(bool state) {TrimMode = state;} void ConsumeFuel(void);
protected: /** The fuel need is calculated based on power levels and flow rate for that
string Name; power level. It is also turned from a rate into an actual amount (pounds)
EngineType Type; by multiplying it by the delta T and the rate.
float X, Y, Z; @return Total fuel requirement for this engine in pounds. */
float EnginePitch; float CalcFuelNeed(void);
float EngineYaw;
float SLFuelFlowMax; /** The oxidizer need is calculated based on power levels and flow rate for that
float SLOxiFlowMax; power level. It is also turned from a rate into an actual amount (pounds)
float MaxThrottle; by multiplying it by the delta T and the rate.
float MinThrottle; @return Total oxidizer requirement for this engine in pounds. */
float CalcOxidizerNeed(void);
float Thrust;
float Throttle; /// Sets engine placement information
float FuelNeed, OxidizerNeed; void SetPlacement(float x, float y, float z, float pitch, float yaw);
bool Starved;
bool Flameout; virtual float GetPowerAvailable(void) {return 0.0;};
bool Running;
float PctPower; bool GetTrimMode(void) {return TrimMode;}
int EngineNumber; void SetTrimMode(bool state) {TrimMode = state;}
bool TrimMode;
protected:
FGFDMExec* FDMExec; string Name;
FGState* State; EngineType Type;
FGAtmosphere* Atmosphere; float X, Y, Z;
FGFCS* FCS; float EnginePitch;
FGPropulsion* Propulsion; float EngineYaw;
FGAircraft* Aircraft; float SLFuelFlowMax;
FGTranslation* Translation; float SLOxiFlowMax;
FGRotation* Rotation; float MaxThrottle;
FGPosition* Position; float MinThrottle;
FGAuxiliary* Auxiliary;
FGOutput* Output; float Thrust;
float Throttle;
vector <int> SourceTanks; float Mixture;
void Debug(void); float FuelNeed, OxidizerNeed;
}; bool Starved;
bool Flameout;
#include "FGState.h" bool Running;
#include "FGFDMExec.h" float PctPower;
#include "FGAtmosphere.h" int EngineNumber;
#include "FGFCS.h" bool TrimMode;
#include "FGAircraft.h"
#include "FGTranslation.h" float ManifoldPressure_inHg;
#include "FGRotation.h" float ExhaustGasTemp_degK;
#include "FGPropulsion.h" float CylinderHeadTemp_degK;
#include "FGPosition.h" float OilPressure_psi;
#include "FGAuxiliary.h" float OilTemp_degK;
#include "FGOutput.h"
#include "FGDefs.h" FGFDMExec* FDMExec;
FGState* State;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGAtmosphere* Atmosphere;
#endif FGFCS* FCS;
FGPropulsion* Propulsion;
FGAircraft* Aircraft;
FGTranslation* Translation;
FGRotation* Rotation;
FGPosition* Position;
FGAuxiliary* Auxiliary;
FGOutput* Output;
vector <int> SourceTanks;
void Debug(void);
};
#include "FGState.h"
#include "FGFDMExec.h"
#include "FGAtmosphere.h"
#include "FGFCS.h"
#include "FGAircraft.h"
#include "FGTranslation.h"
#include "FGRotation.h"
#include "FGPropulsion.h"
#include "FGPosition.h"
#include "FGAuxiliary.h"
#include "FGOutput.h"
#include "FGDefs.h"
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -1,264 +1,339 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGFCS.cpp Module: FGFCS.cpp
Author: Jon Berndt Author: Jon Berndt
Date started: 12/12/98 Date started: 12/12/98
Purpose: Model the flight controls Purpose: Model the flight controls
Called by: FDMExec Called by: FDMExec
------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) ------------- ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later Foundation; either version 2 of the License, or (at your option) any later
version. version.
This program is distributed in the hope that it will be useful, but WITHOUT 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 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details. details.
You should have received a copy of the GNU General Public License along with You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA. Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU General Public License can also be found on Further information about the GNU General Public License can also be found on
the world wide web at http://www.gnu.org. the world wide web at http://www.gnu.org.
FUNCTIONAL DESCRIPTION FUNCTIONAL DESCRIPTION
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
This class models the flight controls for a specific airplane This class models the flight controls for a specific airplane
HISTORY HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
12/12/98 JSB Created 12/12/98 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGDefs.h" #include "FGDefs.h"
#include "FGFCS.h" #include "FGFCS.h"
#include "FGState.h" #include "FGState.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGTranslation.h" #include "FGTranslation.h"
#include "FGRotation.h" #include "FGRotation.h"
#include "FGPosition.h" #include "FGPosition.h"
#include "FGAuxiliary.h" #include "FGAuxiliary.h"
#include "FGOutput.h" #include "FGOutput.h"
#include "filtersjb/FGFilter.h" #include "filtersjb/FGFilter.h"
#include "filtersjb/FGDeadBand.h" #include "filtersjb/FGDeadBand.h"
#include "filtersjb/FGGain.h" #include "filtersjb/FGGain.h"
#include "filtersjb/FGGradient.h" #include "filtersjb/FGGradient.h"
#include "filtersjb/FGSwitch.h" #include "filtersjb/FGSwitch.h"
#include "filtersjb/FGSummer.h" #include "filtersjb/FGSummer.h"
#include "filtersjb/FGFlaps.h" #include "filtersjb/FGFlaps.h"
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FCS; static const char *IdHdr = ID_FCS;
extern short debug_lvl; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)
{
FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex) Name = "FGFCS";
{
Name = "FGFCS"; DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = PTrimCmd = 0.0;
DaPos = DePos = DrPos = DfPos = DsbPos = DspPos = 0.0;
DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = PTrimCmd = 0.0; LeftBrake = RightBrake = CenterBrake = 0.0;
DaPos = DePos = DrPos = DfPos = DsbPos = DspPos = 0.0;
LeftBrake = RightBrake = CenterBrake = 0.0; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
}
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
} //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGFCS::~FGFCS()
{
FGFCS::~FGFCS() ThrottleCmd.clear();
{ ThrottlePos.clear();
ThrottleCmd.clear(); MixtureCmd.clear();
ThrottlePos.clear(); MixturePos.clear();
unsigned int i; unsigned int i;
for(i=0;i<Components.size();i++) delete Components[i]; for(i=0;i<Components.size();i++) delete Components[i];
if (debug_lvl & 2) cout << "Destroyed: FGFCS" << endl; if (debug_lvl & 2) cout << "Destroyed: FGFCS" << endl;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFCS::Run(void) bool FGFCS::Run(void)
{ {
unsigned int i; unsigned int i;
if (!FGModel::Run()) { if (!FGModel::Run()) {
for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i]; for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
for (i=0; i<Components.size(); i++) Components[i]->Run(); for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
} else { for (i=0; i<Components.size(); i++) Components[i]->Run();
} } else {
}
return false;
} return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetThrottleCmd(int engineNum, float setting)
{ void FGFCS::SetThrottleCmd(int engineNum, float setting)
unsigned int ctr; {
unsigned int ctr;
if (engineNum < 0) {
for (ctr=0;ctr<ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting; if ((int)ThrottleCmd.size() > engineNum) {
} else { if (engineNum < 0) {
ThrottleCmd[engineNum] = setting; for (ctr=0;ctr<=ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting;
} } else {
} ThrottleCmd[engineNum] = setting;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } else {
cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
void FGFCS::SetThrottlePos(int engineNum, float setting) << " engines exist, but attempted throttle command is for engine "
{ << engineNum << endl;
unsigned int ctr; }
}
if (engineNum < 0) {
for (ctr=0;ctr<=ThrottleCmd.size();ctr++) ThrottlePos[ctr] = ThrottleCmd[ctr]; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} else {
ThrottlePos[engineNum] = setting; void FGFCS::SetThrottlePos(int engineNum, float setting)
} {
} unsigned int ctr;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if ((int)ThrottlePos.size() > engineNum) {
if (engineNum < 0) {
bool FGFCS::Load(FGConfigFile* AC_cfg) for (ctr=0;ctr<=ThrottlePos.size();ctr++) ThrottlePos[ctr] = setting;
{ } else {
string token; ThrottlePos[engineNum] = setting;
}
Name = AC_cfg->GetValue("NAME"); } else {
if (debug_lvl > 0) cout << " Control System Name: " << Name << endl; cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
AC_cfg->GetNextConfigLine(); << " engines exist, but attempted throttle position setting is for engine "
while ((token = AC_cfg->GetValue()) != "/FLIGHT_CONTROL") { << engineNum << endl;
if (token == "COMPONENT") { }
token = AC_cfg->GetValue("TYPE"); }
if (debug_lvl > 0) cout << " Loading Component \""
<< AC_cfg->GetValue("NAME") //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
<< "\" of type: " << token << endl;
if ((token == "LAG_FILTER") || float FGFCS::GetThrottleCmd(int engineNum)
(token == "LEAD_LAG_FILTER") || {
(token == "SECOND_ORDER_FILTER") || if ((int)ThrottleCmd.size() > engineNum) {
(token == "WASHOUT_FILTER") || if (engineNum < 0) {
(token == "INTEGRATOR") ) { cerr << "Cannot get throttle value for ALL engines" << endl;
Components.push_back(new FGFilter(this, AC_cfg)); } else {
} else if ((token == "PURE_GAIN") || return ThrottleCmd[engineNum];
(token == "SCHEDULED_GAIN") || }
(token == "AEROSURFACE_SCALE") ) { } else {
cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
Components.push_back(new FGGain(this, AC_cfg)); << " engines exist, but throttle setting for engine " << engineNum
<< " is selected" << endl;
} else if (token == "SUMMER") { }
Components.push_back(new FGSummer(this, AC_cfg)); }
} else if (token == "DEADBAND") {
Components.push_back(new FGDeadBand(this, AC_cfg)); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} else if (token == "GRADIENT") {
Components.push_back(new FGGradient(this, AC_cfg)); float FGFCS::GetThrottlePos(int engineNum)
} else if (token == "SWITCH") { {
Components.push_back(new FGSwitch(this, AC_cfg)); if ((int)ThrottlePos.size() > engineNum) {
} else if (token == "FLAPS") { if (engineNum < 0) {
Components.push_back(new FGFlaps(this, AC_cfg)); cerr << "Cannot get throttle value for ALL engines" << endl;
} else { } else {
cerr << "Unknown token [" << token << "] in FCS portion of config file" << endl; return ThrottlePos[engineNum];
return false; }
} } else {
AC_cfg->GetNextConfigLine(); cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
} << " engines exist, but attempted throttle position setting is for engine "
} << engineNum << endl;
return true; }
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGFCS::GetComponentOutput(eParam idx) { void FGFCS::SetMixtureCmd(int engineNum, float setting)
return Components[idx]->GetOutput(); {
} unsigned int ctr;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if (engineNum < 0) {
for (ctr=0;ctr<MixtureCmd.size();ctr++) MixtureCmd[ctr] = setting;
string FGFCS::GetComponentName(int idx) { } else {
return Components[idx]->GetName(); MixtureCmd[engineNum] = setting;
} }
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGFCS::GetBrake(FGLGear::BrakeGroup bg) {
switch (bg) { void FGFCS::SetMixturePos(int engineNum, float setting)
case FGLGear::bgLeft: {
return LeftBrake; unsigned int ctr;
case FGLGear::bgRight:
return RightBrake; if (engineNum < 0) {
case FGLGear::bgCenter: for (ctr=0;ctr<=MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr];
return CenterBrake; } else {
default: MixturePos[engineNum] = setting;
cerr << "GetBrake asked to return a bogus brake value" << endl; }
} }
return 0.0;
} //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool FGFCS::Load(FGConfigFile* AC_cfg)
{
string FGFCS::GetComponentStrings(void) string token;
{
unsigned int comp; Name = Name + ":" + AC_cfg->GetValue("NAME");
if (debug_lvl > 0) cout << " Control System Name: " << Name << endl;
string CompStrings = ""; AC_cfg->GetNextConfigLine();
bool firstime = true; while ((token = AC_cfg->GetValue()) != "/FLIGHT_CONTROL") {
if (token == "COMPONENT") {
for (comp = 0; comp < Components.size(); comp++) { token = AC_cfg->GetValue("TYPE");
if (firstime) firstime = false; if (debug_lvl > 0) cout << " Loading Component \""
else CompStrings += ", "; << AC_cfg->GetValue("NAME")
<< "\" of type: " << token << endl;
CompStrings += Components[comp]->GetName(); if ((token == "LAG_FILTER") ||
} (token == "LEAD_LAG_FILTER") ||
(token == "SECOND_ORDER_FILTER") ||
return CompStrings; (token == "WASHOUT_FILTER") ||
} (token == "INTEGRATOR") ) {
Components.push_back(new FGFilter(this, AC_cfg));
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } else if ((token == "PURE_GAIN") ||
(token == "SCHEDULED_GAIN") ||
string FGFCS::GetComponentValues(void) (token == "AEROSURFACE_SCALE") ) {
{
unsigned int comp; Components.push_back(new FGGain(this, AC_cfg));
string CompValues = ""; } else if (token == "SUMMER") {
char buffer[10]; Components.push_back(new FGSummer(this, AC_cfg));
bool firstime = true; } else if (token == "DEADBAND") {
Components.push_back(new FGDeadBand(this, AC_cfg));
for (comp = 0; comp < Components.size(); comp++) { } else if (token == "GRADIENT") {
if (firstime) firstime = false; Components.push_back(new FGGradient(this, AC_cfg));
else CompValues += ", "; } else if (token == "SWITCH") {
Components.push_back(new FGSwitch(this, AC_cfg));
sprintf(buffer, "%9.6f", Components[comp]->GetOutput()); } else if (token == "FLAPS") {
CompValues += string(buffer); Components.push_back(new FGFlaps(this, AC_cfg));
} } else {
cerr << "Unknown token [" << token << "] in FCS portion of config file" << endl;
return CompValues; return false;
} }
AC_cfg->GetNextConfigLine();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% }
}
void FGFCS::AddThrottle(void) return true;
{ }
ThrottleCmd.push_back(0.0);
ThrottlePos.push_back(0.0); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
float FGFCS::GetComponentOutput(eParam idx) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% return Components[idx]->GetOutput();
}
void FGFCS::Debug(void)
{ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//TODO: Add your source code here
} string FGFCS::GetComponentName(int idx) {
return Components[idx]->GetName();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGFCS::GetBrake(FGLGear::BrakeGroup bg) {
switch (bg) {
case FGLGear::bgLeft:
return LeftBrake;
case FGLGear::bgRight:
return RightBrake;
case FGLGear::bgCenter:
return CenterBrake;
default:
cerr << "GetBrake asked to return a bogus brake value" << endl;
}
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGFCS::GetComponentStrings(void)
{
unsigned int comp;
string CompStrings = "";
bool firstime = true;
for (comp = 0; comp < Components.size(); comp++) {
if (firstime) firstime = false;
else CompStrings += ", ";
CompStrings += Components[comp]->GetName();
}
return CompStrings;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGFCS::GetComponentValues(void)
{
unsigned int comp;
string CompValues = "";
char buffer[10];
bool firstime = true;
for (comp = 0; comp < Components.size(); comp++) {
if (firstime) firstime = false;
else CompValues += ", ";
sprintf(buffer, "%9.6f", Components[comp]->GetOutput());
CompValues += string(buffer);
}
return CompValues;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::AddThrottle(void)
{
ThrottleCmd.push_back(0.0);
ThrottlePos.push_back(0.0);
MixtureCmd.push_back(0.0); // assume throttle and mixture are coupled
MixturePos.push_back(0.0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::Debug(void)
{
//TODO: Add your source code here
}

View file

@ -196,8 +196,13 @@ public:
/** Gets the throttle command. /** Gets the throttle command.
@param engine engine ID number @param engine engine ID number
@return throttle command in percent ( 0 - 100) for the given engine */ @return throttle command in percent ( 0 - 100) for the given engine */
inline float GetThrottleCmd(int engine) { return ThrottleCmd[engine]; } float GetThrottleCmd(int engine);
/** Gets the mixture command.
@param engine engine ID number
@return mixture command in percent ( 0 - 100) for the given engine */
inline float GetMixtureCmd(int engine) { return MixtureCmd[engine]; }
/** Gets the pitch trim command. /** Gets the pitch trim command.
@return pitch trim command in radians */ @return pitch trim command in radians */
inline float GetPitchTrimCmd(void) { return PTrimCmd; } inline float GetPitchTrimCmd(void) { return PTrimCmd; }
@ -232,7 +237,12 @@ public:
/** Gets the throttle position. /** Gets the throttle position.
@param engine engine ID number @param engine engine ID number
@return throttle position for the given engine in percent ( 0 - 100)*/ @return throttle position for the given engine in percent ( 0 - 100)*/
inline float GetThrottlePos(int engine) { return ThrottlePos[engine]; } float GetThrottlePos(int engine);
/** Gets the mixture position.
@param engine engine ID number
@return mixture position for the given engine in percent ( 0 - 100)*/
inline float GetMixturePos(int engine) { return MixturePos[engine]; }
//@} //@}
/** Retrieves the State object pointer. /** Retrieves the State object pointer.
@ -290,6 +300,11 @@ public:
@param engine engine ID number @param engine engine ID number
@param cmd throttle command in percent (0 - 100)*/ @param cmd throttle command in percent (0 - 100)*/
void SetThrottleCmd(int engine, float cmd); void SetThrottleCmd(int engine, float cmd);
/** Sets the mixture command for the specified engine
@param engine engine ID number
@param cmd mixture command in percent (0 - 100)*/
void SetMixtureCmd(int engine, float cmd);
//@} //@}
/// @name Aerosurface position setting /// @name Aerosurface position setting
@ -322,6 +337,11 @@ public:
@param engine engine ID number @param engine engine ID number
@param cmd throttle setting in percent (0 - 100)*/ @param cmd throttle setting in percent (0 - 100)*/
void SetThrottlePos(int engine, float cmd); void SetThrottlePos(int engine, float cmd);
/** Sets the actual mixture setting for the specified engine
@param engine engine ID number
@param cmd mixture setting in percent (0 - 100)*/
void SetMixturePos(int engine, float cmd);
//@} //@}
/// @name Landing Gear brakes /// @name Landing Gear brakes
@ -360,6 +380,8 @@ private:
float PTrimCmd; float PTrimCmd;
vector <float> ThrottleCmd; vector <float> ThrottleCmd;
vector <float> ThrottlePos; vector <float> ThrottlePos;
vector <float> MixtureCmd;
vector <float> MixturePos;
float LeftBrake, RightBrake, CenterBrake; // Brake settings float LeftBrake, RightBrake, CenterBrake; // Brake settings
vector <FGFCSComponent*> Components; vector <FGFCSComponent*> Components;

View file

@ -48,8 +48,13 @@ INCLUDES
# include STL_IOSTREAM # include STL_IOSTREAM
# include STL_ITERATOR # include STL_ITERATOR
#else #else
# include <iostream> # if defined(sgi) && !defined(__GNUC__)
# include <ctime> # include <iostream.h>
# include <time.h>
# else
# include <iostream>
# include <ctime>
# endif
# include <iterator> # include <iterator>
#endif #endif
@ -59,6 +64,7 @@ INCLUDES
#include "FGFCS.h" #include "FGFCS.h"
#include "FGPropulsion.h" #include "FGPropulsion.h"
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "FGGroundReactions.h"
#include "FGAerodynamics.h" #include "FGAerodynamics.h"
#include "FGInertial.h" #include "FGInertial.h"
#include "FGAircraft.h" #include "FGAircraft.h"
@ -72,18 +78,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FDMEXEC; static const char *IdHdr = ID_FDMEXEC;
char highint[5] = {27, '[', '1', 'm', '\0' };
char halfint[5] = {27, '[', '2', 'm', '\0' };
char normint[6] = {27, '[', '2', '2', 'm', '\0' };
char reset[5] = {27, '[', '0', 'm', '\0' };
char underon[5] = {27, '[', '4', 'm', '\0' };
char underoff[6] = {27, '[', '2', '4', 'm', '\0' };
char fgblue[6] = {27, '[', '3', '4', 'm', '\0' };
char fgcyan[6] = {27, '[', '3', '6', 'm', '\0' };
char fgred[6] = {27, '[', '3', '1', 'm', '\0' };
char fggreen[6] = {27, '[', '3', '2', 'm', '\0' };
char fgdef[6] = {27, '[', '3', '9', 'm', '\0' };
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
GLOBAL DECLARATIONS GLOBAL DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -116,22 +110,23 @@ CLASS IMPLEMENTATION
FGFDMExec::FGFDMExec(void) FGFDMExec::FGFDMExec(void)
{ {
Frame = 0; Frame = 0;
FirstModel = 0; FirstModel = 0;
Error = 0; Error = 0;
State = 0; State = 0;
Atmosphere = 0; Atmosphere = 0;
FCS = 0; FCS = 0;
Propulsion = 0; Propulsion = 0;
MassBalance = 0; MassBalance = 0;
Aerodynamics = 0; Aerodynamics = 0;
Inertial = 0; Inertial = 0;
Aircraft = 0; GroundReactions = 0;
Translation = 0; Aircraft = 0;
Rotation = 0; Translation = 0;
Position = 0; Rotation = 0;
Auxiliary = 0; Position = 0;
Output = 0; Auxiliary = 0;
Output = 0;
terminate = false; terminate = false;
frozen = false; frozen = false;
@ -171,23 +166,24 @@ bool FGFDMExec::Allocate(void) {
bool result=true; bool result=true;
Atmosphere = new FGAtmosphere(this); Atmosphere = new FGAtmosphere(this);
FCS = new FGFCS(this); FCS = new FGFCS(this);
Propulsion = new FGPropulsion(this); Propulsion = new FGPropulsion(this);
MassBalance = new FGMassBalance(this); MassBalance = new FGMassBalance(this);
Aerodynamics = new FGAerodynamics (this); Aerodynamics = new FGAerodynamics (this);
Inertial = new FGInertial(this); Inertial = new FGInertial(this);
Aircraft = new FGAircraft(this); GroundReactions = new FGGroundReactions(this);
Translation = new FGTranslation(this); Aircraft = new FGAircraft(this);
Rotation = new FGRotation(this); Translation = new FGTranslation(this);
Position = new FGPosition(this); Rotation = new FGRotation(this);
Auxiliary = new FGAuxiliary(this); Position = new FGPosition(this);
Output = new FGOutput(this); Auxiliary = new FGAuxiliary(this);
Output = new FGOutput(this);
State = new FGState(this); // This must be done here, as the FGState State = new FGState(this); // This must be done here, as the FGState
// class needs valid pointers to the above // class needs valid pointers to the above
// model classes // model classes
// Initialize models so they can communicate with each other // Initialize models so they can communicate with each other
if (!Atmosphere->InitModel()) { if (!Atmosphere->InitModel()) {
@ -208,24 +204,27 @@ bool FGFDMExec::Allocate(void) {
if (!Inertial->InitModel()) { if (!Inertial->InitModel()) {
cerr << fgred << "FGInertial model init failed" << fgdef << endl; cerr << fgred << "FGInertial model init failed" << fgdef << endl;
Error+=32;} Error+=32;}
if (!GroundReactions->InitModel()) {
cerr << fgred << "Ground Reactions model init failed" << fgdef << endl;
Error+=64;}
if (!Aircraft->InitModel()) { if (!Aircraft->InitModel()) {
cerr << fgred << "Aircraft model init failed" << fgdef << endl; cerr << fgred << "Aircraft model init failed" << fgdef << endl;
Error+=64;} Error+=128;}
if (!Translation->InitModel()){ if (!Translation->InitModel()){
cerr << fgred << "Translation model init failed" << fgdef << endl; cerr << fgred << "Translation model init failed" << fgdef << endl;
Error+=128;} Error+=256;}
if (!Rotation->InitModel()) { if (!Rotation->InitModel()) {
cerr << fgred << "Rotation model init failed" << fgdef << endl; cerr << fgred << "Rotation model init failed" << fgdef << endl;
Error+=256;} Error+=512;}
if (!Position->InitModel()) { if (!Position->InitModel()) {
cerr << fgred << "Position model init failed" << fgdef << endl; cerr << fgred << "Position model init failed" << fgdef << endl;
Error+=512;} Error+=1024;}
if (!Auxiliary->InitModel()) { if (!Auxiliary->InitModel()) {
cerr << fgred << "Auxiliary model init failed" << fgdef << endl; cerr << fgred << "Auxiliary model init failed" << fgdef << endl;
Error+=1024;} Error+=2058;}
if (!Output->InitModel()) { if (!Output->InitModel()) {
cerr << fgred << "Output model init failed" << fgdef << endl; cerr << fgred << "Output model init failed" << fgdef << endl;
Error+=2048;} Error+=4096;}
if (Error > 0) result = false; if (Error > 0) result = false;
@ -233,18 +232,19 @@ bool FGFDMExec::Allocate(void) {
// instance, the atmosphere model gets executed every fifth pass it is called // instance, the atmosphere model gets executed every fifth pass it is called
// by the executive. Everything else here gets executed each pass. // by the executive. Everything else here gets executed each pass.
Schedule(Atmosphere, 1); Schedule(Atmosphere, 1);
Schedule(FCS, 1); Schedule(FCS, 1);
Schedule(Propulsion, 1); Schedule(Propulsion, 1);
Schedule(MassBalance, 1); Schedule(MassBalance, 1);
Schedule(Aerodynamics, 1); Schedule(Aerodynamics, 1);
Schedule(Inertial, 1); Schedule(Inertial, 1);
Schedule(Aircraft, 1); Schedule(GroundReactions, 1);
Schedule(Rotation, 1); Schedule(Aircraft, 1);
Schedule(Translation, 1); Schedule(Rotation, 1);
Schedule(Position, 1); Schedule(Translation, 1);
Schedule(Auxiliary, 1); Schedule(Position, 1);
Schedule(Output, 1); Schedule(Auxiliary, 1);
Schedule(Output, 1);
modelLoaded = false; modelLoaded = false;
@ -255,36 +255,38 @@ bool FGFDMExec::Allocate(void) {
bool FGFDMExec::DeAllocate(void) { bool FGFDMExec::DeAllocate(void) {
if ( Atmosphere != 0 ) delete Atmosphere; if ( Atmosphere != 0 ) delete Atmosphere;
if ( FCS != 0 ) delete FCS; if ( FCS != 0 ) delete FCS;
if ( Propulsion != 0) delete Propulsion; if ( Propulsion != 0) delete Propulsion;
if ( MassBalance != 0) delete MassBalance; if ( MassBalance != 0) delete MassBalance;
if ( Aerodynamics != 0) delete Aerodynamics; if ( Aerodynamics != 0) delete Aerodynamics;
if ( Inertial != 0) delete Inertial; if ( Inertial != 0) delete Inertial;
if ( Aircraft != 0 ) delete Aircraft; if ( GroundReactions != 0) delete GroundReactions;
if ( Translation != 0 ) delete Translation; if ( Aircraft != 0 ) delete Aircraft;
if ( Rotation != 0 ) delete Rotation; if ( Translation != 0 ) delete Translation;
if ( Position != 0 ) delete Position; if ( Rotation != 0 ) delete Rotation;
if ( Auxiliary != 0 ) delete Auxiliary; if ( Position != 0 ) delete Position;
if ( Output != 0 ) delete Output; if ( Auxiliary != 0 ) delete Auxiliary;
if ( State != 0 ) delete State; if ( Output != 0 ) delete Output;
if ( State != 0 ) delete State;
FirstModel = 0L; FirstModel = 0L;
Error = 0; Error = 0;
State = 0; State = 0;
Atmosphere = 0; Atmosphere = 0;
FCS = 0; FCS = 0;
Propulsion = 0; Propulsion = 0;
MassBalance = 0; MassBalance = 0;
Aerodynamics = 0; Aerodynamics = 0;
Inertial = 0; Inertial = 0;
Aircraft = 0; GroundReactions = 0;
Translation = 0; Aircraft = 0;
Rotation = 0; Translation = 0;
Position = 0; Rotation = 0;
Auxiliary = 0; Position = 0;
Output = 0; Auxiliary = 0;
Output = 0;
modelLoaded = false; modelLoaded = false;
return modelLoaded; return modelLoaded;
@ -576,7 +578,7 @@ bool FGFDMExec::LoadScript(string script)
exit(-1); exit(-1);
} }
if ( ! State->Reset("aircraft", aircraft, initialize)) if ( ! State->Reset("aircraft", aircraft, initialize))
State->Initialize(2000,0,0,0,0,0,0.5,0.5,40000); State->Initialize(2000,0,0,0,0,0,0.5,0.5,40000,0,0,0);
return true; return true;
} }

View file

@ -42,6 +42,7 @@ INCLUDES
#include "FGModel.h" #include "FGModel.h"
#include "FGInitialCondition.h" #include "FGInitialCondition.h"
#include "FGJSBBase.h"
#include <vector> #include <vector>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -61,6 +62,7 @@ class FGPropulsion;
class FGMassBalance; class FGMassBalance;
class FGAerodynamics; class FGAerodynamics;
class FGInertial; class FGInertial;
class FGGroundReactions;
class FGAircraft; class FGAircraft;
class FGTranslation; class FGTranslation;
class FGRotation; class FGRotation;
@ -194,7 +196,7 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFDMExec class FGFDMExec : public FGJSBBase
{ {
public: public:
/// Default constructor /// Default constructor
@ -275,6 +277,8 @@ public:
inline FGAerodynamics* GetAerodynamics(void){return Aerodynamics;} inline FGAerodynamics* GetAerodynamics(void){return Aerodynamics;}
/// Returns the FGInertial pointer. /// Returns the FGInertial pointer.
inline FGInertial* GetInertial(void) {return Inertial;} inline FGInertial* GetInertial(void) {return Inertial;}
/// Returns the FGGroundReactions pointer.
inline FGGroundReactions* GetGroundReactions(void) {return GroundReactions;}
/// Returns the FGAircraft pointer. /// Returns the FGAircraft pointer.
inline FGAircraft* GetAircraft(void) {return Aircraft;} inline FGAircraft* GetAircraft(void) {return Aircraft;}
/// Returns the FGTranslation pointer. /// Returns the FGTranslation pointer.
@ -312,19 +316,20 @@ private:
float EndTime; float EndTime;
vector <struct condition> Conditions; vector <struct condition> Conditions;
FGState* State; FGState* State;
FGAtmosphere* Atmosphere; FGAtmosphere* Atmosphere;
FGFCS* FCS; FGFCS* FCS;
FGPropulsion* Propulsion; FGPropulsion* Propulsion;
FGMassBalance* MassBalance; FGMassBalance* MassBalance;
FGAerodynamics* Aerodynamics; FGAerodynamics* Aerodynamics;
FGInertial* Inertial; FGInertial* Inertial;
FGAircraft* Aircraft; FGGroundReactions* GroundReactions;
FGTranslation* Translation; FGAircraft* Aircraft;
FGRotation* Rotation; FGTranslation* Translation;
FGPosition* Position; FGRotation* Rotation;
FGAuxiliary* Auxiliary; FGPosition* Position;
FGOutput* Output; FGAuxiliary* Auxiliary;
FGOutput* Output;
bool Allocate(void); bool Allocate(void);
bool DeAllocate(void); bool DeAllocate(void);

View file

@ -45,19 +45,22 @@ HISTORY
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGDefs.h"
#include "FGCoefficient.h" #include "FGCoefficient.h"
#include "FGFactorGroup.h" #include "FGFactorGroup.h"
#include "FGState.h" #include "FGState.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#ifndef FGFS #ifndef FGFS
# include <iomanip> # if defined(sgi) && !defined(__GNUC__)
# include <iomanip.h>
# else
# include <iomanip>
# endif
#else #else
# include STL_IOMANIP # include STL_IOMANIP
#endif #endif
extern short debug_lvl;
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FACTORGROUP; static const char *IdHdr = ID_FACTORGROUP;
@ -128,41 +131,6 @@ float FGFactorGroup::TotalValue(void) {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
string FGFactorGroup::GetCoefficientStrings(void) {
int i;
string CoeffStrings;
CoeffStrings += name;
CoeffStrings += ", ";
CoeffStrings += FGCoefficient::Getname();
for(i=0;i<sum.size();i++) {
CoeffStrings += ", ";
CoeffStrings += sum[i]->Getname();
}
return CoeffStrings;
}
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
string FGFactorGroup::GetCoefficientValues(void) {
int i;
char buffer[10];
string values;
snprintf(buffer,10,"%9.6f",SDtotal);
values += string(buffer);
values += ", ";
snprintf(buffer,10,"%9.6f",FGCoefficient::GetSD() );
values += string(buffer);
values += ", ";
for(i=0;i<sum.size();i++) {
values += sum[i]->GetCoefficientValues();
}
return values;
}
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
void FGFactorGroup::Debug(void) void FGFactorGroup::Debug(void)
{ {
cout << "FGCoefficient::GetSD(): " << FGCoefficient::GetSD() << endl; cout << "FGCoefficient::GetSD(): " << FGCoefficient::GetSD() << endl;

View file

@ -100,8 +100,8 @@ class FGFactorGroup: public FGCoefficient {
bool Load(FGConfigFile *AC_cfg); bool Load(FGConfigFile *AC_cfg);
float TotalValue(void); float TotalValue(void);
string GetCoefficientStrings(void); //string GetCoefficientStrings(void);
string GetCoefficientValues(void); //string GetCoefficientValues(void);
inline float GetSD(void) { return SDtotal; } inline float GetSD(void) { return SDtotal; }
inline float GetFactorSD(void) { return FGCoefficient::GetSD(); } inline float GetFactorSD(void) { return FGCoefficient::GetSD(); }

View file

@ -43,15 +43,15 @@ and the cg.
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGTranslation.h" #include "FGTranslation.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
#include "FGDefs.h" #include "FGDefs.h"
#include "FGForce.h" #include "FGForce.h"
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FORCE; static const char *IdHdr = ID_FORCE;
extern short debug_lvl;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGForce::FGForce(FGFDMExec *FDMExec) : FGForce::FGForce(FGFDMExec *FDMExec) :
@ -82,7 +82,7 @@ FGForce::~FGForce()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector FGForce::GetBodyForces(void) { FGColumnVector3& FGForce::GetBodyForces(void) {
vFb=Transform()*(vFn.multElementWise(vSense)); vFb=Transform()*(vFn.multElementWise(vSense));
@ -99,7 +99,7 @@ FGColumnVector FGForce::GetBodyForces(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGMatrix FGForce::Transform(void) { FGMatrix33 FGForce::Transform(void) {
switch(ttype) { switch(ttype) {
case tWindBody: case tWindBody:
return fdmex->GetState()->GetTs2b(fdmex->GetTranslation()->Getalpha(),fdmex->GetTranslation()->Getbeta()); return fdmex->GetState()->GetTs2b(fdmex->GetTranslation()->Getalpha(),fdmex->GetTranslation()->Getbeta());

View file

@ -60,18 +60,169 @@ INCLUDES
#define ID_FORCE "$Id$" #define ID_FORCE "$Id$"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGMatrix.h" #include "FGJSBBase.h"
#include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Utility class that aids in the conversion of forces between coordinate systems
and calculation of moments.
<br><h3>Resolution of Applied Forces into Moments and Body Axes Components</h3>
<br><p>
All forces acting on the aircraft that cannot be considered a change in weight
need to be resolved into body axis components so that the aircraft acceleration
vectors, both translational and rotational, can be computed. Furthermore, the
moments produced by each force that does not act at a location corresponding to
the center of gravity also need to be computed. Unfortunately, the math required
to do this can be a bit messy and errors are easily introduced so the class
FGForce was created to provide these services in a consistent and reusable
manner.<br><br></p>
<h4>Basic usage</h4>
<p>FGForce requires that its users supply it with the location of the applied
force vector in JSBSim structural coordinates, the sense of each axis in that
coordinate system relative to the body system, the orientation of the vector
also relative to body coordinates and, of course, the force vector itself. With
this information it will compute both the body axis force components and the
resulting moments. Any moments inherently produced by the native system can be
supplied as well and they will be summed with those computed.</p>
<p>A good example for demonstrating the use of this class are the aerodynamic
forces: lift, drag, and side force and the aerodynamic moments about the pitch,
roll and yaw axes. These "native" forces and moments are computed and stored
in the FGColumnVector objects vFs and vMoments. Their native coordinate system
is often referred to as the wind system and is defined as a right-handed system
having its x-axis aligned with the relative velocity vector and pointing towards
the rear of the aircraft , the y-axis extending out the right wing, and the
z-axis directed upwards. This is different than body axes; they are defined such
that the x-axis is lies on the aircraft's roll axis and positive forward, the
y-axis is positive out the right wing, and the z-axis is positive downwards. In
this instance, JSBSim already provides the needed transform and FGForce can make
use of it by calling SetTransformType() once an object is created:</p>
<p><tt>FGForce fgf(FDMExec);</tt><br>
<tt>fgf.SetTransformType(tWindBody);</tt><br><br>
This call need only be made once for each object. The available transforms are
defined in the enumerated type TransformType and are tWindBody, tLocalBody,
tCustom, and tNone. The local-to-body transform, like the wind-to-body, also
makes use of that already available in JSBSim. tNone sets FGForce to do no
angular transform at all, and tCustom allows for modeling force vectors at
arbitrary angles relative to the body system such as that produced by propulsion
systems. Setting up and using a custom transform is covered in more detail below.
Continuing with the example, the point of application of the aerodynamic forces,
the aerodynamic reference point in JSBSim, also needs to be set:</p>
<p><tt>
fgf.SetLocation(x, y, z)</tt></p>
<p>where x, y, and z are in JSBSim structural coordinates.</p>
<p>Initialization is complete and the FGForce object is ready to do its job. As
stated above, the lift, drag, and side force are computed and stored in the
vector vFs and need to be passed to FGForce:</p>
<p><tt>fgf.SetNativeForces(vFs);</tt> </p>
<p>The same applies to the aerodynamic pitching, rolling and yawing moments:</p>
<p><tt>fgf.SetNativeMoments(vMoments);</tt></p>
<p>Note that storing the native forces and moments outside of this class is not
strictly necessary, overloaded SetNativeForces() and SetNativeMoments() methods
which each accept three floats (rather than a vector) are provided and can be
repeatedly called without incurring undue overhead. The body axes force vector
can now be retrieved by calling:</p>
<p><tt>vFb=fgf.GetBodyForces();</tt></p>
<p>This method is where the bulk of the work gets done so calling it more than
once for the same set of native forces and moments should probably be avoided.
Note that the moment calculations are done here as well so they should not be
retrieved after calling the GetBodyForces() method:</p>
<p><tt>vM=fgf.GetMoments();</tt> </p>
<p>As an aside, the native moments are not needed to perform the computations
correctly so, if the FGForce object is not being used to store them then an
alternate approach is to avoid the SetNativeMoments call and perform the sum</p>
<p><tt>vMoments+=fgf.GetMoments();</tt> <br><br>
after the forces have been retrieved. </p>
<h4>Use of the Custom Transform Type</h4>
<p>In cases where the native force vector is not aligned with the body, wind, or
local coordinate systems a custom transform type is provided. A vectorable engine
nozzle will be used to demonstrate its usage. Initialization is much the same:</p>
<p><tt>FGForce fgf(FDMExec);</tt> <br>
<tt>fgf.SetTransformType(tCustom);</tt> <br>
<tt>fgf.SetLocation(x,y,z);</tt> </p>
<p>Except that here the tCustom transform type is specified and the location of
the thrust vector is used rather than the aerodynamic reference point. Thrust is
typically considered to be positive when directed aft while the body x-axis is
positive forward and, if the native system is right handed, the z-axis will be
reversed as well. These differences in sense need to be specified using by the
call: </p>
<p><tt>fgf.SetSense(-1,1,-1);</tt></p>
<p>The angles are specified by calling the method: </p>
<p><tt>fgf.SetAnglesToBody(pitch, roll, yaw);</tt> </p>
<p>in which the transform matrix is computed. Note that these angles should be
taken relative to the body system and not the local as the names might suggest.
For an aircraft with vectorable thrust, this method will need to be called
every time the nozzle angle changes, a fixed engine/nozzle installation, on the
other hand, will require it to be be called only once.</p>
<p>Retrieval of the computed forces and moments is done as detailed above.</p>
<br>
<blockquote>
<p><i>CAVEAT: If the custom system is used to compute
the wind-to-body transform, then the sign of the sideslip
angle must be reversed when calling SetAnglesToBody().
This is true because sideslip angle does not follow the right
hand rule. Using the custom transform type this way
should not be necessary, as it is already provided as a built
in type (and the sign differences are correctly accounted for).</i>
<br></p>
</blockquote>
<h4>Use as a Base Type</h4>
<p>For use as a base type, the native force and moment vector data members are
defined as protected. In this case the SetNativeForces() and SetNativeMoments()
methods need not be used and, instead, the assignments to vFn, the force vector,
and vMn, the moments, can be made directly. Otherwise, the usage is similar.<br>
<br><br></p>
@author Tony Peden
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGForce : public FGJSBBase
class FGForce { {
public: public:
/// Constructor
FGForce(FGFDMExec *FDMExec); FGForce(FGFDMExec *FDMExec);
/// Destructor
~FGForce(); ~FGForce();
enum TransformType { tNone, tWindBody, tLocalBody, tCustom } ttype; enum TransformType { tNone, tWindBody, tLocalBody, tCustom } ttype;
@ -81,22 +232,22 @@ public:
vFn(2)=Fny; vFn(2)=Fny;
vFn(3)=Fnz; vFn(3)=Fnz;
} }
inline void SetNativeForces(FGColumnVector vv) { vFn = vv; }; inline void SetNativeForces(FGColumnVector3 vv) { vFn = vv; };
inline void SetNativeMoments(float Ln,float Mn, float Nn) { inline void SetNativeMoments(float Ln,float Mn, float Nn) {
vMn(1)=Ln; vMn(1)=Ln;
vMn(2)=Mn; vMn(2)=Mn;
vMn(3)=Nn; vMn(3)=Nn;
} }
inline void SetNativeMoments(FGColumnVector vv) { vMn = vv; } inline void SetNativeMoments(FGColumnVector3 vv) { vMn = vv; }
inline FGColumnVector GetNativeForces(void) { return vFn; } inline FGColumnVector3& GetNativeForces(void) { return vFn; }
inline FGColumnVector GetNativeMoments(void) { return vMn; } inline FGColumnVector3& GetNativeMoments(void) { return vMn; }
FGColumnVector GetBodyForces(void); FGColumnVector3& GetBodyForces(void);
inline FGColumnVector GetMoments(void) { return vM; } inline FGColumnVector3& GetMoments(void) { return vM; }
//point of application, JSBsim structural coords //point of application, JSBsim structural coords
//(inches, x +back, y +right, z +up) //(inches, x +back, y +right, z +up)
@ -105,8 +256,8 @@ public:
vXYZn(2) = y; vXYZn(2) = y;
vXYZn(3) = z; vXYZn(3) = z;
} }
inline void SetLocation(FGColumnVector vv) { vXYZn = vv; } inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; }
FGColumnVector GetLocation(void) { return vXYZn; } FGColumnVector3& GetLocation(void) { return vXYZn; }
//these angles are relative to body axes, not earth!!!!! //these angles are relative to body axes, not earth!!!!!
//I'm using these because pitch, roll, and yaw are easy to visualize, //I'm using these because pitch, roll, and yaw are easy to visualize,
@ -116,32 +267,32 @@ public:
//They are in radians. //They are in radians.
void SetAnglesToBody(float broll, float bpitch, float byaw); void SetAnglesToBody(float broll, float bpitch, float byaw);
inline void SetAnglesToBody(FGColumnVector vv) { SetAnglesToBody(vv(1), vv(2), vv(3));} inline void SetAnglesToBody(FGColumnVector3 vv) { SetAnglesToBody(vv(1), vv(2), vv(3));}
inline void SetSense(float x, float y, float z) { vSense(1)=x, vSense(2)=y, vSense(3)=z; } inline void SetSense(float x, float y, float z) { vSense(1)=x, vSense(2)=y, vSense(3)=z; }
inline void SetSense(FGColumnVector vv) { vSense=vv; } inline void SetSense(FGColumnVector3 vv) { vSense=vv; }
inline FGColumnVector GetSense(void) { return vSense; } inline FGColumnVector3& GetSense(void) { return vSense; }
inline void SetTransformType(TransformType ii) { ttype=ii; } inline void SetTransformType(TransformType ii) { ttype=ii; }
inline TransformType GetTransformType(void) { return ttype; } inline TransformType GetTransformType(void) { return ttype; }
FGMatrix Transform(void); FGMatrix33 Transform(void);
protected: protected:
FGColumnVector vFn; FGColumnVector3 vFn;
FGColumnVector vMn; FGColumnVector3 vMn;
FGFDMExec *fdmex; FGFDMExec *fdmex;
void Debug(void); virtual void Debug(void);
private: private:
FGColumnVector vFb; FGColumnVector3 vFb;
FGColumnVector vM; FGColumnVector3 vM;
FGColumnVector vXYZn; FGColumnVector3 vXYZn;
FGColumnVector vDXYZ; FGColumnVector3 vDXYZ;
FGColumnVector vSense; FGColumnVector3 vSense;
FGMatrix mT; FGMatrix33 mT;
}; };
#endif #endif

View file

@ -40,23 +40,98 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_GROUNDREACTIONS; static const char *IdHdr = ID_GROUNDREACTIONS;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex) FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex),
vForces(3),
vMoments(3),
vMaxStaticGrip(3),
vMaxMomentResist(3)
{ {
if (debug_lvl & 2) cout << "Instantiated: FGGroundReactions" << endl; Name = "FGGroundReactions";
GearUp = false;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGGroundReactions:: Run(void) { bool FGGroundReactions::Run(void)
{
float steerAngle = 0.0;
float xForces = 0.0, yForces = 0.0;
if (!FGModel::Run()) { if (!FGModel::Run()) {
vForces.InitMatrix();
vMoments.InitMatrix();
// Only execute gear force code below 300 feet
if ( !GearUp && Position->GetDistanceAGL() < 300.0 ) {
vector <FGLGear>::iterator iGear = lGear.begin();
// Sum forces and moments for all gear, here.
// Some optimizations may be made here - or rather in the gear code itself.
// The gear ::Run() method is called several times - once for each gear.
// Perhaps there is some commonality for things which only need to be
// calculated once.
while (iGear != lGear.end()) {
vForces += iGear->Force();
vMoments += iGear->Moment();
iGear++;
}
// Only execute this code when the aircraft ground speed is very, very small.
if (fabs(Translation->GetUVW(eX)) < 0.1 &&
fabs(Translation->GetUVW(eZ)) < 0.1)
{
// Initialize the comparison matrices.
vMaxStaticGrip.InitMatrix();
vMaxMomentResist.InitMatrix();
iGear = lGear.begin();
// For each gear that is touching the ground (which had better be all of them!)
// calculate the X and Y direction maximum "gripping" power. Also, keep track
// of the number of gear that have weight on wheels. This is probably unnecessary.
while (iGear != lGear.end()) {
// calculate maximum gripping power for each gear here based on brake
// and steering settings
// also calculate total number of wheels with WOW set true?
if (iGear->GetWOW()) {
steerAngle = iGear->GetSteerAngle();
vMaxStaticGrip(eX) += (iGear->GetBrakeFCoeff()*cos(steerAngle) -
iGear->GetstaticFCoeff()*sin(steerAngle))*iGear->GetCompForce();
vMaxStaticGrip(eY) += iGear->GetBrakeFCoeff()*sin(steerAngle) +
iGear->GetstaticFCoeff()*cos(steerAngle)*iGear->GetCompForce();
vMaxStaticGrip(eZ) = 0.0;
// vMaxMomentResist += 1;
}
iGear++;
}
// Calculate the X and Y direction non-gear forces to counteract if needed.
xForces = -1.0 * ( Aerodynamics->GetForces(eX)
+ Propulsion->GetForces(eX)
+ Inertial->GetForces(eX));
yForces = -1.0 * ( Aerodynamics->GetForces(eY)
+ Propulsion->GetForces(eY)
+ Inertial->GetForces(eY));
// These if statement comparisons probably need some validation and work
if (fabs(xForces) < fabs(vMaxStaticGrip(eX))) { // forces exceed gear power
vForces(eX) = xForces;
}
if (fabs(yForces) < fabs(vMaxStaticGrip(eY))) { // forces exceed gear power
vForces(eY) = yForces;
}
vMoments(eZ) = -(Aerodynamics->GetMoments(eZ) + Propulsion->GetMoments(eZ));
}
} else {
// Crash Routine
}
return false; return false;
} else { } else {
@ -68,11 +143,61 @@ bool FGGroundReactions:: Run(void) {
bool FGGroundReactions::Load(FGConfigFile* AC_cfg) bool FGGroundReactions::Load(FGConfigFile* AC_cfg)
{ {
string token;
AC_cfg->GetNextConfigLine();
while ((token = AC_cfg->GetValue()) != "/UNDERCARRIAGE") {
lGear.push_back(FGLGear(AC_cfg, FDMExec));
}
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGGroundReactions::GetGroundReactionStrings(void)
{
string GroundReactionStrings = "";
bool firstime = true;
for (unsigned int i=0;i<lGear.size();i++) {
if (!firstime) GroundReactionStrings += ", ";
GroundReactionStrings += (lGear[i].GetName() + "_WOW, ");
GroundReactionStrings += (lGear[i].GetName() + "_compressLength, ");
GroundReactionStrings += (lGear[i].GetName() + "_compressSpeed, ");
GroundReactionStrings += (lGear[i].GetName() + "_Force");
firstime = false;
}
return GroundReactionStrings;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGGroundReactions::GetGroundReactionValues(void)
{
char buff[20];
string GroundReactionValues = "";
bool firstime = true;
for (unsigned int i=0;i<lGear.size();i++) {
if (!firstime) GroundReactionValues += ", ";
GroundReactionValues += string( lGear[i].GetWOW()?"1":"0" ) + ", ";
GroundReactionValues += (string(gcvt(lGear[i].GetCompLen(), 5, buff)) + ", ");
GroundReactionValues += (string(gcvt(lGear[i].GetCompVel(), 6, buff)) + ", ");
GroundReactionValues += (string(gcvt(lGear[i].GetCompForce(), 10, buff)));
firstime = false;
}
return GroundReactionValues;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGGroundReactions::Debug(void) void FGGroundReactions::Debug(void)
{ {
//TODO: Add your source code here //TODO: Add your source code here

View file

@ -55,6 +55,9 @@ INCLUDES
#include "FGModel.h" #include "FGModel.h"
#include "FGConfigFile.h" #include "FGConfigFile.h"
#include "FGLGear.h"
#include "FGInertial.h"
#include "FGMatrix33.h"
#define ID_GROUNDREACTIONS "$Id$" #define ID_GROUNDREACTIONS "$Id$"
@ -62,16 +65,27 @@ INCLUDES
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGGroundReactions : public FGModel { class FGGroundReactions : public FGModel
{
public: public:
FGGroundReactions(FGFDMExec*); FGGroundReactions(FGFDMExec*);
~FGGroundReactions(); ~FGGroundReactions() {};
bool Run(void); bool Run(void);
bool Load(FGConfigFile* AC_cfg); bool Load(FGConfigFile* AC_cfg);
FGColumnVector3& GetForces(void) {return vForces;}
FGColumnVector3& GetMoments(void) {return vMoments;}
string GetGroundReactionStrings(void);
string GetGroundReactionValues(void);
private: private:
vector <FGLGear> lGear;
bool GearUp;
FGColumnVector3 vForces;
FGColumnVector3 vMoments;
FGColumnVector3 vMaxStaticGrip;
FGColumnVector3 vMaxMomentResist;
void Debug(void); void Debug(void);
}; };

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_INERTIAL; static const char *IdHdr = ID_INERTIAL;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -52,7 +50,8 @@ CLASS IMPLEMENTATION
FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex), FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex),
vForces(3), vForces(3),
vOmegaLocal(3), vOmegaLocal(3),
vRadius(3) vRadius(3),
vGravity(3)
{ {
Name = "FGInertial"; Name = "FGInertial";
@ -81,9 +80,9 @@ bool FGInertial::Run(void)
sphi = sin(Rotation->GetEuler(ePhi)); sphi = sin(Rotation->GetEuler(ePhi));
cphi = cos(Rotation->GetEuler(ePhi)); cphi = cos(Rotation->GetEuler(ePhi));
vForces(eX) = -GRAVITY*stht; vGravity(eX) = vForces(eX) = -GRAVITY*stht;
vForces(eY) = GRAVITY*sphi*ctht; vGravity(eY) = vForces(eY) = GRAVITY*sphi*ctht;
vForces(eZ) = GRAVITY*cphi*ctht; vGravity(eZ) = vForces(eZ) = GRAVITY*cphi*ctht;
// The following equation for vOmegaLocal terms shows the angular velocity // The following equation for vOmegaLocal terms shows the angular velocity
// calculation _for_the_local_frame_ given the earth's rotation (first set) // calculation _for_the_local_frame_ given the earth's rotation (first set)

View file

@ -55,7 +55,9 @@ INCLUDES
#include "FGModel.h" #include "FGModel.h"
#include "FGConfigFile.h" #include "FGConfigFile.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
#define ID_INERTIAL "$Id$" #define ID_INERTIAL "$Id$"
@ -71,14 +73,17 @@ public:
~FGInertial(void); ~FGInertial(void);
bool Run(void); bool Run(void);
FGColumnVector GetForces(void) {return vForces;} FGColumnVector3& GetForces(void) {return vForces;}
FGColumnVector3& GetGravity(void) {return vGravity;}
float GetForces(int n) {return vForces(n);}
bool LoadInertial(FGConfigFile* AC_cfg); bool LoadInertial(FGConfigFile* AC_cfg);
private: private:
void Debug(void); void Debug(void);
FGColumnVector vOmegaLocal; FGColumnVector3 vOmegaLocal;
FGColumnVector vForces; FGColumnVector3 vForces;
FGColumnVector vRadius; FGColumnVector3 vRadius;
FGColumnVector3 vGravity;
}; };
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -54,12 +54,11 @@ INCLUDES
#include "FGAuxiliary.h" #include "FGAuxiliary.h"
#include "FGOutput.h" #include "FGOutput.h"
#include "FGDefs.h" #include "FGDefs.h"
#include "FGConfigFile.h"
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_INITIALCONDITION; static const char *IdHdr = ID_INITIALCONDITION;
extern short debug_lvl;
//****************************************************************************** //******************************************************************************
FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec){ FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec){
@ -71,12 +70,17 @@ FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec){
altitude=hdot=0; altitude=hdot=0;
latitude=longitude=0; latitude=longitude=0;
u=v=w=0; u=v=w=0;
vw=vw=ww=0; uw=vw=ww=0;
vnorth=veast=vdown=0; vnorth=veast=vdown=0;
wnorth=weast=wdown=0;
whead=wcross=0;
wdir=wmag=0;
lastSpeedSet=setvt; lastSpeedSet=setvt;
lastWindSet=setwned;
sea_level_radius = EARTHRAD; sea_level_radius = EARTHRAD;
radius_to_vehicle = EARTHRAD; radius_to_vehicle = EARTHRAD;
terrain_altitude = 0; terrain_altitude = 0;
salpha=sbeta=stheta=sphi=spsi=sgamma=0; salpha=sbeta=stheta=sphi=spsi=sgamma=0;
calpha=cbeta=ctheta=cphi=cpsi=cgamma=1; calpha=cbeta=ctheta=cphi=cpsi=cgamma=1;
@ -130,27 +134,19 @@ void FGInitialCondition::SetVequivalentKtsIC(float tt) {
//****************************************************************************** //******************************************************************************
void FGInitialCondition::SetVgroundFpsIC(float tt) { void FGInitialCondition::SetVgroundFpsIC(float tt) {
//float ua,va,wa; float ua,va,wa;
float vxz; float vxz;
//cout << "FGInitialCondition::SetVgroundFpsIC" << endl;
vg=tt; vg=tt;
lastSpeedSet=setvg; lastSpeedSet=setvg;
vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0; vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0;
calcUVWfromNED(); calcUVWfromNED();
//cout << "\tu,v,w: " << u << ", " << v << ", " << w << endl; ua = u + uw; va = v + vw; wa = w + ww;
calcWindUVW(); vt = sqrt( ua*ua + va*va + wa*wa );
//cout << "\tuw,vw,ww: " << uw << ", " << vw << ", " << ww << endl;
u = -uw; v = -vw; w = -ww;
//ua = u - uw; va = v - vw; wa = w - ww;
//cout << "\tua,va,wa: " << ua << ", " << va << ", " << wa << endl;
vt = sqrt( u*u + v*v + w*w );
alpha = beta = 0; alpha = beta = 0;
vxz = sqrt( u*u + w*w ); vxz = sqrt( u*u + w*w );
if( w != 0 ) alpha = atan2( w, u ); if( w != 0 ) alpha = atan2( w, u );
if( vxz != 0 ) beta = atan2( v, vxz ); if( vxz != 0 ) beta = atan2( v, vxz );
//cout << "\tvt,alpha,beta: " << vt << ", " << alpha*RADTODEG << ", "
// << beta*RADTODEG << endl;
mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
vc=calcVcas(mach); vc=calcVcas(mach);
ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
@ -216,7 +212,6 @@ void FGInitialCondition::SetAlphaRadIC(float tt) {
void FGInitialCondition::SetPitchAngleRadIC(float tt) { void FGInitialCondition::SetPitchAngleRadIC(float tt) {
theta=tt; theta=tt;
stheta=sin(theta); ctheta=cos(theta); stheta=sin(theta); ctheta=cos(theta);
calcWindUVW();
getAlpha(); getAlpha();
} }
@ -226,6 +221,7 @@ void FGInitialCondition::SetBetaRadIC(float tt) {
beta=tt; beta=tt;
sbeta=sin(beta); cbeta=cos(beta); sbeta=sin(beta); cbeta=cos(beta);
getTheta(); getTheta();
} }
//****************************************************************************** //******************************************************************************
@ -274,7 +270,7 @@ float FGInitialCondition::GetUBodyFpsIC(void) {
if(lastSpeedSet == setvg ) if(lastSpeedSet == setvg )
return u; return u;
else else
return vt*calpha*cbeta; return vt*calpha*cbeta - uw;
} }
//****************************************************************************** //******************************************************************************
@ -282,8 +278,9 @@ float FGInitialCondition::GetUBodyFpsIC(void) {
float FGInitialCondition::GetVBodyFpsIC(void) { float FGInitialCondition::GetVBodyFpsIC(void) {
if( lastSpeedSet == setvg ) if( lastSpeedSet == setvg )
return v; return v;
else else {
return vt*sbeta; return vt*sbeta - vw;
}
} }
//****************************************************************************** //******************************************************************************
@ -291,26 +288,87 @@ float FGInitialCondition::GetVBodyFpsIC(void) {
float FGInitialCondition::GetWBodyFpsIC(void) { float FGInitialCondition::GetWBodyFpsIC(void) {
if( lastSpeedSet == setvg ) if( lastSpeedSet == setvg )
return w; return w;
else { else
return vt*salpha*cbeta; return vt*salpha*cbeta -ww;
}
} }
//****************************************************************************** //******************************************************************************
void FGInitialCondition::SetWindNEDFpsIC(float wN, float wE, float wD ) { void FGInitialCondition::SetWindNEDFpsIC(float wN, float wE, float wD ) {
wnorth = wN; weast = wE; wdown = wD; wnorth = wN; weast = wE; wdown = wD;
lastWindSet = setwned;
calcWindUVW();
if(lastSpeedSet == setvg) if(lastSpeedSet == setvg)
SetVgroundFpsIC(vg); SetVgroundFpsIC(vg);
} }
//****************************************************************************** //******************************************************************************
void FGInitialCondition::calcWindUVW(void) { // positive from left
if(lastSpeedSet == setvg ) { void FGInitialCondition::SetHeadWindKtsIC(float head){
whead=head*KTSTOFPS;
lastWindSet=setwhc;
calcWindUVW();
if(lastSpeedSet == setvg)
SetVgroundFpsIC(vg);
}
//******************************************************************************
void FGInitialCondition::SetCrossWindKtsIC(float cross){
wcross=cross*KTSTOFPS;
lastWindSet=setwhc;
calcWindUVW();
if(lastSpeedSet == setvg)
SetVgroundFpsIC(vg);
}
//******************************************************************************
void FGInitialCondition::SetWindDownKtsIC(float wD) {
wdown=wD;
calcWindUVW();
if(lastSpeedSet == setvg)
SetVgroundFpsIC(vg);
}
//******************************************************************************
void FGInitialCondition::SetWindMagKtsIC(float mag) {
wmag=mag*KTSTOFPS;
lastWindSet=setwmd;
calcWindUVW();
if(lastSpeedSet == setvg)
SetVgroundFpsIC(vg);
}
//******************************************************************************
void FGInitialCondition::SetWindDirDegIC(float dir) {
wdir=dir*DEGTORAD;
lastWindSet=setwmd;
calcWindUVW();
if(lastSpeedSet == setvg)
SetVgroundFpsIC(vg);
}
//******************************************************************************
void FGInitialCondition::calcWindUVW(void) {
switch(lastWindSet) {
case setwmd:
wnorth=wmag*cos(wdir);
weast=wmag*sin(wdir);
break;
case setwhc:
wnorth=whead*cos(psi) + wcross*cos(psi+M_PI/2);
weast=whead*sin(psi) + wcross*sin(psi+M_PI/2);
break;
}
uw=wnorth*ctheta*cpsi + uw=wnorth*ctheta*cpsi +
weast*ctheta*spsi - weast*ctheta*spsi -
wdown*stheta; wdown*stheta;
@ -320,6 +378,8 @@ void FGInitialCondition::calcWindUVW(void) {
ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) + ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) +
weast*(cphi*stheta*spsi - sphi*cpsi) + weast*(cphi*stheta*spsi - sphi*cpsi) +
wdown*cphi*ctheta; wdown*cphi*ctheta;
/* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown " /* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown "
<< wnorth << ", " << weast << ", " << wdown << endl; << wnorth << ", " << weast << ", " << wdown << endl;
cout << "FGInitialCondition::calcWindUVW: theta, phi, psi " cout << "FGInitialCondition::calcWindUVW: theta, phi, psi "
@ -327,9 +387,6 @@ void FGInitialCondition::calcWindUVW(void) {
cout << "FGInitialCondition::calcWindUVW: uw, vw, ww " cout << "FGInitialCondition::calcWindUVW: uw, vw, ww "
<< uw << ", " << vw << ", " << ww << endl; */ << uw << ", " << vw << ", " << ww << endl; */
} else {
uw=vw=ww=0;
}
} }
//****************************************************************************** //******************************************************************************
@ -338,7 +395,6 @@ void FGInitialCondition::SetAltitudeFtIC(float tt) {
altitude=tt; altitude=tt;
fdmex->GetPosition()->Seth(altitude); fdmex->GetPosition()->Seth(altitude);
fdmex->GetAtmosphere()->Run(); fdmex->GetAtmosphere()->Run();
//lets try to make sure the user gets what they intended //lets try to make sure the user gets what they intended
switch(lastSpeedSet) { switch(lastSpeedSet) {
@ -380,8 +436,6 @@ void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) {
void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) { void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) {
terrain_altitude=tt; terrain_altitude=tt;
fdmex->GetPosition()->SetDistanceAGL(altitude-terrain_altitude);
fdmex->GetPosition()->SetRunwayRadius(sea_level_radius + terrain_altitude);
} }
//****************************************************************************** //******************************************************************************
@ -458,6 +512,7 @@ bool FGInitialCondition::getAlpha(void) {
calpha=cos(alpha); calpha=cos(alpha);
} }
} }
calcWindUVW();
return result; return result;
} }
@ -476,6 +531,7 @@ bool FGInitialCondition::getTheta(void) {
ctheta=cos(theta); ctheta=cos(theta);
} }
} }
calcWindUVW();
return result; return result;
} }
@ -590,49 +646,50 @@ bool FGInitialCondition::findInterval(float x,float guess) {
//****************************************************************************** //******************************************************************************
bool FGInitialCondition::solve(float *y,float x) { bool FGInitialCondition::solve(float *y,float x)
{
float x1,x2,x3,f1,f2,f3,d,d0; float x1,x2,x3,f1,f2,f3,d,d0;
float eps=1E-5; float eps=1E-5;
float const relax =0.9; float const relax =0.9;
int i; int i;
bool success=false; bool success=false;
//initializations //initializations
d=1; d=1;
x1=xlo;x3=xhi; x1=xlo;x3=xhi;
f1=(this->*sfunc)(x1)-x; f1=(this->*sfunc)(x1)-x;
f3=(this->*sfunc)(x3)-x; f3=(this->*sfunc)(x3)-x;
d0=fabs(x3-x1); d0=fabs(x3-x1);
//iterations //iterations
i=0; i=0;
while ((fabs(d) > eps) && (i < 100)) { while ((fabs(d) > eps) && (i < 100)) {
d=(x3-x1)/d0; d=(x3-x1)/d0;
x2=x1-d*d0*f1/(f3-f1); x2=x1-d*d0*f1/(f3-f1);
f2=(this->*sfunc)(x2)-x; f2=(this->*sfunc)(x2)-x;
//cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl; //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl;
//cout << " " << f1 << "," << f2 << "," << f3 << endl; //cout << " " << f1 << "," << f2 << "," << f3 << endl;
if(fabs(f2) <= 0.001) { if(fabs(f2) <= 0.001) {
x1=x3=x2; x1=x3=x2;
} else if(f1*f2 <= 0.0) { } else if(f1*f2 <= 0.0) {
x3=x2; x3=x2;
f3=f2; f3=f2;
f1=relax*f1; f1=relax*f1;
} else if(f2*f3 <= 0) { } else if(f2*f3 <= 0) {
x1=x2; x1=x2;
f1=f2; f1=f2;
f3=relax*f3; f3=relax*f3;
}
//cout << i << endl;
i++;
}//end while
if(i < 100) {
success=true;
*y=x2;
} }
//cout << i << endl;
i++;
}//end while
if(i < 100) {
success=true;
*y=x2;
}
//cout << "Success= " << success << " Vcas: " << vcas*jsbFPSTOKTS << " Mach: " << x2 << endl; //cout << "Success= " << success << " Vcas: " << vcas*jsbFPSTOKTS << " Mach: " << x2 << endl;
return success; return success;
@ -640,8 +697,69 @@ bool FGInitialCondition::solve(float *y,float x) {
//****************************************************************************** //******************************************************************************
void FGInitialCondition::Debug(void) float FGInitialCondition::GetWindDirDegIC(void) {
{ if(weast != 0.0)
//TODO: Add your source code here return atan2(weast,wnorth)*RADTODEG;
} else if(wnorth > 0)
return 0.0;
else
return 180.0;
}
//******************************************************************************
bool FGInitialCondition::Load(string path, string acname, string fname)
{
string resetDef;
string token="";
float temp;
# ifndef macintosh
resetDef = path + "/" + acname + "/" + fname + ".xml";
# else
resetDef = path + ";" + acname + ";" + fname + ".xml";
# endif
cout << resetDef << endl;
FGConfigFile resetfile(resetDef);
if (!resetfile.IsOpen()) return false;
resetfile.GetNextConfigLine();
token = resetfile.GetValue();
if (token != "initialize") {
cerr << "The reset file " << resetDef
<< " does not appear to be a reset file" << endl;
return false;
}
resetfile.GetNextConfigLine();
resetfile >> token;
while (token != "/initialize" && token != "EOF") {
if (token == "UBODY" ) { resetfile >> temp; SetUBodyFpsIC(temp); }
if (token == "VBODY" ) { resetfile >> temp; SetVBodyFpsIC(temp); }
if (token == "WBODY" ) { resetfile >> temp; SetWBodyFpsIC(temp); }
if (token == "LATITUDE" ) { resetfile >> temp; SetLatitudeDegIC(temp); }
if (token == "LONGITUDE" ) { resetfile >> temp; SetLongitudeDegIC(temp); }
if (token == "PHI" ) { resetfile >> temp; SetRollAngleDegIC(temp); }
if (token == "THETA" ) { resetfile >> temp; SetPitchAngleDegIC(temp); }
if (token == "PSI" ) { resetfile >> temp; SetTrueHeadingDegIC(temp); }
if (token == "ALPHA" ) { resetfile >> temp; SetAlphaDegIC(temp); }
if (token == "BETA" ) { resetfile >> temp; SetBetaDegIC(temp); }
if (token == "GAMMA" ) { resetfile >> temp; SetFlightPathAngleDegIC(temp); }
if (token == "ROC" ) { resetfile >> temp; SetClimbRateFpmIC(temp); }
if (token == "ALTITUDE" ) { resetfile >> temp; SetAltitudeFtIC(temp); }
if (token == "WINDDIR" ) { resetfile >> temp; SetWindDirDegIC(temp); }
if (token == "VWIND" ) { resetfile >> temp; SetWindMagKtsIC(temp); }
if (token == "HWIND" ) { resetfile >> temp; SetHeadWindKtsIC(temp); }
if (token == "XWIND" ) { resetfile >> temp; SetCrossWindKtsIC(temp); }
if (token == "VC" ) { resetfile >> temp; SetVcalibratedKtsIC(temp); }
if (token == "MACH" ) { resetfile >> temp; SetMachIC(temp); }
if (token == "VGROUND" ) { resetfile >> temp; SetVgroundKtsIC(temp); }
resetfile >> token;
}
fdmex->RunIC(this);
return true;
}

View file

@ -23,12 +23,10 @@
Further information about the GNU General Public License can also be found on Further information about the GNU General Public License can also be found on
the world wide web at http://www.gnu.org. the world wide web at http://www.gnu.org.
HISTORY HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
7/1/99 TP Created 7/1/99 TP Created
FUNCTIONAL DESCRIPTION FUNCTIONAL DESCRIPTION
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -50,22 +48,43 @@ INCLUDES
*******************************************************************************/ *******************************************************************************/
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGJSBBase.h"
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INITIALCONDITION "$Id$" #define ID_INITIALCONDITION "$Id$"
/*******************************************************************************
CLASS DECLARATION
*******************************************************************************/
typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
#define jsbFPSTOKTS 0.5924838 #define jsbFPSTOKTS 0.5924838
#define jsbKTSTOFPS 1.6878099 #define jsbKTSTOFPS 1.6878099
typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
typedef enum { setwned, setwmd, setwhc } windset;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Takes a set of initial conditions and provide a kinematically consistent set
of body axis velocity components, euler angles, and altitude. This class
does not attempt to trim the model i.e. the sim will most likely start in a
very dynamic state (unless, of course, you have chosen your IC's wisely)
even after setting it up with this class.
USAGE NOTES
/* USAGE NOTES
With a valid object of FGFDMExec and an aircraft model loaded With a valid object of FGFDMExec and an aircraft model loaded
FGInitialCondition fgic=new FGInitialCondition(FDMExec); FGInitialCondition fgic=new FGInitialCondition(FDMExec);
fgic->SetVcalibratedKtsIC() fgic->SetVcalibratedKtsIC()
@ -82,6 +101,7 @@ typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
FDMExec->RunIC(fgic) FDMExec->RunIC(fgic)
Speed: Speed:
Since vc, ve, vt, and mach all represent speed, the remaining Since vc, ve, vt, and mach all represent speed, the remaining
three are recalculated each time one of them is set (using the three are recalculated each time one of them is set (using the
current altitude). The most recent speed set is remembered so current altitude). The most recent speed set is remembered so
@ -91,10 +111,12 @@ typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
most recent speed set. most recent speed set.
Alpha,Gamma, and Theta: Alpha,Gamma, and Theta:
This class assumes that it will be used to set up the sim for a
This class assumes that it will be used to set up the sim for a
steady, zero pitch rate condition. Since any two of those angles steady, zero pitch rate condition. Since any two of those angles
specifies the third gamma (flight path angle) is favored when setting specifies the third gamma (flight path angle) is favored when setting
alpha and theta and alpha is favored when setting gamma. i.e. alpha and theta and alpha is favored when setting gamma. i.e.
set alpha : recalculate theta using gamma as currently set set alpha : recalculate theta using gamma as currently set
set theta : recalculate alpha using gamma as currently set set theta : recalculate alpha using gamma as currently set
set gamma : recalculate theta using alpha as currently set set gamma : recalculate theta using alpha as currently set
@ -104,12 +126,20 @@ typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
Setting climb rate is, for the purpose of this discussion, Setting climb rate is, for the purpose of this discussion,
considered equivalent to setting gamma. considered equivalent to setting gamma.
@author Anthony K. Peden
@version $Id$
*/ */
class FGInitialCondition {
public:
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGInitialCondition : public FGJSBBase
{
public:
/// Constructor
FGInitialCondition(FGFDMExec *fdmex); FGInitialCondition(FGFDMExec *fdmex);
/// Destructor
~FGInitialCondition(); ~FGInitialCondition();
void SetVcalibratedKtsIC(float tt); void SetVcalibratedKtsIC(float tt);
@ -171,7 +201,17 @@ public:
void SetVnorthFpsIC(float tt); void SetVnorthFpsIC(float tt);
void SetVeastFpsIC(float tt); void SetVeastFpsIC(float tt);
void SetVdownFpsIC(float tt); void SetVdownFpsIC(float tt);
void SetWindNEDFpsIC(float wN, float wE, float wD); void SetWindNEDFpsIC(float wN, float wE, float wD);
void SetWindMagKtsIC(float mag);
void SetWindDirDegIC(float dir);
void SetHeadWindKtsIC(float head);
void SetCrossWindKtsIC(float cross);// positive from left
void SetWindDownKtsIC(float wD);
void SetClimbRateFpsIC(float tt); void SetClimbRateFpsIC(float tt);
inline float GetVgroundFpsIC(void) { return vg; } inline float GetVgroundFpsIC(void) { return vg; }
inline float GetVtrueFpsIC(void) { return vt; } inline float GetVtrueFpsIC(void) { return vt; }
@ -181,6 +221,8 @@ public:
inline float GetWindNFpsIC(void) { return wnorth; } inline float GetWindNFpsIC(void) { return wnorth; }
inline float GetWindEFpsIC(void) { return weast; } inline float GetWindEFpsIC(void) { return weast; }
inline float GetWindDFpsIC(void) { return wdown; } inline float GetWindDFpsIC(void) { return wdown; }
inline float GetWindFpsIC(void) { return sqrt(wnorth*wnorth + weast*weast); }
float GetWindDirDegIC(void);
inline float GetClimbRateFpsIC(void) { return hdot; } inline float GetClimbRateFpsIC(void) { return hdot; }
float GetUBodyFpsIC(void); float GetUBodyFpsIC(void);
float GetVBodyFpsIC(void); float GetVBodyFpsIC(void);
@ -206,6 +248,9 @@ public:
inline float GetPsiRadIC(void) { return psi; } inline float GetPsiRadIC(void) { return psi; }
inline speedset GetSpeedSet(void) { return lastSpeedSet; } inline speedset GetSpeedSet(void) { return lastSpeedSet; }
inline windset GetWindSet(void) { return lastWindSet; }
bool Load(string path, string acname, string fname);
private: private:
float vt,vc,ve,vg; float vt,vc,ve,vg;
@ -216,6 +261,7 @@ private:
float uw,vw,ww; float uw,vw,ww;
float vnorth,veast,vdown; float vnorth,veast,vdown;
float wnorth,weast,wdown; float wnorth,weast,wdown;
float whead, wcross, wdir, wmag;
double sea_level_radius; double sea_level_radius;
double terrain_altitude; double terrain_altitude;
double radius_to_vehicle; double radius_to_vehicle;
@ -230,6 +276,7 @@ private:
fp sfunc; fp sfunc;
speedset lastSpeedSet; speedset lastSpeedSet;
windset lastWindSet;
FGFDMExec *fdmex; FGFDMExec *fdmex;
@ -245,7 +292,6 @@ private:
bool findInterval(float x,float guess); bool findInterval(float x,float guess);
bool solve(float *y, float x); bool solve(float *y, float x);
void Debug(void);
}; };
#endif #endif

View file

@ -53,8 +53,6 @@ GLOBAL DATA
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_LGEAR; static const char *IdHdr = ID_LGEAR;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -62,6 +60,9 @@ CLASS IMPLEMENTATION
FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : vXYZ(3), FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : vXYZ(3),
vMoment(3), vMoment(3),
vWhlBodyVec(3), vWhlBodyVec(3),
vForce(3),
vLocalForce(3),
vWhlVelVec(3),
Exec(fdmex) Exec(fdmex)
{ {
string tmp; string tmp;
@ -181,17 +182,13 @@ FGLGear::~FGLGear()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector FGLGear::Force(void) FGColumnVector3& FGLGear::Force(void)
{ {
float SteerGain, SteerAngle, BrakeFCoeff; float SteerGain;
float SinWheel, CosWheel, SideWhlVel, RollingWhlVel; float SinWheel, CosWheel, SideWhlVel, RollingWhlVel;
float RudderPedal, RollingForce, SideForce, FCoeff; float RudderPedal, RollingForce, SideForce, FCoeff;
float WheelSlip; float WheelSlip;
FGColumnVector vForce(3);
FGColumnVector vLocalForce(3);
FGColumnVector vWhlVelVec(3); // Velocity of this wheel (Local)
vWhlBodyVec = (vXYZ - MassBalance->GetXYZcg()) / 12.0; vWhlBodyVec = (vXYZ - MassBalance->GetXYZcg()) / 12.0;
vWhlBodyVec(eX) = -vWhlBodyVec(eX); vWhlBodyVec(eX) = -vWhlBodyVec(eX);
vWhlBodyVec(eZ) = -vWhlBodyVec(eZ); vWhlBodyVec(eZ) = -vWhlBodyVec(eZ);
@ -225,6 +222,7 @@ FGColumnVector FGLGear::Force(void)
// wheel velocity. // wheel velocity.
vWhlVelVec = State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec); vWhlVelVec = State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);
vWhlVelVec += Position->GetVel(); vWhlVelVec += Position->GetVel();
compressSpeed = vWhlVelVec(eZ); compressSpeed = vWhlVelVec(eZ);
@ -247,30 +245,30 @@ FGColumnVector FGLGear::Force(void)
switch (eBrakeGrp) { switch (eBrakeGrp) {
case bgLeft: case bgLeft:
SteerGain = -maxSteerAngle; SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) + BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
staticFCoeff*FCS->GetBrake(bgLeft); staticFCoeff*FCS->GetBrake(bgLeft);
break; break;
case bgRight: case bgRight:
SteerGain = -maxSteerAngle; SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) + BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
staticFCoeff*FCS->GetBrake(bgRight); staticFCoeff*FCS->GetBrake(bgRight);
break; break;
case bgCenter: case bgCenter:
SteerGain = -maxSteerAngle; SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
staticFCoeff*FCS->GetBrake(bgCenter); staticFCoeff*FCS->GetBrake(bgCenter);
break; break;
case bgNose: case bgNose:
SteerGain = maxSteerAngle; SteerGain = 0.10;
BrakeFCoeff = rollingFCoeff; BrakeFCoeff = rollingFCoeff;
break; break;
case bgTail: case bgTail:
SteerGain = -maxSteerAngle; SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff; BrakeFCoeff = rollingFCoeff;
break; break;
case bgNone: case bgNone:
SteerGain = -maxSteerAngle; SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff; BrakeFCoeff = rollingFCoeff;
break; break;
default: default:
@ -280,7 +278,7 @@ FGColumnVector FGLGear::Force(void)
switch (eSteerType) { switch (eSteerType) {
case stSteer: case stSteer:
SteerAngle = SteerGain*FCS->GetDrCmd(); SteerAngle = SteerGain*FCS->GetDrPos();
break; break;
case stFixed: case stFixed:
SteerAngle = 0.0; SteerAngle = 0.0;
@ -298,8 +296,8 @@ FGColumnVector FGLGear::Force(void)
// For now, steering angle is assumed to happen in the Local Z axis, // For now, steering angle is assumed to happen in the Local Z axis,
// not the strut axis as it should be. Will fix this later. // not the strut axis as it should be. Will fix this later.
SinWheel = sin(Rotation->Getpsi() + SteerAngle*DEGTORAD); SinWheel = sin(Rotation->Getpsi() + SteerAngle);
CosWheel = cos(Rotation->Getpsi() + SteerAngle*DEGTORAD); CosWheel = cos(Rotation->Getpsi() + SteerAngle);
RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel; RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;
SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel; SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;

View file

@ -44,8 +44,11 @@ INCLUDES
#include <string> #include <string>
#include "FGConfigFile.h" #include "FGConfigFile.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -172,7 +175,7 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGLGear class FGLGear : public FGJSBBase
{ {
public: public:
/// Brake grouping enumerators /// Brake grouping enumerators
@ -191,15 +194,15 @@ public:
/// The Force vector for this gear /// The Force vector for this gear
FGColumnVector Force(void); FGColumnVector3& Force(void);
/// The Moment vector for this gear /// The Moment vector for this gear
FGColumnVector Moment(void) {return vMoment;} FGColumnVector3& Moment(void) {return vMoment;}
/// Gets the location of the gear in Body axes /// Gets the location of the gear in Body axes
FGColumnVector GetBodyLocation(void) { return vWhlBodyVec; } FGColumnVector3& GetBodyLocation(void) { return vWhlBodyVec; }
float GetBodyLocation(int idx) { return vWhlBodyVec(idx); } float GetBodyLocation(int idx) { return vWhlBodyVec(idx); }
FGColumnVector GetLocalGear(void) { return vLocalGear; } FGColumnVector3& GetLocalGear(void) { return vLocalGear; }
float GetLocalGear(int idx) { return vLocalGear(idx); } float GetLocalGear(int idx) { return vLocalGear(idx); }
/// Gets the name of the gear /// Gets the name of the gear
@ -212,6 +215,7 @@ public:
inline float GetCompVel(void) {return compressSpeed; } inline float GetCompVel(void) {return compressSpeed; }
/// Gets the gear compression force in pounds /// Gets the gear compression force in pounds
inline float GetCompForce(void) {return Force()(3); } inline float GetCompForce(void) {return Force()(3); }
inline float GetBrakeFCoeff(void) {return BrakeFCoeff;}
/// Sets the brake value in percent (0 - 100) /// Sets the brake value in percent (0 - 100)
inline void SetBrake(double bp) {brakePct = bp;} inline void SetBrake(double bp) {brakePct = bp;}
@ -222,19 +226,25 @@ public:
/** Get the console touchdown reporting feature /** Get the console touchdown reporting feature
@return true if reporting is turned on */ @return true if reporting is turned on */
inline bool GetReport(void) { return ReportEnable; } inline bool GetReport(void) { return ReportEnable; }
inline float GetSteerAngle(void) { return SteerAngle;}
inline float GetstaticFCoeff(void) { return staticFCoeff;}
private: private:
enum {eX=1, eY, eZ}; FGColumnVector3 vXYZ;
FGColumnVector vXYZ; FGColumnVector3 vMoment;
FGColumnVector vMoment; FGColumnVector3 vWhlBodyVec;
FGColumnVector vWhlBodyVec; FGColumnVector3 vLocalGear;
FGColumnVector vLocalGear; FGColumnVector3 vForce;
FGColumnVector3 vLocalForce;
FGColumnVector3 vWhlVelVec; // Velocity of this wheel (Local)
float SteerAngle;
float kSpring; float kSpring;
float bDamp; float bDamp;
float compressLength; float compressLength;
float compressSpeed; float compressSpeed;
float staticFCoeff, dynamicFCoeff, rollingFCoeff; float staticFCoeff, dynamicFCoeff, rollingFCoeff;
float brakePct; float brakePct;
float BrakeFCoeff;
float maxCompLen; float maxCompLen;
double SinkRate; double SinkRate;
double GroundSpeed; double GroundSpeed;

View file

@ -43,8 +43,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_MASSBALANCE; static const char *IdHdr = ID_MASSBALANCE;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -67,7 +67,7 @@ public:
inline float GetIzz(void) {return Izz;} inline float GetIzz(void) {return Izz;}
inline float GetIxz(void) {return Ixz;} inline float GetIxz(void) {return Ixz;}
inline float GetIyz(void) {return Iyz;} inline float GetIyz(void) {return Iyz;}
inline FGColumnVector& GetXYZcg(void) {return vXYZcg;} inline FGColumnVector3& GetXYZcg(void) {return vXYZcg;}
inline float GetXYZcg(int axis) {return vXYZcg(axis);} inline float GetXYZcg(int axis) {return vXYZcg(axis);}
inline void SetEmptyWeight(float EW) { EmptyWeight = EW;} inline void SetEmptyWeight(float EW) { EmptyWeight = EW;}
@ -76,7 +76,7 @@ public:
inline void SetBaseIzz(float bizz) { baseIzz = bizz;} inline void SetBaseIzz(float bizz) { baseIzz = bizz;}
inline void SetBaseIxz(float bixz) { baseIxz = bixz;} inline void SetBaseIxz(float bixz) { baseIxz = bixz;}
inline void SetBaseIyz(float biyz) { baseIyz = biyz;} inline void SetBaseIyz(float biyz) { baseIyz = biyz;}
inline void SetBaseCG(const FGColumnVector& CG) {vbaseXYZcg = CG;} inline void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = CG;}
private: private:
float Weight; float Weight;
@ -92,9 +92,9 @@ private:
float baseIzz; float baseIzz;
float baseIxz; float baseIxz;
float baseIyz; float baseIyz;
FGColumnVector vXYZcg; FGColumnVector3 vXYZcg;
FGColumnVector vXYZtank; FGColumnVector3 vXYZtank;
FGColumnVector vbaseXYZcg; FGColumnVector3 vbaseXYZcg;
void Debug(void); void Debug(void);
}; };

View file

@ -47,6 +47,7 @@ INCLUDES
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "FGAerodynamics.h" #include "FGAerodynamics.h"
#include "FGInertial.h" #include "FGInertial.h"
#include "FGGroundReactions.h"
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGTranslation.h" #include "FGTranslation.h"
#include "FGRotation.h" #include "FGRotation.h"
@ -61,8 +62,6 @@ static const char *IdHdr = ID_MODEL;
GLOBAL DECLARATIONS GLOBAL DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -72,19 +71,20 @@ FGModel::FGModel(FGFDMExec* fdmex)
FDMExec = fdmex; FDMExec = fdmex;
NextModel = 0L; NextModel = 0L;
State = 0; State = 0;
Atmosphere = 0; Atmosphere = 0;
FCS = 0; FCS = 0;
Propulsion = 0; Propulsion = 0;
MassBalance = 0; MassBalance = 0;
Aerodynamics = 0; Aerodynamics = 0;
Inertial = 0; Inertial = 0;
Aircraft = 0; GroundReactions = 0;
Translation = 0; Aircraft = 0;
Rotation = 0; Translation = 0;
Position = 0; Rotation = 0;
Auxiliary = 0; Position = 0;
Output = 0; Auxiliary = 0;
Output = 0;
exe_ctr = 1; exe_ctr = 1;
@ -102,19 +102,20 @@ FGModel::~FGModel()
bool FGModel::InitModel(void) bool FGModel::InitModel(void)
{ {
State = FDMExec->GetState(); State = FDMExec->GetState();
Atmosphere = FDMExec->GetAtmosphere(); Atmosphere = FDMExec->GetAtmosphere();
FCS = FDMExec->GetFCS(); FCS = FDMExec->GetFCS();
Propulsion = FDMExec->GetPropulsion(); Propulsion = FDMExec->GetPropulsion();
MassBalance = FDMExec->GetMassBalance(); MassBalance = FDMExec->GetMassBalance();
Aerodynamics = FDMExec->GetAerodynamics(); Aerodynamics = FDMExec->GetAerodynamics();
Inertial = FDMExec->GetInertial(); Inertial = FDMExec->GetInertial();
Aircraft = FDMExec->GetAircraft(); GroundReactions = FDMExec->GetGroundReactions();
Translation = FDMExec->GetTranslation(); Aircraft = FDMExec->GetAircraft();
Rotation = FDMExec->GetRotation(); Translation = FDMExec->GetTranslation();
Position = FDMExec->GetPosition(); Rotation = FDMExec->GetRotation();
Auxiliary = FDMExec->GetAuxiliary(); Position = FDMExec->GetPosition();
Output = FDMExec->GetOutput(); Auxiliary = FDMExec->GetAuxiliary();
Output = FDMExec->GetOutput();
if (!State || if (!State ||
!Atmosphere || !Atmosphere ||
@ -123,6 +124,7 @@ bool FGModel::InitModel(void)
!MassBalance || !MassBalance ||
!Aerodynamics || !Aerodynamics ||
!Inertial || !Inertial ||
!GroundReactions ||
!Aircraft || !Aircraft ||
!Translation || !Translation ||
!Rotation || !Rotation ||
@ -149,8 +151,3 @@ bool FGModel::Run()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGModel::Debug(void)
{
//TODO: Add your source code here
}

View file

@ -39,6 +39,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGDefs.h" #include "FGDefs.h"
#include "FGJSBBase.h"
#ifdef FGFS #ifdef FGFS
# include <simgear/compiler.h> # include <simgear/compiler.h>
@ -48,7 +49,11 @@ INCLUDES
# include <iostream.h> # include <iostream.h>
# endif # endif
#else #else
# include <iostream> # if defined(sgi) && !defined(__GNUC__)
# include <iostream.h>
# else
# include <iostream>
# endif
#endif #endif
#include <string> #include <string>
@ -73,6 +78,7 @@ class FGPropulsion;
class FGMassBalance; class FGMassBalance;
class FGAerodynamics; class FGAerodynamics;
class FGInertial; class FGInertial;
class FGGroundReactions;
class FGAircraft; class FGAircraft;
class FGTranslation; class FGTranslation;
class FGRotation; class FGRotation;
@ -97,7 +103,7 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGModel class FGModel : public FGJSBBase
{ {
public: public:
@ -123,31 +129,24 @@ public:
virtual int GetRate(void) {return rate;} virtual int GetRate(void) {return rate;}
protected: protected:
enum {eU=1, eV, eW};
enum {eNorth=1, eEast, eDown};
enum {eP=1, eQ, eR};
enum {eL=1, eM, eN};
enum {eX=1, eY, eZ};
enum {ePhi=1, eTht, ePsi};
int exe_ctr; int exe_ctr;
int rate; int rate;
FGFDMExec* FDMExec; FGFDMExec* FDMExec;
FGState* State; FGState* State;
FGAtmosphere* Atmosphere; FGAtmosphere* Atmosphere;
FGFCS* FCS; FGFCS* FCS;
FGPropulsion* Propulsion; FGPropulsion* Propulsion;
FGMassBalance* MassBalance; FGMassBalance* MassBalance;
FGAerodynamics* Aerodynamics; FGAerodynamics* Aerodynamics;
FGInertial* Inertial; FGInertial* Inertial;
FGAircraft* Aircraft; FGGroundReactions* GroundReactions;
FGTranslation* Translation; FGAircraft* Aircraft;
FGRotation* Rotation; FGTranslation* Translation;
FGPosition* Position; FGRotation* Rotation;
FGAuxiliary* Auxiliary; FGPosition* Position;
FGOutput* Output; FGAuxiliary* Auxiliary;
virtual void Debug(void); FGOutput* Output;
}; };
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -47,8 +47,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_NOZZLE; static const char *IdHdr = ID_NOZZLE;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -46,11 +46,6 @@ DEFINITIONS
#define ID_NOZZLE "$Id$"; #define ID_NOZZLE "$Id$";
#ifndef M_PI
# include <simgear/constants.h>
# define M_PI SG_PI
#endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -44,6 +44,7 @@ INCLUDES
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGFCS.h" #include "FGFCS.h"
#include "FGAerodynamics.h" #include "FGAerodynamics.h"
#include "FGGroundReactions.h"
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "FGTranslation.h" #include "FGTranslation.h"
@ -54,8 +55,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_OUTPUT; static const char *IdHdr = ID_OUTPUT;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -94,11 +93,7 @@ bool FGOutput::Run(void)
if (Type == otSocket) { if (Type == otSocket) {
SocketOutput(); SocketOutput();
} else if (Type == otCSV) { } else if (Type == otCSV) {
if (Filename != "COUT" && Filename != "cout" && Filename.size() > 0) { DelimitedOutput(Filename);
DelimitedOutput(Filename);
} else {
DelimitedOutput();
}
} else if (Type == otTerminal) { } else if (Type == otTerminal) {
// Not done yet // Not done yet
} else if (Type == otNone) { } else if (Type == otNone) {
@ -133,320 +128,171 @@ void FGOutput::SetType(string type)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGOutput::DelimitedOutput(void) void FGOutput::DelimitedOutput(string fname)
{ {
# if defined(sgi) && !defined(__GNUC__)
ostream_withassign outstream;
# else
_IO_ostream_withassign outstream;
# endif
if (fname == "COUT" || fname == "cout") {
outstream = cout;
} else {
datafile.open(fname.c_str());
outstream = datafile;
}
if (dFirstPass) { if (dFirstPass) {
cout << "Time"; outstream << "Time";
if (SubSystems & FGAircraft::ssSimulation) { if (SubSystems & FGAircraft::ssSimulation) {
// Nothing here, yet // Nothing here, yet
} }
if (SubSystems & FGAircraft::ssAerosurfaces) { if (SubSystems & FGAircraft::ssAerosurfaces) {
cout << ", "; outstream << ", ";
cout << "Throttle, "; outstream << "Throttle, ";
cout << "Aileron Cmd, "; outstream << "Aileron Cmd, ";
cout << "Elevator Cmd, "; outstream << "Elevator Cmd, ";
cout << "Rudder Cmd, "; outstream << "Rudder Cmd, ";
cout << "Aileron Pos, "; outstream << "Aileron Pos, ";
cout << "Elevator Pos, "; outstream << "Elevator Pos, ";
cout << "Rudder Pos"; outstream << "Rudder Pos";
} }
if (SubSystems & FGAircraft::ssRates) { if (SubSystems & FGAircraft::ssRates) {
cout << ", "; outstream << ", ";
cout << "P, Q, R"; outstream << "P, Q, R";
} }
if (SubSystems & FGAircraft::ssVelocities) { if (SubSystems & FGAircraft::ssVelocities) {
cout << ", "; outstream << ", ";
cout << "QBar, "; outstream << "QBar, ";
cout << "Vtotal, "; outstream << "Vtotal, ";
cout << "UBody, VBody, WBody, "; outstream << "UBody, VBody, WBody, ";
cout << "UAero, VAero, WAero, "; outstream << "UAero, VAero, WAero, ";
cout << "Vn, Ve, Vd"; outstream << "Vn, Ve, Vd";
} }
if (SubSystems & FGAircraft::ssForces) { if (SubSystems & FGAircraft::ssForces) {
cout << ", "; outstream << ", ";
cout << "Drag, Side, Lift, "; outstream << "Drag, Side, Lift, ";
cout << "L/D, "; outstream << "L/D, ";
cout << "Xforce, Yforce, Zforce"; outstream << "Xforce, Yforce, Zforce";
} }
if (SubSystems & FGAircraft::ssMoments) { if (SubSystems & FGAircraft::ssMoments) {
cout << ", "; outstream << ", ";
cout << "L, M, N"; outstream << "L, M, N";
} }
if (SubSystems & FGAircraft::ssAtmosphere) { if (SubSystems & FGAircraft::ssAtmosphere) {
cout << ", "; outstream << ", ";
cout << "Rho"; outstream << "Rho";
} }
if (SubSystems & FGAircraft::ssMassProps) { if (SubSystems & FGAircraft::ssMassProps) {
cout << ", "; outstream << ", ";
cout << "Ixx, "; outstream << "Ixx, ";
cout << "Iyy, "; outstream << "Iyy, ";
cout << "Izz, "; outstream << "Izz, ";
cout << "Ixz, "; outstream << "Ixz, ";
cout << "Mass, "; outstream << "Mass, ";
cout << "Xcg, Ycg, Zcg"; outstream << "Xcg, Ycg, Zcg";
} }
if (SubSystems & FGAircraft::ssPosition) { if (SubSystems & FGAircraft::ssPosition) {
cout << ", "; outstream << ", ";
cout << "Altitude, "; outstream << "Altitude, ";
cout << "Phi, Tht, Psi, "; outstream << "Phi, Tht, Psi, ";
cout << "Alpha, "; outstream << "Alpha, ";
cout << "Latitude, "; outstream << "Latitude, ";
cout << "Longitude, "; outstream << "Longitude, ";
cout << "Distance AGL, "; outstream << "Distance AGL, ";
cout << "Runway Radius"; outstream << "Runway Radius";
} }
if (SubSystems & FGAircraft::ssCoefficients) { if (SubSystems & FGAircraft::ssCoefficients) {
cout << ", "; outstream << ", ";
cout << Aerodynamics->GetCoefficientStrings(); outstream << Aerodynamics->GetCoefficientStrings();
} }
if (SubSystems & FGAircraft::ssGroundReactions) { if (SubSystems & FGAircraft::ssGroundReactions) {
cout << ", "; outstream << ", ";
cout << Aircraft->GetGroundReactionStrings(); outstream << GroundReactions->GetGroundReactionStrings();
} }
if (SubSystems & FGAircraft::ssPropulsion) { if (SubSystems & FGAircraft::ssPropulsion) {
cout << ", "; outstream << ", ";
cout << Propulsion->GetPropulsionStrings(); outstream << Propulsion->GetPropulsionStrings();
} }
cout << endl; outstream << endl;
dFirstPass = false; dFirstPass = false;
} }
cout << State->Getsim_time(); outstream << State->Getsim_time();
if (SubSystems & FGAircraft::ssSimulation) { if (SubSystems & FGAircraft::ssSimulation) {
} }
if (SubSystems & FGAircraft::ssAerosurfaces) { if (SubSystems & FGAircraft::ssAerosurfaces) {
cout << ", "; outstream << ", ";
cout << FCS->GetThrottlePos(0) << ", "; outstream << FCS->GetThrottlePos(0) << ", ";
cout << FCS->GetDaCmd() << ", "; outstream << FCS->GetDaCmd() << ", ";
cout << FCS->GetDeCmd() << ", "; outstream << FCS->GetDeCmd() << ", ";
cout << FCS->GetDrCmd() << ", "; outstream << FCS->GetDrCmd() << ", ";
cout << FCS->GetDaPos() << ", "; outstream << FCS->GetDaPos() << ", ";
cout << FCS->GetDePos() << ", "; outstream << FCS->GetDePos() << ", ";
cout << FCS->GetDrPos(); outstream << FCS->GetDrPos();
} }
if (SubSystems & FGAircraft::ssRates) { if (SubSystems & FGAircraft::ssRates) {
cout << ", "; outstream << ", ";
cout << Rotation->GetPQR(); outstream << Rotation->GetPQR();
} }
if (SubSystems & FGAircraft::ssVelocities) { if (SubSystems & FGAircraft::ssVelocities) {
cout << ", "; outstream << ", ";
cout << Translation->Getqbar() << ", "; outstream << Translation->Getqbar() << ", ";
cout << Translation->GetVt() << ", "; outstream << Translation->GetVt() << ", ";
cout << Translation->GetUVW() << ", "; outstream << Translation->GetUVW() << ", ";
cout << Translation->GetvAero() << ", "; outstream << Translation->GetvAero() << ", ";
cout << Position->GetVel(); outstream << Position->GetVel();
} }
if (SubSystems & FGAircraft::ssForces) { if (SubSystems & FGAircraft::ssForces) {
cout << ", "; outstream << ", ";
cout << Aerodynamics->GetvFs() << ", "; outstream << Aerodynamics->GetvFs() << ", ";
cout << Aerodynamics->GetLoD() << ", "; outstream << Aerodynamics->GetLoD() << ", ";
cout << Aircraft->GetForces(); outstream << Aircraft->GetForces();
} }
if (SubSystems & FGAircraft::ssMoments) { if (SubSystems & FGAircraft::ssMoments) {
cout << ", "; outstream << ", ";
cout << Aircraft->GetMoments(); outstream << Aircraft->GetMoments();
} }
if (SubSystems & FGAircraft::ssAtmosphere) { if (SubSystems & FGAircraft::ssAtmosphere) {
cout << ", "; outstream << ", ";
cout << Atmosphere->GetDensity(); outstream << Atmosphere->GetDensity();
} }
if (SubSystems & FGAircraft::ssMassProps) { if (SubSystems & FGAircraft::ssMassProps) {
cout << ", "; outstream << ", ";
cout << MassBalance->GetIxx() << ", "; outstream << MassBalance->GetIxx() << ", ";
cout << MassBalance->GetIyy() << ", "; outstream << MassBalance->GetIyy() << ", ";
cout << MassBalance->GetIzz() << ", "; outstream << MassBalance->GetIzz() << ", ";
cout << MassBalance->GetIxz() << ", "; outstream << MassBalance->GetIxz() << ", ";
cout << MassBalance->GetMass() << ", "; outstream << MassBalance->GetMass() << ", ";
cout << MassBalance->GetXYZcg(); outstream << MassBalance->GetXYZcg();
} }
if (SubSystems & FGAircraft::ssPosition) { if (SubSystems & FGAircraft::ssPosition) {
cout << ", "; outstream << ", ";
cout << Position->Geth() << ", "; outstream << Position->Geth() << ", ";
cout << Rotation->GetEuler() << ", "; outstream << Rotation->GetEuler() << ", ";
cout << Translation->Getalpha() << ", "; outstream << Translation->Getalpha() << ", ";
cout << Position->GetLatitude() << ", "; outstream << Position->GetLatitude() << ", ";
cout << Position->GetLongitude() << ", "; outstream << Position->GetLongitude() << ", ";
cout << Position->GetDistanceAGL() << ", "; outstream << Position->GetDistanceAGL() << ", ";
cout << Position->GetRunwayRadius(); outstream << Position->GetRunwayRadius();
} }
if (SubSystems & FGAircraft::ssCoefficients) { if (SubSystems & FGAircraft::ssCoefficients) {
cout << ", "; outstream << ", ";
cout << Aerodynamics->GetCoefficientValues(); outstream << Aerodynamics->GetCoefficientValues();
} }
if (SubSystems & FGAircraft::ssGroundReactions) { if (SubSystems & FGAircraft::ssGroundReactions) {
cout << ", "; outstream << ", ";
cout << Aircraft->GetGroundReactionValues(); outstream << GroundReactions->GetGroundReactionValues();
} }
if (SubSystems & FGAircraft::ssPropulsion) { if (SubSystems & FGAircraft::ssPropulsion) {
cout << ", "; outstream << ", ";
cout << Propulsion->GetPropulsionValues(); outstream << Propulsion->GetPropulsionValues();
} }
cout << endl; outstream << endl;
} outstream.flush();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGOutput::DelimitedOutput(string fname)
{
if (sFirstPass) {
datafile.open(fname.c_str());
datafile << "Time";
if (SubSystems & FGAircraft::ssSimulation) {
// Nothing here, yet
}
if (SubSystems & FGAircraft::ssAerosurfaces) {
datafile << ", ";
datafile << "Throttle, ";
datafile << "Aileron Cmd, ";
datafile << "Elevator Cmd, ";
datafile << "Rudder Cmd, ";
datafile << "Aileron Pos, ";
datafile << "Elevator Pos, ";
datafile << "Rudder Pos";
}
if (SubSystems & FGAircraft::ssRates) {
datafile << ", ";
datafile << "P, Q, R";
}
if (SubSystems & FGAircraft::ssVelocities) {
datafile << ", ";
datafile << "QBar, ";
datafile << "Vtotal, ";
datafile << "UBody, VBody, WBody, ";
datafile << "UAero, VAero, WAero, ";
datafile << "Vn, Ve, Vd";
}
if (SubSystems & FGAircraft::ssForces) {
datafile << ", ";
datafile << "Drag, Side, Lift, ";
datafile << "L/D, ";
datafile << "Xforce, Yforce, Zforce";
}
if (SubSystems & FGAircraft::ssMoments) {
datafile << ", ";
datafile << "L, M, N";
}
if (SubSystems & FGAircraft::ssAtmosphere) {
datafile << ", ";
datafile << "Rho";
}
if (SubSystems & FGAircraft::ssMassProps) {
datafile << ", ";
datafile << "Ixx, ";
datafile << "Iyy, ";
datafile << "Izz, ";
datafile << "Ixz, ";
datafile << "Mass, ";
datafile << "Xcg, Ycg, Zcg";
}
if (SubSystems & FGAircraft::ssPosition) {
datafile << ", ";
datafile << "Altitude, ";
datafile << "Phi, Tht, Psi, ";
datafile << "Alpha, ";
datafile << "Latitude, ";
datafile << "Longitude, ";
datafile << "Distance AGL, ";
datafile << "Runway Radius";
}
if (SubSystems & FGAircraft::ssCoefficients) {
datafile << ", ";
datafile << Aerodynamics->GetCoefficientStrings();
}
if (SubSystems & FGAircraft::ssGroundReactions) {
datafile << ", ";
datafile << Aircraft->GetGroundReactionStrings();
}
if (SubSystems & FGAircraft::ssFCS) {
datafile << ", ";
datafile << FCS->GetComponentStrings();
}
if (SubSystems & FGAircraft::ssPropulsion) {
datafile << ", ";
datafile << Propulsion->GetPropulsionStrings();
}
datafile << endl;
sFirstPass = false;
}
datafile << State->Getsim_time();
if (SubSystems & FGAircraft::ssSimulation) {
}
if (SubSystems & FGAircraft::ssAerosurfaces) {
datafile << ", ";
datafile << FCS->GetThrottlePos(0) << ", ";
datafile << FCS->GetDaCmd() << ", ";
datafile << FCS->GetDeCmd() << ", ";
datafile << FCS->GetDrCmd() << ", ";
datafile << FCS->GetDaPos() << ", ";
datafile << FCS->GetDePos() << ", ";
datafile << FCS->GetDrPos();
}
if (SubSystems & FGAircraft::ssRates) {
datafile << ", ";
datafile << Rotation->GetPQR();
}
if (SubSystems & FGAircraft::ssVelocities) {
datafile << ", ";
datafile << Translation->Getqbar() << ", ";
datafile << Translation->GetVt() << ", ";
datafile << Translation->GetUVW() << ", ";
datafile << Translation->GetvAero() << ", ";
datafile << Position->GetVel();
}
if (SubSystems & FGAircraft::ssForces) {
datafile << ", ";
datafile << Aerodynamics->GetvFs() << ", ";
datafile << Aerodynamics->GetLoD() << ", ";
datafile << Aircraft->GetForces();
}
if (SubSystems & FGAircraft::ssMoments) {
datafile << ", ";
datafile << Aircraft->GetMoments();
}
if (SubSystems & FGAircraft::ssAtmosphere) {
datafile << ", ";
datafile << Atmosphere->GetDensity();
}
if (SubSystems & FGAircraft::ssMassProps) {
datafile << ", ";
datafile << MassBalance->GetIxx() << ", ";
datafile << MassBalance->GetIyy() << ", ";
datafile << MassBalance->GetIzz() << ", ";
datafile << MassBalance->GetIxz() << ", ";
datafile << MassBalance->GetMass() << ", ";
datafile << MassBalance->GetXYZcg();
}
if (SubSystems & FGAircraft::ssPosition) {
datafile << ", ";
datafile << Position->Geth() << ", ";
datafile << Rotation->GetEuler() << ", ";
datafile << Translation->Getalpha() << ", ";
datafile << Position->GetLatitude() << ", ";
datafile << Position->GetLongitude() << ", ";
datafile << Position->GetDistanceAGL() << ", ";
datafile << Position->GetRunwayRadius();
}
if (SubSystems & FGAircraft::ssCoefficients) {
datafile << ", ";
datafile << Aerodynamics->GetCoefficientValues();
}
if (SubSystems & FGAircraft::ssGroundReactions) {
datafile << ", ";
datafile << Aircraft->GetGroundReactionValues();
}
if (SubSystems & FGAircraft::ssFCS) {
datafile << ", ";
datafile << FCS->GetComponentValues();
}
if (SubSystems & FGAircraft::ssPropulsion) {
datafile << ", ";
datafile << Propulsion->GetPropulsionValues();
}
datafile << endl;
datafile.flush();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -45,8 +45,13 @@ INCLUDES
# include STL_IOSTREAM # include STL_IOSTREAM
# include STL_FSTREAM # include STL_FSTREAM
#else #else
# include <iostream> # if defined(sgi) && !defined(__GNUC__)
# include <fstream> # include <iostream.h>
# include <fstream.h>
# else
# include <iostream>
# include <fstream>
# endif
#endif #endif
#include "FGfdmSocket.h" #include "FGfdmSocket.h"
@ -65,7 +70,6 @@ public:
bool Run(void); bool Run(void);
void DelimitedOutput(void);
void DelimitedOutput(string); void DelimitedOutput(string);
void SocketOutput(void); void SocketOutput(void);
void SocketStatusOutput(string); void SocketStatusOutput(string);
@ -76,8 +80,6 @@ public:
inline void Disable(void) { enabled = false; } inline void Disable(void) { enabled = false; }
inline bool Toggle(void) {enabled = !enabled; return enabled;} inline bool Toggle(void) {enabled = !enabled; return enabled;}
protected:
private: private:
bool sFirstPass, dFirstPass, enabled; bool sFirstPass, dFirstPass, enabled;
int SubSystems; int SubSystems;

View file

@ -40,17 +40,32 @@ INCLUDES
#include "FGDefs.h" #include "FGDefs.h"
#include "FGPiston.h" #include "FGPiston.h"
#include "FGPropulsion.h"
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_PISTON; static const char *IdHdr = ID_PISTON;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec) FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg)
: FGEngine(exec),
MinManifoldPressure_inHg(6.5),
MaxManifoldPressure_inHg(28.5),
Displacement(360),
MaxHP(200),
Cycles(2),
IdleRPM(900),
// Set constants
CONVERT_CUBIC_INCHES_TO_METERS_CUBED(1.638706e-5),
R_air(287.3),
rho_fuel(800), // estimate
calorific_value_fuel(47.3e6),
Cp_air(1005),
Cp_fuel(1700),
running(true), // FIXME: FGEngine already has 'Running'
cranking(false)
{ {
string token; string token;
@ -58,29 +73,39 @@ FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec)
Eng_cfg->GetNextConfigLine(); Eng_cfg->GetNextConfigLine();
while (Eng_cfg->GetValue() != "/FG_PISTON") { while (Eng_cfg->GetValue() != "/FG_PISTON") {
*Eng_cfg >> token; *Eng_cfg >> token;
if (token == "BRAKEHORSEPOWER") *Eng_cfg >> BrakeHorsePower; if (token == "MINMP") *Eng_cfg >> MinManifoldPressure_inHg;
else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle; else if (token == "MAXMP") *Eng_cfg >> MaxManifoldPressure_inHg;
else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle; else if (token == "DISPLACEMENT") *Eng_cfg >> Displacement;
else if (token == "SLFUELFLOWMAX") *Eng_cfg >> SLFuelFlowMax; else if (token == "MAXHP") *Eng_cfg >> MaxHP;
else if (token == "SPEEDSLOPE") *Eng_cfg >> SpeedSlope; else if (token == "CYCLES") *Eng_cfg >> Cycles;
else if (token == "SPEEDINTERCEPT") *Eng_cfg >> SpeedIntercept; else if (token == "IDLERPM") *Eng_cfg >> IdleRPM;
else if (token == "ALTITUDESLOPE") *Eng_cfg >> AltitudeSlope; else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle;
else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle;
else if (token == "SLFUELFLOWMAX") *Eng_cfg >> SLFuelFlowMax;
else cerr << "Unhandled token in Engine config file: " << token << endl; else cerr << "Unhandled token in Engine config file: " << token << endl;
} }
if (debug_lvl > 0) { if (debug_lvl > 0) {
cout << "\n Engine Name: " << Name << endl; cout << "\n Engine Name: " << Name << endl;
cout << " BrakeHorsePower = " << BrakeHorsePower << endl; cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl;
cout << " MaxThrottle = " << MaxThrottle << endl; cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl;
cout << " MinThrottle = " << MinThrottle << endl; cout << " Displacement: " << Displacement << endl;
cout << " SLFuelFlowMax = " << SLFuelFlowMax << endl; cout << " MaxHP: " << MaxHP << endl;
cout << " SpeedSlope = " << SpeedSlope << endl; cout << " Cycles: " << Cycles << endl;
cout << " SpeedIntercept = " << SpeedIntercept << endl; cout << " IdleRPM: " << IdleRPM << endl;
cout << " AltitudeSlope = " << AltitudeSlope << endl; cout << " MaxThrottle: " << MaxThrottle << endl;
cout << " MinThrottle: " << MinThrottle << endl;
cout << " SLFuelFlowMax: " << SLFuelFlowMax << endl;
} }
Type = etPiston; Type = etPiston;
EngineNumber = 0; EngineNumber = 0; // FIXME: this should be the actual number
OilTemp_degK = 298; // FIXME: should be initialized in FGEngine
dt = State->Getdt();
// Initialisation
volumetric_efficiency = 0.8; // Actually f(speed, load) but this will get us running
if (debug_lvl & 2) cout << "Instantiated: FGPiston" << endl; if (debug_lvl & 2) cout << "Instantiated: FGPiston" << endl;
} }
@ -98,24 +123,362 @@ float FGPiston::Calculate(float PowerRequired)
{ {
float h,EngineMaxPower; float h,EngineMaxPower;
// FIXME: calculate from actual fuel flow
ConsumeFuel(); ConsumeFuel();
Throttle = FCS->GetThrottlePos(EngineNumber); Throttle = FCS->GetThrottlePos(EngineNumber);
Mixture = FCS->GetMixturePos(EngineNumber);
h = Position->Geth(); //
// Input values.
//
// convert from lbs/ft2 to Pa
p_amb = Atmosphere->GetPressure() * 48;
p_amb_sea_level = Atmosphere->GetPressureSL() * 48;
// convert from Rankine to Kelvin
T_amb = Atmosphere->GetTemperature() * (5.0 / 9.0);
RPM = Propulsion->GetThruster(EngineNumber)->GetRPM();
if (RPM < IdleRPM) // kludge
RPM = IdleRPM;
IAS = Auxiliary->GetVcalibratedKTS();
if (h < 0) h = 0; if (Mixture >= 0.5) {
doEngineStartup();
doManifoldPressure();
doAirFlow();
doFuelFlow();
doEnginePower();
doEGT();
doCHT();
doOilTemperature();
doOilPressure();
} else {
HP = 0;
}
EngineMaxPower = (1 + AltitudeSlope*h)*BrakeHorsePower; PowerAvailable = (HP * HPTOFTLBSSEC) - PowerRequired;
PowerAvailable = Throttle*EngineMaxPower*HPTOFTLBSSEC - PowerRequired;
return PowerAvailable; return PowerAvailable;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Look up the power/mixture correlation.
*
* FIXME: this should use JSBSim's interpolation support.
*/
static float Power_Mixture_Correlation(float thi_actual)
{
float AFR_actual = 14.7 / thi_actual;
const int NUM_ELEMENTS = 13;
float AFR[NUM_ELEMENTS] =
{(14.7/1.6), 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, (14.7/0.6)};
float mixPerPow[NUM_ELEMENTS] =
{78, 86, 93.5, 98, 100, 99, 96.4, 92.5, 88, 83, 78.5, 74, 58};
float mixPerPow_actual = 0.0f;
float factor;
float dydx;
int i;
int j = NUM_ELEMENTS;
for (i=0;i<j;i++) {
if (i == (j-1)) {
dydx = (mixPerPow[i] - mixPerPow[i-1]) / (AFR[i] - AFR[i-1]);
mixPerPow_actual = mixPerPow[i] + dydx * (AFR_actual - AFR[i]);
return mixPerPow_actual;
}
if ((i == 0) && (AFR_actual < AFR[i])) {
dydx = (mixPerPow[i] - mixPerPow[i-1]) / (AFR[i] - AFR[i-1]);
mixPerPow_actual = mixPerPow[i] + dydx * (AFR_actual - AFR[i]);
return mixPerPow_actual;
}
if (AFR_actual == AFR[i]) {
mixPerPow_actual = mixPerPow[i];
return mixPerPow_actual;
}
if ((AFR_actual > AFR[i]) && (AFR_actual < AFR[i + 1])) {
factor = (AFR_actual - AFR[i]) / (AFR[i+1] - AFR[i]);
mixPerPow_actual = (factor * (mixPerPow[i+1] - mixPerPow[i])) + mixPerPow[i];
return mixPerPow_actual;
}
}
cerr << "ERROR: error in FGNewEngine::Power_Mixture_Correlation\n";
return mixPerPow_actual;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Look up the combustion efficiency.
*
*
* FIXME: this should use JSBSim's interpolation support.
*/
static float Lookup_Combustion_Efficiency(float thi_actual)
{
const int NUM_ELEMENTS = 11;
float thi[NUM_ELEMENTS] = {0.0, 0.9, 1.0, 1.05, 1.1, 1.15, 1.2, 1.3, 1.4, 1.5, 1.6}; //array of equivalence ratio values
float neta_comb[NUM_ELEMENTS] = {0.98, 0.98, 0.97, 0.95, 0.9, 0.85, 0.79, 0.7, 0.63, 0.57, 0.525}; //corresponding array of combustion efficiency values
//combustion efficiency values from Heywood, "Internal Combustion Engine Fundamentals", ISBN 0-07-100499-8
float neta_comb_actual = 0.0f;
float factor;
int i;
int j = NUM_ELEMENTS; //This must be equal to the number of elements in the lookup table arrays
for (i=0;i<j;i++) {
if(i == (j-1)) {
// Assume linear extrapolation of the slope between the last two points beyond the last point
float dydx = (neta_comb[i] - neta_comb[i-1]) / (thi[i] - thi[i-1]);
neta_comb_actual = neta_comb[i] + dydx * (thi_actual - thi[i]);
return neta_comb_actual;
}
if(thi_actual == thi[i]) {
neta_comb_actual = neta_comb[i];
return neta_comb_actual;
}
if((thi_actual > thi[i]) && (thi_actual < thi[i + 1])) {
//do linear interpolation between the two points
factor = (thi_actual - thi[i]) / (thi[i+1] - thi[i]);
neta_comb_actual = (factor * (neta_comb[i+1] - neta_comb[i])) + neta_comb[i];
return neta_comb_actual;
}
}
//if we get here something has gone badly wrong
cerr << "ERROR: error in FGNewEngine::Lookup_Combustion_Efficiency\n";
return neta_comb_actual;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Start or stop the engine.
*/
void FGPiston::doEngineStartup(void)
{
// TODO: check magnetos, spark, starter, etc. and decide whether
// engine is running
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the nominal manifold pressure in inches hg
*
* This function calculates nominal manifold pressure directly
* from the throttle position, and does not adjust it for the
* difference between the pressure at sea level and the pressure
* at the current altitude (that adjustment takes place in
* {@link #doEnginePower}).
*
* TODO: changes in MP should not be instantaneous -- introduce
* a lag between throttle changes and MP changes, to allow pressure
* to build up or disperse.
*
* Inputs: MinManifoldPressure_inHg, MaxManifoldPressure_inHg, Throttle
*
* Outputs: ManifoldPressure_inHg
*/
void FGPiston::doManifoldPressure(void)
{
ManifoldPressure_inHg = MinManifoldPressure_inHg +
(Throttle * (MaxManifoldPressure_inHg - MinManifoldPressure_inHg));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the air flow through the engine.
*
* Inputs: p_amb, R_air, T_amb, ManifoldPressure_inHg, Displacement,
* RPM, volumetric_efficiency
*
* Outputs: rho_air, m_dot_air
*/
void FGPiston::doAirFlow(void)
{
rho_air = p_amb / (R_air * T_amb);
float rho_air_manifold = rho_air * ManifoldPressure_inHg / 29.6;
float displacement_SI = Displacement * CONVERT_CUBIC_INCHES_TO_METERS_CUBED;
float swept_volume = (displacement_SI * (RPM/60)) / 2;
float v_dot_air = swept_volume * volumetric_efficiency;
m_dot_air = v_dot_air * rho_air_manifold;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the fuel flow into the engine.
*
* Inputs: Mixture, thi_sea_level, p_amb_sea_level, p_amb, m_dot_air
*
* Outputs: equivalence_ratio, m_dot_fuel
*/
void FGPiston::doFuelFlow(void)
{
float thi_sea_level = 1.3 * Mixture;
equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb;
m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the power produced by the engine.
*
* <p>Currently, the JSBSim propellor model does not allow the
* engine to produce enough RPMs to get up to a high horsepower.
* When tested with sufficient RPM, it has no trouble reaching
* 200HP.</p>
*
* Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb,
* equivalence_ratio, Cycles, MaxHP
*
* Outputs: Percentage_Power, HP
*/
void FGPiston::doEnginePower(void)
{
float True_ManifoldPressure_inHg = ManifoldPressure_inHg * p_amb / p_amb_sea_level;
float ManXRPM = True_ManifoldPressure_inHg * RPM;
// FIXME: this needs to be generalized
Percentage_Power = (6e-9 * ManXRPM * ManXRPM) + (8e-4 * ManXRPM) - 1.0;
float T_amb_degF = (T_amb * 1.8) - 459.67;
float T_amb_sea_lev_degF = (288 * 1.8) - 459.67;
Percentage_Power =
Percentage_Power + ((T_amb_sea_lev_degF - T_amb_degF) * 7 /120);
float Percentage_of_best_power_mixture_power =
Power_Mixture_Correlation(equivalence_ratio);
Percentage_Power =
Percentage_Power * Percentage_of_best_power_mixture_power / 100.0;
if (Percentage_Power < 0.0)
Percentage_Power = 0.0;
else if (Percentage_Power > 100.0)
Percentage_Power = 100.0;
HP = Percentage_Power * MaxHP / 100.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the exhaust gas temperature.
*
* Inputs: equivalence_ratio, m_dot_fuel, calorific_value_fuel,
* Cp_air, m_dot_air, Cp_fuel, m_dot_fuel, T_amb, Percentage_Power
*
* Outputs: combustion_efficiency, ExhaustGasTemp_degK
*/
void FGPiston::doEGT(void)
{
combustion_efficiency = Lookup_Combustion_Efficiency(equivalence_ratio);
float enthalpy_exhaust = m_dot_fuel * calorific_value_fuel *
combustion_efficiency * 0.33;
float heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel);
float delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust;
ExhaustGasTemp_degK = T_amb + delta_T_exhaust;
ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * Percentage_Power / 100.0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the cylinder head temperature.
*
* Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel,
* combustion_efficiency, RPM
*
* Outputs: CylinderHeadTemp_degK
*/
void FGPiston::doCHT(void)
{
float h1 = -95.0;
float h2 = -3.95;
float h3 = -0.05;
float arbitary_area = 1.0;
float CpCylinderHead = 800.0;
float MassCylinderHead = 8.0;
float temperature_difference = CylinderHeadTemp_degK - T_amb;
float v_apparent = IAS * 0.5144444;
float v_dot_cooling_air = arbitary_area * v_apparent;
float m_dot_cooling_air = v_dot_cooling_air * rho_air;
float dqdt_from_combustion =
m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;
float dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) +
(h3 * RPM * temperature_difference);
float dqdt_free = h1 * temperature_difference;
float dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free;
float HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead;
CylinderHeadTemp_degK = dqdt_cylinder_head / HeatCapacityCylinderHead;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the oil temperature.
*
* Inputs: Percentage_Power, running flag.
*
* Outputs: OilTemp_degK
*/
void FGPiston::doOilTemperature(void)
{
float idle_percentage_power = 2.3; // approximately
float target_oil_temp; // Steady state oil temp at the current engine conditions
float time_constant; // The time constant for the differential equation
if (running) {
target_oil_temp = 363;
time_constant = 500; // Time constant for engine-on idling.
if (Percentage_Power > idle_percentage_power) {
time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power
}
} else {
target_oil_temp = 298;
time_constant = 1000; // Time constant for engine-off; reflects the fact that oil is no longer getting circulated
}
float dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant;
OilTemp_degK += (dOilTempdt * dt);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/**
* Calculate the oil pressure.
*
* Inputs: RPM
*
* Outputs: OilPressure_psi
*/
void FGPiston::doOilPressure(void)
{
float Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine
float Oil_Press_RPM_Max = 1800; // FIXME: may vary by engine
float Design_Oil_Temp = 85; // FIXME: may vary by engine
// FIXME: WRONG!!! (85 degK???)
float Oil_Viscosity_Index = 0.25;
OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM;
if (OilPressure_psi >= Oil_Press_Relief_Valve) {
OilPressure_psi = Oil_Press_Relief_Valve;
}
OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPiston::Debug(void) void FGPiston::Debug(void)
{ {
//TODO: Add your source code here //TODO: Add your source code here
} }

View file

@ -26,6 +26,7 @@
HISTORY HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
09/12/2000 JSB Created 09/12/2000 JSB Created
10/01/2001 DPM Modified to use equations from Dave Luff's piston model.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES COMMENTS, REFERENCES, and NOTES
@ -45,8 +46,31 @@ INCLUDES
#include "FGEngine.h" #include "FGEngine.h"
#include "FGConfigFile.h" #include "FGConfigFile.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PISTON "$Id$"; #define ID_PISTON "$Id$";
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models Dave Luff's engine model as ported into JSBSim by David Megginson.
@author Jon S. Berndt (Engine framework code and framework-related mods)
@author Dave Luff (engine operational code)
@author David Megginson (porting and additional code)
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -54,7 +78,9 @@ CLASS DECLARATION
class FGPiston : public FGEngine class FGPiston : public FGEngine
{ {
public: public:
/// Constructor
FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg); FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg);
/// Destructor
~FGPiston(); ~FGPiston();
float Calculate(float PowerRequired); float Calculate(float PowerRequired);
@ -66,9 +92,68 @@ private:
float SpeedIntercept; float SpeedIntercept;
float AltitudeSlope; float AltitudeSlope;
float PowerAvailable; float PowerAvailable;
// timestep
float dt;
// engine state
bool running;
bool cranking;
void doEngineStartup(void);
void doManifoldPressure(void);
void doAirFlow(void);
void doFuelFlow(void);
void doEnginePower(void);
void doEGT(void);
void doCHT(void);
void doOilPressure(void);
void doOilTemperature(void);
//
// constants
//
const float CONVERT_CUBIC_INCHES_TO_METERS_CUBED;
const float R_air;
const float rho_fuel; // kg/m^3
const float calorific_value_fuel; // W/Kg (approximate)
const float Cp_air; // J/KgK
const float Cp_fuel; // J/KgK
//
// Configuration
//
float MinManifoldPressure_inHg; // Inches Hg
float MaxManifoldPressure_inHg; // Inches Hg
float Displacement; // cubic inches
float MaxHP; // horsepower
float Cycles; // cycles/power stroke
float IdleRPM; // revolutions per minute
//
// Inputs (in addition to those in FGEngine).
//
float p_amb; // Pascals
float p_amb_sea_level; // Pascals
float T_amb; // degrees Kelvin
float RPM; // revolutions per minute
float IAS; // knots
//
// Outputs (in addition to those in FGEngine).
//
float rho_air;
float volumetric_efficiency;
float m_dot_air;
float equivalence_ratio;
float m_dot_fuel;
float Percentage_Power;
float HP;
float combustion_efficiency;
void Debug(void); void Debug(void);
}; };
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif #endif

View file

@ -63,8 +63,13 @@ INCLUDES
# include <iomanip.h> # include <iomanip.h>
# endif # endif
#else #else
# include <cmath> # if defined(sgi) && !defined(__GNUC__)
# include <iomanip> # include <math.h>
# include <iomanip.h>
# else
# include <cmath>
# include <iomanip>
# endif
#endif #endif
#include "FGPosition.h" #include "FGPosition.h"
@ -82,8 +87,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_POSITION; static const char *IdHdr = ID_POSITION;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -39,7 +39,9 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h" #include "FGModel.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -81,8 +83,8 @@ public:
@return false if no error */ @return false if no error */
bool Run(void); bool Run(void);
inline FGColumnVector GetVel(void) { return vVel; } inline FGColumnVector3& GetVel(void) { return vVel; }
inline FGColumnVector GetVelDot(void) { return vVelDot; } inline FGColumnVector3& GetVelDot(void) { return vVelDot; }
inline double GetVn(void) { return vVel(eX); } inline double GetVn(void) { return vVel(eX); }
inline double GetVe(void) { return vVel(eY); } inline double GetVe(void) { return vVel(eY); }
inline double GetVd(void) { return vVel(eZ); } inline double GetVd(void) { return vVel(eZ); }
@ -97,12 +99,12 @@ public:
inline double GetRunwayRadius(void) { return RunwayRadius; } inline double GetRunwayRadius(void) { return RunwayRadius; }
inline double GetDistanceAGL(void) { return DistanceAGL; } inline double GetDistanceAGL(void) { return DistanceAGL; }
inline double GetRadius(void) { return Radius; } inline double GetRadius(void) { return Radius; }
inline FGColumnVector GetRunwayNormal(void) { return vRunwayNormal; } inline FGColumnVector3& GetRunwayNormal(void) { return vRunwayNormal; }
inline double GetGamma(void) { return gamma; } inline double GetGamma(void) { return gamma; }
inline void SetGamma(float tt) { gamma = tt; } inline void SetGamma(float tt) { gamma = tt; }
inline double GetHOverB(void) { return hoverb; } inline double GetHOverB(void) { return hoverb; }
void SetvVel(const FGColumnVector& v) { vVel = v; } void SetvVel(const FGColumnVector3& v) { vVel = v; }
void SetLatitude(float tt) { Latitude = tt; } void SetLatitude(float tt) { Latitude = tt; }
void SetLongitude(double tt) { Longitude = tt; } void SetLongitude(double tt) { Longitude = tt; }
void Seth(double tt); void Seth(double tt);
@ -114,9 +116,9 @@ public:
} }
private: private:
FGColumnVector vVel; FGColumnVector3 vVel;
FGColumnVector vVelDot; FGColumnVector3 vVelDot;
FGColumnVector vRunwayNormal; FGColumnVector3 vRunwayNormal;
double Vee, invMass, invRadius; double Vee, invMass, invRadius;
double Radius, h; double Radius, h;

View file

@ -40,8 +40,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_PROPELLER; static const char *IdHdr = ID_PROPELLER;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -48,11 +48,6 @@ DEFINITIONS
#define ID_PROPELLER "$Id$" #define ID_PROPELLER "$Id$"
#ifndef M_PI
# include <simgear/constants.h>
# define M_PI SG_PI
#endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -57,8 +57,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_PROPULSION; static const char *IdHdr = ID_PROPULSION;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -70,8 +68,8 @@ FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
numSelectedFuelTanks = numSelectedOxiTanks = 0; numSelectedFuelTanks = numSelectedOxiTanks = 0;
numTanks = numEngines = numThrusters = 0; numTanks = numEngines = numThrusters = 0;
numOxiTanks = numFuelTanks = 0; numOxiTanks = numFuelTanks = 0;
Forces = new FGColumnVector(3); Forces = new FGColumnVector3(3);
Moments = new FGColumnVector(3); Moments = new FGColumnVector3(3);
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
} }
@ -394,7 +392,7 @@ string FGPropulsion::GetPropulsionValues(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector& FGPropulsion::GetTanksCG(void) FGColumnVector3& FGPropulsion::GetTanksCG(void)
{ {
iTank = Tanks.begin(); iTank = Tanks.begin();
vXYZtank.InitMatrix(); vXYZtank.InitMatrix();
@ -423,7 +421,7 @@ float FGPropulsion::GetTanksWeight(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGPropulsion::GetTanksIxx(const FGColumnVector& vXYZcg) float FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
{ {
float I = 0.0; float I = 0.0;
iTank = Tanks.begin(); iTank = Tanks.begin();
@ -436,7 +434,7 @@ float FGPropulsion::GetTanksIxx(const FGColumnVector& vXYZcg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGPropulsion::GetTanksIyy(const FGColumnVector& vXYZcg) float FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
{ {
float I = 0.0; float I = 0.0;
iTank = Tanks.begin(); iTank = Tanks.begin();
@ -449,7 +447,7 @@ float FGPropulsion::GetTanksIyy(const FGColumnVector& vXYZcg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGPropulsion::GetTanksIzz(const FGColumnVector& vXYZcg) float FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
{ {
float I = 0.0; float I = 0.0;
iTank = Tanks.begin(); iTank = Tanks.begin();
@ -462,7 +460,7 @@ float FGPropulsion::GetTanksIzz(const FGColumnVector& vXYZcg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGPropulsion::GetTanksIxz(const FGColumnVector& vXYZcg) float FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
{ {
float I = 0.0; float I = 0.0;
iTank = Tanks.begin(); iTank = Tanks.begin();
@ -475,7 +473,7 @@ float FGPropulsion::GetTanksIxz(const FGColumnVector& vXYZcg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGPropulsion::GetTanksIxy(const FGColumnVector& vXYZcg) float FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
{ {
float I = 0.0; float I = 0.0;
iTank = Tanks.begin(); iTank = Tanks.begin();

View file

@ -163,17 +163,19 @@ public:
string GetPropulsionStrings(void); string GetPropulsionStrings(void);
string GetPropulsionValues(void); string GetPropulsionValues(void);
inline FGColumnVector& GetForces(void) {return *Forces; } inline FGColumnVector3& GetForces(void) {return *Forces; }
inline FGColumnVector& GetMoments(void) {return *Moments;} inline float GetForces(int n) { return (*Forces)(n);}
inline FGColumnVector3& GetMoments(void) {return *Moments;}
inline float GetMoments(int n) {return (*Moments)(n);}
FGColumnVector& GetTanksCG(void); FGColumnVector3& GetTanksCG(void);
float GetTanksWeight(void); float GetTanksWeight(void);
float GetTanksIxx(const FGColumnVector& vXYZcg); float GetTanksIxx(const FGColumnVector3& vXYZcg);
float GetTanksIyy(const FGColumnVector& vXYZcg); float GetTanksIyy(const FGColumnVector3& vXYZcg);
float GetTanksIzz(const FGColumnVector& vXYZcg); float GetTanksIzz(const FGColumnVector3& vXYZcg);
float GetTanksIxz(const FGColumnVector& vXYZcg); float GetTanksIxz(const FGColumnVector3& vXYZcg);
float GetTanksIxy(const FGColumnVector& vXYZcg); float GetTanksIxy(const FGColumnVector3& vXYZcg);
private: private:
vector <FGEngine*> Engines; vector <FGEngine*> Engines;
@ -188,9 +190,9 @@ private:
unsigned int numTanks; unsigned int numTanks;
unsigned int numThrusters; unsigned int numThrusters;
float dt; float dt;
FGColumnVector *Forces; FGColumnVector3 *Forces;
FGColumnVector *Moments; FGColumnVector3 *Moments;
FGColumnVector vXYZtank; FGColumnVector3 vXYZtank;
void Debug(void); void Debug(void);
}; };

View file

@ -44,8 +44,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ROCKET; static const char *IdHdr = ID_ROCKET;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -70,8 +70,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ROTATION; static const char *IdHdr = ID_ROTATION;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -60,16 +60,17 @@ INCLUDES
# include <simgear/compiler.h> # include <simgear/compiler.h>
# include <math.h> # include <math.h>
#else #else
# include <cmath> # if defined (sgi) && !defined(__GNUC__)
#endif # include <math.h>
# else
#ifndef M_PI # include <cmath>
# include <simgear/constants.h> # endif
# define M_PI SG_PI
#endif #endif
#include "FGModel.h" #include "FGModel.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
#define ID_ROTATION "$Id$" #define ID_ROTATION "$Id$"
@ -85,16 +86,16 @@ public:
bool Run(void); bool Run(void);
inline FGColumnVector GetPQR(void) {return vPQR;} inline FGColumnVector3& GetPQR(void) {return vPQR;}
inline float GetPQR(int axis) {return vPQR(axis);} inline float GetPQR(int axis) {return vPQR(axis);}
inline FGColumnVector GetPQRdot(void) {return vPQRdot;} inline FGColumnVector3& GetPQRdot(void) {return vPQRdot;}
inline float GetPQRdot(int idx) {return vPQRdot(idx);} inline float GetPQRdot(int idx) {return vPQRdot(idx);}
inline FGColumnVector GetEuler(void) {return vEuler;} inline FGColumnVector3& GetEuler(void) {return vEuler;}
inline float GetEuler(int axis) {return vEuler(axis);} inline float GetEuler(int axis) {return vEuler(axis);}
inline FGColumnVector GetEulerRates(void) { return vEulerRates; } inline FGColumnVector3& GetEulerRates(void) { return vEulerRates; }
inline float GetEulerRates(int axis) { return vEulerRates(axis); } inline float GetEulerRates(int axis) { return vEulerRates(axis); }
inline void SetPQR(FGColumnVector tt) {vPQR = tt;} inline void SetPQR(FGColumnVector3 tt) {vPQR = tt;}
inline void SetEuler(FGColumnVector tt) {vEuler = tt;} inline void SetEuler(FGColumnVector3 tt) {vEuler = tt;}
inline float Getphi(void) {return vEuler(1);} inline float Getphi(void) {return vEuler(1);}
inline float Gettht(void) {return vEuler(2);} inline float Gettht(void) {return vEuler(2);}
@ -109,12 +110,12 @@ public:
inline float GetSinpsi(void) {return sPsi;} inline float GetSinpsi(void) {return sPsi;}
private: private:
FGColumnVector vPQR; FGColumnVector3 vPQR;
FGColumnVector vPQRdot; FGColumnVector3 vPQRdot;
FGColumnVector vMoments; FGColumnVector3 vMoments;
FGColumnVector vEuler; FGColumnVector3 vEuler;
FGColumnVector vEulerRates; FGColumnVector3 vEulerRates;
FGColumnVector vlastPQRdot; FGColumnVector3 vlastPQRdot;
float cTht,sTht; float cTht,sTht;
float cPhi,sPhi; float cPhi,sPhi;

View file

@ -40,8 +40,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ROTOR; static const char *IdHdr = ID_ROTOR;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -40,12 +40,11 @@ INCLUDES
# include <simgear/compiler.h> # include <simgear/compiler.h>
# include <math.h> # include <math.h>
#else #else
# include <cmath> # if defined(sgi) && !defined(__GNUC__)
#endif # include <math.h>
# else
#ifndef M_PI # include <cmath>
# include <simgear/constants.h> # endif
# define M_PI SG_PI
#endif #endif
#include "FGState.h" #include "FGState.h"
@ -53,8 +52,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_STATE; static const char *IdHdr = ID_STATE;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
MACROS MACROS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -79,7 +76,10 @@ FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3),
vlastQdot(4), vlastQdot(4),
vQdot(4), vQdot(4),
vTmp(4), vTmp(4),
vEuler(3) vEuler(3),
vUVW(3),
vLocalVelNED(3),
vLocalEuler(3)
{ {
FDMExec = fdex; FDMExec = fdex;
@ -137,6 +137,14 @@ FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3),
RegisterVariable(FG_LEFT_BRAKE_CMD, " left_brake_cmd " ); RegisterVariable(FG_LEFT_BRAKE_CMD, " left_brake_cmd " );
RegisterVariable(FG_RIGHT_BRAKE_CMD," right_brake_cmd "); RegisterVariable(FG_RIGHT_BRAKE_CMD," right_brake_cmd ");
RegisterVariable(FG_CENTER_BRAKE_CMD," center_brake_cmd "); RegisterVariable(FG_CENTER_BRAKE_CMD," center_brake_cmd ");
RegisterVariable(FG_ALPHAH, " h-tail alpha " );
RegisterVariable(FG_ALPHAW, " wing alpha " );
RegisterVariable(FG_LBARH, " h-tail arm " );
RegisterVariable(FG_LBARV, " v-tail arm " );
RegisterVariable(FG_HTAILAREA, " h-tail area " );
RegisterVariable(FG_VTAILAREA, " v-tail area " );
RegisterVariable(FG_VBARH, " h-tail volume " );
RegisterVariable(FG_VBARV, " v-tail volume " );
RegisterVariable(FG_SET_LOGGING, " data_logging " ); RegisterVariable(FG_SET_LOGGING, " data_logging " );
if (debug_lvl & 2) cout << "Instantiated: FGState" << endl; if (debug_lvl & 2) cout << "Instantiated: FGState" << endl;
@ -165,8 +173,22 @@ float FGState::GetParameter(eParam val_idx) {
return Aircraft->GetWingSpan(); return Aircraft->GetWingSpan();
case FG_CBAR: case FG_CBAR:
return Aircraft->Getcbar(); return Aircraft->Getcbar();
case FG_LBARH:
return Aircraft->Getlbarh();
case FG_LBARV:
return Aircraft->Getvbarh();
case FG_HTAILAREA:
return Aircraft->GetHTailArea();
case FG_VTAILAREA:
return Aircraft->GetVTailArea();
case FG_VBARH:
return Aircraft->Getvbarh();
case FG_VBARV:
return Aircraft->Getvbarv();
case FG_ALPHA: case FG_ALPHA:
return Translation->Getalpha(); return Translation->Getalpha();
case FG_ALPHAW:
return Translation->Getalpha() + Aircraft->GetWingIncidence();
case FG_ALPHADOT: case FG_ALPHADOT:
return Translation->Getadot(); return Translation->Getadot();
case FG_BETA: case FG_BETA:
@ -336,44 +358,63 @@ void FGState::SetParameter(eParam val_idx, float val) {
// Reset: Assume all angles READ FROM FILE IN DEGREES !! // Reset: Assume all angles READ FROM FILE IN DEGREES !!
// //
bool FGState::Reset(string path, string acname, string fname) { bool FGState::Reset(string path, string acname, string fname)
{
string resetDef; string resetDef;
string token="";
float U, V, W; float U, V, W;
float phi, tht, psi; float phi, tht, psi;
float latitude, longitude, h; float latitude, longitude, h;
float wdir, wmag, wnorth, weast;
# ifndef macintosh
resetDef = path + "/" + acname + "/" + fname + ".xml"; resetDef = path + "/" + acname + "/" + fname + ".xml";
# else
resetDef = path + ";" + acname + ";" + fname + ".xml";
# endif
#if defined ( sgi ) && !defined( __GNUC__ ) FGConfigFile resetfile(resetDef);
ifstream resetfile(resetDef.c_str(), ios::in ); if (!resetfile.IsOpen()) return false;
#else
ifstream resetfile(resetDef.c_str(), ios::in | ios::binary );
#endif
if (resetfile) { resetfile.GetNextConfigLine();
resetfile >> U; token = resetfile.GetValue();
resetfile >> V; if (token != "initialize") {
resetfile >> W; cerr << "The reset file " << resetDef
resetfile >> latitude; << " does not appear to be a reset file" << endl;
resetfile >> longitude;
resetfile >> phi;
resetfile >> tht;
resetfile >> psi;
resetfile >> h;
resetfile.close();
Position->SetLatitude(latitude*DEGTORAD);
Position->SetLongitude(longitude*DEGTORAD);
Position->Seth(h);
Initialize(U, V, W, phi*DEGTORAD, tht*DEGTORAD, psi*DEGTORAD,
latitude*DEGTORAD, longitude*DEGTORAD, h);
return true;
} else {
cerr << "Unable to load reset file " << fname << endl;
return false; return false;
} }
resetfile.GetNextConfigLine();
resetfile >> token;
while (token != "/initialize" && token != "EOF") {
if (token == "UBODY") resetfile >> U;
if (token == "VBODY") resetfile >> V;
if (token == "WBODY") resetfile >> W;
if (token == "LATITUDE") resetfile >> latitude;
if (token == "LONGITUDE") resetfile >> longitude;
if (token == "PHI") resetfile >> phi;
if (token == "THETA") resetfile >> tht;
if (token == "PSI") resetfile >> psi;
if (token == "ALTITUDE") resetfile >> h;
if (token == "WINDDIR") resetfile >> wdir;
if (token == "VWIND") resetfile >> wmag;
resetfile >> token;
}
Position->SetLatitude(latitude*DEGTORAD);
Position->SetLongitude(longitude*DEGTORAD);
Position->Seth(h);
wnorth = wmag*KTSTOFPS*cos(wdir*DEGTORAD);
weast = wmag*KTSTOFPS*sin(wdir*DEGTORAD);
Initialize(U, V, W, phi*DEGTORAD, tht*DEGTORAD, psi*DEGTORAD,
latitude*DEGTORAD, longitude*DEGTORAD, h, wnorth, weast, 0.0);
return true;
} }
//*************************************************************************** //***************************************************************************
@ -383,34 +424,40 @@ bool FGState::Reset(string path, string acname, string fname) {
void FGState::Initialize(float U, float V, float W, void FGState::Initialize(float U, float V, float W,
float phi, float tht, float psi, float phi, float tht, float psi,
float Latitude, float Longitude, float H) { float Latitude, float Longitude, float H,
FGColumnVector vUVW(3); float wnorth, float weast, float wdown)
FGColumnVector vLocalVelNED(3); {
FGColumnVector vLocalEuler(3);
float alpha, beta; float alpha, beta;
float qbar, Vt; float qbar, Vt;
FGColumnVector3 vAero;
Position->SetLatitude(Latitude); Position->SetLatitude(Latitude);
Position->SetLongitude(Longitude); Position->SetLongitude(Longitude);
Position->Seth(H); Position->Seth(H);
Atmosphere->Run(); Atmosphere->Run();
if (W != 0.0)
alpha = U*U > 0.0 ? atan2(W, U) : 0.0;
else
alpha = 0.0;
if (V != 0.0)
beta = U*U+W*W > 0.0 ? atan2(V, (fabs(U)/U)*sqrt(U*U + W*W)) : 0.0;
else
beta = 0.0;
vUVW << U << V << W;
Translation->SetUVW(vUVW);
vLocalEuler << phi << tht << psi; vLocalEuler << phi << tht << psi;
Rotation->SetEuler(vLocalEuler); Rotation->SetEuler(vLocalEuler);
InitMatrices(phi, tht, psi);
vUVW << U << V << W;
Translation->SetUVW(vUVW);
Atmosphere->SetWindNED(wnorth, weast, wdown);
vAero = vUVW + mTl2b*Atmosphere->GetWindNED();
if (vAero(eW) != 0.0)
alpha = vAero(eU)*vAero(eU) > 0.0 ? atan2(vAero(eW), vAero(eU)) : 0.0;
else
alpha = 0.0;
if (vAero(eV) != 0.0)
beta = vAero(eU)*vAero(eU)+vAero(eW)*vAero(eW) > 0.0 ? atan2(vAero(eV), (fabs(vAero(eU))/vAero(eU))*sqrt(vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW))) : 0.0;
else
beta = 0.0;
Translation->SetAB(alpha, beta); Translation->SetAB(alpha, beta);
Vt = sqrt(U*U + V*V + W*W); Vt = sqrt(U*U + V*V + W*W);
@ -421,8 +468,6 @@ void FGState::Initialize(float U, float V, float W,
qbar = 0.5*(U*U + V*V + W*W)*Atmosphere->GetDensity(); qbar = 0.5*(U*U + V*V + W*W)*Atmosphere->GetDensity();
Translation->Setqbar(qbar); Translation->Setqbar(qbar);
InitMatrices(phi, tht, psi);
vLocalVelNED = mTb2l*vUVW; vLocalVelNED = mTb2l*vUVW;
Position->SetvVel(vLocalVelNED); Position->SetvVel(vLocalVelNED);
} }
@ -434,7 +479,8 @@ void FGState::Initialize(FGInitialCondition *FGIC) {
float tht,psi,phi; float tht,psi,phi;
float U, V, W, h; float U, V, W, h;
float latitude, longitude; float latitude, longitude;
float wnorth,weast, wdown;
latitude = FGIC->GetLatitudeRadIC(); latitude = FGIC->GetLatitudeRadIC();
longitude = FGIC->GetLongitudeRadIC(); longitude = FGIC->GetLongitudeRadIC();
h = FGIC->GetAltitudeFtIC(); h = FGIC->GetAltitudeFtIC();
@ -444,13 +490,16 @@ void FGState::Initialize(FGInitialCondition *FGIC) {
tht = FGIC->GetThetaRadIC(); tht = FGIC->GetThetaRadIC();
phi = FGIC->GetPhiRadIC(); phi = FGIC->GetPhiRadIC();
psi = FGIC->GetPsiRadIC(); psi = FGIC->GetPsiRadIC();
wnorth = FGIC->GetWindNFpsIC();
Initialize(U, V, W, phi, tht, psi, latitude, longitude, h); weast = FGIC->GetWindEFpsIC();
wdown = FGIC->GetWindDFpsIC();
Position->SetSeaLevelRadius( FGIC->GetSeaLevelRadiusFtIC() ); Position->SetSeaLevelRadius( FGIC->GetSeaLevelRadiusFtIC() );
Position->SetRunwayRadius( FGIC->GetSeaLevelRadiusFtIC() + Position->SetRunwayRadius( FGIC->GetSeaLevelRadiusFtIC() +
FGIC->GetTerrainAltitudeFtIC() ); FGIC->GetTerrainAltitudeFtIC() );
// need to fix the wind speed args, here.
Initialize(U, V, W, phi, tht, psi, latitude, longitude, h, wnorth, weast, wdown);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -546,7 +595,7 @@ void FGState::CalcMatrices(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGState::IntegrateQuat(FGColumnVector vPQR, int rate) { void FGState::IntegrateQuat(FGColumnVector3 vPQR, int rate) {
vQdot(1) = -0.5*(vQtrn(2)*vPQR(eP) + vQtrn(3)*vPQR(eQ) + vQtrn(4)*vPQR(eR)); vQdot(1) = -0.5*(vQtrn(2)*vPQR(eP) + vQtrn(3)*vPQR(eQ) + vQtrn(4)*vPQR(eR));
vQdot(2) = 0.5*(vQtrn(1)*vPQR(eP) + vQtrn(3)*vPQR(eR) - vQtrn(4)*vPQR(eQ)); vQdot(2) = 0.5*(vQtrn(1)*vPQR(eP) + vQtrn(3)*vPQR(eR) - vQtrn(4)*vPQR(eQ));
vQdot(3) = 0.5*(vQtrn(1)*vPQR(eQ) + vQtrn(4)*vPQR(eP) - vQtrn(2)*vPQR(eR)); vQdot(3) = 0.5*(vQtrn(1)*vPQR(eQ) + vQtrn(4)*vPQR(eP) - vQtrn(2)*vPQR(eR));
@ -560,7 +609,7 @@ void FGState::IntegrateQuat(FGColumnVector vPQR, int rate) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector FGState::CalcEuler(void) { FGColumnVector3& FGState::CalcEuler(void) {
if (mTl2b(3,3) == 0.0) mTl2b(3,3) = 0.0000001; if (mTl2b(3,3) == 0.0) mTl2b(3,3) = 0.0000001;
if (mTl2b(1,1) == 0.0) mTl2b(1,1) = 0.0000001; if (mTl2b(1,1) == 0.0) mTl2b(1,1) = 0.0000001;
@ -575,7 +624,8 @@ FGColumnVector FGState::CalcEuler(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGMatrix FGState::GetTs2b(float alpha, float beta) { FGMatrix33& FGState::GetTs2b(float alpha, float beta)
{
float ca, cb, sa, sb; float ca, cb, sa, sb;
ca = cos(alpha); ca = cos(alpha);
@ -596,6 +646,76 @@ FGMatrix FGState::GetTs2b(float alpha, float beta) {
return mTs2b; return mTs2b;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGState::ReportState(void) {
char out[80], flap[10], gear[10];
cout << endl << " JSBSim State" << endl;
snprintf(out,80," Weight: %7.0f lbs. CG: %5.1f, %5.1f, %5.1f inches\n",
FDMExec->GetMassBalance()->GetWeight(),
FDMExec->GetMassBalance()->GetXYZcg(1),
FDMExec->GetMassBalance()->GetXYZcg(2),
FDMExec->GetMassBalance()->GetXYZcg(3));
cout << out;
if( FCS->GetDfPos() <= 0.01)
snprintf(flap,10,"Up");
else
snprintf(flap,10,"%2.0f",FCS->GetDfPos());
if(Aircraft->GetGearUp() == true)
snprintf(gear,10,"Up");
else
snprintf(gear,10,"Down");
snprintf(out,80, " Flaps: %3s Gear: %4s\n",flap,gear);
cout << out;
snprintf(out,80, " Speed: %4.0f KCAS Mach: %5.2f\n",
FDMExec->GetAuxiliary()->GetVcalibratedKTS(),
GetParameter(FG_MACH) );
cout << out;
snprintf(out,80, " Altitude: %7.0f ft. AGL Altitude: %7.0f ft.\n",
Position->Geth(),
Position->GetDistanceAGL() );
cout << out;
snprintf(out,80, " Angle of Attack: %6.2f deg Pitch Angle: %6.2f deg\n",
GetParameter(FG_ALPHA)*RADTODEG,
Rotation->Gettht()*RADTODEG );
cout << out;
snprintf(out,80, " Flight Path Angle: %6.2f deg Climb Rate: %5.0f ft/min\n",
Position->GetGamma()*RADTODEG,
Position->Gethdot()*60 );
cout << out;
snprintf(out,80, " Normal Load Factor: %4.2f g's Pitch Rate: %5.2f deg/s\n",
Aerodynamics->GetNlf(),
GetParameter(FG_PITCHRATE)*RADTODEG );
cout << out;
snprintf(out,80, " Heading: %3.0f deg true Sideslip: %5.2f deg\n",
Rotation->Getpsi()*RADTODEG,
GetParameter(FG_BETA)*RADTODEG );
cout << out;
snprintf(out,80, " Bank Angle: %5.2f deg\n",
Rotation->Getphi()*RADTODEG );
cout << out;
snprintf(out,80, " Elevator: %5.2f deg Left Aileron: %5.2f deg Rudder: %5.2f deg\n",
GetParameter(FG_ELEVATOR_POS)*RADTODEG,
GetParameter(FG_AILERON_POS)*RADTODEG,
GetParameter(FG_RUDDER_POS)*RADTODEG );
cout << out;
snprintf(out,80, " Throttle: %5.2f%c\n",
FCS->GetThrottlePos(0),'%' );
cout << out;
snprintf(out,80, " Wind Components: %5.2f kts head wind, %5.2f kts cross wind\n",
FDMExec->GetAuxiliary()->GetHeadWind()*jsbFPSTOKTS,
FDMExec->GetAuxiliary()->GetCrossWind()*jsbFPSTOKTS );
cout << out;
snprintf(out,80, " Ground Speed: %4.0f knots , Ground Track: %3.0f deg true\n",
Position->GetVground()*jsbFPSTOKTS,
Position->GetGroundTrack()*RADTODEG );
cout << out;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGState::Debug(void) void FGState::Debug(void)

View file

@ -26,9 +26,6 @@
FUNCTIONAL DESCRIPTION FUNCTIONAL DESCRIPTION
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Based on Flightgear code, which is based on LaRCSim. This class wraps all
global state variables (such as velocity, position, orientation, etc.).
HISTORY HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
11/17/98 JSB Created 11/17/98 JSB Created
@ -52,14 +49,21 @@ INCLUDES
# include <fstream.h> # include <fstream.h>
# endif # endif
#else #else
# include <fstream> # if defined(sgi) && !defined(__GNUC__)
# include <fstream.h>
# else
# include <fstream>
# endif
#endif #endif
#include <string> #include <string>
#include <map> #include <map>
#include "FGDefs.h" #include "FGDefs.h"
#include "FGJSBBase.h"
#include "FGInitialCondition.h" #include "FGInitialCondition.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -77,6 +81,7 @@ class FGRotation;
class FGAtmosphere; class FGAtmosphere;
class FGOutput; class FGOutput;
class FGPosition; class FGPosition;
class FGFDMExec;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
@ -86,77 +91,235 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
CLASS DOCUMENTATION CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Encapsulates the calculation of aircraft state.
@author Jon S. Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFDMExec; class FGState : public FGJSBBase
{
class FGState {
public: public:
/** Constructor
@param Executive a pointer to the parent executive object */
FGState(FGFDMExec*); FGState(FGFDMExec*);
/// Destructor
~FGState(); ~FGState();
enum {ePhi=1, eTht, ePsi}; /** Specifies the Reset file to use.
enum {eP=1, eQ, eR}; The reset file normally resides in the same directory as an aircraft config file.
enum {eU=1, eV, eW}; it includes the following information:
enum {eDrag=1, eSide, eLift}; <ul>
<li>U, the body X-Axis velocity</li>
<li>V, the body Y-Axis velocity</li>
<li>W, the body Z-Axis velocity</li>
<li>Latitude measured in radians from the equator, negative values are south.</li>
<li>Longitude, measured in radians from the Greenwich meridian, negative values are west.</li>
<li>Phi, the roll angle in radians.</li>
<li>Theta, the pitch attitude in radians.</li>
<li>Psi, the heading angle in radians.</li>
<li>H, the altitude in feet</li>
<li>Wind Direction, the direction the wind is coming <u>from</u>.</li>
<li>Wind magnitude, the wind speed in fps.</li>
</ul>
@param path the path string leading to the specific aircraft file, i.e. "aircraft".
@param aircraft the name of the aircraft, i.e. "c172".
@param filename the name of the reset file without an extension, i.e. "reset00".
@return true if successful, false if the file could not be opened.
*/
bool Reset(string path, string aircraft, string filename);
bool Reset(string, string, string); /** Initializes the simulation state based on the passed-in parameters.
void Initialize(float, float, float, float, float, float, float, float, float); @param U the body X-Axis velocity in fps.
@param V the body Y-Axis velocity in fps.
@param W the body Z-Axis velocity in fps.
@param lat latitude measured in radians from the equator, negative values are south.
@param lon longitude, measured in radians from the Greenwich meridian, negative values are west.
@param phi the roll angle in radians.
@param tht the pitch angle in radians.
@param psi the heading angle in radians measured clockwise from north.
@param h altitude in feet.
@param wnorth north velocity in feet per second
@param weast eastward velocity in feet per second
@param wdown downward velocity in feet per second
*/
void Initialize(float U,
float V,
float W,
float lat,
float lon,
float phi,
float tht,
float psi,
float h,
float wnorth,
float weast,
float wdown);
/** Initializes the simulation state based on parameters from an Initial Conditions object.
@param FGIC pointer to an initial conditions object.
@see FGInitialConditions.
*/
void Initialize(FGInitialCondition *FGIC); void Initialize(FGInitialCondition *FGIC);
bool StoreData(string);
/** Stores state data in the supplied file name.
@param filename the file to store the data in.
@return true if successful.
*/
bool StoreData(string filename);
/// returns the speed of sound in feet per second.
inline float Geta(void) { return a; } inline float Geta(void) { return a; }
/// Returns the simulation time in seconds.
inline float Getsim_time(void) { return sim_time; } inline float Getsim_time(void) { return sim_time; }
/// Returns the simulation delta T.
inline float Getdt(void) { return dt; } inline float Getdt(void) { return dt; }
/// Suspends the simulation and sets the delta T to zero.
inline void Suspend(void) {saved_dt = dt; dt = 0.0;} inline void Suspend(void) {saved_dt = dt; dt = 0.0;}
/// Resumes the simulation by resetting delta T to the correct value.
inline void Resume(void) {dt = saved_dt;} inline void Resume(void) {dt = saved_dt;}
/** Retrieves a parameter.
The parameters that can be retrieved are enumerated in FGDefs.h.
@param val_idx one of the enumerated JSBSim parameters.
@return the value of the parameter.
*/
float GetParameter(eParam val_idx); float GetParameter(eParam val_idx);
/** Retrieves a parameter.
The parameters that can be retrieved are enumerated in FGDefs.h.
@param val_string a string representing one of the enumerated JSBSim parameters,
i.e. "FG_QBAR".
@return the value of the parameter.
*/
float GetParameter(string val_string); float GetParameter(string val_string);
/** Retrieves the JSBSim parameter enumerated item given the text string.
@param val_string the parameter string, i.e. "FG_QBAR".
@return the JSBSim parameter index (an enumerated type) for the supplied string.
*/
eParam GetParameterIndex(string val_string); eParam GetParameterIndex(string val_string);
inline void Seta(float tt) { a = tt; } /** Sets the speed of sound.
@param speed the speed of sound in feet per second.
*/
inline void Seta(float speed) { a = speed; }
inline float Setsim_time(float tt) { /** Sets the current sim time.
sim_time = tt; @param cur_time the current time
@return the current time.
*/
inline float Setsim_time(float cur_time) {
sim_time = cur_time;
return sim_time; return sim_time;
} }
inline void Setdt(float tt) { dt = tt; }
/** Sets the integration time step for the simulation executive.
@param delta_t the time step in seconds.
*/
inline void Setdt(float delta_t) { dt = delta_t; }
void SetParameter(eParam, float); /** Sets the JSBSim parameter to the supplied value.
@param prm the JSBSim parameter to set, i.e. FG_RUDDER_POS.
@param val the value to give the parameter.
*/
void SetParameter(eParam prm, float val);
/** Increments the simulation time.
@return the new simulation time.
*/
inline float IncrTime(void) { inline float IncrTime(void) {
sim_time+=dt; sim_time+=dt;
return sim_time; return sim_time;
} }
/** Initializes the transformation matrices.
@param phi the roll angle in radians.
@param tht the pitch angle in radians.
@param psi the heading angle in radians
*/
void InitMatrices(float phi, float tht, float psi); void InitMatrices(float phi, float tht, float psi);
/** Calculates the local-to-body and body-to-local conversion matrices.
*/
void CalcMatrices(void); void CalcMatrices(void);
void IntegrateQuat(FGColumnVector vPQR, int rate);
FGColumnVector CalcEuler(void); /** Integrates the quaternion.
FGMatrix GetTs2b(float alpha, float beta); Given the supplied rotational rate vector and integration rate, the quaternion
FGMatrix GetTl2b(void) { return mTl2b; } is integrated. The quaternion is later used to update the transformation
float GetTl2b(int i, int j) { return mTl2b(i,j);} matrices.
FGMatrix GetTb2l(void) { return mTb2l; } @param vPQR the body rotational rate column vector.
@param rate the integration rate in seconds.
*/
void IntegrateQuat(FGColumnVector3 vPQR, int rate);
/** Calculates Euler angles from the local-to-body matrix.
@return a reference to the vEuler column vector.
*/
FGColumnVector3& CalcEuler(void);
/** Calculates and returns the stability-to-body axis transformation matrix.
@param alpha angle of attack in radians.
@param beta angle of sideslip in radians.
@return a reference to the stability-to-body transformation matrix.
*/
FGMatrix33& GetTs2b(float alpha, float beta);
/** Retrieves the local-to-body transformation matrix.
@return a reference to the local-to-body transformation matrix.
*/
FGMatrix33& GetTl2b(void) { return mTl2b; }
/** Retrieves a specific local-to-body matrix element.
@param r matrix row index.
@param c matrix column index.
@return the matrix element described by the row and column supplied.
*/
float GetTl2b(int r, int c) { return mTl2b(r,c);}
/** Retrieves the body-to-local transformation matrix.
@return a reference to the body-to-local matrix.
*/
FGMatrix33& GetTb2l(void) { return mTb2l; }
/** Retrieves a specific body-to-local matrix element.
@param r matrix row index.
@param c matrix column index.
@return the matrix element described by the row and column supplied.
*/
float GetTb2l(int i, int j) { return mTb2l(i,j);} float GetTb2l(int i, int j) { return mTb2l(i,j);}
/** Prints a summary of simulator state (speed, altitude,
configuration, etc.)
*/
void ReportState(void);
typedef map<eParam, string> ParamMap; typedef map<eParam, string> ParamMap;
ParamMap paramdef; ParamMap paramdef;
private: private:
float a; // speed of sound float a; // speed of sound
float sim_time, dt; float sim_time, dt;
float saved_dt; float saved_dt;
FGFDMExec* FDMExec; FGFDMExec* FDMExec;
FGMatrix mTb2l; FGMatrix33 mTb2l;
FGMatrix mTl2b; FGMatrix33 mTl2b;
FGMatrix mTs2b; FGMatrix33 mTs2b;
FGColumnVector vQtrn; FGColumnVector4 vQtrn;
FGColumnVector vlastQdot; FGColumnVector4 vlastQdot;
FGColumnVector3 vUVW;
FGColumnVector3 vLocalVelNED;
FGColumnVector3 vLocalEuler;
FGColumnVector4 vQdot;
FGColumnVector4 vTmp;
FGColumnVector3 vEuler;
FGAircraft* Aircraft; FGAircraft* Aircraft;
FGPosition* Position; FGPosition* Position;
@ -171,10 +334,6 @@ private:
CoeffMap coeffdef; CoeffMap coeffdef;
void Debug(void); void Debug(void);
int ActiveEngine; int ActiveEngine;
FGColumnVector vQdot;
FGColumnVector vTmp;
FGColumnVector vEuler;
}; };
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -47,8 +47,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TABLE; static const char *IdHdr = ID_TABLE;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -96,8 +94,8 @@ float** FGTable::Allocate(void)
FGTable::~FGTable() FGTable::~FGTable()
{ {
for (int r=0; r<=nRows; r++) if (Data[r]) delete Data[r]; for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r];
if (Data) delete Data; if (Data) delete[] Data;
if (debug_lvl & 2) cout << "Destroyed: FGTable" << endl; if (debug_lvl & 2) cout << "Destroyed: FGTable" << endl;
} }

View file

@ -39,6 +39,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGConfigFile.h" #include "FGConfigFile.h"
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -71,8 +72,8 @@ CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGTable { class FGTable : public FGJSBBase
{
public: public:
~FGTable(); ~FGTable();
FGTable(int nRows); FGTable(int nRows);

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TANK; static const char *IdHdr = ID_TANK;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -45,6 +45,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGConfigFile.h" #include "FGConfigFile.h"
#include "FGJSBBase.h"
#ifdef FGFS #ifdef FGFS
# include <simgear/compiler.h> # include <simgear/compiler.h>
@ -58,9 +59,11 @@ INCLUDES
#else #else
# include <string> # include <string>
using std::string; using std::string;
using std::cerr; # if !defined(sgi) || defined(__GNUC__)
using std::endl; using std::cerr;
using std::cout; using std::endl;
using std::cout;
# endif
#endif #endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -73,7 +76,7 @@ DEFINES
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGTank class FGTank : public FGJSBBase
{ {
public: public:
FGTank(FGConfigFile*); FGTank(FGConfigFile*);

View file

@ -40,8 +40,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_THRUSTER; static const char *IdHdr = ID_THRUSTER;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -47,6 +47,19 @@ INCLUDES
#define ID_THRUSTER "$Id$" #define ID_THRUSTER "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Base class for specific thrusting devices such as propellers, nozzles, etc.
@author Jon Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -54,7 +67,9 @@ CLASS DECLARATION
class FGThruster : public FGForce { class FGThruster : public FGForce {
public: public:
/// Constructor
FGThruster(FGFDMExec *FDMExec); FGThruster(FGFDMExec *FDMExec);
/// Destructor
virtual ~FGThruster(); virtual ~FGThruster();
enum eType {ttNozzle, ttRotor, ttPropeller}; enum eType {ttNozzle, ttRotor, ttPropeller};
@ -74,7 +89,7 @@ protected:
float Thrust; float Thrust;
float PowerRequired; float PowerRequired;
float deltaT; float deltaT;
void Debug(void); virtual void Debug(void);
}; };
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -72,8 +72,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TRANSLATION; static const char *IdHdr = ID_TRANSLATION;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -83,9 +81,6 @@ FGTranslation::FGTranslation(FGFDMExec* fdmex) : FGModel(fdmex),
vUVW(3), vUVW(3),
vUVWdot(3), vUVWdot(3),
vNcg(3), vNcg(3),
vPQR(3),
vForces(3),
vEuler(3),
vlastUVWdot(3), vlastUVWdot(3),
mVel(3,3), mVel(3,3),
vAero(3) vAero(3)
@ -96,7 +91,6 @@ FGTranslation::FGTranslation(FGFDMExec* fdmex) : FGModel(fdmex),
Mach = 0.0; Mach = 0.0;
alpha = beta = 0.0; alpha = beta = 0.0;
adot = bdot = 0.0; adot = bdot = 0.0;
rho = 0.002378;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl; if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
} }
@ -110,12 +104,12 @@ FGTranslation::~FGTranslation()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGTranslation::Run(void) { bool FGTranslation::Run(void)
{
float Tc = 0.5*State->Getdt()*rate;
if (!FGModel::Run()) { if (!FGModel::Run()) {
GetState();
mVel(1,1) = 0.0; mVel(1,1) = 0.0;
mVel(1,2) = -vUVW(eW); mVel(1,2) = -vUVW(eW);
mVel(1,3) = vUVW(eV); mVel(1,3) = vUVW(eV);
@ -126,37 +120,40 @@ bool FGTranslation::Run(void) {
mVel(3,2) = vUVW(eU); mVel(3,2) = vUVW(eU);
mVel(3,3) = 0.0; mVel(3,3) = 0.0;
vUVWdot = mVel*vPQR + vForces/Mass; vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetForces()/MassBalance->GetMass();
vNcg = vUVWdot*INVGRAVITY; vNcg = vUVWdot*INVGRAVITY;
vUVW += 0.5*dt*rate*(vlastUVWdot + vUVWdot); vUVW += Tc * (vlastUVWdot + vUVWdot);
vAero = vUVW + State->GetTl2b()*Atmosphere->GetWindNED(); vAero = vUVW + State->GetTl2b()*Atmosphere->GetWindNED();
Vt = vAero.Magnitude(); Vt = vAero.Magnitude();
if ( Vt > 1) {
if (vAero(eW) != 0.0)
alpha = vAero(eU)*vAero(eU) > 0.0 ? atan2(vAero(eW), vAero(eU)) : 0.0;
if (vAero(eV) != 0.0)
beta = vAero(eU)*vAero(eU)+vAero(eW)*vAero(eW) > 0.0 ? atan2(vAero(eV),
sqrt(vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW))) : 0.0;
if (vAero(eW) != 0.0) // stolen, quite shamelessly, from LaRCsim
alpha = vAero(eU)*vAero(eU) > 0.0 ? atan2(vAero(eW), vAero(eU)) : 0.0; float mUW = (vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW));
if (vAero(eV) != 0.0) float signU=1;
beta = vAero(eU)*vAero(eU)+vAero(eW)*vAero(eW) > 0.0 ? atan2(vAero(eV), if (vAero(eU) != 0.0)
sqrt(vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW))) : 0.0; signU = vAero(eU)/fabs(vAero(eU));
// stolen, quite shamelessly, from LaRCsim if ( (mUW == 0.0) || (Vt == 0.0) ) {
float mUW = (vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW)); adot = 0.0;
float signU=1; bdot = 0.0;
if (vAero(eU) != 0.0) } else {
signU = vAero(eU)/fabs(vAero(eU)); adot = (vAero(eU)*vAero(eW) - vAero(eW)*vUVWdot(eU))/mUW;
bdot = (signU*mUW*vUVWdot(eV) - vAero(eV)*(vAero(eU)*vUVWdot(eU)
if ( (mUW == 0.0) || (Vt == 0.0) ) { + vAero(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
adot = 0.0; }
bdot = 0.0;
} else { } else {
adot = (vAero(eU)*vAero(eW) - vAero(eW)*vUVWdot(eU))/mUW; alpha = beta = adot = bdot = 0;
bdot = (signU*mUW*vUVWdot(eV) - vAero(eV)*(vAero(eU)*vUVWdot(eU)
+ vAero(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
} }
qbar = 0.5*rho*Vt*Vt; qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt;
Mach = Vt / State->Geta(); Mach = Vt / State->Geta();
vlastUVWdot = vUVWdot; vlastUVWdot = vUVWdot;
@ -171,20 +168,6 @@ bool FGTranslation::Run(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTranslation::GetState(void) {
dt = State->Getdt();
vPQR = Rotation->GetPQR();
vForces = Aircraft->GetForces();
Mass = MassBalance->GetMass();
rho = Atmosphere->GetDensity();
vEuler = Rotation->GetEuler();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTranslation::Debug(void) void FGTranslation::Debug(void)
{ {
if (debug_lvl & 16) { // Sanity check variables if (debug_lvl & 16) { // Sanity check variables

View file

@ -64,11 +64,17 @@ INCLUDES
# include <math.h> # include <math.h>
# endif # endif
#else #else
# include <cmath> # if defined(sgi) && !defined(__GNUC__)
# include <math.h>
# else
# include <cmath>
# endif
#endif #endif
#include "FGModel.h" #include "FGModel.h"
#include "FGMatrix.h" #include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
#define ID_TRANSLATION "$Id$" #define ID_TRANSLATION "$Id$"
@ -81,14 +87,14 @@ public:
FGTranslation(FGFDMExec*); FGTranslation(FGFDMExec*);
~FGTranslation(); ~FGTranslation();
inline FGColumnVector GetUVW (void) { return vUVW; } inline FGColumnVector3& GetUVW (void) { return vUVW; }
inline float GetUVW (int idx) { return vUVW(idx); } inline float GetUVW (int idx) { return vUVW(idx); }
inline FGColumnVector GetUVWdot(void) { return vUVWdot; } inline FGColumnVector3& GetUVWdot(void) { return vUVWdot; }
inline float GetUVWdot(int idx) { return vUVWdot(idx); } inline float GetUVWdot(int idx) { return vUVWdot(idx); }
inline FGColumnVector GetNcg (void) { return vNcg; } inline FGColumnVector3& GetNcg (void) { return vNcg; }
inline float GetNcg (int idx) { return vNcg(idx); } inline float GetNcg (int idx) { return vNcg(idx); }
inline FGColumnVector GetvAero (void) { return vAero; } inline FGColumnVector3& GetvAero (void) { return vAero; }
inline float GetvAero (int idx) { return vAero(idx); } inline float GetvAero (int idx) { return vAero(idx); }
inline float Getalpha(void) { return alpha; } inline float Getalpha(void) { return alpha; }
inline float Getbeta (void) { return beta; } inline float Getbeta (void) { return beta; }
@ -98,7 +104,7 @@ public:
inline float Getadot (void) { return adot; } inline float Getadot (void) { return adot; }
inline float Getbdot (void) { return bdot; } inline float Getbdot (void) { return bdot; }
void SetUVW(FGColumnVector tt) { vUVW = tt; } void SetUVW(FGColumnVector3 tt) { vUVW = tt; }
inline void Setalpha(float tt) { alpha = tt; } inline void Setalpha(float tt) { alpha = tt; }
inline void Setbeta (float tt) { beta = tt; } inline void Setbeta (float tt) { beta = tt; }
@ -112,26 +118,19 @@ public:
bool Run(void); bool Run(void);
protected:
private: private:
FGColumnVector vUVW; FGColumnVector3 vUVW;
FGColumnVector vUVWdot; FGColumnVector3 vUVWdot;
FGColumnVector vNcg; FGColumnVector3 vNcg;
FGColumnVector vPQR; FGColumnVector3 vlastUVWdot;
FGColumnVector vForces; FGMatrix33 mVel;
FGColumnVector vEuler; FGColumnVector3 vAero;
FGColumnVector vlastUVWdot;
FGMatrix mVel;
FGColumnVector vAero;
float Vt, qbar, Mach; float Vt, qbar, Mach;
float Mass, dt; float dt;
float alpha, beta; float alpha, beta;
float adot,bdot; float adot,bdot;
float rho;
void GetState(void);
void Debug(void); void Debug(void);
}; };

View file

@ -60,8 +60,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TRIM; static const char *IdHdr = ID_TRIM;
extern short debug_lvl;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTrim::FGTrim(FGFDMExec *FDMExec,FGInitialCondition *FGIC, TrimMode tt ) { FGTrim::FGTrim(FGFDMExec *FDMExec,FGInitialCondition *FGIC, TrimMode tt ) {

View file

@ -49,6 +49,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGJSBBase.h"
#include "FGRotation.h" #include "FGRotation.h"
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGState.h" #include "FGState.h"
@ -69,12 +70,12 @@ DEFINITIONS
#define ID_TRIM "$Id$" #define ID_TRIM "$Id$"
typedef enum { tLongitudinal, tFull, tGround, tCustom, tNone } TrimMode;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
typedef enum { tLongitudinal, tFull, tGround, tCustom, tNone } TrimMode;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -135,7 +136,8 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGTrim { class FGTrim : public FGJSBBase
{
private: private:
vector<FGTrimAxis*> TrimAxes; vector<FGTrimAxis*> TrimAxes;

View file

@ -45,8 +45,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TRIMAXIS; static const char *IdHdr = ID_TRIMAXIS;
extern short debug_lvl;
/*****************************************************************************/ /*****************************************************************************/
FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st, FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,

View file

@ -41,6 +41,7 @@ INCLUDES
#include <string> #include <string>
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGJSBBase.h"
#include "FGRotation.h" #include "FGRotation.h"
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGState.h" #include "FGState.h"
@ -72,7 +73,8 @@ enum State { tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt };
enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL, enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL,
tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading }; tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading };
class FGTrimAxis { class FGTrimAxis : public FGJSBBase
{
public: public:
FGTrimAxis(FGFDMExec* fdmex, FGInitialCondition *ic, State st, FGTrimAxis(FGFDMExec* fdmex, FGInitialCondition *ic, State st,
Control ctrl ); Control ctrl );

View file

@ -43,8 +43,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TURBOJET; static const char *IdHdr = ID_TURBOJET;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -43,8 +43,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TURBOPROP; static const char *IdHdr = ID_TURBOPROP;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -43,8 +43,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TURBOSHAFT; static const char *IdHdr = ID_TURBOSHAFT;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -50,7 +50,11 @@ INCLUDES
# include <math.h> # include <math.h>
# endif # endif
#else #else
# include <cmath> # if defined(sgi) && !defined(__GNUC__)
# include <math.h>
# else
# include <cmath>
# endif
#endif #endif
#include "FGUtility.h" #include "FGUtility.h"
@ -60,8 +64,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_UTILITY; static const char *IdHdr = ID_UTILITY;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -38,6 +38,8 @@ SENTRY
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINES DEFINES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -51,7 +53,7 @@ CLASS DECLARATION
class FGFDMExec; class FGFDMExec;
class FGState; class FGState;
class FGUtility class FGUtility : public FGJSBBase
{ {
public: public:
FGUtility(void); FGUtility(void);

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FDMSOCKET; static const char *IdHdr = ID_FDMSOCKET;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -52,7 +50,7 @@ FGfdmSocket::FGfdmSocket(string address, int port)
{ {
size = 0; size = 0;
#if defined(__BORLANDC__) || defined(_MSC_VER) #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
WSADATA wsaData; WSADATA wsaData;
int PASCAL FAR wsaReturnCode; int PASCAL FAR wsaReturnCode;
wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData); wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);

View file

@ -54,16 +54,22 @@ INCLUDES
SG_USING_STD(endl); SG_USING_STD(endl);
# endif # endif
#else #else
# include <iostream>
# include <fstream>
# include <string> # include <string>
using std::cout; # if defined(sgi) && !defined(__GNUC__)
using std::endl; # include <iostream.h>
# include <fstream.h>
# else
# include <iostream>
# include <fstream>
using std::cout;
using std::endl;
# endif
#endif #endif
#include <sys/types.h> #include <sys/types.h>
#include "FGJSBBase.h"
#if defined(__BORLANDC__) || defined(_MSC_VER) #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
#include <winsock.h> #include <winsock.h>
#else #else
#include <sys/socket.h> #include <sys/socket.h>
@ -84,7 +90,8 @@ CLASS DECLARATION
using std::string; using std::string;
class FGfdmSocket { class FGfdmSocket : public FGJSBBase
{
public: public:
FGfdmSocket(string, int); FGfdmSocket(string, int);
~FGfdmSocket(); ~FGfdmSocket();

View file

@ -60,60 +60,13 @@ INCLUDES
# include <time.h> # include <time.h>
# endif # endif
#else #else
#include <iostream> # if defined(sgi) && !defined(__GNUC__)
#include <ctime> # include <iostream.h>
#endif # include <time.h>
# else
#if __BORLANDC__ > 0x540 # include <iostream>
#include <condefs.h> # include <ctime>
USEUNIT("FGUtility.cpp"); # endif
USEUNIT("FGAircraft.cpp");
USEUNIT("FGAtmosphere.cpp");
USEUNIT("FGAuxiliary.cpp");
USEUNIT("FGCoefficient.cpp");
USEUNIT("FGConfigFile.cpp");
USEUNIT("FGEngine.cpp");
USEUNIT("FGFCS.cpp");
USEUNIT("FGFDMExec.cpp");
USEUNIT("FGfdmSocket.cpp");
USEUNIT("FGForce.cpp");
USEUNIT("FGGroundReactions.cpp");
USEUNIT("FGInertial.cpp");
USEUNIT("FGInitialCondition.cpp");
USEUNIT("FGLGear.cpp");
USEUNIT("FGMassBalance.cpp");
USEUNIT("FGMatrix.cpp");
USEUNIT("FGModel.cpp");
USEUNIT("FGNozzle.cpp");
USEUNIT("FGOutput.cpp");
USEUNIT("FGPiston.cpp");
USEUNIT("FGPosition.cpp");
USEUNIT("FGJSBBase.cpp");
USEUNIT("FGPropulsion.cpp");
USEUNIT("FGRocket.cpp");
USEUNIT("FGRotation.cpp");
USEUNIT("FGRotor.cpp");
USEUNIT("FGState.cpp");
USEUNIT("FGTable.cpp");
USEUNIT("FGTank.cpp");
USEUNIT("FGThruster.cpp");
USEUNIT("FGTranslation.cpp");
USEUNIT("FGTrim.cpp");
USEUNIT("FGTrimAxis.cpp");
USEUNIT("FGTurboJet.cpp");
USEUNIT("FGTurboProp.cpp");
USEUNIT("FGTurboShaft.cpp");
USEUNIT("FGAerodynamics.cpp");
USEUNIT("filtersjb\FGSwitch.cpp");
USEUNIT("filtersjb\FGFCSComponent.cpp");
USEUNIT("filtersjb\FGFilter.cpp");
USEUNIT("filtersjb\FGFlaps.cpp");
USEUNIT("filtersjb\FGGain.cpp");
USEUNIT("filtersjb\FGGradient.cpp");
USEUNIT("filtersjb\FGSummer.cpp");
USEUNIT("filtersjb\FGDeadBand.cpp");
USEUNIT("FGPropeller.cpp");
//---------------------------------------------------------------------------
#endif #endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -187,13 +140,16 @@ int main(int argc, char** argv)
exit(-1); exit(-1);
} }
} else { } else {
result = FDMExec->LoadModel("aircraft", "engine", string(argv[1])); // result = FDMExec->LoadModel("aircraft", "engine", string(argv[1]));
FGInitialCondition IC(FDMExec);
result = IC.Load("aircraft","engine",string(argv[1]));
if (!result) { if (!result) {
cerr << "Aircraft file " << argv[1] << " was not found" << endl; cerr << "Aircraft file " << argv[1] << " was not found" << endl;
exit(-1); exit(-1);
} }
if ( ! FDMExec->GetState()->Reset("aircraft", string(argv[1]), string(argv[2]))) if ( ! FDMExec->GetState()->Reset("aircraft", string(argv[1]), string(argv[2])))
FDMExec->GetState()->Initialize(2000,0,0,0,0,0,0.5,0.5,40000); FDMExec->GetState()->Initialize(2000,0,0,0,0,0,0.5,0.5,40000, 0, 0, 0);
} }
while (FDMExec->Run()) {} while (FDMExec->Run()) {}

View file

@ -17,17 +17,22 @@ libJSBSim_a_SOURCES = \
FGAtmosphere.cpp FGAtmosphere.h \ FGAtmosphere.cpp FGAtmosphere.h \
FGAuxiliary.cpp FGAuxiliary.h \ FGAuxiliary.cpp FGAuxiliary.h \
FGCoefficient.cpp FGCoefficient.h \ FGCoefficient.cpp FGCoefficient.h \
FGColumnVector3.cpp FGColumnVector3.h \
FGColumnVector4.cpp FGColumnVector4.h \
FGConfigFile.cpp FGConfigFile.h \ FGConfigFile.cpp FGConfigFile.h \
FGDefs.h \ FGDefs.h \
FGFCS.cpp FGFCS.h \ FGFCS.cpp FGFCS.h \
FGFDMExec.cpp FGFDMExec.h \ FGFDMExec.cpp FGFDMExec.h \
FGFactorGroup.cpp FGFactorGroup.h \ FGFactorGroup.cpp FGFactorGroup.h \
FGForce.cpp FGForce.h \ FGForce.cpp FGForce.h \
FGGroundReactions.cpp FGGroundReactions.h \
FGInertial.cpp FGInertial.h \ FGInertial.cpp FGInertial.h \
FGInitialCondition.cpp FGInitialCondition.h \ FGInitialCondition.cpp FGInitialCondition.h \
FGJSBBase.cpp FGJSBBase.h \
FGLGear.cpp FGLGear.h \ FGLGear.cpp FGLGear.h \
FGMassBalance.cpp FGMassBalance.h \ FGMassBalance.cpp FGMassBalance.h \
FGMatrix.cpp FGMatrix.h \ FGMatrix.cpp FGMatrix.h \
FGMatrix33.cpp FGMatrix33.h \
FGModel.cpp FGModel.h \ FGModel.cpp FGModel.h \
FGNozzle.cpp FGNozzle.h \ FGNozzle.cpp FGNozzle.h \
FGOutput.cpp FGOutput.h \ FGOutput.cpp FGOutput.h \

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_DEADBAND; static const char *IdHdr = ID_DEADBAND;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FCSCOMPONENT; static const char *IdHdr = ID_FCSCOMPONENT;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -43,6 +43,7 @@ INCLUDES
#include <string> #include <string>
#include "../FGDefs.h" #include "../FGDefs.h"
#include "../FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
@ -89,7 +90,7 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFCSComponent class FGFCSComponent : public FGJSBBase
{ {
public: public:
/// Constructor /// Constructor
@ -115,7 +116,7 @@ protected:
eParam OutputIdx; eParam OutputIdx;
float Output; float Output;
bool IsOutput; bool IsOutput;
void Debug(void); virtual void Debug(void);
}; };
#include "../FGFCS.h" #include "../FGFCS.h"

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FILTER; static const char *IdHdr = ID_FILTER;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -113,6 +111,12 @@ FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
cc = (2.00*C3 - dt*C2) / denom; cc = (2.00*C3 - dt*C2) / denom;
break; break;
case eOrder2: case eOrder2:
denom = 4.0*C3 + 2.0*C5*dt + C6*dt*dt;
ca = 4.0*C1 + 2.0*C2*dt + C3*dt*dt / denom;
cb = 2.0*C3*dt*dt - 8.0*C1 / denom;
cc = 4.0*C1 - 2.0*C2*dt + C3*dt*dt / denom;
cd = 2.0*C6*dt*dt - 8.0*C4 / denom;
ce = 4.0*C3 - 2.0*C5*dt + C6*dt*dt / denom;
break; break;
case eWashout: case eWashout:
denom = 2.00 + dt*C1; denom = 2.00 + dt*C1;
@ -122,6 +126,9 @@ FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
case eIntegrator: case eIntegrator:
ca = dt*C1 / 2.00; ca = dt*C1 / 2.00;
break; break;
case eUnknown:
cerr << "Unknown filter type" << endl;
break;
} }
if (debug_lvl > 0) { if (debug_lvl > 0) {
@ -162,12 +169,13 @@ bool FGFilter::Run(void)
switch (FilterType) { switch (FilterType) {
case eLag: case eLag:
Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb; Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb;
// Output = Input * ca + PreviousOutput1 * cb;
break; break;
case eLeadLag: case eLeadLag:
Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc; Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc;
break; break;
case eOrder2: case eOrder2:
Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc
- PreviousOutput1 * cd - PreviousOutput2 * ce;
break; break;
case eWashout: case eWashout:
Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb; Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;

View file

@ -103,6 +103,7 @@ private:
float cb; float cb;
float cc; float cc;
float cd; float cd;
float ce;
float C1; float C1;
float C2; float C2;
float C3; float C3;
@ -118,3 +119,4 @@ private:
}; };
#endif #endif

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FLAPS; static const char *IdHdr = ID_FLAPS;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_GAIN; static const char *IdHdr = ID_GAIN;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_GRADIENT; static const char *IdHdr = ID_GRADIENT;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_SUMMER; static const char *IdHdr = ID_SUMMER;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

View file

@ -42,8 +42,6 @@ INCLUDES
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_SWITCH; static const char *IdHdr = ID_SWITCH;
extern short debug_lvl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/