static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_AERODYNAMICS;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
vForces = State->GetTs2b(alpha, beta)*vFs;
- // see http://home.earthlink.net/~apeden/jsbsim_moments_due_to_forces.txt
- // for details on this
-
- vDXYZcg(eX) = -(Aircraft->GetXYZrp(eX) - MassBalance->GetXYZcg(eX))/12.0;
- vDXYZcg(eY) = (Aircraft->GetXYZrp(eY) - MassBalance->GetXYZcg(eY))/12.0;
- vDXYZcg(eZ) = -(Aircraft->GetXYZrp(eZ) - MassBalance->GetXYZcg(eZ))/12.0;
+ vDXYZcg(eX) = -(Aircraft->GetXYZrp(eX)
+ - MassBalance->GetXYZcg(eX))*INCHTOFT;
+ vDXYZcg(eY) = (Aircraft->GetXYZrp(eY)
+ - MassBalance->GetXYZcg(eY))*INCHTOFT;
+ vDXYZcg(eZ) = -(Aircraft->GetXYZrp(eZ)
+ - MassBalance->GetXYZcg(eZ))*INCHTOFT;
- 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);
+ vMoments = vDXYZcg*vForces; // M = r X F
for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) {
/** Gets the total aerodynamic force vector.
@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.
@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 FGColumnVector GetvFs(void) { return vFs; }
+ inline FGColumnVector3& GetvFs(void) { return vFs; }
inline float GetvFs(int axis) { return vFs(axis); }
float GetLoD(void);
AxisIndex AxisIdx;
typedef vector<FGCoefficient*> CoeffArray;
CoeffArray* Coeff;
- FGColumnVector vFs;
- FGColumnVector vForces;
- FGColumnVector vMoments;
- FGColumnVector vLastFs;
- FGColumnVector vDXYZcg;
+ FGColumnVector3 vFs;
+ FGColumnVector3 vForces;
+ FGColumnVector3 vMoments;
+ FGColumnVector3 vLastFs;
+ FGColumnVector3 vDXYZcg;
void Debug(void);
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
# include <math.h>
# endif
#else
-# include <cmath>
+# if defined (sgi) && !defined(__GNUC__)
+# include <math.h>
+# else
+# include <cmath>
+# endif
#endif
#include "FGAircraft.h"
#include "FGMassBalance.h"
#include "FGInertial.h"
+#include "FGGroundReactions.h"
#include "FGAerodynamics.h"
#include "FGTranslation.h"
#include "FGRotation.h"
static const char *IdSrc = "$Id$";
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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
vForces(3),
vXYZrp(3),
vXYZep(3),
- vEuler(3),
vDXYZcg(3),
- vAeroBodyForces(3)
+ vBodyAccel(3)
{
Name = "FGAircraft";
-
GearUp = false;
-
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;
}
ReadOutput(AC_cfg);
}
}
-
+
return true;
}
bool FGAircraft::Run(void)
{
if (!FGModel::Run()) { // if false then execute this Run()
- GetState();
-
vForces.InitMatrix();
- vMoments.InitMatrix();
-
- FMProp();
- FMAero();
- FMMass();
- FMGear();
+ vForces += Aerodynamics->GetForces();
+ vForces += Inertial->GetForces();
+ vForces += Propulsion->GetForces();
+ vForces += GroundReactions->GetForces();
+ vMoments.InitMatrix();
+ vMoments += Aerodynamics->GetMoments();
+ vMoments += Propulsion->GetMoments();
+ vMoments += GroundReactions->GetMoments();
+
+ vBodyAccel = vForces/MassBalance->GetMass();
+
return false;
} else { // skip Run() execution this time
return true;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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)
{
string token = "";
string parameter;
float EW, bixx, biyy, bizz, bixz, biyz;
- FGColumnVector vbaseXYZcg(3);
+ FGColumnVector3 vbaseXYZcg(3);
AC_cfg->GetNextConfigLine();
} else if (parameter == "AC_WINGSPAN") {
*AC_cfg >> WingSpan;
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") {
*AC_cfg >> cbar;
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") {
*AC_cfg >> bixx;
if (debug_lvl > 0) cout << " baseIxx: " << bixx << 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)) {
cerr << "Propulsion not successfully loaded" << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGAircraft::ReadFlightControls(FGConfigFile* AC_cfg) {
+void FGAircraft::ReadFlightControls(FGConfigFile* AC_cfg)
+{
if (!FCS->Load(AC_cfg)) {
cerr << "Flight Controls not successfully loaded" << endl;
}
if (!Aerodynamics->Load(AC_cfg)) {
cerr << "Aerodynamics not successfully loaded" << endl;
}
-
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGAircraft::ReadUndercarriage(FGConfigFile* AC_cfg) {
- string token;
-
- AC_cfg->GetNextConfigLine();
-
- while ((token = AC_cfg->GetValue()) != "/UNDERCARRIAGE") {
- lGear.push_back(FGLGear(AC_cfg, FDMExec));
+void FGAircraft::ReadUndercarriage(FGConfigFile* AC_cfg)
+{
+ if (!GroundReactions->Load(AC_cfg)) {
+ cerr << "Ground Reactions not successfully loaded" << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGAircraft::ReadOutput(FGConfigFile* AC_cfg) {
+void FGAircraft::ReadOutput(FGConfigFile* AC_cfg)
+{
string token, parameter;
int OutRate = 0;
int subsystems = 0;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg) {
+void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg)
+{
string token = AC_cfg->GetValue();
string scratch;
AircraftName = AC_cfg->GetValue("NAME");
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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)
{
//TODO: Add your source code here
#include "FGModel.h"
#include "FGPropulsion.h"
#include "FGConfigFile.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
#include "FGLGear.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 FGAircraft : public FGModel {
- enum {eL=1, eM, eN};
- enum {eX=1, eY, eZ};
- enum {eP=1, eQ, eR};
- enum {ePhi=1, eTht, ePsi};
-
public:
/** Constructor
@param Executive a pointer to the parent executive object */
inline float GetWingSpan(void) { return WingSpan; }
/// Gets the average wing chord
inline float Getcbar(void) { return cbar; }
- inline FGColumnVector GetMoments(void) { return vMoments; }
- inline FGColumnVector GetForces(void) { return vForces; }
- inline FGColumnVector GetAeroBodyForces(void) { return vAeroBodyForces; }
- inline float GetAeroBodyForces(int axis) { return vAeroBodyForces(axis); }
- inline FGColumnVector GetXYZrp(void) { return vXYZrp; }
- inline FGColumnVector GetXYZep(void) { return vXYZep; }
+ inline float GetWingIncidence(void) { return WingIncidence; }
+ inline float GetHTailArea(void) { return HTailArea; }
+ inline float GetHTailArm(void) { return HTailArm; }
+ inline float GetVTailArea(void) { return VTailArea; }
+ inline float GetVTailArm(void) { return VTailArm; }
+ 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 GetXYZep(int idx) { return vXYZep(idx); }
inline float GetAlphaCLMax(void) { return alphaclmax; }
inline void SetAlphaCLMax(float tt) { alphaclmax=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
enum SubSystems {
/** Subsystem: Simulation (= 1) */ ssSimulation = 1,
} subsystems;
private:
- void GetState(void);
- void FMAero(void);
- void FMGear(void);
- void FMMass(void);
- void FMProp(void);
- FGColumnVector vMoments;
- FGColumnVector vForces;
- FGColumnVector vXYZrp;
- FGColumnVector vXYZep;
- FGColumnVector vEuler;
- FGColumnVector vDXYZcg;
- FGColumnVector vAeroBodyForces;
- float alpha, beta;
- float WingArea, WingSpan, cbar;
+ FGColumnVector3 vMoments;
+ FGColumnVector3 vForces;
+ FGColumnVector3 vXYZrp;
+ FGColumnVector3 vXYZep;
+ FGColumnVector3 vEuler;
+ FGColumnVector3 vDXYZcg;
+ FGColumnVector3 vBodyAccel;
+ float WingArea, WingSpan, cbar, WingIncidence;
+ float HTailArea, VTailArea, HTailArm, VTailArm;
+ float lbarh,lbarv,vbarh,vbarv;
float alphaclmax,alphaclmin;
- float dt;
string CFGVersion;
string AircraftName;
#include "FGAuxiliary.h"
#include "FGOutput.h"
#include "FGDefs.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ATMOSPHERE;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
vWindNED(3)
{
Name = "FGAtmosphere";
+ lastIndex=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);
SLtemperature = temperature;
SLpressure = pressure;
SLdensity = density;
SLsoundspeed = sqrt(SHRATIO*Reng*temperature);
+ rSLtemperature = 1.0/temperature;
+ rSLpressure = 1.0/pressure;
+ rSLdensity = 1.0/density;
+ rSLsoundspeed = 1.0/SLsoundspeed;
useExternal=false;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
bool FGAtmosphere::Run(void)
{
- //cout << "In FGAtmosphere::Run(void)" << endl;
if (!FGModel::Run()) { // if false then execute this Run()
//do temp, pressure, and density first
if (!useExternal) {
- //cout << "Atmosphere: Using internal model, altitude= ";
h = Position->Geth();
-
Calculate(h);
} else {
density = exDensity;
if (psiw < 0) psiw += 2*M_PI;
soundspeed = sqrt(SHRATIO*Reng*temperature);
- //cout << "Atmosphere: soundspeed: " << soundspeed << endl;
+
State->Seta(soundspeed);
} else { // skip Run() execution this time
{
//see reference [1]
- float slope,reftemp,refpress,refdens;
- int i=0;
- float htab[]={0,36089,82020,154198,173882,259183,295272,344484}; //ft.
+ float slope,reftemp,refpress;
+ int i=0; bool lookup = false;
// cout << "Atmosphere: h=" << altitude << " rho= " << density << endl;
- if (altitude <= htab[0]) {
- altitude=0;
- } else if (altitude >= htab[7]){
- i = 7;
- altitude = htab[7];
- } else {
- while (htab[i+1] < altitude) {
- i++;
- }
- }
+ i=lastIndex;
+ if(altitude < htab[lastIndex]) {
+ if (altitude <= 0) {
+ i=0; altitude=0;
+ } else {
+ i=lastIndex-1;
+ while (htab[i] > altitude) { 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) {
case 0: // sea level
- slope = -0.0035662; // R/ft.
- reftemp = 518.688; // R
- refpress = 2116.17; // psf
- refdens = 0.0023765; // slugs/cubic ft.
+ slope = -0.00356616; // R/ft.
+ reftemp = 518.67; // R
+ refpress = 2116.22; // psf
+ //refdens = 0.00237767; // slugs/cubic ft.
break;
case 1: // 36089 ft.
slope = 0;
- reftemp = 389.988;
- refpress = 474.1;
- refdens = 0.0007078;
- break;
- case 2: // 82020 ft.
- slope = 0.00164594;
- reftemp = 389.988;
- refpress = 52.7838;
- refdens = 7.8849E-5;
+ reftemp = 389.97;
+ refpress = 472.452;
+ //refdens = 0.000706032;
break;
- case 3: // 154198 ft.
- slope = 0;
- reftemp = 508.788;
- refpress = 2.62274;
- refdens = 3.01379E-6;
+ case 2: // 65616 ft.
+ slope = 0.00054864;
+ reftemp = 389.97;
+ refpress = 114.636;
+ //refdens = 0.000171306;
break;
- case 4: // 173882 ft.
- slope = -0.00246891;
- reftemp = 508.788;
- refpress = 1.28428;
- refdens = 1.47035e-06;
+ case 3: // 104986 ft.
+ slope = 0.00153619;
+ reftemp = 411.57;
+ refpress = 8.36364;
+ //refdens = 1.18422e-05;
break;
- case 5: // 259183 ft.
+ case 4: // 154199 ft.
slope = 0;
- reftemp = 298.188;
- refpress = 0.0222008;
- refdens = 4.33396e-08;
+ reftemp = 487.17;
+ refpress = 0.334882;
+ //refdens = 4.00585e-7;
+ break;
+ case 5: // 170603 ft.
+ slope = -0.00109728;
+ reftemp = 487.17;
+ refpress = 0.683084;
+ //refdens = 8.17102e-7;
break;
- case 6: // 295272 ft.
- slope = 0.00219459;
- reftemp = 298.188;
- refpress = 0.00215742;
- refdens = 4.21368e-09;
+ case 6: // 200131 ft.
+ slope = -0.00219456;
+ reftemp = 454.17;
+ refpress = 0.00684986;
+ //refdens = 8.77702e-9;
break;
- case 7: // 344484 ft.
+ case 7: // 259186 ft.
slope = 0;
- reftemp = 406.188;
- refpress = 0.000153755;
- refdens = 2.20384e-10;
+ reftemp = 325.17;
+ refpress = 0.000122276;
+ //refdens = 2.19541e-10;
break;
}
-
+
if (slope == 0) {
temperature = reftemp;
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 {
temperature = reftemp+slope*(altitude-htab[i]);
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;
-
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*******************************************************************************/
#include "FGModel.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#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,
1989, ISBN 0-07-001641-0
-
-*******************************************************************************
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models the standard atmosphere.
+ @author Tony Peden, Jon Berndt
+ @version $Id$
+*/
+
+/******************************************************************************
CLASS DECLARATION
*******************************************************************************/
class FGAtmosphere : public FGModel {
public:
+ /// Constructor
FGAtmosphere(FGFDMExec*);
+ /// Destructor
~FGAtmosphere();
+ /** Runs the Atmosphere model; called by the Executive
+ @return false if no error */
bool Run(void);
+ /// Returns the temperature in degrees Rankine.
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;}
+ /// Returns the speed of sound in ft/sec.
inline float GetSoundSpeed(void) {return soundspeed;}
- inline float GetTemperatureSL(void) { return SLtemperature; } //Rankine, altitude in feet
- inline float GetDensitySL(void) { return SLdensity; } //slugs/ft^3
- inline float GetPressureSL(void) { return SLpressure; } //lbs/ft^2
- inline float GetSoundSpeedSL(void) { return SLsoundspeed; } //ft/s
-
- inline float GetTemperatureRatio(void) { return temperature/SLtemperature; }
- inline float GetDensityRatio(void) { return density/SLdensity; }
- inline float GetPressureRatio(void) { return pressure/SLpressure; }
- inline float GetSoundSpeedRatio(void) { return soundspeed/SLsoundspeed; }
-
+ /// Returns the sea level temperature in degrees Rankine.
+ inline float GetTemperatureSL(void) { return SLtemperature; }
+ /// Returns the sea level density in slugs/ft^3
+ 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; }
+
+ /// Returns the ratio of at-altitude temperature over the sea level value.
+ inline float GetTemperatureRatio(void) { return temperature*rSLtemperature; }
+ /// Returns the ratio of at-altitude density over the sea level value.
+ 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; }
+ /// Tells the simulator to use the internal atmosphere model.
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; }
+ /// Provides the external atmosphere model with an interface to set the temperature.
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; }
+ /// Provides the external atmosphere model with an interface to set the pressure.
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 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; }
-protected:
-
private:
float rho;
+ int lastIndex;
float h;
+ float htab[8];
float SLtemperature,SLdensity,SLpressure,SLsoundspeed;
+ float rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
float temperature,density,pressure,soundspeed;
bool useExternal;
float exTemperature,exDensity,exPressure;
- FGColumnVector vWindNED;
+ FGColumnVector3 vWindNED;
float psiw;
void Calculate(float altitude);
#include "FGAircraft.h"
#include "FGPosition.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 *IdHdr = ID_AUXILIARY;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
vcas = sqrt(7*psl/rhosl*(A-1));
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();
- vPilotAccel = Translation->GetUVWdot()
- + Rotation->GetPQRdot() * vToEyePt
- + Rotation->GetPQR() * (Rotation->GetPQR() * vToEyePt);
+
+ vPilotAccel = Aircraft->GetBodyAccel()
+ + Rotation->GetPQRdot() * vToEyePt
+ + Rotation->GetPQR() * (Rotation->GetPQR() * vToEyePt)
+ + Inertial->GetGravity();
earthPosAngle += State->Getdt()*OMEGA_EARTH;
return false;
psi = Rotation->Getpsi();
vw = Atmosphere->GetWindNED().Magnitude();
- return -vw*cos(psiw - psi);
+ return vw*cos(psiw - psi);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
inline float GetVequivalentFPS(void) { return veas; }
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 FGColumnVector GetNpilot(void) { return vPilotAccel*INVGRAVITY; }
+ inline FGColumnVector3 GetNpilot(void) { return vPilotAccel*INVGRAVITY; }
inline float GetNpilot(int idx) { return (vPilotAccel*INVGRAVITY)(idx); }
inline float GetEarthPositionAngle(void) { return earthPosAngle; }
// (apeden@earthlink.net) or you can add it your self using the
// isentropic flow equations
- FGColumnVector vPilotAccel;
- FGColumnVector vToEyePt;
+ FGColumnVector3 vPilotAccel;
+ FGColumnVector3 vToEyePt;
float earthPosAngle;
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include "FGDefs.h"
#include "FGCoefficient.h"
#include "FGState.h"
#include "FGFDMExec.h"
#ifndef FGFS
-# include <iomanip>
+# if defined(sgi) && !defined(__GNUC__)
+# include <iomanip.h>
+# else
+# include <iomanip>
+# endif
#else
# include STL_IOMANIP
#endif
static const char *IdSrc = "$Id$";
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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
string FGCoefficient::GetCoefficientValues(void) {
char buffer[10];
string value;
- //value = ", ";
- snprintf(buffer,10,"%9.6f",SD);
- value += string(buffer);
+
+ sprintf(buffer,"%9.6f",SD);
+ value = string(buffer);
return value;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
#include "FGConfigFile.h"
#include "FGDefs.h"
#include "FGTable.h"
+#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGCoefficient
+class FGCoefficient : public FGJSBBase
{
public:
FGCoefficient(FGFDMExec*);
- ~FGCoefficient();
+ virtual ~FGCoefficient();
virtual bool Load(FGConfigFile* AC_cfg);
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_CONFIGFILE;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
SG_USING_STD(cout);
# endif
#else
-# include <fstream>
-# include <iostream>
# include <string>
- using std::string;
- using std::ostream;
- using std::istream;
- using std::ifstream;
- using std::ios;
- using std::cerr;
- using std::endl;
- using std::cout;
+# if defined(sgi) && !defined(__GNUC__)
+# include <fstream.h>
+# include <iostream.h>
+# else
+# include <fstream>
+# include <iostream>
+ using std::ostream;
+ using std::istream;
+ using std::ifstream;
+ using std::ios;
+ using std::cerr;
+ using std::endl;
+ using std::cout;
+# endif
+ using std::string;
#endif
#include "FGDefs.h"
+#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGConfigFile
+class FGConfigFile : public FGJSBBase
{
public:
/** Constructor
#ifndef FGDEFS_H
#define FGDEFS_H
-#define MAX_ENGINES 10
-#define MAX_TANKS 30
#define GRAVITY 32.174
#define INVGRAVITY 0.031081
#define EARTHRAD 20925650.00 // feet, equatorial
#define EARTHRADSQRD 437882827922500.0
#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 SHRATIO 1.4 //Specific Heat Ratio
#define RADTODEG 57.29578
#define INCHTOFT 0.08333333
#define OMEGA_EARTH .00007272205217
#define NEEDED_CFG_VERSION "1.40"
-#define JSBSIM_VERSION "0.8.6"
+#define JSBSIM_VERSION "0.8.7"
#define HPTOFTLBSSEC 550
#define METERS_TO_FEET 3.2808
FG_FLAPS_CMD,
FG_THROTTLE_CMD,
FG_THROTTLE_POS,
+ FG_MIXTURE_CMD,\r
+ FG_MIXTURE_POS,\r
FG_ACTIVE_ENGINE,
FG_HOVERB,
FG_PITCH_TRIM_CMD,
FG_LEFT_BRAKE_CMD,
FG_CENTER_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 {
# include <fstream.h>
# endif
#else
-# include <fstream>
+# if defined(sgi) && !defined(__GNUC__)
+# include <fstream.h>
+# else
+# include <fstream>
+# endif
#endif
#include "FGEngine.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ENGINE;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
Auxiliary = FDMExec->GetAuxiliary();
Output = FDMExec->GetOutput();
+ Mixture = 1.0; // FIXME: get actual value\r
Thrust = PctPower = 0.0;
Starved = Flameout = false;
Running = true;
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header: FGEngine.h
- Author: Jon S. Berndt
- Date started: 01/21/99
-
- ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
-
- 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
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- details.
-
- 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
- Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-
-Based on Flightgear code, which is based on LaRCSim. This class simulates
-a generic engine.
-
-HISTORY
---------------------------------------------------------------------------------
-01/21/99 JSB Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGENGINE_H
-#define FGENGINE_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-# include <simgear/compiler.h>
-# include STL_STRING
- SG_USING_STD(string);
-# ifdef SG_HAVE_STD_INCLUDES
-# include <vector>
-# else
-# include <vector.h>
-# endif
-#else
-# include <vector>
-# include <string>
-#endif
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_ENGINE "$Id$"
-
-using std::string;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGFDMExec;
-class FGState;
-class FGAtmosphere;
-class FGFCS;
-class FGAircraft;
-class FGTranslation;
-class FGRotation;
-class FGPropulsion;
-class FGPosition;
-class FGAuxiliary;
-class FGOutput;
-
-using std::vector;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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.
- @author Jon S. Berndt
- @version $Id$
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGEngine {
-public:
- FGEngine(FGFDMExec* exec);
- virtual ~FGEngine();
-
- enum EngineType {etUnknown, etRocket, etPiston, etTurboProp, etTurboJet, etTurboShaft};
-
- virtual float GetThrottleMin(void) { return MinThrottle; }
- virtual float GetThrottleMax(void) { return MaxThrottle; }
- float GetThrottle(void) { return Throttle; }
- float GetThrust(void) { return Thrust; }
- bool GetStarved(void) { return Starved; }
- bool GetFlameout(void) { return Flameout; }
- bool GetRunning(void) { return Running; }
- int GetType(void) { return Type; }
- string GetName(void) { return Name; }
-
- void SetStarved(bool tt) {Starved = tt;}
- void SetStarved(void) {Starved = true;}
-
- void SetRunning(bool bb) { Running=bb; }
- void SetName(string name) {Name = name;}
- void AddFeedTank(int tkID);
-
- /** Calculates the thrust of the engine, and other engine functions.
- @param PowerRequired this is the power required to run the thrusting device
- such as a propeller. This resisting effect must be provided to the
- engine model.
- @return Thrust in pounds */
- virtual float Calculate(float PowerRequired) {return 0.0;};
-
- /** Reduces the fuel in the active tanks by the amount required.
- This function should be called from within the
- derived class' Calculate() function before any other calculations are
- done. This base class method removes fuel from the fuel tanks as
- appropriate, and sets the starved flag if necessary. */
- void ConsumeFuel(void);
-
- /** The fuel need is calculated based on power levels and flow rate for that
- power level. It is also turned from a rate into an actual amount (pounds)
- by multiplying it by the delta T and the rate.
- @return Total fuel requirement for this engine in pounds. */
- float CalcFuelNeed(void);
-
- /** The oxidizer need is calculated based on power levels and flow rate for that
- power level. It is also turned from a rate into an actual amount (pounds)
- by multiplying it by the delta T and the rate.
- @return Total oxidizer requirement for this engine in pounds. */
- float CalcOxidizerNeed(void);
-
- /// Sets engine placement information
- void SetPlacement(float x, float y, float z, float pitch, float yaw);
-
- virtual float GetPowerAvailable(void) {return 0.0;};
-
- bool GetTrimMode(void) {return TrimMode;}
- void SetTrimMode(bool state) {TrimMode = state;}
-
-protected:
- string Name;
- EngineType Type;
- float X, Y, Z;
- float EnginePitch;
- float EngineYaw;
- float SLFuelFlowMax;
- float SLOxiFlowMax;
- float MaxThrottle;
- float MinThrottle;
-
- float Thrust;
- float Throttle;
- float FuelNeed, OxidizerNeed;
- bool Starved;
- bool Flameout;
- bool Running;
- float PctPower;
- int EngineNumber;
- bool TrimMode;
-
- FGFDMExec* FDMExec;
- FGState* State;
- FGAtmosphere* Atmosphere;
- 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
-
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+ Header: FGEngine.h\r
+ Author: Jon S. Berndt\r
+ Date started: 01/21/99\r
+\r
+ ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------\r
+\r
+ This program is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License as published by the Free Software\r
+ Foundation; either version 2 of the License, or (at your option) any later\r
+ version.\r
+\r
+ This program is distributed in the hope that it will be useful, but WITHOUT\r
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
+ details.\r
+\r
+ You should have received a copy of the GNU General Public License along with\r
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
+ Place - Suite 330, Boston, MA 02111-1307, USA.\r
+\r
+ Further information about the GNU General Public License can also be found on\r
+ the world wide web at http://www.gnu.org.\r
+\r
+FUNCTIONAL DESCRIPTION\r
+--------------------------------------------------------------------------------\r
+\r
+Based on Flightgear code, which is based on LaRCSim. This class simulates\r
+a generic engine.\r
+\r
+HISTORY\r
+--------------------------------------------------------------------------------\r
+01/21/99 JSB Created\r
+\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+SENTRY\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#ifndef FGENGINE_H\r
+#define FGENGINE_H\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+INCLUDES\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#ifdef FGFS\r
+# include <simgear/compiler.h>\r
+# include STL_STRING\r
+ SG_USING_STD(string);\r
+# ifdef SG_HAVE_STD_INCLUDES\r
+# include <vector>\r
+# else\r
+# include <vector.h>\r
+# endif\r
+#else\r
+# include <vector>\r
+# include <string>\r
+#endif\r
+\r
+#include "FGJSBBase.h"\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+DEFINITIONS\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#define ID_ENGINE "$Id$"\r
+\r
+using std::string;\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+FORWARD DECLARATIONS\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+class FGFDMExec;\r
+class FGState;\r
+class FGAtmosphere;\r
+class FGFCS;\r
+class FGAircraft;\r
+class FGTranslation;\r
+class FGRotation;\r
+class FGPropulsion;\r
+class FGPosition;\r
+class FGAuxiliary;\r
+class FGOutput;\r
+\r
+using std::vector;\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+CLASS DOCUMENTATION\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+/** Base class for all engines.\r
+ This base class contains methods and members common to all engines, such as\r
+ logic to drain fuel from the appropriate tank, etc.\r
+ @author Jon S. Berndt\r
+ @version $Id$ \r
+*/\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+CLASS DECLARATION\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+class FGEngine : public FGJSBBase\r
+{\r
+public:\r
+ FGEngine(FGFDMExec* exec);\r
+ virtual ~FGEngine();\r
+\r
+ enum EngineType {etUnknown, etRocket, etPiston, etTurboProp, etTurboJet, etTurboShaft};\r
+\r
+ virtual float GetThrottleMin(void) { return MinThrottle; }\r
+ virtual float GetThrottleMax(void) { return MaxThrottle; }\r
+ float GetThrottle(void) { return Throttle; }\r
+ float GetMixture(void) { return Mixture; }\r
+ float GetThrust(void) { return Thrust; }\r
+ bool GetStarved(void) { return Starved; }\r
+ bool GetFlameout(void) { return Flameout; }\r
+ bool GetRunning(void) { return Running; }\r
+ int GetType(void) { return Type; }\r
+ string GetName(void) { return Name; }\r
+\r
+ virtual float getManifoldPressure_inHg () const {\r
+ return ManifoldPressure_inHg;\r
+ }\r
+ virtual float getExhaustGasTemp_degF () const {\r
+ return (ExhaustGasTemp_degK - 273) * (9.0 / 5.0) + 32.0;\r
+ }\r
+ virtual float getCylinderHeadTemp_degF () const {\r
+ return (CylinderHeadTemp_degK - 273) * (9.0 / 5.0) + 32.0;\r
+ }\r
+ virtual float getOilPressure_psi () const {\r
+ return OilPressure_psi;\r
+ }\r
+ virtual float getOilTemp_degF () const {\r
+ return (OilTemp_degK - 273.0) * (9.0 / 5.0) + 32.0;\r
+ }\r
+\r
+ void SetStarved(bool tt) {Starved = tt;}\r
+ void SetStarved(void) {Starved = true;}\r
+\r
+ void SetRunning(bool bb) { Running=bb; }\r
+ void SetName(string name) {Name = name;}\r
+ void AddFeedTank(int tkID);\r
+\r
+ /** Calculates the thrust of the engine, and other engine functions.\r
+ @param PowerRequired this is the power required to run the thrusting device\r
+ such as a propeller. This resisting effect must be provided to the \r
+ engine model.\r
+ @return Thrust in pounds */\r
+ virtual float Calculate(float PowerRequired) {return 0.0;};\r
+\r
+ /** Reduces the fuel in the active tanks by the amount required.\r
+ This function should be called from within the\r
+ derived class' Calculate() function before any other calculations are\r
+ done. This base class method removes fuel from the fuel tanks as\r
+ appropriate, and sets the starved flag if necessary. */\r
+ void ConsumeFuel(void);\r
+\r
+ /** The fuel need is calculated based on power levels and flow rate for that\r
+ power level. It is also turned from a rate into an actual amount (pounds)\r
+ by multiplying it by the delta T and the rate.\r
+ @return Total fuel requirement for this engine in pounds. */\r
+ float CalcFuelNeed(void);\r
+\r
+ /** The oxidizer need is calculated based on power levels and flow rate for that\r
+ power level. It is also turned from a rate into an actual amount (pounds)\r
+ by multiplying it by the delta T and the rate.\r
+ @return Total oxidizer requirement for this engine in pounds. */\r
+ float CalcOxidizerNeed(void);\r
+\r
+ /// Sets engine placement information\r
+ void SetPlacement(float x, float y, float z, float pitch, float yaw);\r
+\r
+ virtual float GetPowerAvailable(void) {return 0.0;};\r
+\r
+ bool GetTrimMode(void) {return TrimMode;}\r
+ void SetTrimMode(bool state) {TrimMode = state;}\r
+\r
+protected:\r
+ string Name;\r
+ EngineType Type;\r
+ float X, Y, Z;\r
+ float EnginePitch;\r
+ float EngineYaw;\r
+ float SLFuelFlowMax;\r
+ float SLOxiFlowMax;\r
+ float MaxThrottle;\r
+ float MinThrottle;\r
+\r
+ float Thrust;\r
+ float Throttle;\r
+ float Mixture;\r
+ float FuelNeed, OxidizerNeed;\r
+ bool Starved;\r
+ bool Flameout;\r
+ bool Running;\r
+ float PctPower;\r
+ int EngineNumber;\r
+ bool TrimMode;\r
+\r
+ float ManifoldPressure_inHg;\r
+ float ExhaustGasTemp_degK;\r
+ float CylinderHeadTemp_degK;\r
+ float OilPressure_psi;\r
+ float OilTemp_degK;\r
+\r
+ FGFDMExec* FDMExec;\r
+ FGState* State;\r
+ FGAtmosphere* Atmosphere;\r
+ FGFCS* FCS;\r
+ FGPropulsion* Propulsion;\r
+ FGAircraft* Aircraft;\r
+ FGTranslation* Translation;\r
+ FGRotation* Rotation;\r
+ FGPosition* Position;\r
+ FGAuxiliary* Auxiliary;\r
+ FGOutput* Output;\r
+\r
+ vector <int> SourceTanks;\r
+ void Debug(void);\r
+};\r
+\r
+#include "FGState.h"\r
+#include "FGFDMExec.h"\r
+#include "FGAtmosphere.h"\r
+#include "FGFCS.h"\r
+#include "FGAircraft.h"\r
+#include "FGTranslation.h"\r
+#include "FGRotation.h"\r
+#include "FGPropulsion.h"\r
+#include "FGPosition.h"\r
+#include "FGAuxiliary.h"\r
+#include "FGOutput.h"\r
+#include "FGDefs.h"\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+#endif\r
+\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module: FGFCS.cpp
- Author: Jon Berndt
- Date started: 12/12/98
- Purpose: Model the flight controls
- Called by: FDMExec
-
- ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
-
- 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
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- details.
-
- 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
- Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-This class models the flight controls for a specific airplane
-
-HISTORY
---------------------------------------------------------------------------------
-12/12/98 JSB Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGDefs.h"
-
-#include "FGFCS.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-#include "FGAtmosphere.h"
-#include "FGAircraft.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGPosition.h"
-#include "FGAuxiliary.h"
-#include "FGOutput.h"
-
-#include "filtersjb/FGFilter.h"
-#include "filtersjb/FGDeadBand.h"
-#include "filtersjb/FGGain.h"
-#include "filtersjb/FGGradient.h"
-#include "filtersjb/FGSwitch.h"
-#include "filtersjb/FGSummer.h"
-#include "filtersjb/FGFlaps.h"
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_FCS;
-
-extern short debug_lvl;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)
-{
- Name = "FGFCS";
-
- DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = PTrimCmd = 0.0;
- DaPos = DePos = DrPos = DfPos = DsbPos = DspPos = 0.0;
- LeftBrake = RightBrake = CenterBrake = 0.0;
-
- if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGFCS::~FGFCS()
-{
- ThrottleCmd.clear();
- ThrottlePos.clear();
-
- unsigned int i;
-
- for(i=0;i<Components.size();i++) delete Components[i];
- if (debug_lvl & 2) cout << "Destroyed: FGFCS" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGFCS::Run(void)
-{
- unsigned int i;
-
- if (!FGModel::Run()) {
- for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
- for (i=0; i<Components.size(); i++) Components[i]->Run();
- } else {
- }
-
- return false;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFCS::SetThrottleCmd(int engineNum, float setting)
-{
- unsigned int ctr;
-
- if (engineNum < 0) {
- for (ctr=0;ctr<ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting;
- } else {
- ThrottleCmd[engineNum] = setting;
- }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFCS::SetThrottlePos(int engineNum, float setting)
-{
- unsigned int ctr;
-
- if (engineNum < 0) {
- for (ctr=0;ctr<=ThrottleCmd.size();ctr++) ThrottlePos[ctr] = ThrottleCmd[ctr];
- } else {
- ThrottlePos[engineNum] = setting;
- }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGFCS::Load(FGConfigFile* AC_cfg)
-{
- string token;
-
- Name = AC_cfg->GetValue("NAME");
- if (debug_lvl > 0) cout << " Control System Name: " << Name << endl;
- AC_cfg->GetNextConfigLine();
- while ((token = AC_cfg->GetValue()) != "/FLIGHT_CONTROL") {
- 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") ||
- (token == "LEAD_LAG_FILTER") ||
- (token == "SECOND_ORDER_FILTER") ||
- (token == "WASHOUT_FILTER") ||
- (token == "INTEGRATOR") ) {
- Components.push_back(new FGFilter(this, AC_cfg));
- } else if ((token == "PURE_GAIN") ||
- (token == "SCHEDULED_GAIN") ||
- (token == "AEROSURFACE_SCALE") ) {
-
- Components.push_back(new FGGain(this, AC_cfg));
-
- } 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));
- } else if (token == "SWITCH") {
- Components.push_back(new FGSwitch(this, AC_cfg));
- } else if (token == "FLAPS") {
- Components.push_back(new FGFlaps(this, AC_cfg));
- } else {
- cerr << "Unknown token [" << token << "] in FCS portion of config file" << endl;
- return false;
- }
- AC_cfg->GetNextConfigLine();
- }
- }
- return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-float FGFCS::GetComponentOutput(eParam idx) {
- return Components[idx]->GetOutput();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFCS::Debug(void)
-{
- //TODO: Add your source code here
-}
-
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+ \r
+ Module: FGFCS.cpp\r
+ Author: Jon Berndt\r
+ Date started: 12/12/98\r
+ Purpose: Model the flight controls\r
+ Called by: FDMExec\r
+ \r
+ ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------\r
+ \r
+ This program is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License as published by the Free Software\r
+ Foundation; either version 2 of the License, or (at your option) any later\r
+ version.\r
+ \r
+ This program is distributed in the hope that it will be useful, but WITHOUT\r
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
+ details.\r
+ \r
+ You should have received a copy of the GNU General Public License along with\r
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
+ Place - Suite 330, Boston, MA 02111-1307, USA.\r
+ \r
+ Further information about the GNU General Public License can also be found on\r
+ the world wide web at http://www.gnu.org.\r
+ \r
+FUNCTIONAL DESCRIPTION\r
+--------------------------------------------------------------------------------\r
+This class models the flight controls for a specific airplane\r
+ \r
+HISTORY\r
+--------------------------------------------------------------------------------\r
+12/12/98 JSB Created\r
+ \r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+INCLUDES\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#include "FGDefs.h"\r
+\r
+#include "FGFCS.h"\r
+#include "FGState.h"\r
+#include "FGFDMExec.h"\r
+#include "FGAtmosphere.h"\r
+#include "FGAircraft.h"\r
+#include "FGTranslation.h"\r
+#include "FGRotation.h"\r
+#include "FGPosition.h"\r
+#include "FGAuxiliary.h"\r
+#include "FGOutput.h"\r
+\r
+#include "filtersjb/FGFilter.h"\r
+#include "filtersjb/FGDeadBand.h"\r
+#include "filtersjb/FGGain.h"\r
+#include "filtersjb/FGGradient.h"\r
+#include "filtersjb/FGSwitch.h"\r
+#include "filtersjb/FGSummer.h"\r
+#include "filtersjb/FGFlaps.h"\r
+\r
+static const char *IdSrc = "$Id$";\r
+static const char *IdHdr = ID_FCS;\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+CLASS IMPLEMENTATION\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)\r
+{\r
+ Name = "FGFCS";\r
+\r
+ DaCmd = DeCmd = DrCmd = DfCmd = DsbCmd = DspCmd = PTrimCmd = 0.0;\r
+ DaPos = DePos = DrPos = DfPos = DsbPos = DspPos = 0.0;\r
+ LeftBrake = RightBrake = CenterBrake = 0.0;\r
+\r
+ if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+FGFCS::~FGFCS()\r
+{\r
+ ThrottleCmd.clear();\r
+ ThrottlePos.clear();\r
+ MixtureCmd.clear();\r
+ MixturePos.clear();\r
+\r
+ unsigned int i;\r
+\r
+ for(i=0;i<Components.size();i++) delete Components[i];\r
+ if (debug_lvl & 2) cout << "Destroyed: FGFCS" << endl;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+bool FGFCS::Run(void)\r
+{\r
+ unsigned int i;\r
+\r
+ if (!FGModel::Run()) {\r
+ for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];\r
+ for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];\r
+ for (i=0; i<Components.size(); i++) Components[i]->Run();\r
+ } else {\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGFCS::SetThrottleCmd(int engineNum, float setting)\r
+{\r
+ unsigned int ctr;\r
+\r
+ if ((int)ThrottleCmd.size() > engineNum) {\r
+ if (engineNum < 0) {\r
+ for (ctr=0;ctr<=ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting;\r
+ } else {\r
+ ThrottleCmd[engineNum] = setting;\r
+ }\r
+ } else {\r
+ cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()\r
+ << " engines exist, but attempted throttle command is for engine "\r
+ << engineNum << endl;\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGFCS::SetThrottlePos(int engineNum, float setting)\r
+{\r
+ unsigned int ctr;\r
+\r
+ if ((int)ThrottlePos.size() > engineNum) {\r
+ if (engineNum < 0) {\r
+ for (ctr=0;ctr<=ThrottlePos.size();ctr++) ThrottlePos[ctr] = setting;\r
+ } else {\r
+ ThrottlePos[engineNum] = setting;\r
+ }\r
+ } else {\r
+ cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()\r
+ << " engines exist, but attempted throttle position setting is for engine "\r
+ << engineNum << endl;\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+float FGFCS::GetThrottleCmd(int engineNum)\r
+{\r
+ if ((int)ThrottleCmd.size() > engineNum) {\r
+ if (engineNum < 0) {\r
+ cerr << "Cannot get throttle value for ALL engines" << endl;\r
+ } else {\r
+ return ThrottleCmd[engineNum];\r
+ }\r
+ } else {\r
+ cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()\r
+ << " engines exist, but throttle setting for engine " << engineNum\r
+ << " is selected" << endl;\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+float FGFCS::GetThrottlePos(int engineNum)\r
+{\r
+ if ((int)ThrottlePos.size() > engineNum) {\r
+ if (engineNum < 0) {\r
+ cerr << "Cannot get throttle value for ALL engines" << endl;\r
+ } else {\r
+ return ThrottlePos[engineNum];\r
+ }\r
+ } else {\r
+ cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()\r
+ << " engines exist, but attempted throttle position setting is for engine "\r
+ << engineNum << endl;\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGFCS::SetMixtureCmd(int engineNum, float setting)\r
+{\r
+ unsigned int ctr;\r
+\r
+ if (engineNum < 0) {\r
+ for (ctr=0;ctr<MixtureCmd.size();ctr++) MixtureCmd[ctr] = setting;\r
+ } else {\r
+ MixtureCmd[engineNum] = setting;\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGFCS::SetMixturePos(int engineNum, float setting)\r
+{\r
+ unsigned int ctr;\r
+\r
+ if (engineNum < 0) {\r
+ for (ctr=0;ctr<=MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr];\r
+ } else {\r
+ MixturePos[engineNum] = setting;\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+bool FGFCS::Load(FGConfigFile* AC_cfg)\r
+{\r
+ string token;\r
+\r
+ Name = Name + ":" + AC_cfg->GetValue("NAME");\r
+ if (debug_lvl > 0) cout << " Control System Name: " << Name << endl;\r
+ AC_cfg->GetNextConfigLine();\r
+ while ((token = AC_cfg->GetValue()) != "/FLIGHT_CONTROL") {\r
+ if (token == "COMPONENT") {\r
+ token = AC_cfg->GetValue("TYPE");\r
+ if (debug_lvl > 0) cout << " Loading Component \""\r
+ << AC_cfg->GetValue("NAME")\r
+ << "\" of type: " << token << endl;\r
+ if ((token == "LAG_FILTER") ||\r
+ (token == "LEAD_LAG_FILTER") ||\r
+ (token == "SECOND_ORDER_FILTER") ||\r
+ (token == "WASHOUT_FILTER") ||\r
+ (token == "INTEGRATOR") ) {\r
+ Components.push_back(new FGFilter(this, AC_cfg));\r
+ } else if ((token == "PURE_GAIN") ||\r
+ (token == "SCHEDULED_GAIN") ||\r
+ (token == "AEROSURFACE_SCALE") ) {\r
+\r
+ Components.push_back(new FGGain(this, AC_cfg));\r
+\r
+ } else if (token == "SUMMER") {\r
+ Components.push_back(new FGSummer(this, AC_cfg));\r
+ } else if (token == "DEADBAND") {\r
+ Components.push_back(new FGDeadBand(this, AC_cfg));\r
+ } else if (token == "GRADIENT") {\r
+ Components.push_back(new FGGradient(this, AC_cfg));\r
+ } else if (token == "SWITCH") {\r
+ Components.push_back(new FGSwitch(this, AC_cfg));\r
+ } else if (token == "FLAPS") {\r
+ Components.push_back(new FGFlaps(this, AC_cfg));\r
+ } else {\r
+ cerr << "Unknown token [" << token << "] in FCS portion of config file" << endl;\r
+ return false;\r
+ }\r
+ AC_cfg->GetNextConfigLine();\r
+ }\r
+ }\r
+ return true;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+float FGFCS::GetComponentOutput(eParam idx) {\r
+ return Components[idx]->GetOutput();\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+string FGFCS::GetComponentName(int idx) {\r
+ return Components[idx]->GetName();\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+float FGFCS::GetBrake(FGLGear::BrakeGroup bg) {\r
+ switch (bg) {\r
+ case FGLGear::bgLeft:\r
+ return LeftBrake;\r
+ case FGLGear::bgRight:\r
+ return RightBrake;\r
+ case FGLGear::bgCenter:\r
+ return CenterBrake;\r
+ default:\r
+ cerr << "GetBrake asked to return a bogus brake value" << endl;\r
+ }\r
+ return 0.0;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+string FGFCS::GetComponentStrings(void)\r
+{\r
+ unsigned int comp;\r
+\r
+ string CompStrings = "";\r
+ bool firstime = true;\r
+\r
+ for (comp = 0; comp < Components.size(); comp++) {\r
+ if (firstime) firstime = false;\r
+ else CompStrings += ", ";\r
+\r
+ CompStrings += Components[comp]->GetName();\r
+ }\r
+\r
+ return CompStrings;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+string FGFCS::GetComponentValues(void)\r
+{\r
+ unsigned int comp;\r
+\r
+ string CompValues = "";\r
+ char buffer[10];\r
+ bool firstime = true;\r
+\r
+ for (comp = 0; comp < Components.size(); comp++) {\r
+ if (firstime) firstime = false;\r
+ else CompValues += ", ";\r
+\r
+ sprintf(buffer, "%9.6f", Components[comp]->GetOutput());\r
+ CompValues += string(buffer);\r
+ }\r
+\r
+ return CompValues;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGFCS::AddThrottle(void)\r
+{\r
+ ThrottleCmd.push_back(0.0);\r
+ ThrottlePos.push_back(0.0);\r
+ MixtureCmd.push_back(0.0); // assume throttle and mixture are coupled\r
+ MixturePos.push_back(0.0);\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGFCS::Debug(void)\r
+{\r
+ //TODO: Add your source code here\r
+}\r
+\r
/** Gets the throttle command.
@param engine engine ID number
@return throttle command in percent ( 0 - 100) for the given engine */
- inline float GetThrottleCmd(int engine) { return ThrottleCmd[engine]; }
-
+ float GetThrottleCmd(int engine);\r
+\r
+ /** Gets the mixture command.\r
+ @param engine engine ID number\r
+ @return mixture command in percent ( 0 - 100) for the given engine */\r
+ inline float GetMixtureCmd(int engine) { return MixtureCmd[engine]; }\r
+\r
/** Gets the pitch trim command.
@return pitch trim command in radians */
inline float GetPitchTrimCmd(void) { return PTrimCmd; }
/** Gets the throttle position.
@param engine engine ID number
@return throttle position for the given engine in percent ( 0 - 100)*/
- inline float GetThrottlePos(int engine) { return ThrottlePos[engine]; }
+ float GetThrottlePos(int engine);\r
+\r
+ /** Gets the mixture position.\r
+ @param engine engine ID number\r
+ @return mixture position for the given engine in percent ( 0 - 100)*/\r
+ inline float GetMixturePos(int engine) { return MixturePos[engine]; }\r
//@}
/** Retrieves the State object pointer.
@param engine engine ID number
@param cmd throttle command in percent (0 - 100)*/
void SetThrottleCmd(int engine, float cmd);
+\r
+ /** Sets the mixture command for the specified engine\r
+ @param engine engine ID number\r
+ @param cmd mixture command in percent (0 - 100)*/\r
+ void SetMixtureCmd(int engine, float cmd);\r
//@}
/// @name Aerosurface position setting
@param engine engine ID number
@param cmd throttle setting in percent (0 - 100)*/
void SetThrottlePos(int engine, float cmd);
+\r
+ /** Sets the actual mixture setting for the specified engine\r
+ @param engine engine ID number\r
+ @param cmd mixture setting in percent (0 - 100)*/\r
+ void SetMixturePos(int engine, float cmd);\r
//@}
/// @name Landing Gear brakes
float PTrimCmd;
vector <float> ThrottleCmd;
vector <float> ThrottlePos;
+ vector <float> MixtureCmd;\r
+ vector <float> MixturePos;\r
float LeftBrake, RightBrake, CenterBrake; // Brake settings
vector <FGFCSComponent*> Components;
# include STL_IOSTREAM
# include STL_ITERATOR
#else
-# include <iostream>
-# include <ctime>
+# if defined(sgi) && !defined(__GNUC__)
+# include <iostream.h>
+# include <time.h>
+# else
+# include <iostream>
+# include <ctime>
+# endif
# include <iterator>
#endif
#include "FGFCS.h"
#include "FGPropulsion.h"
#include "FGMassBalance.h"
+#include "FGGroundReactions.h"
#include "FGAerodynamics.h"
#include "FGInertial.h"
#include "FGAircraft.h"
static const char *IdSrc = "$Id$";
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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGFDMExec::FGFDMExec(void)
{
- Frame = 0;
- FirstModel = 0;
- Error = 0;
- State = 0;
- Atmosphere = 0;
- FCS = 0;
- Propulsion = 0;
- MassBalance = 0;
- Aerodynamics = 0;
- Inertial = 0;
- Aircraft = 0;
- Translation = 0;
- Rotation = 0;
- Position = 0;
- Auxiliary = 0;
- Output = 0;
+ Frame = 0;
+ FirstModel = 0;
+ Error = 0;
+ State = 0;
+ Atmosphere = 0;
+ FCS = 0;
+ Propulsion = 0;
+ MassBalance = 0;
+ Aerodynamics = 0;
+ Inertial = 0;
+ GroundReactions = 0;
+ Aircraft = 0;
+ Translation = 0;
+ Rotation = 0;
+ Position = 0;
+ Auxiliary = 0;
+ Output = 0;
terminate = false;
frozen = false;
bool result=true;
- Atmosphere = new FGAtmosphere(this);
- FCS = new FGFCS(this);
- Propulsion = new FGPropulsion(this);
- MassBalance = new FGMassBalance(this);
- Aerodynamics = new FGAerodynamics (this);
- Inertial = new FGInertial(this);
- Aircraft = new FGAircraft(this);
- Translation = new FGTranslation(this);
- Rotation = new FGRotation(this);
- Position = new FGPosition(this);
- Auxiliary = new FGAuxiliary(this);
- Output = new FGOutput(this);
+ Atmosphere = new FGAtmosphere(this);
+ FCS = new FGFCS(this);
+ Propulsion = new FGPropulsion(this);
+ MassBalance = new FGMassBalance(this);
+ Aerodynamics = new FGAerodynamics (this);
+ Inertial = new FGInertial(this);
+ GroundReactions = new FGGroundReactions(this);
+ Aircraft = new FGAircraft(this);
+ Translation = new FGTranslation(this);
+ Rotation = new FGRotation(this);
+ Position = new FGPosition(this);
+ Auxiliary = new FGAuxiliary(this);
+ Output = new FGOutput(this);
State = new FGState(this); // This must be done here, as the FGState
// class needs valid pointers to the above
- // model classes
-
+ // model classes
+
// Initialize models so they can communicate with each other
if (!Atmosphere->InitModel()) {
if (!Inertial->InitModel()) {
cerr << fgred << "FGInertial model init failed" << fgdef << endl;
Error+=32;}
+ if (!GroundReactions->InitModel()) {
+ cerr << fgred << "Ground Reactions model init failed" << fgdef << endl;
+ Error+=64;}
if (!Aircraft->InitModel()) {
cerr << fgred << "Aircraft model init failed" << fgdef << endl;
- Error+=64;}
+ Error+=128;}
if (!Translation->InitModel()){
cerr << fgred << "Translation model init failed" << fgdef << endl;
- Error+=128;}
+ Error+=256;}
if (!Rotation->InitModel()) {
cerr << fgred << "Rotation model init failed" << fgdef << endl;
- Error+=256;}
+ Error+=512;}
if (!Position->InitModel()) {
cerr << fgred << "Position model init failed" << fgdef << endl;
- Error+=512;}
+ Error+=1024;}
if (!Auxiliary->InitModel()) {
cerr << fgred << "Auxiliary model init failed" << fgdef << endl;
- Error+=1024;}
+ Error+=2058;}
if (!Output->InitModel()) {
cerr << fgred << "Output model init failed" << fgdef << endl;
- Error+=2048;}
+ Error+=4096;}
if (Error > 0) result = false;
// instance, the atmosphere model gets executed every fifth pass it is called
// by the executive. Everything else here gets executed each pass.
- Schedule(Atmosphere, 1);
- Schedule(FCS, 1);
- Schedule(Propulsion, 1);
- Schedule(MassBalance, 1);
- Schedule(Aerodynamics, 1);
- Schedule(Inertial, 1);
- Schedule(Aircraft, 1);
- Schedule(Rotation, 1);
- Schedule(Translation, 1);
- Schedule(Position, 1);
- Schedule(Auxiliary, 1);
- Schedule(Output, 1);
+ Schedule(Atmosphere, 1);
+ Schedule(FCS, 1);
+ Schedule(Propulsion, 1);
+ Schedule(MassBalance, 1);
+ Schedule(Aerodynamics, 1);
+ Schedule(Inertial, 1);
+ Schedule(GroundReactions, 1);
+ Schedule(Aircraft, 1);
+ Schedule(Rotation, 1);
+ Schedule(Translation, 1);
+ Schedule(Position, 1);
+ Schedule(Auxiliary, 1);
+ Schedule(Output, 1);
modelLoaded = false;
bool FGFDMExec::DeAllocate(void) {
- if ( Atmosphere != 0 ) delete Atmosphere;
- if ( FCS != 0 ) delete FCS;
- if ( Propulsion != 0) delete Propulsion;
- if ( MassBalance != 0) delete MassBalance;
- if ( Aerodynamics != 0) delete Aerodynamics;
- if ( Inertial != 0) delete Inertial;
- if ( Aircraft != 0 ) delete Aircraft;
- if ( Translation != 0 ) delete Translation;
- if ( Rotation != 0 ) delete Rotation;
- if ( Position != 0 ) delete Position;
- if ( Auxiliary != 0 ) delete Auxiliary;
- if ( Output != 0 ) delete Output;
- if ( State != 0 ) delete State;
+ if ( Atmosphere != 0 ) delete Atmosphere;
+ if ( FCS != 0 ) delete FCS;
+ if ( Propulsion != 0) delete Propulsion;
+ if ( MassBalance != 0) delete MassBalance;
+ if ( Aerodynamics != 0) delete Aerodynamics;
+ if ( Inertial != 0) delete Inertial;
+ if ( GroundReactions != 0) delete GroundReactions;
+ if ( Aircraft != 0 ) delete Aircraft;
+ if ( Translation != 0 ) delete Translation;
+ if ( Rotation != 0 ) delete Rotation;
+ if ( Position != 0 ) delete Position;
+ if ( Auxiliary != 0 ) delete Auxiliary;
+ if ( Output != 0 ) delete Output;
+ if ( State != 0 ) delete State;
FirstModel = 0L;
Error = 0;
- State = 0;
- Atmosphere = 0;
- FCS = 0;
- Propulsion = 0;
- MassBalance = 0;
- Aerodynamics = 0;
- Inertial = 0;
- Aircraft = 0;
- Translation = 0;
- Rotation = 0;
- Position = 0;
- Auxiliary = 0;
- Output = 0;
+ State = 0;
+ Atmosphere = 0;
+ FCS = 0;
+ Propulsion = 0;
+ MassBalance = 0;
+ Aerodynamics = 0;
+ Inertial = 0;
+ GroundReactions = 0;
+ Aircraft = 0;
+ Translation = 0;
+ Rotation = 0;
+ Position = 0;
+ Auxiliary = 0;
+ Output = 0;
modelLoaded = false;
return modelLoaded;
exit(-1);
}
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;
}
#include "FGModel.h"
#include "FGInitialCondition.h"
+#include "FGJSBBase.h"
#include <vector>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class FGMassBalance;
class FGAerodynamics;
class FGInertial;
+class FGGroundReactions;
class FGAircraft;
class FGTranslation;
class FGRotation;
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGFDMExec
+class FGFDMExec : public FGJSBBase
{
public:
/// Default constructor
inline FGAerodynamics* GetAerodynamics(void){return Aerodynamics;}
/// Returns the FGInertial pointer.
inline FGInertial* GetInertial(void) {return Inertial;}
+ /// Returns the FGGroundReactions pointer.
+ inline FGGroundReactions* GetGroundReactions(void) {return GroundReactions;}
/// Returns the FGAircraft pointer.
inline FGAircraft* GetAircraft(void) {return Aircraft;}
/// Returns the FGTranslation pointer.
float EndTime;
vector <struct condition> Conditions;
- FGState* State;
- FGAtmosphere* Atmosphere;
- FGFCS* FCS;
- FGPropulsion* Propulsion;
- FGMassBalance* MassBalance;
- FGAerodynamics* Aerodynamics;
- FGInertial* Inertial;
- FGAircraft* Aircraft;
- FGTranslation* Translation;
- FGRotation* Rotation;
- FGPosition* Position;
- FGAuxiliary* Auxiliary;
- FGOutput* Output;
+ FGState* State;
+ FGAtmosphere* Atmosphere;
+ FGFCS* FCS;
+ FGPropulsion* Propulsion;
+ FGMassBalance* MassBalance;
+ FGAerodynamics* Aerodynamics;
+ FGInertial* Inertial;
+ FGGroundReactions* GroundReactions;
+ FGAircraft* Aircraft;
+ FGTranslation* Translation;
+ FGRotation* Rotation;
+ FGPosition* Position;
+ FGAuxiliary* Auxiliary;
+ FGOutput* Output;
bool Allocate(void);
bool DeAllocate(void);
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include "FGDefs.h"
#include "FGCoefficient.h"
#include "FGFactorGroup.h"
#include "FGState.h"
#include "FGFDMExec.h"
#ifndef FGFS
-# include <iomanip>
+# if defined(sgi) && !defined(__GNUC__)
+# include <iomanip.h>
+# else
+# include <iomanip>
+# endif
#else
# include STL_IOMANIP
#endif
-extern short debug_lvl;
-
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FACTORGROUP;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-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)
{
cout << "FGCoefficient::GetSD(): " << FGCoefficient::GetSD() << endl;
bool Load(FGConfigFile *AC_cfg);
float TotalValue(void);
- string GetCoefficientStrings(void);
- string GetCoefficientValues(void);
+ //string GetCoefficientStrings(void);
+ //string GetCoefficientValues(void);
inline float GetSD(void) { return SDtotal; }
inline float GetFactorSD(void) { return FGCoefficient::GetSD(); }
#include "FGFDMExec.h"
#include "FGAircraft.h"
#include "FGTranslation.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
#include "FGDefs.h"
#include "FGForce.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FORCE;
-extern short debug_lvl;
-
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGForce::FGForce(FGFDMExec *FDMExec) :
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGColumnVector FGForce::GetBodyForces(void) {
+FGColumnVector3& FGForce::GetBodyForces(void) {
vFb=Transform()*(vFn.multElementWise(vSense));
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGMatrix FGForce::Transform(void) {
+FGMatrix33 FGForce::Transform(void) {
switch(ttype) {
case tWindBody:
return fdmex->GetState()->GetTs2b(fdmex->GetTranslation()->Getalpha(),fdmex->GetTranslation()->Getbeta());
#define ID_FORCE "$Id$"
#include "FGFDMExec.h"
-#include "FGMatrix.h"
+#include "FGJSBBase.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
+COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGForce {
+/** 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>
-public:
+<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 FGForce : public FGJSBBase
+{
+public:
+ /// Constructor
FGForce(FGFDMExec *FDMExec);
+ /// Destructor
~FGForce();
enum TransformType { tNone, tWindBody, tLocalBody, tCustom } ttype;
vFn(2)=Fny;
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) {
vMn(1)=Ln;
vMn(2)=Mn;
vMn(3)=Nn;
}
- inline void SetNativeMoments(FGColumnVector vv) { vMn = vv; }
+ inline void SetNativeMoments(FGColumnVector3 vv) { vMn = vv; }
- inline FGColumnVector GetNativeForces(void) { return vFn; }
- inline FGColumnVector GetNativeMoments(void) { return vMn; }
+ inline FGColumnVector3& GetNativeForces(void) { return vFn; }
+ 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
//(inches, x +back, y +right, z +up)
vXYZn(2) = y;
vXYZn(3) = z;
}
- inline void SetLocation(FGColumnVector vv) { vXYZn = vv; }
- FGColumnVector GetLocation(void) { return vXYZn; }
+ inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; }
+ FGColumnVector3& GetLocation(void) { return vXYZn; }
//these angles are relative to body axes, not earth!!!!!
//I'm using these because pitch, roll, and yaw are easy to visualize,
//They are in radians.
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(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 TransformType GetTransformType(void) { return ttype; }
- FGMatrix Transform(void);
+ FGMatrix33 Transform(void);
protected:
- FGColumnVector vFn;
- FGColumnVector vMn;
+ FGColumnVector3 vFn;
+ FGColumnVector3 vMn;
FGFDMExec *fdmex;
- void Debug(void);
+ virtual void Debug(void);
private:
- FGColumnVector vFb;
- FGColumnVector vM;
- FGColumnVector vXYZn;
- FGColumnVector vDXYZ;
- FGColumnVector vSense;
+ FGColumnVector3 vFb;
+ FGColumnVector3 vM;
+ FGColumnVector3 vXYZn;
+ FGColumnVector3 vDXYZ;
+ FGColumnVector3 vSense;
- FGMatrix mT;
+ FGMatrix33 mT;
};
#endif
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_GROUNDREACTIONS;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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()) {
+ 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;
} else {
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;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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)
{
//TODO: Add your source code here
#include "FGModel.h"
#include "FGConfigFile.h"
+#include "FGLGear.h"
+#include "FGInertial.h"
+#include "FGMatrix33.h"
#define ID_GROUNDREACTIONS "$Id$"
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGGroundReactions : public FGModel {
-
+class FGGroundReactions : public FGModel
+{
public:
FGGroundReactions(FGFDMExec*);
- ~FGGroundReactions();
+ ~FGGroundReactions() {};
bool Run(void);
bool Load(FGConfigFile* AC_cfg);
+ FGColumnVector3& GetForces(void) {return vForces;}
+ FGColumnVector3& GetMoments(void) {return vMoments;}
+ string GetGroundReactionStrings(void);
+ string GetGroundReactionValues(void);
private:
+ vector <FGLGear> lGear;
+ bool GearUp;
+ FGColumnVector3 vForces;
+ FGColumnVector3 vMoments;
+ FGColumnVector3 vMaxStaticGrip;
+ FGColumnVector3 vMaxMomentResist;
+
void Debug(void);
};
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_INERTIAL;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex),
vForces(3),
vOmegaLocal(3),
- vRadius(3)
+ vRadius(3),
+ vGravity(3)
{
Name = "FGInertial";
sphi = sin(Rotation->GetEuler(ePhi));
cphi = cos(Rotation->GetEuler(ePhi));
- vForces(eX) = -GRAVITY*stht;
- vForces(eY) = GRAVITY*sphi*ctht;
- vForces(eZ) = GRAVITY*cphi*ctht;
+ vGravity(eX) = vForces(eX) = -GRAVITY*stht;
+ vGravity(eY) = vForces(eY) = GRAVITY*sphi*ctht;
+ vGravity(eZ) = vForces(eZ) = GRAVITY*cphi*ctht;
// The following equation for vOmegaLocal terms shows the angular velocity
// calculation _for_the_local_frame_ given the earth's rotation (first set)
#include "FGModel.h"
#include "FGConfigFile.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
#define ID_INERTIAL "$Id$"
~FGInertial(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);
private:
void Debug(void);
- FGColumnVector vOmegaLocal;
- FGColumnVector vForces;
- FGColumnVector vRadius;
+ FGColumnVector3 vOmegaLocal;
+ FGColumnVector3 vForces;
+ FGColumnVector3 vRadius;
+ FGColumnVector3 vGravity;
};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#include "FGAuxiliary.h"
#include "FGOutput.h"
#include "FGDefs.h"
+#include "FGConfigFile.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_INITIALCONDITION;
-extern short debug_lvl;
-
//******************************************************************************
FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec){
altitude=hdot=0;
latitude=longitude=0;
u=v=w=0;
- vw=vw=ww=0;
+ uw=vw=ww=0;
vnorth=veast=vdown=0;
+ wnorth=weast=wdown=0;
+ whead=wcross=0;
+ wdir=wmag=0;
lastSpeedSet=setvt;
+ lastWindSet=setwned;
sea_level_radius = EARTHRAD;
radius_to_vehicle = EARTHRAD;
terrain_altitude = 0;
+
salpha=sbeta=stheta=sphi=spsi=sgamma=0;
calpha=cbeta=ctheta=cphi=cpsi=cgamma=1;
//******************************************************************************
void FGInitialCondition::SetVgroundFpsIC(float tt) {
- //float ua,va,wa;
+ float ua,va,wa;
float vxz;
- //cout << "FGInitialCondition::SetVgroundFpsIC" << endl;
vg=tt;
lastSpeedSet=setvg;
vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0;
calcUVWfromNED();
- //cout << "\tu,v,w: " << u << ", " << v << ", " << w << endl;
- calcWindUVW();
- //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 );
+ ua = u + uw; va = v + vw; wa = w + ww;
+ vt = sqrt( ua*ua + va*va + wa*wa );
alpha = beta = 0;
vxz = sqrt( u*u + w*w );
if( w != 0 ) alpha = atan2( w, u );
if( vxz != 0 ) beta = atan2( v, vxz );
- //cout << "\tvt,alpha,beta: " << vt << ", " << alpha*RADTODEG << ", "
- // << beta*RADTODEG << endl;
mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
vc=calcVcas(mach);
ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
void FGInitialCondition::SetPitchAngleRadIC(float tt) {
theta=tt;
stheta=sin(theta); ctheta=cos(theta);
- calcWindUVW();
getAlpha();
}
beta=tt;
sbeta=sin(beta); cbeta=cos(beta);
getTheta();
+
}
//******************************************************************************
if(lastSpeedSet == setvg )
return u;
else
- return vt*calpha*cbeta;
+ return vt*calpha*cbeta - uw;
}
//******************************************************************************
float FGInitialCondition::GetVBodyFpsIC(void) {
if( lastSpeedSet == setvg )
return v;
- else
- return vt*sbeta;
+ else {
+ return vt*sbeta - vw;
+ }
}
//******************************************************************************
float FGInitialCondition::GetWBodyFpsIC(void) {
if( lastSpeedSet == setvg )
return w;
- else {
- return vt*salpha*cbeta;
- }
+ else
+ return vt*salpha*cbeta -ww;
}
//******************************************************************************
void FGInitialCondition::SetWindNEDFpsIC(float wN, float wE, float wD ) {
wnorth = wN; weast = wE; wdown = wD;
+ lastWindSet = setwned;
+ calcWindUVW();
if(lastSpeedSet == setvg)
SetVgroundFpsIC(vg);
+}
+
+//******************************************************************************
+
+// positive from left
+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) {
- if(lastSpeedSet == setvg ) {
-
+
+ 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 +
weast*ctheta*spsi -
wdown*stheta;
ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) +
weast*(cphi*stheta*spsi - sphi*cpsi) +
wdown*cphi*ctheta;
+
+
/* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown "
<< wnorth << ", " << weast << ", " << wdown << endl;
cout << "FGInitialCondition::calcWindUVW: theta, phi, psi "
cout << "FGInitialCondition::calcWindUVW: uw, vw, ww "
<< uw << ", " << vw << ", " << ww << endl; */
- } else {
- uw=vw=ww=0;
- }
}
//******************************************************************************
altitude=tt;
fdmex->GetPosition()->Seth(altitude);
fdmex->GetAtmosphere()->Run();
-
//lets try to make sure the user gets what they intended
switch(lastSpeedSet) {
void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) {
terrain_altitude=tt;
- fdmex->GetPosition()->SetDistanceAGL(altitude-terrain_altitude);
- fdmex->GetPosition()->SetRunwayRadius(sea_level_radius + terrain_altitude);
}
//******************************************************************************
calpha=cos(alpha);
}
}
+ calcWindUVW();
return result;
}
ctheta=cos(theta);
}
}
+ calcWindUVW();
return result;
}
//******************************************************************************
-bool FGInitialCondition::solve(float *y,float x) {
+bool FGInitialCondition::solve(float *y,float x)
+{
float x1,x2,x3,f1,f2,f3,d,d0;
float eps=1E-5;
float const relax =0.9;
int i;
bool success=false;
- //initializations
+ //initializations
d=1;
- x1=xlo;x3=xhi;
- f1=(this->*sfunc)(x1)-x;
- f3=(this->*sfunc)(x3)-x;
- d0=fabs(x3-x1);
-
- //iterations
- i=0;
- while ((fabs(d) > eps) && (i < 100)) {
- d=(x3-x1)/d0;
- x2=x1-d*d0*f1/(f3-f1);
-
- f2=(this->*sfunc)(x2)-x;
- //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl;
- //cout << " " << f1 << "," << f2 << "," << f3 << endl;
-
- if(fabs(f2) <= 0.001) {
- x1=x3=x2;
- } else if(f1*f2 <= 0.0) {
- x3=x2;
- f3=f2;
- f1=relax*f1;
- } else if(f2*f3 <= 0) {
- x1=x2;
- f1=f2;
- f3=relax*f3;
- }
- //cout << i << endl;
- i++;
- }//end while
- if(i < 100) {
- success=true;
- *y=x2;
+ x1=xlo;x3=xhi;
+ f1=(this->*sfunc)(x1)-x;
+ f3=(this->*sfunc)(x3)-x;
+ d0=fabs(x3-x1);
+
+ //iterations
+ i=0;
+ while ((fabs(d) > eps) && (i < 100)) {
+ d=(x3-x1)/d0;
+ x2=x1-d*d0*f1/(f3-f1);
+
+ f2=(this->*sfunc)(x2)-x;
+ //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl;
+ //cout << " " << f1 << "," << f2 << "," << f3 << endl;
+
+ if(fabs(f2) <= 0.001) {
+ x1=x3=x2;
+ } else if(f1*f2 <= 0.0) {
+ x3=x2;
+ f3=f2;
+ f1=relax*f1;
+ } else if(f2*f3 <= 0) {
+ x1=x2;
+ f1=f2;
+ f3=relax*f3;
}
+ //cout << i << endl;
+ i++;
+ }//end while
+ if(i < 100) {
+ success=true;
+ *y=x2;
+ }
//cout << "Success= " << success << " Vcas: " << vcas*jsbFPSTOKTS << " Mach: " << x2 << endl;
return success;
//******************************************************************************
-void FGInitialCondition::Debug(void)
+float FGInitialCondition::GetWindDirDegIC(void) {
+ if(weast != 0.0)
+ 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)
{
- //TODO: Add your source code here
-}
+ 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;
+}
Further information about the GNU General Public License can also be found on
the world wide web at http://www.gnu.org.
-
HISTORY
--------------------------------------------------------------------------------
7/1/99 TP Created
-
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
*******************************************************************************/
#include "FGFDMExec.h"
+#include "FGJSBBase.h"
#include "FGAtmosphere.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
-#define ID_INITIALCONDITION "$Id$"
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-/*******************************************************************************
-CLASS DECLARATION
-*******************************************************************************/
+#define ID_INITIALCONDITION "$Id$"
+#define jsbFPSTOKTS 0.5924838
+#define jsbKTSTOFPS 1.6878099
typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
+typedef enum { setwned, setwmd, setwhc } windset;
-#define jsbFPSTOKTS 0.5924838
-#define jsbKTSTOFPS 1.6878099
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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
FGInitialCondition fgic=new FGInitialCondition(FDMExec);
fgic->SetVcalibratedKtsIC()
FDMExec->RunIC(fgic)
Speed:
+
Since vc, ve, vt, and mach all represent speed, the remaining
three are recalculated each time one of them is set (using the
current altitude). The most recent speed set is remembered so
most recent speed set.
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
specifies the third gamma (flight path angle) is favored when setting
alpha and theta and alpha is favored when setting gamma. i.e.
+
set alpha : recalculate theta using gamma as currently set
set theta : recalculate alpha using gamma as currently set
set gamma : recalculate theta using alpha as currently set
Setting climb rate is, for the purpose of this discussion,
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);
+ /// Destructor
~FGInitialCondition();
void SetVcalibratedKtsIC(float tt);
void SetVnorthFpsIC(float tt);
void SetVeastFpsIC(float tt);
void SetVdownFpsIC(float tt);
+
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);
inline float GetVgroundFpsIC(void) { return vg; }
inline float GetVtrueFpsIC(void) { return vt; }
inline float GetWindNFpsIC(void) { return wnorth; }
inline float GetWindEFpsIC(void) { return weast; }
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; }
float GetUBodyFpsIC(void);
float GetVBodyFpsIC(void);
inline float GetPsiRadIC(void) { return psi; }
inline speedset GetSpeedSet(void) { return lastSpeedSet; }
+ inline windset GetWindSet(void) { return lastWindSet; }
+
+ bool Load(string path, string acname, string fname);
private:
float vt,vc,ve,vg;
float uw,vw,ww;
float vnorth,veast,vdown;
float wnorth,weast,wdown;
+ float whead, wcross, wdir, wmag;
double sea_level_radius;
double terrain_altitude;
double radius_to_vehicle;
fp sfunc;
speedset lastSpeedSet;
+ windset lastWindSet;
FGFDMExec *fdmex;
bool findInterval(float x,float guess);
bool solve(float *y, float x);
- void Debug(void);
};
#endif
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_LGEAR;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : vXYZ(3),
vMoment(3),
vWhlBodyVec(3),
+ vForce(3),
+ vLocalForce(3),
+ vWhlVelVec(3),
Exec(fdmex)
{
string tmp;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGColumnVector FGLGear::Force(void)
+FGColumnVector3& FGLGear::Force(void)
{
- float SteerGain, SteerAngle, BrakeFCoeff;
+ float SteerGain;
float SinWheel, CosWheel, SideWhlVel, RollingWhlVel;
float RudderPedal, RollingForce, SideForce, FCoeff;
float WheelSlip;
- FGColumnVector vForce(3);
- FGColumnVector vLocalForce(3);
- FGColumnVector vWhlVelVec(3); // Velocity of this wheel (Local)
-
vWhlBodyVec = (vXYZ - MassBalance->GetXYZcg()) / 12.0;
vWhlBodyVec(eX) = -vWhlBodyVec(eX);
vWhlBodyVec(eZ) = -vWhlBodyVec(eZ);
// wheel velocity.
vWhlVelVec = State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);
+
vWhlVelVec += Position->GetVel();
compressSpeed = vWhlVelVec(eZ);
switch (eBrakeGrp) {
case bgLeft:
- SteerGain = -maxSteerAngle;
+ SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
staticFCoeff*FCS->GetBrake(bgLeft);
break;
case bgRight:
- SteerGain = -maxSteerAngle;
+ SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
staticFCoeff*FCS->GetBrake(bgRight);
break;
case bgCenter:
- SteerGain = -maxSteerAngle;
+ SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
staticFCoeff*FCS->GetBrake(bgCenter);
break;
case bgNose:
- SteerGain = maxSteerAngle;
+ SteerGain = 0.10;
BrakeFCoeff = rollingFCoeff;
break;
case bgTail:
- SteerGain = -maxSteerAngle;
+ SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff;
break;
case bgNone:
- SteerGain = -maxSteerAngle;
+ SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff;
break;
default:
switch (eSteerType) {
case stSteer:
- SteerAngle = SteerGain*FCS->GetDrCmd();
+ SteerAngle = SteerGain*FCS->GetDrPos();
break;
case stFixed:
SteerAngle = 0.0;
// 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.
- SinWheel = sin(Rotation->Getpsi() + SteerAngle*DEGTORAD);
- CosWheel = cos(Rotation->Getpsi() + SteerAngle*DEGTORAD);
+ SinWheel = sin(Rotation->Getpsi() + SteerAngle);
+ CosWheel = cos(Rotation->Getpsi() + SteerAngle);
RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;
SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;
#include <string>
#include "FGConfigFile.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
#include "FGFDMExec.h"
+#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGLGear
+class FGLGear : public FGJSBBase
{
public:
/// Brake grouping enumerators
/// The Force vector for this gear
- FGColumnVector Force(void);
+ FGColumnVector3& Force(void);
/// 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
- FGColumnVector GetBodyLocation(void) { return vWhlBodyVec; }
+ FGColumnVector3& GetBodyLocation(void) { return vWhlBodyVec; }
float GetBodyLocation(int idx) { return vWhlBodyVec(idx); }
- FGColumnVector GetLocalGear(void) { return vLocalGear; }
+ FGColumnVector3& GetLocalGear(void) { return vLocalGear; }
float GetLocalGear(int idx) { return vLocalGear(idx); }
/// Gets the name of the gear
inline float GetCompVel(void) {return compressSpeed; }
/// Gets the gear compression force in pounds
inline float GetCompForce(void) {return Force()(3); }
+ inline float GetBrakeFCoeff(void) {return BrakeFCoeff;}
/// Sets the brake value in percent (0 - 100)
inline void SetBrake(double bp) {brakePct = bp;}
/** Get the console touchdown reporting feature
@return true if reporting is turned on */
inline bool GetReport(void) { return ReportEnable; }
+ inline float GetSteerAngle(void) { return SteerAngle;}
+ inline float GetstaticFCoeff(void) { return staticFCoeff;}
private:
- enum {eX=1, eY, eZ};
- FGColumnVector vXYZ;
- FGColumnVector vMoment;
- FGColumnVector vWhlBodyVec;
- FGColumnVector vLocalGear;
+ FGColumnVector3 vXYZ;
+ FGColumnVector3 vMoment;
+ FGColumnVector3 vWhlBodyVec;
+ FGColumnVector3 vLocalGear;
+ FGColumnVector3 vForce;
+ FGColumnVector3 vLocalForce;
+ FGColumnVector3 vWhlVelVec; // Velocity of this wheel (Local)
+ float SteerAngle;
float kSpring;
float bDamp;
float compressLength;
float compressSpeed;
float staticFCoeff, dynamicFCoeff, rollingFCoeff;
float brakePct;
+ float BrakeFCoeff;
float maxCompLen;
double SinkRate;
double GroundSpeed;
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_MASSBALANCE;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
inline float GetIzz(void) {return Izz;}
inline float GetIxz(void) {return Ixz;}
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 void SetEmptyWeight(float EW) { EmptyWeight = EW;}
inline void SetBaseIzz(float bizz) { baseIzz = bizz;}
inline void SetBaseIxz(float bixz) { baseIxz = bixz;}
inline void SetBaseIyz(float biyz) { baseIyz = biyz;}
- inline void SetBaseCG(const FGColumnVector& CG) {vbaseXYZcg = CG;}
+ inline void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = CG;}
private:
float Weight;
float baseIzz;
float baseIxz;
float baseIyz;
- FGColumnVector vXYZcg;
- FGColumnVector vXYZtank;
- FGColumnVector vbaseXYZcg;
+ FGColumnVector3 vXYZcg;
+ FGColumnVector3 vXYZtank;
+ FGColumnVector3 vbaseXYZcg;
void Debug(void);
};
#include "FGMassBalance.h"
#include "FGAerodynamics.h"
#include "FGInertial.h"
+#include "FGGroundReactions.h"
#include "FGAircraft.h"
#include "FGTranslation.h"
#include "FGRotation.h"
GLOBAL DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FDMExec = fdmex;
NextModel = 0L;
- State = 0;
- Atmosphere = 0;
- FCS = 0;
- Propulsion = 0;
- MassBalance = 0;
- Aerodynamics = 0;
- Inertial = 0;
- Aircraft = 0;
- Translation = 0;
- Rotation = 0;
- Position = 0;
- Auxiliary = 0;
- Output = 0;
+ State = 0;
+ Atmosphere = 0;
+ FCS = 0;
+ Propulsion = 0;
+ MassBalance = 0;
+ Aerodynamics = 0;
+ Inertial = 0;
+ GroundReactions = 0;
+ Aircraft = 0;
+ Translation = 0;
+ Rotation = 0;
+ Position = 0;
+ Auxiliary = 0;
+ Output = 0;
exe_ctr = 1;
bool FGModel::InitModel(void)
{
- State = FDMExec->GetState();
- Atmosphere = FDMExec->GetAtmosphere();
- FCS = FDMExec->GetFCS();
- Propulsion = FDMExec->GetPropulsion();
- MassBalance = FDMExec->GetMassBalance();
- Aerodynamics = FDMExec->GetAerodynamics();
- Inertial = FDMExec->GetInertial();
- Aircraft = FDMExec->GetAircraft();
- Translation = FDMExec->GetTranslation();
- Rotation = FDMExec->GetRotation();
- Position = FDMExec->GetPosition();
- Auxiliary = FDMExec->GetAuxiliary();
- Output = FDMExec->GetOutput();
+ State = FDMExec->GetState();
+ Atmosphere = FDMExec->GetAtmosphere();
+ FCS = FDMExec->GetFCS();
+ Propulsion = FDMExec->GetPropulsion();
+ MassBalance = FDMExec->GetMassBalance();
+ Aerodynamics = FDMExec->GetAerodynamics();
+ Inertial = FDMExec->GetInertial();
+ GroundReactions = FDMExec->GetGroundReactions();
+ Aircraft = FDMExec->GetAircraft();
+ Translation = FDMExec->GetTranslation();
+ Rotation = FDMExec->GetRotation();
+ Position = FDMExec->GetPosition();
+ Auxiliary = FDMExec->GetAuxiliary();
+ Output = FDMExec->GetOutput();
if (!State ||
!Atmosphere ||
!MassBalance ||
!Aerodynamics ||
!Inertial ||
+ !GroundReactions ||
!Aircraft ||
!Translation ||
!Rotation ||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGModel::Debug(void)
-{
- //TODO: Add your source code here
-}
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGDefs.h"
+#include "FGJSBBase.h"
#ifdef FGFS
# include <simgear/compiler.h>
# include <iostream.h>
# endif
#else
-# include <iostream>
+# if defined(sgi) && !defined(__GNUC__)
+# include <iostream.h>
+# else
+# include <iostream>
+# endif
#endif
#include <string>
class FGMassBalance;
class FGAerodynamics;
class FGInertial;
+class FGGroundReactions;
class FGAircraft;
class FGTranslation;
class FGRotation;
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGModel
+class FGModel : public FGJSBBase
{
public:
virtual int GetRate(void) {return rate;}
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 rate;
- FGFDMExec* FDMExec;
- FGState* State;
- FGAtmosphere* Atmosphere;
- FGFCS* FCS;
- FGPropulsion* Propulsion;
- FGMassBalance* MassBalance;
- FGAerodynamics* Aerodynamics;
- FGInertial* Inertial;
- FGAircraft* Aircraft;
- FGTranslation* Translation;
- FGRotation* Rotation;
- FGPosition* Position;
- FGAuxiliary* Auxiliary;
- FGOutput* Output;
- virtual void Debug(void);
+ FGFDMExec* FDMExec;
+ FGState* State;
+ FGAtmosphere* Atmosphere;
+ FGFCS* FCS;
+ FGPropulsion* Propulsion;
+ FGMassBalance* MassBalance;
+ FGAerodynamics* Aerodynamics;
+ FGInertial* Inertial;
+ FGGroundReactions* GroundReactions;
+ FGAircraft* Aircraft;
+ FGTranslation* Translation;
+ FGRotation* Rotation;
+ FGPosition* Position;
+ FGAuxiliary* Auxiliary;
+ FGOutput* Output;
};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_NOZZLE;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_NOZZLE "$Id$";
-#ifndef M_PI
-# include <simgear/constants.h>
-# define M_PI SG_PI
-#endif
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGAtmosphere.h"
#include "FGFCS.h"
#include "FGAerodynamics.h"
+#include "FGGroundReactions.h"
#include "FGAircraft.h"
#include "FGMassBalance.h"
#include "FGTranslation.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_OUTPUT;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
if (Type == otSocket) {
SocketOutput();
} else if (Type == otCSV) {
- if (Filename != "COUT" && Filename != "cout" && Filename.size() > 0) {
- DelimitedOutput(Filename);
- } else {
- DelimitedOutput();
- }
+ DelimitedOutput(Filename);
} else if (Type == otTerminal) {
// Not done yet
} else if (Type == otNone) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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) {
- cout << "Time";
+ outstream << "Time";
if (SubSystems & FGAircraft::ssSimulation) {
// Nothing here, yet
}
if (SubSystems & FGAircraft::ssAerosurfaces) {
- cout << ", ";
- cout << "Throttle, ";
- cout << "Aileron Cmd, ";
- cout << "Elevator Cmd, ";
- cout << "Rudder Cmd, ";
- cout << "Aileron Pos, ";
- cout << "Elevator Pos, ";
- cout << "Rudder Pos";
+ outstream << ", ";
+ outstream << "Throttle, ";
+ outstream << "Aileron Cmd, ";
+ outstream << "Elevator Cmd, ";
+ outstream << "Rudder Cmd, ";
+ outstream << "Aileron Pos, ";
+ outstream << "Elevator Pos, ";
+ outstream << "Rudder Pos";
}
if (SubSystems & FGAircraft::ssRates) {
- cout << ", ";
- cout << "P, Q, R";
+ outstream << ", ";
+ outstream << "P, Q, R";
}
if (SubSystems & FGAircraft::ssVelocities) {
- cout << ", ";
- cout << "QBar, ";
- cout << "Vtotal, ";
- cout << "UBody, VBody, WBody, ";
- cout << "UAero, VAero, WAero, ";
- cout << "Vn, Ve, Vd";
+ outstream << ", ";
+ outstream << "QBar, ";
+ outstream << "Vtotal, ";
+ outstream << "UBody, VBody, WBody, ";
+ outstream << "UAero, VAero, WAero, ";
+ outstream << "Vn, Ve, Vd";
}
if (SubSystems & FGAircraft::ssForces) {
- cout << ", ";
- cout << "Drag, Side, Lift, ";
- cout << "L/D, ";
- cout << "Xforce, Yforce, Zforce";
+ outstream << ", ";
+ outstream << "Drag, Side, Lift, ";
+ outstream << "L/D, ";
+ outstream << "Xforce, Yforce, Zforce";
}
if (SubSystems & FGAircraft::ssMoments) {
- cout << ", ";
- cout << "L, M, N";
+ outstream << ", ";
+ outstream << "L, M, N";
}
if (SubSystems & FGAircraft::ssAtmosphere) {
- cout << ", ";
- cout << "Rho";
+ outstream << ", ";
+ outstream << "Rho";
}
if (SubSystems & FGAircraft::ssMassProps) {
- cout << ", ";
- cout << "Ixx, ";
- cout << "Iyy, ";
- cout << "Izz, ";
- cout << "Ixz, ";
- cout << "Mass, ";
- cout << "Xcg, Ycg, Zcg";
+ outstream << ", ";
+ outstream << "Ixx, ";
+ outstream << "Iyy, ";
+ outstream << "Izz, ";
+ outstream << "Ixz, ";
+ outstream << "Mass, ";
+ outstream << "Xcg, Ycg, Zcg";
}
if (SubSystems & FGAircraft::ssPosition) {
- cout << ", ";
- cout << "Altitude, ";
- cout << "Phi, Tht, Psi, ";
- cout << "Alpha, ";
- cout << "Latitude, ";
- cout << "Longitude, ";
- cout << "Distance AGL, ";
- cout << "Runway Radius";
+ outstream << ", ";
+ outstream << "Altitude, ";
+ outstream << "Phi, Tht, Psi, ";
+ outstream << "Alpha, ";
+ outstream << "Latitude, ";
+ outstream << "Longitude, ";
+ outstream << "Distance AGL, ";
+ outstream << "Runway Radius";
}
if (SubSystems & FGAircraft::ssCoefficients) {
- cout << ", ";
- cout << Aerodynamics->GetCoefficientStrings();
+ outstream << ", ";
+ outstream << Aerodynamics->GetCoefficientStrings();
}
if (SubSystems & FGAircraft::ssGroundReactions) {
- cout << ", ";
- cout << Aircraft->GetGroundReactionStrings();
+ outstream << ", ";
+ outstream << GroundReactions->GetGroundReactionStrings();
}
if (SubSystems & FGAircraft::ssPropulsion) {
- cout << ", ";
- cout << Propulsion->GetPropulsionStrings();
+ outstream << ", ";
+ outstream << Propulsion->GetPropulsionStrings();
}
- cout << endl;
+ outstream << endl;
dFirstPass = false;
}
- cout << State->Getsim_time();
+ outstream << State->Getsim_time();
if (SubSystems & FGAircraft::ssSimulation) {
}
if (SubSystems & FGAircraft::ssAerosurfaces) {
- cout << ", ";
- cout << FCS->GetThrottlePos(0) << ", ";
- cout << FCS->GetDaCmd() << ", ";
- cout << FCS->GetDeCmd() << ", ";
- cout << FCS->GetDrCmd() << ", ";
- cout << FCS->GetDaPos() << ", ";
- cout << FCS->GetDePos() << ", ";
- cout << FCS->GetDrPos();
+ outstream << ", ";
+ outstream << FCS->GetThrottlePos(0) << ", ";
+ outstream << FCS->GetDaCmd() << ", ";
+ outstream << FCS->GetDeCmd() << ", ";
+ outstream << FCS->GetDrCmd() << ", ";
+ outstream << FCS->GetDaPos() << ", ";
+ outstream << FCS->GetDePos() << ", ";
+ outstream << FCS->GetDrPos();
}
if (SubSystems & FGAircraft::ssRates) {
- cout << ", ";
- cout << Rotation->GetPQR();
+ outstream << ", ";
+ outstream << Rotation->GetPQR();
}
if (SubSystems & FGAircraft::ssVelocities) {
- cout << ", ";
- cout << Translation->Getqbar() << ", ";
- cout << Translation->GetVt() << ", ";
- cout << Translation->GetUVW() << ", ";
- cout << Translation->GetvAero() << ", ";
- cout << Position->GetVel();
+ outstream << ", ";
+ outstream << Translation->Getqbar() << ", ";
+ outstream << Translation->GetVt() << ", ";
+ outstream << Translation->GetUVW() << ", ";
+ outstream << Translation->GetvAero() << ", ";
+ outstream << Position->GetVel();
}
if (SubSystems & FGAircraft::ssForces) {
- cout << ", ";
- cout << Aerodynamics->GetvFs() << ", ";
- cout << Aerodynamics->GetLoD() << ", ";
- cout << Aircraft->GetForces();
+ outstream << ", ";
+ outstream << Aerodynamics->GetvFs() << ", ";
+ outstream << Aerodynamics->GetLoD() << ", ";
+ outstream << Aircraft->GetForces();
}
if (SubSystems & FGAircraft::ssMoments) {
- cout << ", ";
- cout << Aircraft->GetMoments();
+ outstream << ", ";
+ outstream << Aircraft->GetMoments();
}
if (SubSystems & FGAircraft::ssAtmosphere) {
- cout << ", ";
- cout << Atmosphere->GetDensity();
+ outstream << ", ";
+ outstream << Atmosphere->GetDensity();
}
if (SubSystems & FGAircraft::ssMassProps) {
- cout << ", ";
- cout << MassBalance->GetIxx() << ", ";
- cout << MassBalance->GetIyy() << ", ";
- cout << MassBalance->GetIzz() << ", ";
- cout << MassBalance->GetIxz() << ", ";
- cout << MassBalance->GetMass() << ", ";
- cout << MassBalance->GetXYZcg();
+ outstream << ", ";
+ outstream << MassBalance->GetIxx() << ", ";
+ outstream << MassBalance->GetIyy() << ", ";
+ outstream << MassBalance->GetIzz() << ", ";
+ outstream << MassBalance->GetIxz() << ", ";
+ outstream << MassBalance->GetMass() << ", ";
+ outstream << MassBalance->GetXYZcg();
}
if (SubSystems & FGAircraft::ssPosition) {
- cout << ", ";
- cout << Position->Geth() << ", ";
- cout << Rotation->GetEuler() << ", ";
- cout << Translation->Getalpha() << ", ";
- cout << Position->GetLatitude() << ", ";
- cout << Position->GetLongitude() << ", ";
- cout << Position->GetDistanceAGL() << ", ";
- cout << Position->GetRunwayRadius();
+ outstream << ", ";
+ outstream << Position->Geth() << ", ";
+ outstream << Rotation->GetEuler() << ", ";
+ outstream << Translation->Getalpha() << ", ";
+ outstream << Position->GetLatitude() << ", ";
+ outstream << Position->GetLongitude() << ", ";
+ outstream << Position->GetDistanceAGL() << ", ";
+ outstream << Position->GetRunwayRadius();
}
if (SubSystems & FGAircraft::ssCoefficients) {
- cout << ", ";
- cout << Aerodynamics->GetCoefficientValues();
+ outstream << ", ";
+ outstream << Aerodynamics->GetCoefficientValues();
}
if (SubSystems & FGAircraft::ssGroundReactions) {
- cout << ", ";
- cout << Aircraft->GetGroundReactionValues();
+ outstream << ", ";
+ outstream << GroundReactions->GetGroundReactionValues();
}
if (SubSystems & FGAircraft::ssPropulsion) {
- cout << ", ";
- cout << Propulsion->GetPropulsionValues();
+ outstream << ", ";
+ outstream << Propulsion->GetPropulsionValues();
}
- cout << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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();
+ outstream << endl;
+ outstream.flush();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# include STL_IOSTREAM
# include STL_FSTREAM
#else
-# include <iostream>
-# include <fstream>
+# if defined(sgi) && !defined(__GNUC__)
+# include <iostream.h>
+# include <fstream.h>
+# else
+# include <iostream>
+# include <fstream>
+# endif
#endif
#include "FGfdmSocket.h"
bool Run(void);
- void DelimitedOutput(void);
void DelimitedOutput(string);
void SocketOutput(void);
void SocketStatusOutput(string);
inline void Disable(void) { enabled = false; }
inline bool Toggle(void) {enabled = !enabled; return enabled;}
-protected:
-
private:
bool sFirstPass, dFirstPass, enabled;
int SubSystems;
#include "FGDefs.h"
#include "FGPiston.h"
+#include "FGPropulsion.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_PISTON;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
Eng_cfg->GetNextConfigLine();
while (Eng_cfg->GetValue() != "/FG_PISTON") {
*Eng_cfg >> token;
- if (token == "BRAKEHORSEPOWER") *Eng_cfg >> BrakeHorsePower;
- else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle;
- else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle;
- else if (token == "SLFUELFLOWMAX") *Eng_cfg >> SLFuelFlowMax;
- else if (token == "SPEEDSLOPE") *Eng_cfg >> SpeedSlope;
- else if (token == "SPEEDINTERCEPT") *Eng_cfg >> SpeedIntercept;
- else if (token == "ALTITUDESLOPE") *Eng_cfg >> AltitudeSlope;
+ if (token == "MINMP") *Eng_cfg >> MinManifoldPressure_inHg;
+ else if (token == "MAXMP") *Eng_cfg >> MaxManifoldPressure_inHg;
+ else if (token == "DISPLACEMENT") *Eng_cfg >> Displacement;
+ else if (token == "MAXHP") *Eng_cfg >> MaxHP;
+ else if (token == "CYCLES") *Eng_cfg >> Cycles;
+ else if (token == "IDLERPM") *Eng_cfg >> IdleRPM;
+ 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;
}
if (debug_lvl > 0) {
cout << "\n Engine Name: " << Name << endl;
- cout << " BrakeHorsePower = " << BrakeHorsePower << endl;
- cout << " MaxThrottle = " << MaxThrottle << endl;
- cout << " MinThrottle = " << MinThrottle << endl;
- cout << " SLFuelFlowMax = " << SLFuelFlowMax << endl;
- cout << " SpeedSlope = " << SpeedSlope << endl;
- cout << " SpeedIntercept = " << SpeedIntercept << endl;
- cout << " AltitudeSlope = " << AltitudeSlope << endl;
+ cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl;
+ cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl;
+ cout << " Displacement: " << Displacement << endl;
+ cout << " MaxHP: " << MaxHP << endl;
+ cout << " Cycles: " << Cycles << endl;
+ cout << " IdleRPM: " << IdleRPM << endl;
+ cout << " MaxThrottle: " << MaxThrottle << endl;
+ cout << " MinThrottle: " << MinThrottle << endl;
+ cout << " SLFuelFlowMax: " << SLFuelFlowMax << endl;
}
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;
}
{
float h,EngineMaxPower;
+ // FIXME: calculate from actual fuel flow
ConsumeFuel();
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 = Throttle*EngineMaxPower*HPTOFTLBSSEC - PowerRequired;
-
+ PowerAvailable = (HP * HPTOFTLBSSEC) - PowerRequired;
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)
{
- //TODO: Add your source code here
+ //TODO: Add your source code here
}
HISTORY
--------------------------------------------------------------------------------
09/12/2000 JSB Created
+10/01/2001 DPM Modified to use equations from Dave Luff's piston model.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
#include "FGEngine.h"
#include "FGConfigFile.h"
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
#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 FGPiston : public FGEngine
{
public:
+ /// Constructor
FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg);
+ /// Destructor
~FGPiston();
float Calculate(float PowerRequired);
float SpeedIntercept;
float AltitudeSlope;
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);
};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif
-
# include <iomanip.h>
# endif
#else
-# include <cmath>
-# include <iomanip>
+# if defined(sgi) && !defined(__GNUC__)
+# include <math.h>
+# include <iomanip.h>
+# else
+# include <cmath>
+# include <iomanip>
+# endif
#endif
#include "FGPosition.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_POSITION;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@return false if no error */
bool Run(void);
- inline FGColumnVector GetVel(void) { return vVel; }
- inline FGColumnVector GetVelDot(void) { return vVelDot; }
+ inline FGColumnVector3& GetVel(void) { return vVel; }
+ inline FGColumnVector3& GetVelDot(void) { return vVelDot; }
inline double GetVn(void) { return vVel(eX); }
inline double GetVe(void) { return vVel(eY); }
inline double GetVd(void) { return vVel(eZ); }
inline double GetRunwayRadius(void) { return RunwayRadius; }
inline double GetDistanceAGL(void) { return DistanceAGL; }
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 void SetGamma(float tt) { gamma = tt; }
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 SetLongitude(double tt) { Longitude = tt; }
void Seth(double tt);
}
private:
- FGColumnVector vVel;
- FGColumnVector vVelDot;
- FGColumnVector vRunwayNormal;
+ FGColumnVector3 vVel;
+ FGColumnVector3 vVelDot;
+ FGColumnVector3 vRunwayNormal;
double Vee, invMass, invRadius;
double Radius, h;
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_PROPELLER;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPELLER "$Id$"
-#ifndef M_PI
-# include <simgear/constants.h>
-# define M_PI SG_PI
-#endif
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_PROPULSION;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
numSelectedFuelTanks = numSelectedOxiTanks = 0;
numTanks = numEngines = numThrusters = 0;
numOxiTanks = numFuelTanks = 0;
- Forces = new FGColumnVector(3);
- Moments = new FGColumnVector(3);
+ Forces = new FGColumnVector3(3);
+ Moments = new FGColumnVector3(3);
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGColumnVector& FGPropulsion::GetTanksCG(void)
+FGColumnVector3& FGPropulsion::GetTanksCG(void)
{
iTank = Tanks.begin();
vXYZtank.InitMatrix();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-float FGPropulsion::GetTanksIxx(const FGColumnVector& vXYZcg)
+float FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
{
float I = 0.0;
iTank = Tanks.begin();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-float FGPropulsion::GetTanksIyy(const FGColumnVector& vXYZcg)
+float FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
{
float I = 0.0;
iTank = Tanks.begin();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-float FGPropulsion::GetTanksIzz(const FGColumnVector& vXYZcg)
+float FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
{
float I = 0.0;
iTank = Tanks.begin();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-float FGPropulsion::GetTanksIxz(const FGColumnVector& vXYZcg)
+float FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
{
float I = 0.0;
iTank = Tanks.begin();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-float FGPropulsion::GetTanksIxy(const FGColumnVector& vXYZcg)
+float FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
{
float I = 0.0;
iTank = Tanks.begin();
string GetPropulsionStrings(void);
string GetPropulsionValues(void);
- inline FGColumnVector& GetForces(void) {return *Forces; }
- inline FGColumnVector& GetMoments(void) {return *Moments;}
+ inline FGColumnVector3& GetForces(void) {return *Forces; }
+ 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 GetTanksIxx(const FGColumnVector& vXYZcg);
- float GetTanksIyy(const FGColumnVector& vXYZcg);
- float GetTanksIzz(const FGColumnVector& vXYZcg);
- float GetTanksIxz(const FGColumnVector& vXYZcg);
- float GetTanksIxy(const FGColumnVector& vXYZcg);
+ float GetTanksIxx(const FGColumnVector3& vXYZcg);
+ float GetTanksIyy(const FGColumnVector3& vXYZcg);
+ float GetTanksIzz(const FGColumnVector3& vXYZcg);
+ float GetTanksIxz(const FGColumnVector3& vXYZcg);
+ float GetTanksIxy(const FGColumnVector3& vXYZcg);
private:
vector <FGEngine*> Engines;
unsigned int numTanks;
unsigned int numThrusters;
float dt;
- FGColumnVector *Forces;
- FGColumnVector *Moments;
- FGColumnVector vXYZtank;
+ FGColumnVector3 *Forces;
+ FGColumnVector3 *Moments;
+ FGColumnVector3 vXYZtank;
void Debug(void);
};
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ROCKET;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ROTATION;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
# include <simgear/compiler.h>
# include <math.h>
#else
-# include <cmath>
-#endif
-
-#ifndef M_PI
-# include <simgear/constants.h>
-# define M_PI SG_PI
+# if defined (sgi) && !defined(__GNUC__)
+# include <math.h>
+# else
+# include <cmath>
+# endif
#endif
#include "FGModel.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
#define ID_ROTATION "$Id$"
bool Run(void);
- inline FGColumnVector GetPQR(void) {return vPQR;}
+ inline FGColumnVector3& GetPQR(void) {return vPQR;}
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 FGColumnVector GetEuler(void) {return vEuler;}
+ inline FGColumnVector3& GetEuler(void) {return vEuler;}
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 void SetPQR(FGColumnVector tt) {vPQR = tt;}
- inline void SetEuler(FGColumnVector tt) {vEuler = tt;}
+ inline void SetPQR(FGColumnVector3 tt) {vPQR = tt;}
+ inline void SetEuler(FGColumnVector3 tt) {vEuler = tt;}
inline float Getphi(void) {return vEuler(1);}
inline float Gettht(void) {return vEuler(2);}
inline float GetSinpsi(void) {return sPsi;}
private:
- FGColumnVector vPQR;
- FGColumnVector vPQRdot;
- FGColumnVector vMoments;
- FGColumnVector vEuler;
- FGColumnVector vEulerRates;
- FGColumnVector vlastPQRdot;
+ FGColumnVector3 vPQR;
+ FGColumnVector3 vPQRdot;
+ FGColumnVector3 vMoments;
+ FGColumnVector3 vEuler;
+ FGColumnVector3 vEulerRates;
+ FGColumnVector3 vlastPQRdot;
float cTht,sTht;
float cPhi,sPhi;
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ROTOR;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
# include <simgear/compiler.h>
# include <math.h>
#else
-# include <cmath>
-#endif
-
-#ifndef M_PI
-# include <simgear/constants.h>
-# define M_PI SG_PI
+# if defined(sgi) && !defined(__GNUC__)
+# include <math.h>
+# else
+# include <cmath>
+# endif
#endif
#include "FGState.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_STATE;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
MACROS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
vlastQdot(4),
vQdot(4),
vTmp(4),
- vEuler(3)
+ vEuler(3),
+ vUVW(3),
+ vLocalVelNED(3),
+ vLocalEuler(3)
{
FDMExec = fdex;
RegisterVariable(FG_LEFT_BRAKE_CMD, " left_brake_cmd " );
RegisterVariable(FG_RIGHT_BRAKE_CMD," right_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 " );
if (debug_lvl & 2) cout << "Instantiated: FGState" << endl;
return Aircraft->GetWingSpan();
case FG_CBAR:
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:
return Translation->Getalpha();
+ case FG_ALPHAW:
+ return Translation->Getalpha() + Aircraft->GetWingIncidence();
case FG_ALPHADOT:
return Translation->Getadot();
case FG_BETA:
// 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 token="";
+
float U, V, W;
float phi, tht, psi;
float latitude, longitude, h;
+ float wdir, wmag, wnorth, weast;
+# ifndef macintosh
resetDef = path + "/" + acname + "/" + fname + ".xml";
-
-#if defined ( sgi ) && !defined( __GNUC__ )
- ifstream resetfile(resetDef.c_str(), ios::in );
-#else
- ifstream resetfile(resetDef.c_str(), ios::in | ios::binary );
-#endif
-
- if (resetfile) {
- resetfile >> U;
- resetfile >> V;
- resetfile >> W;
- resetfile >> latitude;
- 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;
+# else
+ resetDef = path + ";" + acname + ";" + fname + ".xml";
+# endif
+
+ 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 >> 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;
}
//***************************************************************************
void FGState::Initialize(float U, float V, float W,
float phi, float tht, float psi,
- float Latitude, float Longitude, float H) {
- FGColumnVector vUVW(3);
- FGColumnVector vLocalVelNED(3);
- FGColumnVector vLocalEuler(3);
+ float Latitude, float Longitude, float H,
+ float wnorth, float weast, float wdown)
+{
float alpha, beta;
float qbar, Vt;
+ FGColumnVector3 vAero;
Position->SetLatitude(Latitude);
Position->SetLongitude(Longitude);
Position->Seth(H);
Atmosphere->Run();
+
+ vLocalEuler << phi << tht << psi;
+ Rotation->SetEuler(vLocalEuler);
- if (W != 0.0)
- alpha = U*U > 0.0 ? atan2(W, U) : 0.0;
+ 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 (V != 0.0)
- beta = U*U+W*W > 0.0 ? atan2(V, (fabs(U)/U)*sqrt(U*U + W*W)) : 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;
- vUVW << U << V << W;
- Translation->SetUVW(vUVW);
-
- vLocalEuler << phi << tht << psi;
- Rotation->SetEuler(vLocalEuler);
-
Translation->SetAB(alpha, beta);
Vt = sqrt(U*U + V*V + W*W);
qbar = 0.5*(U*U + V*V + W*W)*Atmosphere->GetDensity();
Translation->Setqbar(qbar);
- InitMatrices(phi, tht, psi);
-
vLocalVelNED = mTb2l*vUVW;
Position->SetvVel(vLocalVelNED);
}
float tht,psi,phi;
float U, V, W, h;
float latitude, longitude;
-
+ float wnorth,weast, wdown;
+
latitude = FGIC->GetLatitudeRadIC();
longitude = FGIC->GetLongitudeRadIC();
h = FGIC->GetAltitudeFtIC();
tht = FGIC->GetThetaRadIC();
phi = FGIC->GetPhiRadIC();
psi = FGIC->GetPsiRadIC();
-
- Initialize(U, V, W, phi, tht, psi, latitude, longitude, h);
+ wnorth = FGIC->GetWindNFpsIC();
+ weast = FGIC->GetWindEFpsIC();
+ wdown = FGIC->GetWindDFpsIC();
Position->SetSeaLevelRadius( FGIC->GetSeaLevelRadiusFtIC() );
Position->SetRunwayRadius( FGIC->GetSeaLevelRadiusFtIC() +
FGIC->GetTerrainAltitudeFtIC() );
+ // need to fix the wind speed args, here.
+ Initialize(U, V, W, phi, tht, psi, latitude, longitude, h, wnorth, weast, wdown);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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(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));
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGColumnVector FGState::CalcEuler(void) {
+FGColumnVector3& FGState::CalcEuler(void) {
if (mTl2b(3,3) == 0.0) mTl2b(3,3) = 0.0000001;
if (mTl2b(1,1) == 0.0) mTl2b(1,1) = 0.0000001;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGMatrix FGState::GetTs2b(float alpha, float beta) {
+FGMatrix33& FGState::GetTs2b(float alpha, float beta)
+{
float ca, cb, sa, sb;
ca = cos(alpha);
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)
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
--------------------------------------------------------------------------------
11/17/98 JSB Created
# include <fstream.h>
# endif
#else
-# include <fstream>
+# if defined(sgi) && !defined(__GNUC__)
+# include <fstream.h>
+# else
+# include <fstream>
+# endif
#endif
#include <string>
#include <map>
#include "FGDefs.h"
+#include "FGJSBBase.h"
#include "FGInitialCondition.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
class FGAtmosphere;
class FGOutput;
class FGPosition;
+class FGFDMExec;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+/** Encapsulates the calculation of aircraft state.
+ @author Jon S. Berndt
+ @version $Id$
+*/
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGFDMExec;
-
-class FGState {
+class FGState : public FGJSBBase
+{
public:
+ /** Constructor
+ @param Executive a pointer to the parent executive object */
FGState(FGFDMExec*);
+ /// Destructor
~FGState();
- enum {ePhi=1, eTht, ePsi};
- enum {eP=1, eQ, eR};
- enum {eU=1, eV, eW};
- enum {eDrag=1, eSide, eLift};
-
- bool Reset(string, string, string);
- void Initialize(float, float, float, float, float, float, float, float, float);
+ /** Specifies the Reset file to use.
+ The reset file normally resides in the same directory as an aircraft config file.
+ it includes the following information:
+ <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);
+
+ /** Initializes the simulation state based on the passed-in parameters.
+ @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);
- 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; }
+ /// Returns the simulation time in seconds.
inline float Getsim_time(void) { return sim_time; }
+ /// Returns the simulation delta T.
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;}
+ /// Resumes the simulation by resetting delta T to the correct value.
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);
+
+ /** 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);
- eParam GetParameterIndex(string val_string);
- inline void Seta(float tt) { a = tt; }
+ /** 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);
- inline float Setsim_time(float tt) {
- sim_time = tt;
+ /** Sets the speed of sound.
+ @param speed the speed of sound in feet per second.
+ */
+ inline void Seta(float speed) { a = speed; }
+
+ /** Sets the current sim time.
+ @param cur_time the current time
+ @return the current time.
+ */
+ inline float Setsim_time(float cur_time) {
+ sim_time = cur_time;
return sim_time;
}
- inline void Setdt(float tt) { dt = tt; }
-
- void SetParameter(eParam, float);
-
+
+ /** 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; }
+
+ /** 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) {
sim_time+=dt;
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);
+
+ /** Calculates the local-to-body and body-to-local conversion matrices.
+ */
void CalcMatrices(void);
- void IntegrateQuat(FGColumnVector vPQR, int rate);
- FGColumnVector CalcEuler(void);
- FGMatrix GetTs2b(float alpha, float beta);
- FGMatrix GetTl2b(void) { return mTl2b; }
- float GetTl2b(int i, int j) { return mTl2b(i,j);}
- FGMatrix GetTb2l(void) { return mTb2l; }
+
+ /** Integrates the quaternion.
+ Given the supplied rotational rate vector and integration rate, the quaternion
+ is integrated. The quaternion is later used to update the transformation
+ matrices.
+ @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);}
+
+ /** Prints a summary of simulator state (speed, altitude,
+ configuration, etc.)
+ */
+ void ReportState(void);
+
+
typedef map<eParam, string> ParamMap;
ParamMap paramdef;
private:
-
float a; // speed of sound
float sim_time, dt;
float saved_dt;
FGFDMExec* FDMExec;
- FGMatrix mTb2l;
- FGMatrix mTl2b;
- FGMatrix mTs2b;
- FGColumnVector vQtrn;
- FGColumnVector vlastQdot;
+ FGMatrix33 mTb2l;
+ FGMatrix33 mTl2b;
+ FGMatrix33 mTs2b;
+ FGColumnVector4 vQtrn;
+ FGColumnVector4 vlastQdot;
+ FGColumnVector3 vUVW;
+ FGColumnVector3 vLocalVelNED;
+ FGColumnVector3 vLocalEuler;
+ FGColumnVector4 vQdot;
+ FGColumnVector4 vTmp;
+ FGColumnVector3 vEuler;
FGAircraft* Aircraft;
FGPosition* Position;
CoeffMap coeffdef;
void Debug(void);
int ActiveEngine;
-
- FGColumnVector vQdot;
- FGColumnVector vTmp;
- FGColumnVector vEuler;
};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TABLE;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGTable::~FGTable()
{
- for (int r=0; r<=nRows; r++) if (Data[r]) delete Data[r];
- if (Data) delete Data;
+ for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r];
+ if (Data) delete[] Data;
if (debug_lvl & 2) cout << "Destroyed: FGTable" << endl;
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGConfigFile.h"
+#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGTable {
-
+class FGTable : public FGJSBBase
+{
public:
~FGTable();
FGTable(int nRows);
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TANK;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGConfigFile.h"
+#include "FGJSBBase.h"
#ifdef FGFS
# include <simgear/compiler.h>
#else
# include <string>
using std::string;
- using std::cerr;
- using std::endl;
- using std::cout;
+# if !defined(sgi) || defined(__GNUC__)
+ using std::cerr;
+ using std::endl;
+ using std::cout;
+# endif
#endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGTank
+class FGTank : public FGJSBBase
{
public:
FGTank(FGConfigFile*);
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_THRUSTER;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#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 FGThruster : public FGForce {
public:
+ /// Constructor
FGThruster(FGFDMExec *FDMExec);
+ /// Destructor
virtual ~FGThruster();
enum eType {ttNozzle, ttRotor, ttPropeller};
float Thrust;
float PowerRequired;
float deltaT;
- void Debug(void);
+ virtual void Debug(void);
};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TRANSLATION;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
vUVW(3),
vUVWdot(3),
vNcg(3),
- vPQR(3),
- vForces(3),
- vEuler(3),
vlastUVWdot(3),
mVel(3,3),
vAero(3)
Mach = 0.0;
alpha = beta = 0.0;
adot = bdot = 0.0;
- rho = 0.002378;
if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGTranslation::Run(void) {
+bool FGTranslation::Run(void)
+{
+ float Tc = 0.5*State->Getdt()*rate;
if (!FGModel::Run()) {
- GetState();
-
mVel(1,1) = 0.0;
mVel(1,2) = -vUVW(eW);
mVel(1,3) = vUVW(eV);
mVel(3,2) = vUVW(eU);
mVel(3,3) = 0.0;
- vUVWdot = mVel*vPQR + vForces/Mass;
+ vUVWdot = mVel*Rotation->GetPQR() + Aircraft->GetForces()/MassBalance->GetMass();
vNcg = vUVWdot*INVGRAVITY;
- vUVW += 0.5*dt*rate*(vlastUVWdot + vUVWdot);
+ vUVW += Tc * (vlastUVWdot + vUVWdot);
vAero = vUVW + State->GetTl2b()*Atmosphere->GetWindNED();
Vt = vAero.Magnitude();
-
- 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;
-
- // stolen, quite shamelessly, from LaRCsim
- float mUW = (vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW));
- float signU=1;
- if (vAero(eU) != 0.0)
- signU = vAero(eU)/fabs(vAero(eU));
-
- if ( (mUW == 0.0) || (Vt == 0.0) ) {
- adot = 0.0;
- bdot = 0.0;
+ 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;
+
+ // stolen, quite shamelessly, from LaRCsim
+ float mUW = (vAero(eU)*vAero(eU) + vAero(eW)*vAero(eW));
+ float signU=1;
+ if (vAero(eU) != 0.0)
+ signU = vAero(eU)/fabs(vAero(eU));
+
+ if ( (mUW == 0.0) || (Vt == 0.0) ) {
+ adot = 0.0;
+ bdot = 0.0;
+ } else {
+ adot = (vAero(eU)*vAero(eW) - vAero(eW)*vUVWdot(eU))/mUW;
+ bdot = (signU*mUW*vUVWdot(eV) - vAero(eV)*(vAero(eU)*vUVWdot(eU)
+ + vAero(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
+ }
} else {
- adot = (vAero(eU)*vAero(eW) - vAero(eW)*vUVWdot(eU))/mUW;
- bdot = (signU*mUW*vUVWdot(eV) - vAero(eV)*(vAero(eU)*vUVWdot(eU)
- + vAero(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
+ alpha = beta = adot = bdot = 0;
}
- qbar = 0.5*rho*Vt*Vt;
+ qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt;
Mach = Vt / State->Geta();
vlastUVWdot = vUVWdot;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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)
{
if (debug_lvl & 16) { // Sanity check variables
# include <math.h>
# endif
#else
-# include <cmath>
+# if defined(sgi) && !defined(__GNUC__)
+# include <math.h>
+# else
+# include <cmath>
+# endif
#endif
#include "FGModel.h"
-#include "FGMatrix.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
#define ID_TRANSLATION "$Id$"
FGTranslation(FGFDMExec*);
~FGTranslation();
- inline FGColumnVector GetUVW (void) { return vUVW; }
- inline float GetUVW (int idx) { return vUVW(idx); }
- inline FGColumnVector GetUVWdot(void) { return vUVWdot; }
- inline float GetUVWdot(int idx) { return vUVWdot(idx); }
- inline FGColumnVector GetNcg (void) { return vNcg; }
- inline float GetNcg (int idx) { return vNcg(idx); }
- inline FGColumnVector GetvAero (void) { return vAero; }
- inline float GetvAero (int idx) { return vAero(idx); }
+ inline FGColumnVector3& GetUVW (void) { return vUVW; }
+ inline float GetUVW (int idx) { return vUVW(idx); }
+ inline FGColumnVector3& GetUVWdot(void) { return vUVWdot; }
+ inline float GetUVWdot(int idx) { return vUVWdot(idx); }
+ inline FGColumnVector3& GetNcg (void) { return vNcg; }
+ inline float GetNcg (int idx) { return vNcg(idx); }
+ inline FGColumnVector3& GetvAero (void) { return vAero; }
+ inline float GetvAero (int idx) { return vAero(idx); }
inline float Getalpha(void) { return alpha; }
inline float Getbeta (void) { return beta; }
inline float Getadot (void) { return adot; }
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 Setbeta (float tt) { beta = tt; }
bool Run(void);
-protected:
-
private:
- FGColumnVector vUVW;
- FGColumnVector vUVWdot;
- FGColumnVector vNcg;
- FGColumnVector vPQR;
- FGColumnVector vForces;
- FGColumnVector vEuler;
- FGColumnVector vlastUVWdot;
- FGMatrix mVel;
- FGColumnVector vAero;
+ FGColumnVector3 vUVW;
+ FGColumnVector3 vUVWdot;
+ FGColumnVector3 vNcg;
+ FGColumnVector3 vlastUVWdot;
+ FGMatrix33 mVel;
+ FGColumnVector3 vAero;
float Vt, qbar, Mach;
- float Mass, dt;
+ float dt;
float alpha, beta;
float adot,bdot;
- float rho;
- void GetState(void);
void Debug(void);
};
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TRIM;
-extern short debug_lvl;
-
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTrim::FGTrim(FGFDMExec *FDMExec,FGInitialCondition *FGIC, TrimMode tt ) {
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFDMExec.h"
+#include "FGJSBBase.h"
#include "FGRotation.h"
#include "FGAtmosphere.h"
#include "FGState.h"
#define ID_TRIM "$Id$"
+typedef enum { tLongitudinal, tFull, tGround, tCustom, tNone } TrimMode;
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-typedef enum { tLongitudinal, tFull, tGround, tCustom, tNone } TrimMode;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGTrim {
+class FGTrim : public FGJSBBase
+{
private:
vector<FGTrimAxis*> TrimAxes;
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TRIMAXIS;
-extern short debug_lvl;
-
/*****************************************************************************/
FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
#include <string>
#include "FGFDMExec.h"
+#include "FGJSBBase.h"
#include "FGRotation.h"
#include "FGAtmosphere.h"
#include "FGState.h"
enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL,
tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading };
-class FGTrimAxis {
+class FGTrimAxis : public FGJSBBase
+{
public:
FGTrimAxis(FGFDMExec* fdmex, FGInitialCondition *ic, State st,
Control ctrl );
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TURBOJET;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TURBOPROP;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TURBOSHAFT;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
# include <math.h>
# endif
#else
-# include <cmath>
+# if defined(sgi) && !defined(__GNUC__)
+# include <math.h>
+# else
+# include <cmath>
+# endif
#endif
#include "FGUtility.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_UTILITY;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include "FGJSBBase.h"
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFDMExec;
class FGState;
-class FGUtility
+class FGUtility : public FGJSBBase
{
public:
FGUtility(void);
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FDMSOCKET;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
{
size = 0;
- #if defined(__BORLANDC__) || defined(_MSC_VER)
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
WSADATA wsaData;
int PASCAL FAR wsaReturnCode;
wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
SG_USING_STD(endl);
# endif
#else
-# include <iostream>
-# include <fstream>
# include <string>
- using std::cout;
- using std::endl;
+# if defined(sgi) && !defined(__GNUC__)
+# include <iostream.h>
+# include <fstream.h>
+# else
+# include <iostream>
+# include <fstream>
+ using std::cout;
+ using std::endl;
+# endif
#endif
#include <sys/types.h>
+#include "FGJSBBase.h"
-#if defined(__BORLANDC__) || defined(_MSC_VER)
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
#include <winsock.h>
#else
#include <sys/socket.h>
using std::string;
-class FGfdmSocket {
+class FGfdmSocket : public FGJSBBase
+{
public:
FGfdmSocket(string, int);
~FGfdmSocket();
# include <time.h>
# endif
#else
-#include <iostream>
-#include <ctime>
-#endif
-
-#if __BORLANDC__ > 0x540
-#include <condefs.h>
-USEUNIT("FGUtility.cpp");
-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");
-//---------------------------------------------------------------------------
+# if defined(sgi) && !defined(__GNUC__)
+# include <iostream.h>
+# include <time.h>
+# else
+# include <iostream>
+# include <ctime>
+# endif
#endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
exit(-1);
}
} 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) {
cerr << "Aircraft file " << argv[1] << " was not found" << endl;
exit(-1);
}
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()) {}
FGAtmosphere.cpp FGAtmosphere.h \
FGAuxiliary.cpp FGAuxiliary.h \
FGCoefficient.cpp FGCoefficient.h \
+ FGColumnVector3.cpp FGColumnVector3.h \
+ FGColumnVector4.cpp FGColumnVector4.h \
FGConfigFile.cpp FGConfigFile.h \
FGDefs.h \
FGFCS.cpp FGFCS.h \
FGFDMExec.cpp FGFDMExec.h \
FGFactorGroup.cpp FGFactorGroup.h \
FGForce.cpp FGForce.h \
+ FGGroundReactions.cpp FGGroundReactions.h \
FGInertial.cpp FGInertial.h \
FGInitialCondition.cpp FGInitialCondition.h \
+ FGJSBBase.cpp FGJSBBase.h \
FGLGear.cpp FGLGear.h \
FGMassBalance.cpp FGMassBalance.h \
FGMatrix.cpp FGMatrix.h \
+ FGMatrix33.cpp FGMatrix33.h \
FGModel.cpp FGModel.h \
FGNozzle.cpp FGNozzle.h \
FGOutput.cpp FGOutput.h \
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_DEADBAND;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FCSCOMPONENT;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <string>
#include "../FGDefs.h"
+#include "../FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGFCSComponent
+class FGFCSComponent : public FGJSBBase
{
public:
/// Constructor
eParam OutputIdx;
float Output;
bool IsOutput;
- void Debug(void);
+ virtual void Debug(void);
};
#include "../FGFCS.h"
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FILTER;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
cc = (2.00*C3 - dt*C2) / denom;
break;
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;
case eWashout:
denom = 2.00 + dt*C1;
case eIntegrator:
ca = dt*C1 / 2.00;
break;
+ case eUnknown:
+ cerr << "Unknown filter type" << endl;
+ break;
}
if (debug_lvl > 0) {
switch (FilterType) {
case eLag:
Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb;
-// Output = Input * ca + PreviousOutput1 * cb;
break;
case eLeadLag:
Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc;
break;
case eOrder2:
+ Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc
+ - PreviousOutput1 * cd - PreviousOutput2 * ce;
break;
case eWashout:
Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
float cb;
float cc;
float cd;
+ float ce;
float C1;
float C2;
float C3;
};
#endif
+
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FLAPS;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_GAIN;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_GRADIENT;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_SUMMER;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_SWITCH;
-extern short debug_lvl;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/