Module: FGAircraft.cpp
Author: Jon S. Berndt
- Date started: 12/12/98
+ Date started: 12/12/98
Purpose: Encapsulates an aircraft
Called by: FGFDMExec
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
-Models the aircraft reactions and forces.
-
-ARGUMENTS
---------------------------------------------------------------------------------
-
+Models the aircraft reactions and forces. This class is instantiated by the
+FGFDMExec class and scheduled as an FDM entry. LoadAircraft() is supplied with a
+name of a valid, registered aircraft, and the data file is parsed.
HISTORY
--------------------------------------------------------------------------------
********************************************************************************
INCLUDES
*******************************************************************************/
-#include "FGAircraft.h"
-
-#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <math.h>
+
+#ifdef FGFS
+# include <Include/compiler.h>
+# ifdef FG_HAVE_STD_INCLUDES
+# include <cmath>
+# else
+# include <math.h>
+# endif
+#else
+# include <cmath>
+#endif
+
+#include "FGAircraft.h"
+#include "FGTranslation.h"
+#include "FGRotation.h"
+#include "FGAtmosphere.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+#include "FGFCS.h"
+#include "FGPosition.h"
+#include "FGAuxiliary.h"
+#include "FGOutput.h"
/*******************************************************************************
************************************ CODE **************************************
*******************************************************************************/
-
-FGAircraft::FGAircraft(void) : FGModel()
+FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex)
{
int i;
- strcpy(Name,"FGAircraft");
+ Name = "FGAircraft";
- for (i=0;i<6;i++) Axis[i] = (char*)malloc(7);
for (i=0;i<6;i++) coeff_ctr[i] = 0;
- strcpy(Axis[LiftCoeff],"CLIFT");
- strcpy(Axis[DragCoeff],"CDRAG");
- strcpy(Axis[SideCoeff],"CSIDE");
- strcpy(Axis[RollCoeff],"CROLL");
- strcpy(Axis[PitchCoeff],"CPITCH");
- strcpy(Axis[YawCoeff],"CYAW");
+ Axis[LiftCoeff] = "CLIFT";
+ Axis[DragCoeff] = "CDRAG";
+ Axis[SideCoeff] = "CSIDE";
+ Axis[RollCoeff] = "CROLL";
+ Axis[PitchCoeff] = "CPITCH";
+ Axis[YawCoeff] = "CYAW";
}
}
-bool FGAircraft::LoadAircraft(char* fname)
+bool FGAircraft::LoadAircraft(string aircraft_path, string engine_path,
+ string fname)
{
- char path[250];
- char fullpath[275];
- char filename[275];
- char aircraftDef[2100];
- char tag[220];
+ string path;
+ string fullpath;
+ string filename;
+ string aircraftDef;
+ string tag;
DIR* dir;
DIR* coeffdir;
- struct dirent* dirEntry = 0L;
- struct dirent* coeffdirEntry = 0L;
+ struct dirent* dirEntry;
+ struct dirent* coeffdirEntry;
struct stat st;
struct stat st2;
ifstream coeffInFile;
- char scratch[250];
-
- sprintf(aircraftDef, "/h/curt/projects/FlightGear/Simulator/FDM/JSBsim/aircraft/%s/%s.dat", fname, fname);
- ifstream aircraftfile(aircraftDef);
+ aircraftDef = aircraft_path + "/" + fname + "/" + fname + ".dat";
+ ifstream aircraftfile(aircraftDef.c_str());
if (aircraftfile) {
- aircraftfile >> AircraftName;
- aircraftfile >> WingArea;
- aircraftfile >> WingSpan;
- aircraftfile >> cbar;
- aircraftfile >> Ixx;
- aircraftfile >> Iyy;
- aircraftfile >> Izz;
- aircraftfile >> Ixz;
- aircraftfile >> Weight;
- m = Weight / 32.174;
+ aircraftfile >> AircraftName; // String with no embedded spaces
+ aircraftfile >> WingArea; // square feet
+ aircraftfile >> WingSpan; // feet
+ aircraftfile >> cbar; // feet
+ aircraftfile >> Ixx; // slug ft^2
+ aircraftfile >> Iyy; // "
+ aircraftfile >> Izz; // "
+ aircraftfile >> Ixz; // "
+ aircraftfile >> EmptyWeight; // pounds
+ EmptyMass = EmptyWeight / GRAVITY;
aircraftfile >> tag;
numTanks = numEngines = 0;
numSelectedOxiTanks = numSelectedFuelTanks = 0;
- while (strstr(tag,"EOF") == 0) {
- if (strstr(tag,"CGLOC")) {
- aircraftfile >> Xcg;
- aircraftfile >> Ycg;
- aircraftfile >> Zcg;
- } else if (strstr(tag,"EYEPOINTLOC")) {
- aircraftfile >> Xep;
- aircraftfile >> Yep;
- aircraftfile >> Zep;
- } else if (strstr(tag,"TANK")) {
+ while ( !(tag == "EOF") ) {
+ if (tag == "CGLOC") {
+ aircraftfile >> Xcg; // inches
+ aircraftfile >> Ycg; // inches
+ aircraftfile >> Zcg; // inches
+ } else if (tag == "EYEPOINTLOC") {
+ aircraftfile >> Xep; // inches
+ aircraftfile >> Yep; // inches
+ aircraftfile >> Zep; // inches
+ } else if (tag == "TANK") {
Tank[numTanks] = new FGTank(aircraftfile);
switch(Tank[numTanks]->GetType()) {
- case 0:
- numSelectedOxiTanks++;
- break;
- case 1:
+ case FGTank::ttFUEL:
numSelectedFuelTanks++;
break;
+ case FGTank::ttOXIDIZER:
+ numSelectedOxiTanks++;
+ break;
}
numTanks++;
- } else if (strstr(tag,"ENGINE")) {
+ } else if (tag == "ENGINE") {
aircraftfile >> tag;
- Engine[numEngines] = new FGEngine(tag);
+ Engine[numEngines] = new FGEngine(FDMExec, engine_path, tag,
+ numEngines);
numEngines++;
}
aircraftfile >> tag;
// track of the number of coefficients registered for each of the
// previously mentioned axis.
- sprintf(path,"/h/curt/projects/FlightGear/Simulator/FDM/JSBsim/aircraft/%s/",AircraftName);
- if ( dir = opendir(path) ) {
+ path = aircraft_path + "/" + AircraftName + "/";
+ if (dir = opendir(path.c_str())) {
while (dirEntry = readdir(dir)) {
- sprintf(fullpath,"%s%s",path,dirEntry->d_name);
- stat(fullpath,&st);
+ fullpath = path + dirEntry->d_name;
+ stat(fullpath.c_str(),&st);
if ((st.st_mode & S_IFMT) == S_IFDIR) {
for (int axis_ctr=0; axis_ctr < 6; axis_ctr++) {
- if (strstr(dirEntry->d_name,Axis[axis_ctr])) {
- if (coeffdir = opendir(fullpath)) {
+ if (dirEntry->d_name == Axis[axis_ctr]) {
+ if (coeffdir = opendir(fullpath.c_str())) {
while (coeffdirEntry = readdir(coeffdir)) {
if (coeffdirEntry->d_name[0] != '.') {
- sprintf(filename,"%s%s/%s",path,Axis[axis_ctr],coeffdirEntry->d_name);
- stat(filename,&st2);
+ filename = path + Axis[axis_ctr] + "/" + coeffdirEntry->d_name;
+ stat(filename.c_str(),&st2);
if (st2.st_size > 6) {
- Coeff[axis_ctr][coeff_ctr[axis_ctr]] = new FGCoefficient(filename);
+ Coeff[axis_ctr][coeff_ctr[axis_ctr]] = new FGCoefficient(FDMExec, filename);
coeff_ctr[axis_ctr]++;
}
}
for (int i = 0; i < 3; i++) Forces[i] = Moments[i] = 0.0;
+ MassChange();
+
FProp(); FAero(); FGear(); FMass();
MProp(); MAero(); MGear(); MMass();
}
+void FGAircraft::MassChange()
+{
+ // UPDATE TANK CONTENTS
+ //
+ // For each engine, cycle through the tanks and draw an equal amount of
+ // fuel (or oxidizer) from each active tank. The needed amount of fuel is
+ // determined by the engine in the FGEngine class. If more fuel is needed
+ // than is available in the tank, then that amount is considered a shortage,
+ // and will be drawn from the next tank. If the engine cannot be fed what it
+ // needs, it will be considered to be starved, and will shut down.
+
+ float Oshortage, Fshortage;
+
+ for (int e=0; e<numEngines; e++) {
+ Fshortage = Oshortage = 0.0;
+ for (int t=0; t<numTanks; t++) {
+ switch(Engine[e]->GetType()) {
+ case FGEngine::etRocket:
+
+ switch(Tank[t]->GetType()) {
+ case FGTank::ttFUEL:
+ if (Tank[t]->GetSelected()) {
+ Fshortage = Tank[t]->Reduce((Engine[e]->CalcFuelNeed()/
+ numSelectedFuelTanks)*(dt*rate) + Fshortage);
+ }
+ break;
+ case FGTank::ttOXIDIZER:
+ if (Tank[t]->GetSelected()) {
+ Oshortage = Tank[t]->Reduce((Engine[e]->CalcOxidizerNeed()/
+ numSelectedOxiTanks)*(dt*rate) + Oshortage);
+ }
+ break;
+ }
+ break;
+
+ case FGEngine::etPiston:
+ case FGEngine::etTurboJet:
+ case FGEngine::etTurboProp:
+
+ if (Tank[t]->GetSelected()) {
+ Fshortage = Tank[t]->Reduce((Engine[e]->CalcFuelNeed()/
+ numSelectedFuelTanks)*(dt*rate) + Fshortage);
+ }
+ break;
+ }
+ }
+ if ((Fshortage <= 0.0) || (Oshortage <= 0.0)) Engine[e]->SetStarved();
+ else Engine[e]->SetStarved(false);
+ }
+
+ Weight = EmptyWeight;
+ for (int t=0; t<numTanks; t++)
+ Weight += Tank[t]->GetContents();
+
+ Mass = Weight / GRAVITY;
+}
+
+
void FGAircraft::FAero(void)
{
float F[3];
void FGAircraft::FMass(void)
{
- Forces[0] += -g*sin(tht) * m;
- Forces[1] += g*sin(phi)*cos(tht) * m;
- Forces[2] += g*cos(phi)*cos(tht) * m;
+ Forces[0] += -GRAVITY*sin(tht) * Mass;
+ Forces[1] += GRAVITY*sin(phi)*cos(tht) * Mass;
+ Forces[2] += GRAVITY*cos(phi)*cos(tht) * Mass;
}
void FGAircraft::FProp(void)
{
- float Oshortage, Fshortage;
-
for (int i=0;i<numEngines;i++) {
Forces[0] += Engine[i]->CalcThrust();
}
-
- //
- // UPDATE TANK CONTENTS
- //
- // For each engine, cycle through the tanks and draw an equal amount of
- // fuel (or oxidizer) from each active tank. The needed amount of fuel is
- // determined by the engine in the FGEngine class. If more fuel is needed
- // than is available in the tank, then that amount is considered a shortage,
- // and will be drawn from the next tank. If the engine cannot be fed what it
- // needs, it will be considered to be starved, and will shut down.
-
- for (int e=0; e<numEngines; e++) {
- Fshortage = Oshortage = 0.0;
- for (int t=0; t<numTanks; t++) {
- switch(Engine[e]->GetType()) {
- case 0: // Rocket
- switch(Tank[t]->GetType()) {
- case 0: // Fuel
- if (Tank[t]->GetSelected()) {
- Fshortage = Tank[t]->Reduce((Engine[e]->CalcFuelNeed()/numSelectedFuelTanks)*(dt*rate) + Fshortage);
- }
- break;
- case 1: // Oxidizer
- if (Tank[t]->GetSelected()) {
- Oshortage = Tank[t]->Reduce((Engine[e]->CalcOxidizerNeed()/numSelectedOxiTanks)*(dt*rate) + Oshortage);
- }
- break;
- }
- break;
- default: // piston, turbojet, turbofan, etc.
- if (Tank[t]->GetSelected()) {
- Fshortage = Tank[t]->Reduce((Engine[e]->CalcFuelNeed()/numSelectedFuelTanks)*(dt*rate) + Fshortage);
- }
- break;
- }
- }
- if ((Fshortage < 0.0) || (Oshortage < 0.0)) Engine[e]->SetStarved();
- else Engine[e]->SetStarved(false);
- }
-
}
void FGAircraft::GetState(void)
{
- Ixx = State->GetIxx();
- Iyy = State->GetIyy();
- Izz = State->GetIzz();
- Ixz = State->GetIxz();
- alpha = State->Getalpha();
- beta = State->Getbeta();
- m = State->Getm();
- phi = State->Getphi();
- tht = State->Gettht();
- psi = State->Getpsi();
- g = State->Getg();
dt = State->Getdt();
+
+ alpha = Translation->Getalpha();
+ beta = Translation->Getbeta();
+ phi = Rotation->Getphi();
+ tht = Rotation->Gettht();
+ psi = Rotation->Getpsi();
}
void FGAircraft::PutState(void)
{
- State->SetIxx(Ixx);
- State->SetIyy(Iyy);
- State->SetIzz(Izz);
- State->SetIxz(Ixz);
- State->SetFx(Forces[0]);
- State->SetFy(Forces[1]);
- State->SetFz(Forces[2]);
- State->SetL(Moments[0]);
- State->SetM(Moments[1]);
- State->SetN(Moments[2]);
- State->Setm(m);
}