1
0
Fork 0

sync. with JSBSim v. 2.0

This commit is contained in:
ehofman 2006-01-12 15:04:22 +00:00
parent fcfe5d2010
commit 932b38a87e
134 changed files with 18734 additions and 2844 deletions

View file

@ -514,7 +514,13 @@ AC_CONFIG_FILES([ \
src/FDM/ExternalNet/Makefile \
src/FDM/ExternalPipe/Makefile \
src/FDM/JSBSim/Makefile \
src/FDM/JSBSim/filtersjb/Makefile \
src/FDM/JSBSim/initialization/Makefile \
src/FDM/JSBSim/input_output/Makefile \
src/FDM/JSBSim/math/Makefile \
src/FDM/JSBSim/models/Makefile \
src/FDM/JSBSim/models/flight_control/Makefile \
src/FDM/JSBSim/models/atmosphere/Makefile \
src/FDM/JSBSim/models/propulsion/Makefile \
src/FDM/LaRCsim/Makefile \
src/FDM/SP/Makefile \
src/FDM/UIUCModel/Makefile \

View file

@ -41,10 +41,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef FGFS
# include <simgear/compiler.h>
# include STL_IOSTREAM
@ -60,21 +56,22 @@ INCLUDES
#include "FGFDMExec.h"
#include "FGState.h"
#include "FGAtmosphere.h"
#include "FGFCS.h"
#include "FGGroundCallback.h"
#include "FGPropulsion.h"
#include "FGMassBalance.h"
#include "FGGroundReactions.h"
#include "FGAerodynamics.h"
#include "FGInertial.h"
#include "FGAircraft.h"
#include "FGPropagate.h"
#include "FGAuxiliary.h"
#include "FGOutput.h"
#include "FGConfigFile.h"
#include "FGInitialCondition.h"
#include "FGPropertyManager.h"
#include <models/FGAtmosphere.h>
#include <models/atmosphere/FGMSIS.h>
#include <models/atmosphere/FGMars.h>
#include <models/FGFCS.h>
#include <models/FGPropulsion.h>
#include <models/FGMassBalance.h>
#include <models/FGGroundReactions.h>
#include <models/FGAerodynamics.h>
#include <models/FGInertial.h>
#include <models/FGAircraft.h>
#include <models/FGPropagate.h>
#include <models/FGAuxiliary.h>
#include <models/FGInput.h>
#include <models/FGOutput.h>
#include <initialization/FGInitialCondition.h>
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
@ -110,12 +107,13 @@ void checkTied ( FGPropertyManager *node )
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Constructor
FGFDMExec::FGFDMExec(FGPropertyManager* root)
FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
{
Frame = 0;
FirstModel = 0;
Error = 0;
GroundCallback = 0;
State = 0;
Atmosphere = 0;
FCS = 0;
@ -125,22 +123,25 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root)
Inertial = 0;
GroundReactions = 0;
Aircraft = 0;
GroundCallback = 0;
Propagate = 0;
Auxiliary = 0;
Output = 0;
Input = 0;
IC = 0;
Trim = 0;
terminate = false;
frozen = false;
modelLoaded = false;
IsSlave = false;
holding = false;
// Multiple FDM's are stopped for now. We need to ensure that
// the "user" instance always gets the zeroeth instance number,
// because there may be instruments or scripts tied to properties
// in the jsbsim[0] node.
// ToDo: it could be that when JSBSim is reset and a new FDM is wanted, that
// process might try setting FDMctr = 0. Then the line below would not need
// to be commented out.
IdFDM = FDMctr;
//FDMctr++;
@ -151,31 +152,35 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root)
debug_lvl = 1;
}
if (root == 0) master= new FGPropertyManager;
else master = root;
if (Root == 0) master= new FGPropertyManager;
else master = Root;
instance = master->GetNode("/fdm/jsbsim",IdFDM,true);
Debug(0);
// this is here to catch errors in binding member functions
// to the property tree.
// this is to catch errors in binding member functions to the property tree.
try {
Allocate();
} catch ( string msg ) {
cout << "Caught error: " << msg << endl;
exit(1);
}
Constructing = true;
typedef int (FGFDMExec::*iPMF)(void) const;
instance->Tie("simulation/do_trim", this, (iPMF)0, &FGFDMExec::DoTrim);
Constructing = false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGFDMExec::~FGFDMExec()
{
instance->Untie("simulation/do_trim");
try {
DeAllocate();
checkTied( instance );
if (Root == 0) delete master;
} catch ( string msg ) {
cout << "Caught error: " << msg << endl;
}
@ -200,14 +205,14 @@ bool FGFDMExec::Allocate(void)
Inertial = new FGInertial(this);
GroundReactions = new FGGroundReactions(this);
Aircraft = new FGAircraft(this);
GroundCallback = new FGGroundCallback();
Propagate = new FGPropagate(this);
Auxiliary = new FGAuxiliary(this);
Output = new FGOutput(this);
Input = new FGInput(this);
State = new FGState(this); // This must be done here, as the FGState
// class needs valid pointers to the above
// model classes
GroundCallback = new FGGroundCallback();
State = new FGState(this); // This must be done here, as the FGState
// class needs valid pointers to the above
// model classes
// Initialize models so they can communicate with each other
@ -237,23 +242,23 @@ bool FGFDMExec::Allocate(void)
Error+=128;}
if (!Propagate->InitModel()) {
cerr << fgred << "Propagate model init failed" << fgdef << endl;
Error+=512;}
Error+=256;}
if (!Auxiliary->InitModel()) {
cerr << fgred << "Auxiliary model init failed" << fgdef << endl;
Error+=2058;}
if (!Output->InitModel()) {
cerr << fgred << "Output model init failed" << fgdef << endl;
Error+=4096;}
Error+=512;}
if (!Input->InitModel()) {
cerr << fgred << "Input model init failed" << fgdef << endl;
Error+=1024;}
if (Error > 0) result = false;
IC = new FGInitialCondition(this);
// Schedule a model. The second arg (the integer) is the pass number. For
// instance, the atmosphere model gets executed every fifth pass it is called
// by the executive. Everything else here gets executed each pass.
// IC and Trim objects are NOT scheduled.
// instance, the atmosphere model could get executed every fifth pass it is called
// by the executive. IC and Trim objects are NOT scheduled.
Schedule(Input, 1);
Schedule(Atmosphere, 1);
Schedule(FCS, 1);
Schedule(Propulsion, 1);
@ -264,7 +269,6 @@ bool FGFDMExec::Allocate(void)
Schedule(Aircraft, 1);
Schedule(Propagate, 1);
Schedule(Auxiliary, 1);
Schedule(Output, 1);
modelLoaded = false;
@ -275,6 +279,7 @@ bool FGFDMExec::Allocate(void)
bool FGFDMExec::DeAllocate(void)
{
delete Input;
delete Atmosphere;
delete FCS;
delete Propulsion;
@ -285,9 +290,14 @@ bool FGFDMExec::DeAllocate(void)
delete Aircraft;
delete Propagate;
delete Auxiliary;
delete Output;
delete State;
for (int i=0; i<Outputs.size(); i++) {
if (Outputs[i]) delete Outputs[i];
}
Outputs.clear();
delete IC;
delete Trim;
@ -297,6 +307,7 @@ bool FGFDMExec::DeAllocate(void)
Error = 0;
State = 0;
Input = 0;
Atmosphere = 0;
FCS = 0;
Propulsion = 0;
@ -307,7 +318,6 @@ bool FGFDMExec::DeAllocate(void)
Aircraft = 0;
Propagate = 0;
Auxiliary = 0;
Output = 0;
modelLoaded = false;
return modelLoaded;
@ -346,8 +356,6 @@ bool FGFDMExec::Run(void)
{
FGModel* model_iterator;
if (frozen) return true;
model_iterator = FirstModel;
if (model_iterator == 0L) return false;
@ -364,27 +372,29 @@ bool FGFDMExec::Run(void)
}
frame = Frame++;
State->IncrTime();
if (!Holding()) State->IncrTime();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This call will cause the sim time to reset to 0.0
bool FGFDMExec::RunIC(void)
{
State->Suspend();
State->SuspendIntegration();
State->Initialize(IC);
Run();
State->Resume();
State->ResumeIntegration();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::SetGroundCallback(FGGroundCallback* p) {
if (GroundCallback)
delete GroundCallback;
void FGFDMExec::SetGroundCallback(FGGroundCallback* p)
{
if (GroundCallback) delete GroundCallback;
GroundCallback = p;
}
@ -408,7 +418,6 @@ vector <string> FGFDMExec::EnumerateFDMs(void)
bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model,
bool addModelToPath)
{
FGFDMExec::AircraftPath = AircraftPath;
FGFDMExec::EnginePath = EnginePath;
@ -417,13 +426,15 @@ bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model,
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::LoadModel(string model, bool addModelToPath)
{
bool result = true;
string token;
string aircraftCfgFileName;
string separator = "/";
# ifdef macintosh
separator = ";";
# endif
if( AircraftPath.empty() || EnginePath.empty() ) {
cerr << "Error: attempted to load aircraft with undefined ";
@ -432,16 +443,16 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
}
aircraftCfgFileName = AircraftPath;
# ifndef macintosh
if (addModelToPath) aircraftCfgFileName += "/" + model;
aircraftCfgFileName += "/" + model + ".xml";
# else
if (addModelToPath) aircraftCfgFileName += ";" + model;
aircraftCfgFileName += ";" + model + ".xml";
# endif
if (addModelToPath) aircraftCfgFileName += separator + model;
aircraftCfgFileName += separator + model + ".xml";
FGConfigFile AC_cfg(aircraftCfgFileName);
if (!AC_cfg.IsOpen()) return false;
FGXMLParse *XMLParse = new FGXMLParse();
Element* element = 0L;
Element* document;
ifstream input_file(aircraftCfgFileName.c_str());
readXML(input_file, *XMLParse);
document = XMLParse->GetDocument();
modelName = model;
@ -450,36 +461,35 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
Allocate();
}
if (!ReadPrologue(&AC_cfg)) return false;
ReadPrologue(document);
element = document->GetElement();
while ((AC_cfg.GetNextConfigLine() != string("EOF")) &&
(token = AC_cfg.GetValue()) != string("/FDM_CONFIG")) {
if (token == "METRICS") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Metrics" << fgdef << endl;
if (!ReadMetrics(&AC_cfg)) result = false;
} else if (token == "SLAVE") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Slave flight vehicle: " << fgdef
<< AC_cfg.GetValue("NAME") << endl;
if (!ReadSlave(&AC_cfg)) result = false;
} else if (token == "AERODYNAMICS") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Aerodynamics" << fgdef << endl;
if (!ReadAerodynamics(&AC_cfg)) result = false;
} else if (token == "UNDERCARRIAGE") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Landing Gear" << fgdef << endl;
if (!ReadUndercarriage(&AC_cfg)) result = false;
} else if (token == "PROPULSION") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Propulsion" << fgdef << endl;
if (!ReadPropulsion(&AC_cfg)) result = false;
} else if (token == "FLIGHT_CONTROL") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Flight Control" << fgdef << endl;
if (!ReadFlightControls(&AC_cfg)) result = false;
} else if (token == "AUTOPILOT") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Autopilot" << fgdef << endl;
if (!ReadFlightControls(&AC_cfg)) result = false;
} else if (token == "OUTPUT") {
if (debug_lvl > 0) cout << fgcyan << "\n Reading Output directives" << fgdef << endl;
if (!ReadOutput(&AC_cfg)) result = false;
bool result = true;
while (element && result) {
string element_name = element->GetName();
if (element_name == "fileheader" ) result = ReadFileHeader(element);
else if (element_name == "slave") result = ReadSlave(element);
else if (element_name == "metrics") result = Aircraft->Load(element);
else if (element_name == "mass_balance") result = MassBalance->Load(element);
else if (element_name == "ground_reactions") result = GroundReactions->Load(element);
else if (element_name == "propulsion") result = Propulsion->Load(element);
else if (element_name == "autopilot") result = FCS->Load(element);
else if (element_name == "flight_control") result = FCS->Load(element);
else if (element_name == "aerodynamics") result = Aerodynamics->Load(element);
else if (element_name == "input") result = Input->Load(element);
else if (element_name == "output") {
FGOutput* Output = new FGOutput(this);
Output->InitModel();
Schedule(Output, 1);
Outputs.push_back(Output);
result = Output->Load(element);
}
else {
cerr << "Found unexpected subsystem: " << element_name << ", exiting." << endl;
result = false;
break;
}
element = document->GetNextElement();
}
if (result) {
@ -487,32 +497,93 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
Debug(3);
} else {
cerr << fgred
<< " FGFDMExec: Failed to load aircraft and/or engine model"
<< " JSBSim failed to load aircraft and/or engine model"
<< fgdef << endl;
return false;
}
struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = "";
masterPCS.node = (FGPropertyManager*)master;
BuildPropertyCatalog(&masterPCS);
return result;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadPrologue(FGConfigFile* AC_cfg)
void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
{
string token = AC_cfg->GetValue();
string scratch;
string AircraftName;
struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure;
int node_idx = 0;
char int_buf[10];
AircraftName = AC_cfg->GetValue("NAME");
for (int i=0; i<pcs->node->nChildren(); i++) {
pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
node_idx = pcs->node->getChild(i)->getIndex();
sprintf(int_buf, "[%d]", node_idx);
if (node_idx != 0) pcsNew->base_string += string(int_buf);
if (pcs->node->getChild(i)->nChildren() == 0) {
PropertyCatalog.push_back(pcsNew->base_string);
} else {
pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
BuildPropertyCatalog(pcsNew);
}
}
delete pcsNew;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGFDMExec::QueryPropertyCatalog(string in)
{
string results="";
for (int i=0; i<PropertyCatalog.size(); i++) {
if (PropertyCatalog[i].find(in) != string::npos) results += PropertyCatalog[i] + "\n";
}
if (results.empty()) return "No matches found\n";
return results;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadFileHeader(Element* el)
{
bool result = true; // true for success
if (debug_lvl & ~1) return result;
if (el->FindElement("author"))
cout << " Model Author: " << el->FindElement("author")->GetDataLine() << endl;
if (el->FindElement("filecreationdate"))
cout << " Creation Date: " << el->FindElement("filecreationdate")->GetDataLine() << endl;
if (el->FindElement("version"))
cout << " Version: " << el->FindElement("version")->GetDataLine() << endl;
if (el->FindElement("description"))
cout << " Description: " << el->FindElement("description")->GetDataLine() << endl;
return result;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document element
{
bool result = true; // true for success
if (!el) return false;
string AircraftName = el->GetAttributeValue("name");
Aircraft->SetAircraftName(AircraftName);
if (debug_lvl > 0) cout << underon << "Reading Aircraft Configuration File"
if (debug_lvl & 1) cout << underon << "Reading Aircraft Configuration File"
<< underoff << ": " << highint << AircraftName << normint << endl;
scratch = AC_cfg->GetValue("VERSION").c_str();
CFGVersion = AC_cfg->GetValue("VERSION");
Release = AC_cfg->GetValue("RELEASE");
CFGVersion = el->GetAttributeValue("version");
Release = el->GetAttributeValue("release");
if (debug_lvl > 0)
if (debug_lvl & 1)
cout << " Version: " << highint << CFGVersion
<< normint << endl;
if (CFGVersion != needed_cfg_version) {
@ -523,10 +594,7 @@ bool FGFDMExec::ReadPrologue(FGConfigFile* AC_cfg)
return false;
}
if (Release == "ALPHA" && debug_lvl > 0) {
#ifndef _MSC_VER
system("banner ALPHA");
#endif
if (Release == "ALPHA" && (debug_lvl & 1)) {
cout << endl << endl
<< highint << "This aircraft model is an " << fgred << Release
<< reset << highint << " release!!!" << endl << endl << reset
@ -534,24 +602,33 @@ bool FGFDMExec::ReadPrologue(FGConfigFile* AC_cfg)
<< " will not fly as expected." << endl << endl
<< fgred << highint << "Use this model for development purposes ONLY!!!"
<< normint << reset << endl << endl;
} else if (Release == "BETA" && debug_lvl > 0) {
#ifndef _MSC_VER
system("banner BETA");
#endif
} else if (Release == "BETA" && (debug_lvl & 1)) {
cout << endl << endl
<< highint << "This aircraft model is a " << fgred << Release
<< reset << highint << " release!!!" << endl << endl << reset
<< "This aircraft model probably will not fly as expected." << endl << endl
<< fgblue << highint << "Use this model for development purposes ONLY!!!"
<< normint << reset << endl << endl;
} else if (Release == "PRODUCTION" && (debug_lvl & 1)) {
cout << endl << endl
<< highint << "This aircraft model is a " << fgblue << Release
<< reset << highint << " release." << endl << endl << reset;
} else if (debug_lvl & 1) {
cout << endl << endl
<< highint << "This aircraft model is an " << fgred << Release
<< reset << highint << " release!!!" << endl << endl << reset
<< "This aircraft model may not even properly load, and probably"
<< " will not fly as expected." << endl << endl
<< fgred << highint << "Use this model for development purposes ONLY!!!"
<< normint << reset << endl << endl;
}
return true;
return result;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
bool FGFDMExec::ReadSlave(Element* el)
{
// Add a new slaveData object to the slave FDM list
// Populate that slaveData element with a new FDMExec object
@ -567,8 +644,8 @@ bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
SlaveFDMList.push_back(new slaveData);
SlaveFDMList.back()->exec = new FGFDMExec();
SlaveFDMList.back()->exec->SetSlave();
string AircraftName = AC_cfg->GetValue("FILE");
/*
string AircraftName = AC_cfg->GetValue("file");
debug_lvl = 0; // turn off debug output for slave vehicle
@ -580,15 +657,15 @@ bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
AC_cfg->GetNextConfigLine();
while ((token = AC_cfg->GetValue()) != string("/SLAVE")) {
*AC_cfg >> token;
if (token == "XLOC") { *AC_cfg >> SlaveFDMList.back()->x; }
else if (token == "YLOC") { *AC_cfg >> SlaveFDMList.back()->y; }
else if (token == "ZLOC") { *AC_cfg >> SlaveFDMList.back()->z; }
else if (token == "PITCH") { *AC_cfg >> SlaveFDMList.back()->pitch;}
else if (token == "YAW") { *AC_cfg >> SlaveFDMList.back()->yaw; }
else if (token == "ROLL") { *AC_cfg >> SlaveFDMList.back()->roll; }
if (token == "xloc") { *AC_cfg >> SlaveFDMList.back()->x; }
else if (token == "yloc") { *AC_cfg >> SlaveFDMList.back()->y; }
else if (token == "zloc") { *AC_cfg >> SlaveFDMList.back()->z; }
else if (token == "pitch") { *AC_cfg >> SlaveFDMList.back()->pitch;}
else if (token == "yaw") { *AC_cfg >> SlaveFDMList.back()->yaw; }
else if (token == "roll") { *AC_cfg >> SlaveFDMList.back()->roll; }
else cerr << "Unknown identifier: " << token << " in slave vehicle definition" << endl;
}
*/
if (debug_lvl > 0) {
cout << " X = " << SlaveFDMList.back()->x << endl;
cout << " Y = " << SlaveFDMList.back()->y << endl;
@ -603,84 +680,87 @@ bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadPropulsion(FGConfigFile* AC_cfg)
FGPropertyManager* FGFDMExec::GetPropertyManager(void)
{
if (!Propulsion->Load(AC_cfg)) {
cerr << " Propulsion not successfully loaded" << endl;
return false;
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadFlightControls(FGConfigFile* AC_cfg)
{
if (!FCS->Load(AC_cfg)) {
cerr << " Flight Controls not successfully loaded" << endl;
return false;
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadAerodynamics(FGConfigFile* AC_cfg)
{
if (!Aerodynamics->Load(AC_cfg)) {
cerr << " Aerodynamics not successfully loaded" << endl;
return false;
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadUndercarriage(FGConfigFile* AC_cfg)
{
if (!GroundReactions->Load(AC_cfg)) {
cerr << " Ground Reactions not successfully loaded" << endl;
return false;
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadMetrics(FGConfigFile* AC_cfg)
{
if (!Aircraft->Load(AC_cfg)) {
cerr << " Aircraft metrics not successfully loaded" << endl;
return false;
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::ReadOutput(FGConfigFile* AC_cfg)
{
if (!Output->Load(AC_cfg)) {
cerr << " Output not successfully loaded" << endl;
return false;
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyManager* FGFDMExec::GetPropertyManager(void) {
return instance;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTrim* FGFDMExec::GetTrim(void) {
FGTrim* FGFDMExec::GetTrim(void)
{
delete Trim;
Trim = new FGTrim(this,tNone);
return Trim;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::DisableOutput(void)
{
for (int i=0; i<Outputs.size(); i++) {
Outputs[i]->Disable();
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::EnableOutput(void)
{
for (int i=0; i<Outputs.size(); i++) {
Outputs[i]->Enable();
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::DoTrim(int mode)
{
double saved_time;
cout << "DoTrim called" << endl;
if (Constructing) return;
if (mode < 0 || mode > JSBSim::tNone) {
cerr << endl << "Illegal trimming mode!" << endl << endl;
return;
}
saved_time = State->Getsim_time();
FGTrim trim(this, (JSBSim::TrimMode)mode);
if ( !trim.DoTrim() ) cerr << endl << "Trim Failed" << endl << endl;
trim.Report();
State->Setsim_time(saved_time);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::UseAtmosphereMSIS(void)
{
FGAtmosphere *oldAtmosphere = Atmosphere;
Atmosphere = new MSIS(this);
if (!Atmosphere->InitModel()) {
cerr << fgred << "MSIS Atmosphere model init failed" << fgdef << endl;
Error+=1;
}
delete oldAtmosphere;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::UseAtmosphereMars(void)
{
/*
FGAtmosphere *oldAtmosphere = Atmosphere;
Atmosphere = new FGMars(this);
if (!Atmosphere->InitModel()) {
cerr << fgred << "Mars Atmosphere model init failed" << fgdef << endl;
Error+=1;
}
delete oldAtmosphere;
*/
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
@ -721,7 +801,7 @@ void FGFDMExec::Debug(int from)
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
if (from == 2) {
cout << "================== Frame: " << Frame << " Time: "
<< State->Getsim_time() << endl;
<< State->Getsim_time() << " dt: " << State->Getdt() << endl;
}
}
if (debug_lvl & 8 ) { // Runtime state variables
@ -737,3 +817,4 @@ void FGFDMExec::Debug(int from)
}
}

View file

@ -40,13 +40,16 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
#include "FGTrim.h"
#include "FGInitialCondition.h"
#include "FGJSBBase.h"
#include "FGGroundCallback.h"
#include "FGPropertyManager.h"
#include "FGPropagate.h"
#include <models/FGModel.h>
#include <models/FGOutput.h>
#include <models/FGInput.h>
#include <initialization/FGTrim.h>
#include <initialization/FGInitialCondition.h>
#include <FGJSBBase.h>
#include <input_output/FGPropertyManager.h>
#include <input_output/FGXMLParse.h>
#include <input_output/FGGroundCallback.h>
#include <models/FGPropagate.h>
#include <vector>
@ -74,8 +77,7 @@ CLASS DOCUMENTATION
When an aircraft model is loaded the config file is parsed and for each of the
sections of the config file (propulsion, flight control, etc.) the
corresponding "ReadXXX()" method is called. From within this method the
"Load()" method of that system is called (e.g. LoadFCS).
corresponding Load() method is called (e.g. LoadFCS).
<h4>JSBSim Debugging Directives</h4>
@ -134,17 +136,12 @@ public:
/** Initializes the sim from the initial condition object and executes
each scheduled model without integrating i.e. dt=0.
@return true if successful
*/
@return true if successful */
bool RunIC(void);
/// Freezes the sim
void Freeze(void) {frozen = true;}
/// Resumes the sim
void Resume(void) {frozen = false;}
void SetGroundCallback(FGGroundCallback*);
/** Sets the ground callback pointer.
@param gc A pointer to a ground callback object. */
void SetGroundCallback(FGGroundCallback* gc);
/** Loads an aircraft model.
@param AircraftPath path to the aircraft directory. For instance:
@ -162,7 +159,6 @@ public:
bool LoadModel(string AircraftPath, string EnginePath, string model,
bool addModelToPath = true);
/** Loads an aircraft model. The paths to the aircraft and engine
config file directories must be set prior to calling this. See
below.
@ -175,37 +171,23 @@ public:
@return true if successful*/
bool LoadModel(string model, bool addModelToPath = true);
/** Sets the path to the engine config file directories.
@param path path to the directory under which engine config
files are kept, for instance "engine"
*/
files are kept, for instance "engine" */
bool SetEnginePath(string path) { EnginePath = path; return true; }
/** Sets the path to the aircraft config file directories.
@param path path to the aircraft directory. For instance:
"aircraft". Under aircraft, then, would be directories for various
modeled aircraft such as C172/, x15/, etc.
*/
modeled aircraft such as C172/, x15/, etc. */
bool SetAircraftPath(string path) { AircraftPath = path; return true; }
/** Sets the path to the autopilot config file directories.
@param path path to the control directory. For instance:
"control".
*/
// bool SetControlPath(string path) { ControlPath = path; return true; }
/// @name Top-level executive State and Model retrieval mechanism
//@{
/// Returns the FGState pointer.
inline FGState* GetState(void) {return State;}
/// Returns the FGAtmosphere pointer.
inline FGAtmosphere* GetAtmosphere(void) {return Atmosphere;}
/// Returns the FGFCS pointer.
inline FGFCS* GetFCS(void) {return FCS;}
/// Returns the FGGroundCallback pointer.
inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;}
/// Returns the FGPropulsion pointer.
inline FGPropulsion* GetPropulsion(void) {return Propulsion;}
/// Returns the FGAircraft pointer.
@ -222,41 +204,100 @@ public:
inline FGPropagate* GetPropagate(void) {return Propagate;}
/// Returns the FGAuxiliary pointer.
inline FGAuxiliary* GetAuxiliary(void) {return Auxiliary;}
/// Returns the FGOutput pointer.
inline FGOutput* GetOutput(void) {return Output;}
/// Returns the FGInput pointer.
inline FGInput* GetInput(void) {return Input;}
/// Returns the FGGroundCallback pointer.
inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;}
/// Returns the FGState pointer.
inline FGState* GetState(void) {return State;}
// Returns a pointer to the FGInitialCondition object
inline FGInitialCondition* GetIC(void) {return IC;}
// Returns a pointer to the FGTrim object
FGTrim* GetTrim(void);
inline FGTrim* GetTrim(void);
//@}
/// Retrieves the engine path.
inline string GetEnginePath(void) {return EnginePath;}
/// Retrieves the aircraft path.
inline string GetAircraftPath(void) {return AircraftPath;}
// /// Retrieves the control path.
// inline string GetControlPath(void) {return ControlPath;}
/// Returns the model name.
string GetModelName(void) { return modelName; }
/// Returns a pointer to the property manager object.
FGPropertyManager* GetPropertyManager(void);
/// Returns a vector of strings representing the names of all loaded models (future)
vector <string> EnumerateFDMs(void);
/// Marks this instance of the Exec object as a "slave" object.
void SetSlave(void) {IsSlave = true;}
/** Executes trimming in the selected mode.
* @param mode Specifies how to trim:
* - tLongitudinal=0
* - tFull
* - tGround
* - tPullup
* - tCustom
* - tTurn
* - tNone
*/
void DoTrim(int mode);
/// Disables data logging to all outputs.
void DisableOutput(void);
/// Enables data logging to all outputs.
void EnableOutput(void);
/// Pauses execution by preventing time from incrementing.
void Hold(void) {holding = true;}
/// Resumes execution from a "Hold".
void Resume(void) {holding = false;}
/// Returns true if the simulation is Holding (i.e. simulation time is not moving).
bool Holding(void) {return holding;}
struct PropertyCatalogStructure {
/// Name of the property.
string base_string;
/// The node for the property.
FGPropertyManager *node;
};
/** Builds a catalog of properties.
* This function descends the property tree and creates a list (an STL vector)
* containing the name and node for all properties.
* @param pcs The "root" property catalog structure pointer. */
void BuildPropertyCatalog(struct PropertyCatalogStructure* pcs);
/** Retrieves property or properties matching the supplied string.
* A string is returned that contains a carriage return delimited list of all
* strings in the property catalog that matches the supplied chack string.
* @param check The string to search for in the property catalog.
* @return the carriage-return-delimited string containing all matching strings
* in the catalog. */
string QueryPropertyCatalog(string check);
/// Use the MSIS atmosphere model.
void UseAtmosphereMSIS(void);
/// Use the Mars atmosphere model. (Not operative yet.)
void UseAtmosphereMars(void);
private:
FGModel* FirstModel;
bool frozen;
bool terminate;
bool holding;
bool Constructing;
int Error;
unsigned int Frame;
unsigned int IdFDM;
FGPropertyManager* Root;
static unsigned int FDMctr;
bool modelLoaded;
string modelName;
bool IsSlave;
static FGPropertyManager *master;
FGPropertyManager *instance;
vector <string> PropertyCatalog;
struct slaveData {
FGFDMExec* exec;
@ -279,15 +320,14 @@ private:
string AircraftPath;
string EnginePath;
// string ControlPath;
string CFGVersion;
string Release;
FGGroundCallback* GroundCallback;
FGState* State;
FGAtmosphere* Atmosphere;
FGFCS* FCS;
FGGroundCallback* GroundCallback;
FGPropulsion* Propulsion;
FGMassBalance* MassBalance;
FGAerodynamics* Aerodynamics;
@ -296,21 +336,17 @@ private:
FGAircraft* Aircraft;
FGPropagate* Propagate;
FGAuxiliary* Auxiliary;
FGOutput* Output;
FGInput* Input;
vector <FGOutput*> Outputs;
FGInitialCondition* IC;
FGTrim *Trim;
vector <slaveData*> SlaveFDMList;
bool ReadMetrics(FGConfigFile*);
bool ReadSlave(FGConfigFile*);
bool ReadPropulsion(FGConfigFile*);
bool ReadFlightControls(FGConfigFile*);
bool ReadAerodynamics(FGConfigFile*);
bool ReadUndercarriage(FGConfigFile*);
bool ReadPrologue(FGConfigFile*);
bool ReadOutput(FGConfigFile*);
bool ReadFileHeader(Element*);
bool ReadSlave(Element*);
bool ReadPrologue(Element*);
bool Allocate(void);
bool DeAllocate(void);

View file

@ -76,6 +76,7 @@ const double FGJSBBase::radtodeg = 57.29578;
const double FGJSBBase::degtorad = 1.745329E-2;
const double FGJSBBase::hptoftlbssec = 550.0;
const double FGJSBBase::psftoinhg = 0.014138;
const double FGJSBBase::psftopa = 47.88;
const double FGJSBBase::fpstokts = 0.592484;
const double FGJSBBase::ktstofps = 1.68781;
const double FGJSBBase::inchtoft = 0.08333333;
@ -92,8 +93,8 @@ const double FGJSBBase::SHRatio = 1.40;
const double FGJSBBase::slugtolb = 32.174049;
const double FGJSBBase::lbtoslug = 1.0/slugtolb;
const string FGJSBBase::needed_cfg_version = "1.65";
const string FGJSBBase::JSBSim_version = "0.9.5";
const string FGJSBBase::needed_cfg_version = "2.0";
const string FGJSBBase::JSBSim_version = "0.9.10.111805";
std::queue <FGJSBBase::Message*> FGJSBBase::Messages;
FGJSBBase::Message FGJSBBase::localMsg;

View file

@ -42,18 +42,18 @@ INCLUDES
#ifdef FGFS
# include <simgear/compiler.h>
# include <simgear/constants.h>
# include <math.h>
# include <queue>
# include STL_STRING
SG_USING_STD(string);
# ifndef M_PI
# define M_PI SG_PI
# endif
# ifndef M_PI
# include <simgear/constants.h>
# define M_PI SG_PI
# endif
#else
#else // JSBSim section
# include <queue>
# include <string>
@ -65,13 +65,27 @@ SG_USING_STD(string);
using std::string;
# ifndef M_PI
# define M_PI 3.14159265358979323846
# endif
# if defined(_MSC_VER) && _MSC_VER <= 1200
# ifndef max
# define max(a,b) (((a) > (b)) ? (a) : (b))
# endif
# ifndef min
# define min(a,b) (((a) < (b)) ? (a) : (b))
# endif
# else
using std::fabs;
# endif
# ifndef M_PI
# define M_PI 3.14159265358979323846
# endif
#endif
#if !defined(WIN32) || defined(__GNUC__) || ( defined(_MSC_VER) && (_MSC_VER >= 1400))
#if !defined(WIN32) || defined(__GNUC__)
using std::max;
#endif
@ -92,6 +106,8 @@ CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** JSBSim Base class.
* This class provides universal constants, utility functions, messaging
* functions, and enumerated constants to JSBSim.
@author Jon S. Berndt
@version $Id$
*/
@ -178,23 +194,40 @@ public:
@return pointer to a Message structure (or NULL if no mesage) */
Message* ProcessMessage(void);
//@}
/** Returns the version number of JSBSim.
* @return The version number of JSBSim. */
string GetVersion(void) {return JSBSim_version;}
/// Disables highlighting in the console output.
void disableHighLighting(void);
static short debug_lvl;
/** Converts from degrees Kelvin to degrees Fahrenheit.
* @param kelvin The temperature in degrees Kelvin.
* @return The temperature in Fahrenheit. */
static double KelvinToFahrenheit (double kelvin) {
return 1.8*kelvin - 459.4;
}
/** Converts from degrees Rankine to degrees Celsius.
* @param rankine The temperature in degrees Rankine.
* @return The temperature in Celsius. */
static double RankineToCelsius (double rankine) {
return (rankine - 491.67)/1.8;
}
/** Converts from degrees Fahrenheit to degrees Celsius.
* @param fahrenheit The temperature in degrees Fahrenheit.
* @return The temperature in Celsius. */
static double FahrenheitToCelsius (double fahrenheit) {
return (fahrenheit - 32.0)/1.8;
}
/** Converts from degrees Celsius to degrees Fahrenheit.
* @param celsius The temperature in degrees Celsius.
* @return The temperature in Fahrenheit. */
static double CelsiusToFahrenheit (double celsius) {
return celsius * 1.8 + 32.0;
}
@ -247,6 +280,7 @@ protected:
static const double degtorad;
static const double hptoftlbssec;
static const double psftoinhg;
static const double psftopa;
static const double fpstokts;
static const double ktstofps;
static const double inchtoft;
@ -257,8 +291,8 @@ protected:
static const double slugtolb;
static const string needed_cfg_version;
static const string JSBSim_version;
};
public:
/// Moments L, M, N
enum {eL = 1, eM, eN };
/// Rates P, Q, R
@ -280,6 +314,8 @@ enum {eLat = 1, eLong, eRad };
/// Conversion specifiers
enum {inNone = 0, inDegrees, inRadians, inMeters, inFeet };
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -36,10 +36,6 @@ HISTORY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef FGFS
# include <simgear/compiler.h>
# include <math.h>
@ -81,7 +77,6 @@ FGState::FGState(FGFDMExec* fdex)
Propagate = FDMExec->GetPropagate();
Auxiliary = FDMExec->GetAuxiliary();
FCS = FDMExec->GetFCS();
Output = FDMExec->GetOutput();
Atmosphere = FDMExec->GetAtmosphere();
Aerodynamics = FDMExec->GetAerodynamics();
GroundReactions = FDMExec->GetGroundReactions();

View file

@ -59,20 +59,19 @@ INCLUDES
#include <string>
#include <map>
#include "FGJSBBase.h"
#include "FGInitialCondition.h"
#include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGQuaternion.h"
#include <initialization/FGInitialCondition.h>
#include <math/FGMatrix33.h>
#include <math/FGColumnVector3.h>
#include <math/FGQuaternion.h>
#include "FGFDMExec.h"
#include "FGAtmosphere.h"
#include "FGFCS.h"
#include "FGPropagate.h"
#include "FGAuxiliary.h"
#include "FGAerodynamics.h"
#include "FGOutput.h"
#include "FGAircraft.h"
#include "FGGroundReactions.h"
#include "FGPropulsion.h"
#include <models/FGAtmosphere.h>
#include <models/FGFCS.h>
#include <models/FGPropagate.h>
#include <models/FGAuxiliary.h>
#include <models/FGAerodynamics.h>
#include <models/FGAircraft.h>
#include <models/FGGroundReactions.h>
#include <models/FGPropulsion.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -117,12 +116,16 @@ public:
/// Returns the simulation time in seconds.
inline double Getsim_time(void) const { return sim_time; }
/// Returns the simulation delta T.
inline double Getdt(void) { return dt; }
inline double Getdt(void) {
return dt;
}
/// Suspends the simulation and sets the delta T to zero.
inline void Suspend(void) {saved_dt = dt; dt = 0.0;}
inline void SuspendIntegration(void) {saved_dt = dt; dt = 0.0;}
/// Resumes the simulation by resetting delta T to the correct value.
inline void Resume(void) {dt = saved_dt;}
inline void ResumeIntegration(void) {dt = saved_dt;}
bool IntegrationSuspended(void) {return dt == 0.0;}
/** Sets the current sim time.
@param cur_time the current time
@ -136,7 +139,9 @@ public:
/** Sets the integration time step for the simulation executive.
@param delta_t the time step in seconds.
*/
inline void Setdt(double delta_t) { dt = delta_t; }
inline void Setdt(double delta_t) {
dt = delta_t;
}
/** Increments the simulation time.
@return the new simulation time.
@ -174,7 +179,6 @@ private:
FGAircraft* Aircraft;
FGPropagate* Propagate;
FGOutput* Output;
FGAtmosphere* Atmosphere;
FGFCS* FCS;
FGAerodynamics* Aerodynamics;

View file

@ -47,30 +47,35 @@
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <FDM/JSBSim/FGFDMExec.h>
#include <FDM/JSBSim/FGAircraft.h>
#include <FDM/JSBSim/FGFCS.h>
#include <FDM/JSBSim/FGPropagate.h>
#include <FDM/JSBSim/FGState.h>
#include <FDM/JSBSim/FGAuxiliary.h>
#include <FDM/JSBSim/FGInitialCondition.h>
#include <FDM/JSBSim/FGTrim.h>
#include <FDM/JSBSim/FGAtmosphere.h>
#include <FDM/JSBSim/FGMassBalance.h>
#include <FDM/JSBSim/FGAerodynamics.h>
#include <FDM/JSBSim/FGLGear.h>
#include <FDM/JSBSim/FGPropertyManager.h>
#include <FDM/JSBSim/FGEngine.h>
#include <FDM/JSBSim/FGPiston.h>
#include <FDM/JSBSim/FGGroundCallback.h>
#include <FDM/JSBSim/FGTurbine.h>
#include <FDM/JSBSim/FGRocket.h>
#include <FDM/JSBSim/FGElectric.h>
#include <FDM/JSBSim/FGNozzle.h>
#include <FDM/JSBSim/FGPropeller.h>
#include <FDM/JSBSim/FGRotor.h>
#include <FDM/JSBSim/FGTank.h>
#include "JSBSim.hxx"
#include <FDM/JSBSim/FGFDMExec.h>
#include <FDM/JSBSim/FGJSBBase.h>
#include <FDM/JSBSim/FGState.h>
#include <FDM/JSBSim/initialization/FGInitialCondition.h>
#include <FDM/JSBSim/initialization/FGTrim.h>
#include <FDM/JSBSim/models/FGModel.h>
#include <FDM/JSBSim/models/FGAircraft.h>
#include <FDM/JSBSim/models/FGFCS.h>
#include <FDM/JSBSim/models/FGPropagate.h>
#include <FDM/JSBSim/models/FGAuxiliary.h>
#include <FDM/JSBSim/models/FGAtmosphere.h>
#include <FDM/JSBSim/models/FGMassBalance.h>
#include <FDM/JSBSim/models/FGAerodynamics.h>
#include <FDM/JSBSim/models/FGLGear.h>
#include <FDM/JSBSim/models/propulsion/FGEngine.h>
#include <FDM/JSBSim/models/propulsion/FGPiston.h>
#include <FDM/JSBSim/models/propulsion/FGTurbine.h>
#include <FDM/JSBSim/models/propulsion/FGTurboProp.h>
#include <FDM/JSBSim/models/propulsion/FGRocket.h>
#include <FDM/JSBSim/models/propulsion/FGElectric.h>
#include <FDM/JSBSim/models/propulsion/FGNozzle.h>
#include <FDM/JSBSim/models/propulsion/FGPropeller.h>
#include <FDM/JSBSim/models/propulsion/FGRotor.h>
#include <FDM/JSBSim/models/propulsion/FGTank.h>
#include <FDM/JSBSim/input_output/FGPropertyManager.h>
#include <FDM/JSBSim/input_output/FGGroundCallback.h>
using namespace JSBSim;
static inline double
FMAX (double a, double b)
@ -142,10 +147,6 @@ FGJSBsim::FGJSBsim( double dt )
}
}
reset_on_crash = fgGetBool("/sim/reset-on-crash", false);
crashed = false;
fgSetBool("/sim/crashed", false);
fdmex = new FGFDMExec( (FGPropertyManager*)globals->get_props() );
// Register ground callback.
@ -288,9 +289,6 @@ void FGJSBsim::init()
// Explicitly call the superclass's
// init method first.
#ifdef FG_WEATHERCM
Atmosphere->UseInternal();
#else
if (fgGetBool("/environment/params/control-fdm-atmosphere")) {
Atmosphere->UseExternal();
Atmosphere->SetExTemperature(
@ -307,7 +305,6 @@ void FGJSBsim::init()
} else {
Atmosphere->UseInternal();
}
#endif
fgic->SetVnorthFpsIC( wind_from_north->getDoubleValue() );
fgic->SetVeastFpsIC( wind_from_east->getDoubleValue() );
@ -339,9 +336,9 @@ void FGJSBsim::init()
switch(fgic->GetSpeedSet()) {
case setned:
SG_LOG(SG_FLIGHT,SG_INFO, " Vn,Ve,Vd= "
<< Propagate->GetVel(eNorth) << ", "
<< Propagate->GetVel(eEast) << ", "
<< Propagate->GetVel(eDown) << " ft/s");
<< Propagate->GetVel(FGJSBBase::eNorth) << ", "
<< Propagate->GetVel(FGJSBBase::eEast) << ", "
<< Propagate->GetVel(FGJSBBase::eDown) << " ft/s");
break;
case setuvw:
SG_LOG(SG_FLIGHT,SG_INFO, " U,V,W= "
@ -363,11 +360,11 @@ void FGJSBsim::init()
stall_warning->setDoubleValue(0);
SG_LOG( SG_FLIGHT, SG_INFO, " Bank Angle: "
<< Propagate->GetEuler(ePhi)*RADTODEG << " deg" );
<< Propagate->GetEuler(FGJSBBase::ePhi)*RADTODEG << " deg" );
SG_LOG( SG_FLIGHT, SG_INFO, " Pitch Angle: "
<< Propagate->GetEuler(eTht)*RADTODEG << " deg" );
<< Propagate->GetEuler(FGJSBBase::eTht)*RADTODEG << " deg" );
SG_LOG( SG_FLIGHT, SG_INFO, " True Heading: "
<< Propagate->GetEuler(ePsi)*RADTODEG << " deg" );
<< Propagate->GetEuler(FGJSBBase::ePsi)*RADTODEG << " deg" );
SG_LOG( SG_FLIGHT, SG_INFO, " Latitude: "
<< Propagate->GetLocation().GetLatitudeDeg() << " deg" );
SG_LOG( SG_FLIGHT, SG_INFO, " Longitude: "
@ -487,12 +484,6 @@ void FGJSBsim::update( double dt )
// translate JSBsim back to FG structure so that the
// autopilot (and the rest of the sim can use the updated values
copy_from_JSBsim();
// crashed (altitude AGL < 0)
if (get_Altitude_AGL() < 0.0) {
crash_message = "Attempted to fly under ground.";
crash_handler();
}
}
/******************************************************************************/
@ -534,6 +525,7 @@ bool FGJSBsim::copy_to_JSBsim()
FCS->SetThrottleCmd(i, globals->get_controls()->get_throttle(i));
FCS->SetMixtureCmd(i, globals->get_controls()->get_mixture(i));
FCS->SetPropAdvanceCmd(i, globals->get_controls()->get_prop_advance(i));
FCS->SetFeatherCmd(i, globals->get_controls()->get_feather(i));
switch (Propulsion->GetEngine(i)->GetType()) {
case FGEngine::etPiston:
@ -557,6 +549,17 @@ bool FGJSBsim::copy_to_JSBsim()
FGRocket* eng = (FGRocket*)Propulsion->GetEngine(i);
break;
} // end FGRocket code block
case FGEngine::etTurboprop:
{ // FGTurboProp code block
FGTurboProp* eng = (FGTurboProp*)Propulsion->GetEngine(i);
eng->SetReverse( globals->get_controls()->get_reverser(i) );
eng->SetCutoff( globals->get_controls()->get_cutoff(i) );
eng->SetIgnition( globals->get_controls()->get_ignition(i) );
eng->SetGeneratorPower( globals->get_controls()->get_generator_breaker(i) );
eng->SetCondition( globals->get_controls()->get_condition(i) );
break;
} // end FGTurboProp code block
}
{ // FGEngine code block
@ -636,18 +639,18 @@ bool FGJSBsim::copy_from_JSBsim()
// Velocities
_set_Velocities_Local( Propagate->GetVel(eNorth),
Propagate->GetVel(eEast),
Propagate->GetVel(eDown) );
_set_Velocities_Local( Propagate->GetVel(FGJSBBase::eNorth),
Propagate->GetVel(FGJSBBase::eEast),
Propagate->GetVel(FGJSBBase::eDown) );
_set_Velocities_Wind_Body( Propagate->GetUVW(1),
Propagate->GetUVW(2),
Propagate->GetUVW(3) );
// Make the HUD work ...
_set_Velocities_Ground( Propagate->GetVel(eNorth),
Propagate->GetVel(eEast),
-Propagate->GetVel(eDown) );
_set_Velocities_Ground( Propagate->GetVel(FGJSBBase::eNorth),
Propagate->GetVel(FGJSBBase::eEast),
-Propagate->GetVel(FGJSBBase::eDown) );
_set_V_rel_wind( Auxiliary->GetVt() );
@ -657,13 +660,13 @@ bool FGJSBsim::copy_from_JSBsim()
_set_V_ground_speed( Auxiliary->GetVground() );
_set_Omega_Body( Propagate->GetPQR(eP),
Propagate->GetPQR(eQ),
Propagate->GetPQR(eR) );
_set_Omega_Body( Propagate->GetPQR(FGJSBBase::eP),
Propagate->GetPQR(FGJSBBase::eQ),
Propagate->GetPQR(FGJSBBase::eR) );
_set_Euler_Rates( Auxiliary->GetEulerRates(ePhi),
Auxiliary->GetEulerRates(eTht),
Auxiliary->GetEulerRates(ePsi) );
_set_Euler_Rates( Auxiliary->GetEulerRates(FGJSBBase::ePhi),
Auxiliary->GetEulerRates(FGJSBBase::eTht),
Auxiliary->GetEulerRates(FGJSBBase::ePsi) );
_set_Mach_number( Auxiliary->GetMach() );
@ -674,7 +677,7 @@ bool FGJSBsim::copy_from_JSBsim()
_set_Altitude_AGL( Propagate->GetDistanceAGL() );
{
double loc_cart[3] = { l(eX), l(eY), l(eZ) };
double loc_cart[3] = { l(FGJSBBase::eX), l(FGJSBBase::eY), l(FGJSBBase::eZ) };
double contact[3], d[3], sd, t;
int id;
is_valid_m(&t, d, &sd);
@ -684,9 +687,9 @@ bool FGJSBsim::copy_from_JSBsim()
_set_Runway_altitude( rwrad - get_Sea_level_radius() );
}
_set_Euler_Angles( Propagate->GetEuler(ePhi),
Propagate->GetEuler(eTht),
Propagate->GetEuler(ePsi) );
_set_Euler_Angles( Propagate->GetEuler(FGJSBBase::ePhi),
Propagate->GetEuler(FGJSBBase::eTht),
Propagate->GetEuler(FGJSBBase::ePsi) );
_set_Alpha( Auxiliary->Getalpha() );
_set_Beta( Auxiliary->Getbeta() );
@ -751,6 +754,28 @@ bool FGJSBsim::copy_from_JSBsim()
globals->get_controls()->set_augmentation(i, eng->GetAugmentation() );
} // end FGTurbine code block
break;
case FGEngine::etTurboprop:
{ // FGTurboProp code block
FGTurboProp* eng = (FGTurboProp*)Propulsion->GetEngine(i);
node->setDoubleValue("n1", eng->GetN1());
//node->setDoubleValue("n2", eng->GetN2());
node->setDoubleValue("itt_degf", 32 + eng->GetITT()*9/5);
node->setBoolValue("ignition", eng->GetIgnition());
node->setDoubleValue("nozzle-pos-norm", eng->GetNozzle());
node->setDoubleValue("inlet-pos-norm", eng->GetInlet());
node->setDoubleValue("oil-pressure-psi", eng->getOilPressure_psi());
node->setBoolValue("reversed", eng->GetReversed());
node->setBoolValue("cutoff", eng->GetCutoff());
node->setBoolValue("starting", eng->GetEngStarting());
node->setBoolValue("generator-power", eng->GetGeneratorPower());
node->setBoolValue("damaged", eng->GetCondition());
node->setBoolValue("ielu-intervent", eng->GetIeluIntervent());
node->setDoubleValue("oil-temperature-degf", eng->getOilTemp_degF());
// node->setBoolValue("onfire", eng->GetFire());
globals->get_controls()->set_reverser(i, eng->GetReversed() );
globals->get_controls()->set_cutoff(i, eng->GetCutoff() );
} // end FGTurboProp code block
break;
case FGEngine::etElectric:
{ // FGElectric code block
FGElectric* eng = (FGElectric*)Propulsion->GetEngine(i);
@ -782,6 +807,7 @@ bool FGJSBsim::copy_from_JSBsim()
tnode->setDoubleValue("rpm", thruster->GetRPM());
tnode->setDoubleValue("pitch", prop->GetPitch());
tnode->setDoubleValue("torque", prop->GetTorque());
tnode->setBoolValue("feathered", prop->GetFeather());
} // end FGPropeller code block
break;
case FGThruster::ttRotor:
@ -823,23 +849,32 @@ bool FGJSBsim::copy_from_JSBsim()
speedbrake_pos_pct->setDoubleValue( FCS->GetDsbPos(ofNorm) );
spoilers_pos_pct->setDoubleValue( FCS->GetDspPos(ofNorm) );
// force a sim reset if crashed (altitude AGL < 0)
if (get_Altitude_AGL() < 0.0) {
fgSetBool("/sim/crashed", true);
SGPropertyNode* node = fgGetNode("/sim/presets", true);
globals->get_commands()->execute("old-reinit-dialog", node);
}
return true;
}
bool FGJSBsim::ToggleDataLogging(void)
{
return fdmex->GetOutput()->Toggle();
// ToDo: handle this properly
fdmex->DisableOutput();
return false;
}
bool FGJSBsim::ToggleDataLogging(bool state)
{
if (state) {
fdmex->GetOutput()->Enable();
fdmex->EnableOutput();
return true;
} else {
fdmex->GetOutput()->Disable();
fdmex->DisableOutput();
return false;
}
}
@ -1098,17 +1133,3 @@ void FGJSBsim::update_ic(void)
}
}
void FGJSBsim::crash_handler(void)
{
if (crashed) return; // we already crashed
crashed = true;
fgSetBool("/sim/crashed", true);
SG_LOG( SG_FLIGHT, SG_WARN, " Crash: " << crash_message );
if (reset_on_crash) {
SGPropertyNode* node = fgGetNode("/sim/presets", true);
globals->get_commands()->execute("old-reinit-dialog", node);
} else {
fgSetBool("/sim/freeze/master", true);
fgSetBool("/sim/freeze/clock", true);
}
}

View file

@ -72,7 +72,8 @@ class FGOutput;
class FGInitialCondition;
}
using namespace JSBSim;
// Adding it here will cause a namespace clash in FlightGear -EMH-
// using namespace JSBSim;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
@ -205,24 +206,21 @@ public:
void do_trim(void);
void update_ic(void);
//** Handle a crash of the user aircraft. */
void crash_handler();
private:
FGFDMExec *fdmex;
FGInitialCondition *fgic;
JSBSim::FGFDMExec *fdmex;
JSBSim::FGInitialCondition *fgic;
bool needTrim;
FGState* State;
FGAtmosphere* Atmosphere;
FGFCS* FCS;
FGPropulsion* Propulsion;
FGMassBalance* MassBalance;
FGAircraft* Aircraft;
FGPropagate* Propagate;
FGAuxiliary* Auxiliary;
FGAerodynamics* Aerodynamics;
FGGroundReactions *GroundReactions;
JSBSim::FGState* State;
JSBSim::FGAtmosphere* Atmosphere;
JSBSim::FGFCS* FCS;
JSBSim::FGPropulsion* Propulsion;
JSBSim::FGMassBalance* MassBalance;
JSBSim::FGAircraft* Aircraft;
JSBSim::FGPropagate* Propagate;
JSBSim::FGAuxiliary* Auxiliary;
JSBSim::FGAerodynamics* Aerodynamics;
JSBSim::FGGroundReactions *GroundReactions;
int runcount;
double trim_elev;
@ -266,10 +264,6 @@ private:
void init_gear(void);
void update_gear(void);
bool reset_on_crash;
bool crashed;
string crash_message;
};

View file

@ -1,58 +1,9 @@
SUBDIRS = filtersjb
EXTRA_DIST = Makefile.solo
SUBDIRS = initialization models input_output math
noinst_LIBRARIES = libJSBSim.a
libJSBSim_a_SOURCES = \
FGAerodynamics.cpp FGAerodynamics.h \
FGAircraft.cpp FGAircraft.h \
FGAtmosphere.cpp FGAtmosphere.h \
FGAuxiliary.cpp FGAuxiliary.h \
FGCoefficient.cpp FGCoefficient.h \
FGColumnVector3.cpp FGColumnVector3.h \
FGConfigFile.cpp FGConfigFile.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 \
FGMatrix33.cpp FGMatrix33.h \
FGModel.cpp FGModel.h \
FGNozzle.cpp FGNozzle.h \
FGOutput.cpp FGOutput.h \
FGPiston.cpp FGPiston.h \
FGPropeller.cpp FGPropeller.h \
FGPropulsion.cpp FGPropulsion.h \
FGRotor.cpp FGRotor.h \
FGRocket.cpp FGRocket.h \
FGScript.cpp FGScript.h \
FGState.cpp FGState.h \
FGTable.cpp FGTable.h \
FGThruster.cpp FGThruster.h \
FGTrim.cpp FGTrim.h \
FGTrimAxis.cpp FGTrimAxis.h \
FGTurbine.cpp FGTurbine.h \
FGEngine.cpp FGEngine.h \
FGTank.cpp FGTank.h \
FGfdmSocket.cpp FGfdmSocket.h \
FGTurbine.cpp FGTurbine.h \
FGPropertyManager.cpp FGPropertyManager.h \
FGPropagate.cpp FGPropagate.h \
FGLocation.cpp FGLocation.h \
FGQuaternion.cpp FGQuaternion.h \
FGElectric.cpp FGElectric.h \
FGGroundCallback.cpp FGGroundCallback.h \
JSBSim.cxx JSBSim.hxx
libJSBSim_a_SOURCES = FGFDMExec.cpp FGJSBBase.cpp FGState.cpp JSBSim.cxx
noinst_HEADERS = FGFDMExec.h FGJSBBase.h FGState.h JSBSim.hxx
# noinst_PROGRAMS = testJSBsim
AM_CXXFLAGS = -DFGFS
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/FDM/JSBSim

View file

@ -1,413 +0,0 @@
CC = g++
INCLUDES = -I.
LINKDIR= -Lfiltersjb/
JSBSim_objects = FGAircraft.o FGAtmosphere.o FGCoefficient.o FGFCS.o FGFDMExec.o\
FGModel.o FGOutput.o FGPosition.o FGRotation.o FGState.o FGTranslation.o\
FGUtility.o FGTank.o FGAuxiliary.o FGfdmSocket.o FGTrim.o FGTrimAxis.o\
FGConfigFile.o FGInitialCondition.o FGLGear.o FGMatrix.o FGPropulsion.o FGRocket.o\
FGTurboShaft.o FGTurboJet.o FGTurboProp.o FGPiston.o FGForce.o FGThruster.o FGEngine.o\
FGTable.o FGPropeller.o FGNozzle.o FGAerodynamics.o FGMassBalance.o FGInertial.o\
FGFactorGroup.o
JSBSim : $(JSBSim_objects) JSBSim.o libFCSComponents.a
$(CC) $(INCLUDES) $(CCOPTS) $(LINKDIR) $(JSBSim_objects) JSBSim.o -oJSBSim -lm -lFCSComponents
libFCSComponents.a:
cd filtersjb; make -fMakefile.solo; cd ..
FGAerodynamics.o: FGAerodynamics.cpp FGAerodynamics.h FGModel.h \
FGDefs.h FGConfigFile.h FGState.h FGInitialCondition.h FGFDMExec.h \
FGAtmosphere.h FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h \
filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
FGCoefficient.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGAerodynamics.cpp
FGAircraft.o: FGAircraft.cpp FGAircraft.h FGModel.h FGDefs.h \
FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGInitialCondition.h \
FGFDMExec.h FGAtmosphere.h FGMatrix.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGConfigFile.h FGPosition.h FGRotation.h FGMassBalance.h \
FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGNozzle.h FGInertial.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGAircraft.cpp
FGAtmosphere.o: FGAtmosphere.cpp FGAtmosphere.h FGModel.h FGDefs.h \
FGMatrix.h FGState.h FGInitialCondition.h FGFDMExec.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGAtmosphere.cpp
FGAuxiliary.o: FGAuxiliary.cpp FGAuxiliary.h FGModel.h FGDefs.h \
FGMatrix.h FGTranslation.h FGRotation.h FGAtmosphere.h FGState.h \
FGInitialCondition.h FGFDMExec.h FGFCS.h filtersjb/FGFCSComponent.h \
filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h \
FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h FGPosition.h \
FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGAuxiliary.cpp
FGCoefficient.o: FGCoefficient.cpp FGCoefficient.h FGConfigFile.h \
FGDefs.h FGTable.h FGState.h FGInitialCondition.h FGFDMExec.h \
FGModel.h FGAtmosphere.h FGMatrix.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h \
FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h FGOutput.h \
FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h \
FGTank.h FGPropeller.h FGThruster.h FGForce.h FGNozzle.h \
FGMassBalance.h FGAerodynamics.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGCoefficient.cpp
FGColumnVector3.o: FGColumnVector3.cpp FGColumnVector3.h FGMatrix.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGColumnVector3.cpp
FGConfigFile.o: FGConfigFile.cpp FGConfigFile.h FGDefs.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGConfigFile.cpp
FGEngine.o: FGEngine.cpp FGEngine.h FGState.h FGDefs.h \
FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGEngine.cpp
FGFCS.o: FGFCS.cpp FGDefs.h FGFCS.h filtersjb/FGFCSComponent.h \
filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGModel.h FGLGear.h \
FGConfigFile.h FGMatrix.h FGFDMExec.h FGInitialCondition.h \
FGAtmosphere.h FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h \
FGState.h FGTranslation.h FGRotation.h FGPosition.h FGAerodynamics.h \
FGMassBalance.h FGCoefficient.h FGTable.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h \
FGNozzle.h filtersjb/FGFilter.h filtersjb/../FGConfigFile.h \
filtersjb/FGDeadBand.h filtersjb/FGGain.h filtersjb/../FGTable.h \
filtersjb/FGGradient.h filtersjb/FGSwitch.h filtersjb/FGSummer.h \
filtersjb/FGFlaps.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGFCS.cpp
FGFDMExec.o: FGFDMExec.cpp FGFDMExec.h FGModel.h FGDefs.h \
FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGState.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
FGFactorGroup.h FGInertial.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGFDMExec.cpp
FGFactorGroup.o: FGFactorGroup.cpp FGCoefficient.h FGConfigFile.h \
FGDefs.h FGTable.h FGFactorGroup.h FGAerodynamics.h FGModel.h \
FGState.h FGInitialCondition.h FGFDMExec.h FGAtmosphere.h FGMatrix.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGAircraft.h FGPropulsion.h FGRocket.h \
FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h \
FGNozzle.h FGMassBalance.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGFactorGroup.cpp
FGForce.o: FGForce.cpp FGFDMExec.h FGModel.h FGDefs.h \
FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGConfigFile.h FGPosition.h FGRotation.h FGMassBalance.h \
FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGNozzle.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGForce.cpp
FGGroundReactions.o: FGGroundReactions.cpp FGGroundReactions.h \
FGModel.h FGDefs.h FGConfigFile.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGGroundReactions.cpp
FGInertial.o: FGInertial.cpp FGInertial.h FGModel.h FGDefs.h \
FGConfigFile.h FGMatrix.h FGPosition.h FGMassBalance.h FGPropulsion.h \
FGRocket.h FGEngine.h FGState.h FGInitialCondition.h FGFDMExec.h \
FGAtmosphere.h FGFCS.h filtersjb/FGFCSComponent.h \
filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGAircraft.h \
FGRotation.h FGTranslation.h FGAerodynamics.h FGCoefficient.h \
FGTable.h FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h \
FGPiston.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h \
FGPropeller.h FGThruster.h FGForce.h FGNozzle.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGInertial.cpp
FGInitialCondition.o: FGInitialCondition.cpp FGInitialCondition.h \
FGFDMExec.h FGModel.h FGDefs.h FGAtmosphere.h FGMatrix.h FGState.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGInitialCondition.cpp
FGLGear.o: FGLGear.cpp FGLGear.h FGConfigFile.h FGDefs.h FGMatrix.h \
FGFDMExec.h FGModel.h FGInitialCondition.h FGAtmosphere.h \
FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGTranslation.h FGRotation.h FGPosition.h FGAerodynamics.h \
FGMassBalance.h FGCoefficient.h FGTable.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h \
FGNozzle.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGLGear.cpp
FGMassBalance.o: FGMassBalance.cpp FGMassBalance.h FGModel.h FGDefs.h \
FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGInitialCondition.h \
FGFDMExec.h FGAtmosphere.h FGMatrix.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGConfigFile.h FGAircraft.h FGPosition.h FGRotation.h \
FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGNozzle.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGMassBalance.cpp
FGMatrix.o: FGMatrix.cpp FGMatrix.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGMatrix.cpp
FGModel.o: FGModel.cpp FGModel.h FGDefs.h FGState.h \
FGInitialCondition.h FGFDMExec.h FGAtmosphere.h FGMatrix.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
FGFactorGroup.h FGInertial.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGModel.cpp
FGNozzle.o: FGNozzle.cpp FGNozzle.h FGThruster.h FGForce.h FGFDMExec.h \
FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h FGMatrix.h \
FGConfigFile.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGNozzle.cpp
FGOutput.o: FGOutput.cpp FGOutput.h FGModel.h FGDefs.h FGfdmSocket.h \
FGState.h FGInitialCondition.h FGFDMExec.h FGAtmosphere.h FGMatrix.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
FGPosition.h FGAuxiliary.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGOutput.cpp
FGPiston.o: FGPiston.cpp FGDefs.h FGPiston.h FGEngine.h FGState.h \
FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h \
FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGPiston.cpp
FGPosition.o: FGPosition.cpp FGPosition.h FGModel.h FGDefs.h \
FGMatrix.h FGAtmosphere.h FGState.h FGInitialCondition.h FGFDMExec.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
FGCoefficient.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGPosition.cpp
FGPropeller.o: FGPropeller.cpp FGPropeller.h FGThruster.h FGForce.h \
FGFDMExec.h FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h \
FGMatrix.h FGConfigFile.h FGTable.h FGTranslation.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGPropeller.cpp
FGPropulsion.o: FGPropulsion.cpp FGPropulsion.h FGModel.h FGDefs.h \
FGRocket.h FGEngine.h FGState.h FGInitialCondition.h FGFDMExec.h \
FGAtmosphere.h FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h \
filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h \
FGAircraft.h FGPosition.h FGRotation.h FGMassBalance.h \
FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGNozzle.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGPropulsion.cpp
FGRocket.o: FGRocket.cpp FGDefs.h FGRocket.h FGEngine.h FGState.h \
FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGPiston.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h \
FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGRocket.cpp
FGRotation.o: FGRotation.cpp FGRotation.h FGModel.h FGDefs.h \
FGMatrix.h FGAtmosphere.h FGState.h FGInitialCondition.h FGFDMExec.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGPosition.h \
FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
FGCoefficient.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGRotation.cpp
FGRotor.o: FGRotor.cpp FGRotor.h FGThruster.h FGForce.h FGFDMExec.h \
FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h FGMatrix.h \
FGConfigFile.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGRotor.cpp
FGState.o: FGState.cpp FGState.h FGDefs.h FGInitialCondition.h \
FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h FGFCS.h \
filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGState.cpp
FGTable.o: FGTable.cpp FGTable.h FGConfigFile.h FGDefs.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTable.cpp
FGTank.o: FGTank.cpp FGDefs.h FGTank.h FGConfigFile.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTank.cpp
FGThruster.o: FGThruster.cpp FGThruster.h FGForce.h FGFDMExec.h \
FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h FGMatrix.h \
FGConfigFile.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGThruster.cpp
FGTranslation.o: FGTranslation.cpp FGTranslation.h FGModel.h FGDefs.h \
FGMatrix.h FGRotation.h FGAtmosphere.h FGState.h FGInitialCondition.h \
FGFDMExec.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGPosition.h FGAuxiliary.h \
FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTranslation.cpp
FGTrim.o: FGTrim.cpp FGFDMExec.h FGModel.h FGDefs.h \
FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGTrim.h FGRotation.h \
FGState.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGPosition.h \
FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
FGCoefficient.h FGFactorGroup.h FGTrimAxis.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTrim.cpp
FGTrimAxis.o: FGTrimAxis.cpp FGFDMExec.h FGModel.h FGDefs.h \
FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGTrimAxis.h \
FGRotation.h FGState.h FGFCS.h filtersjb/FGFCSComponent.h \
filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h \
FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h \
FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTrimAxis.cpp
FGTurboJet.o: FGTurboJet.cpp FGTurboJet.h FGEngine.h FGState.h \
FGDefs.h FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h \
FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGPiston.h FGTurboShaft.h FGTurboProp.h \
FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTurboJet.cpp
FGTurboProp.o: FGTurboProp.cpp FGTurboProp.h FGEngine.h FGState.h \
FGDefs.h FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h \
FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTurboProp.cpp
FGTurboShaft.o: FGTurboShaft.cpp FGTurboShaft.h FGEngine.h FGState.h \
FGDefs.h FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h \
FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGPiston.h FGTurboJet.h FGTurboProp.h \
FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
FGfdmSocket.h FGAuxiliary.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGTurboShaft.cpp
FGUtility.o: FGUtility.cpp FGUtility.h FGState.h FGDefs.h \
FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
FGAerodynamics.h FGCoefficient.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGUtility.cpp
FGfdmSocket.o: FGfdmSocket.cpp FGfdmSocket.h
$(CC) $(INCLUDES) $(CCOPTS) -c FGfdmSocket.cpp
JSBSim.o: JSBSim.cpp FGFDMExec.h FGModel.h FGDefs.h \
FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGRotation.h FGState.h \
FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGPosition.h \
FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
FGCoefficient.h FGFactorGroup.h
$(CC) $(INCLUDES) $(CCOPTS) -c JSBSim.cpp
x15trim.o:x15trim.cpp
$(CC) $(INCLUDES) $(CCOPTS) -c x15trim.cpp
x15trim:$(JSBSim_objects) x15trim.o libFCSComponents.a
$(CC) $(INCLUDES) $(CCOPTS) $(LINKDIR) $(JSBSim_objects) x15trim.o -ox15trim -lm -lFCSComponents
clean:
-mv *.*~ backup
-rm *.o
all:
touch *.cpp
cd filtersjb; make all -fMakefile.solo; cd ..
make JSBSim -fMakefile.solo
debug:
touch *.cpp
touch filtersjb/*.cpp
cd filtersjb; make debug CCOPTS=-g -fMakefile.solo; cd ..
make JSBSim CCOPTS=-g -fMakefile.solo

View file

@ -1,76 +0,0 @@
Contents
--------
1) Introduction
2) Building with autoconf/automake
3) Contact
1) Introduction
---------------
JSBSim is a multi-platform, general purpose object-oriented Flight
Dynamics Model (FDM) written in C++. Jon Berndt and Tony Peden began
about mid-1998 writing JSBSim. As of this writing it is the default
FDM for FlightGear. JSBSim can also be run in a standalone batch mode
for testing and study. More information on JSBSim can be found at the
JSBSim home page here:
http://jsbsim.sourceforge.net
The standalone version of JSBSim can be easily built from the command
line of a unix or unix-like (CygWin/Linux/Unix/IRIX, etc.) system like
this:
make -fMakefile.solo
If you are on an IRIX machine you can use the Makefile.irix makefile.
Directions are also provided below for using traditional auto* utilities
also provided with JSBSim.
2) Building with autoconf/automake
----------------------------------
Unpack the distribution tarball (if needed - CVS users will have
downloaded the code directly) using your preferred method, and change
to the working directory. For example :
$ tar xvfz JSBSim-0.1.2.tar.gz
$ cd JSBSim-0.1.2
NOTE for CVS users: If you are using JSBSim from a CVS checkout, or
snapshot, you will need to create the initial configure script. The
commands to do this have been included in the 'autogen.sh' script, so
just :
$ ./autogen.sh
If you wish to customise your version of JSBSim, use the following to
determine any build-time options you may be interested in.
$ ./configure --help
Then :
$ ./configure
This will check your system platform, compiler and other local
configuration variables needed to build JSBSim, and generates the
necessary Makefiles. Next :
$ make
Will compile the various classes, and link the library. Finally :
$ make install
Unless specified otherwise (with --prefix configure option), this will
install 'JSBSim.a' into '/usr/local/lib'.
3) Contact
----------
For more information on JSBSim contact Jon Berndt at jsbsim@hal-pc.org.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,328 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGInitialCondition.h
Author: Tony Peden
Date started: 7/1/99
------------- Copyright (C) 1999 Anthony K. Peden (apeden@earthlink.net) -------------
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.
HISTORY
--------------------------------------------------------------------------------
7/1/99 TP Created
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
The purpose of this class is to take 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.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGINITIALCONDITION_H
#define FGINITIALCONDITION_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <FGFDMExec.h>
#include <FGJSBBase.h>
#include <math/FGColumnVector3.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INITIALCONDITION "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
typedef enum { setwned, setwmd, setwhc } windset;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
With a valid object of FGFDMExec and an aircraft model loaded
FGInitialCondition fgic=new FGInitialCondition(FDMExec);
fgic->SetVcalibratedKtsIC()
fgic->SetAltitudeFtIC();
//to directly into Run
FDMExec->GetState()->Initialize(fgic)
delete fgic;
FDMExec->Run()
//or to loop the sim w/o integrating
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
that if and when altitude is reset, the last set speed is used
to recalculate the remaining three. Setting any of the body
components forces a recalculation of vt and vt then becomes the
most recent speed set.
Alpha,Gamma, and Theta:
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
The idea being that gamma is most interesting to pilots (since it
is indicative of climb rate).
Setting climb rate is, for the purpose of this discussion,
considered equivalent to setting gamma.
These are the items that can be set in an initialization file:
UBODY <velocity, ft/sec>
VBODY <velocity, ft/sec>
WBODY <velocity, ft/sec>
LATITUDE <position, degrees>
LONGITUDE <position, degrees>
PHI <orientation, degrees>
THETA <orientation, degrees>
PSI <orientation, degrees>
ALPHA <angle, degrees>
BETA <angle, degrees>
GAMMA <angle, degrees>
ROC <vertical velocity, ft/sec>
ALTITUDE <altitude, ft>
WINDDIR <wind from-angle, degrees>
VWIND <magnitude wind speed, ft/sec>
HWIND <headwind speed, knots>
XWIND <crosswind speed, knots>
VC <calibrated airspeed, ft/sec>
MACH <mach>
VGROUND <ground speed, ft/sec>
RUNNING <0 or 1>
@author Tony Peden
@version "$Id$"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGInitialCondition : public FGJSBBase
{
public:
/// Constructor
FGInitialCondition(FGFDMExec *fdmex);
/// Destructor
~FGInitialCondition();
void SetVcalibratedKtsIC(double tt);
void SetVequivalentKtsIC(double tt);
inline void SetVtrueKtsIC(double tt) { SetVtrueFpsIC(tt*ktstofps); }
inline void SetVgroundKtsIC(double tt) { SetVgroundFpsIC(tt*ktstofps); }
void SetMachIC(double tt);
inline void SetAlphaDegIC(double tt) { SetAlphaRadIC(tt*degtorad); }
inline void SetBetaDegIC(double tt) { SetBetaRadIC(tt*degtorad);}
inline void SetPitchAngleDegIC(double tt) { SetPitchAngleRadIC(tt*degtorad); }
inline void SetRollAngleDegIC(double tt) { SetRollAngleRadIC(tt*degtorad);}
inline void SetTrueHeadingDegIC(double tt){ SetTrueHeadingRadIC(tt*degtorad); }
void SetClimbRateFpmIC(double tt);
inline void SetFlightPathAngleDegIC(double tt) { SetFlightPathAngleRadIC(tt*degtorad); }
void SetAltitudeFtIC(double tt);
void SetAltitudeAGLFtIC(double tt);
void SetSeaLevelRadiusFtIC(double tt);
void SetTerrainAltitudeFtIC(double tt);
inline void SetLatitudeDegIC(double tt) { latitude=tt*degtorad; }
inline void SetLongitudeDegIC(double tt) { longitude=tt*degtorad; }
inline double GetVcalibratedKtsIC(void) const { return vc*fpstokts; }
inline double GetVequivalentKtsIC(void) const { return ve*fpstokts; }
inline double GetVgroundKtsIC(void) const { return vg*fpstokts; }
inline double GetVtrueKtsIC(void) const { return vt*fpstokts; }
inline double GetMachIC(void) const { return mach; }
inline double GetClimbRateFpmIC(void) const { return hdot*60; }
inline double GetFlightPathAngleDegIC(void)const { return gamma*radtodeg; }
inline double GetAlphaDegIC(void) const { return alpha*radtodeg; }
inline double GetBetaDegIC(void) const { return beta*radtodeg; }
inline double GetPitchAngleDegIC(void) const { return theta*radtodeg; }
inline double GetRollAngleDegIC(void) const { return phi*radtodeg; }
inline double GetHeadingDegIC(void) const { return psi*radtodeg; }
inline double GetLatitudeDegIC(void) const { return latitude*radtodeg; }
inline double GetLongitudeDegIC(void) const { return longitude*radtodeg; }
inline double GetAltitudeFtIC(void) const { return altitude; }
inline double GetAltitudeAGLFtIC(void) const { return altitude - terrain_altitude; }
inline double GetSeaLevelRadiusFtIC(void) const { return sea_level_radius; }
inline double GetTerrainAltitudeFtIC(void) const { return terrain_altitude; }
void SetVgroundFpsIC(double tt);
void SetVtrueFpsIC(double tt);
void SetUBodyFpsIC(double tt);
void SetVBodyFpsIC(double tt);
void SetWBodyFpsIC(double tt);
void SetVnorthFpsIC(double tt);
void SetVeastFpsIC(double tt);
void SetVdownFpsIC(double tt);
void SetPRadpsIC(double tt) { p = tt; }
void SetQRadpsIC(double tt) { q = tt; }
void SetRRadpsIC(double tt) { r = tt; }
void SetWindNEDFpsIC(double wN, double wE, double wD);
void SetWindMagKtsIC(double mag);
void SetWindDirDegIC(double dir);
void SetHeadWindKtsIC(double head);
void SetCrossWindKtsIC(double cross);// positive from left
void SetWindDownKtsIC(double wD);
void SetClimbRateFpsIC(double tt);
inline double GetVgroundFpsIC(void) const { return vg; }
inline double GetVtrueFpsIC(void) const { return vt; }
inline double GetWindUFpsIC(void) const { return uw; }
inline double GetWindVFpsIC(void) const { return vw; }
inline double GetWindWFpsIC(void) const { return ww; }
inline double GetWindNFpsIC(void) const { return wnorth; }
inline double GetWindEFpsIC(void) const { return weast; }
inline double GetWindDFpsIC(void) const { return wdown; }
inline double GetWindFpsIC(void) const { return sqrt(wnorth*wnorth + weast*weast); }
double GetWindDirDegIC(void);
inline double GetClimbRateFpsIC(void) const { return hdot; }
double GetUBodyFpsIC(void) const;
double GetVBodyFpsIC(void) const;
double GetWBodyFpsIC(void) const;
double GetPRadpsIC() const { return p; }
double GetQRadpsIC() const { return q; }
double GetRRadpsIC() const { return r; }
void SetFlightPathAngleRadIC(double tt);
void SetAlphaRadIC(double tt);
void SetPitchAngleRadIC(double tt);
void SetBetaRadIC(double tt);
void SetRollAngleRadIC(double tt);
void SetTrueHeadingRadIC(double tt);
inline void SetLatitudeRadIC(double tt) { latitude=tt; }
inline void SetLongitudeRadIC(double tt) { longitude=tt; }
inline double GetFlightPathAngleRadIC(void) const { return gamma; }
inline double GetAlphaRadIC(void) const { return alpha; }
inline double GetPitchAngleRadIC(void) const { return theta; }
inline double GetBetaRadIC(void) const { return beta; }
inline double GetRollAngleRadIC(void) const { return phi; }
inline double GetHeadingRadIC(void) const { return psi; }
inline double GetLatitudeRadIC(void) const { return latitude; }
inline double GetLongitudeRadIC(void) const { return longitude; }
inline double GetThetaRadIC(void) const { return theta; }
inline double GetPhiRadIC(void) const { return phi; }
inline double GetPsiRadIC(void) const { return psi; }
inline speedset GetSpeedSet(void) { return lastSpeedSet; }
inline windset GetWindSet(void) { return lastWindSet; }
bool Load(string rstname, bool useStoredPath = true );
void bind(void);
void unbind(void);
private:
double vt,vc,ve,vg;
double mach;
double altitude,hdot;
double latitude,longitude;
double u,v,w;
double p,q,r;
double uw,vw,ww;
double vnorth,veast,vdown;
double wnorth,weast,wdown;
double whead, wcross, wdir, wmag;
double sea_level_radius;
double terrain_altitude;
double radius_to_vehicle;
double alpha, beta, theta, phi, psi, gamma;
double salpha,sbeta,stheta,sphi,spsi,sgamma;
double calpha,cbeta,ctheta,cphi,cpsi,cgamma;
double xlo, xhi,xmin,xmax;
typedef double (FGInitialCondition::*fp)(double x);
fp sfunc;
speedset lastSpeedSet;
windset lastWindSet;
FGFDMExec *fdmex;
FGPropertyManager *PropertyManager;
bool getAlpha(void);
bool getTheta(void);
bool getMachFromVcas(double *Mach,double vcas);
double GammaEqOfTheta(double Theta);
double GammaEqOfAlpha(double Alpha);
double calcVcas(double Mach);
void calcUVWfromNED(void);
void calcWindUVW(void);
bool findInterval(double x,double guess);
bool solve(double *y, double x);
void Debug(int from);
};
}
#endif

View file

@ -39,23 +39,22 @@ scheme. */
// !!!!!!! BEWARE ALL YE WHO ENTER HERE !!!!!!!
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <stdlib.h>
#include "FGFDMExec.h"
#include "FGAtmosphere.h"
#include <FGFDMExec.h>
#include <models/FGAtmosphere.h>
#include "FGInitialCondition.h"
#include "FGTrim.h"
#include "FGAircraft.h"
#include "FGMassBalance.h"
#include "FGGroundReactions.h"
#include "FGInertial.h"
#include "FGAerodynamics.h"
#include "FGColumnVector3.h"
#include <models/FGAircraft.h>
#include <models/FGMassBalance.h>
#include <models/FGGroundReactions.h>
#include <models/FGInertial.h>
#include <models/FGAerodynamics.h>
#include <math/FGColumnVector3.h>
#if _MSC_VER
#pragma warning (disable : 4786 4788)
@ -241,7 +240,7 @@ bool FGTrim::DoTrim(void) {
fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false);
}
fdmex->GetOutput()->Disable();
fdmex->DisableOutput();
fgic->SetPRadpsIC(0.0);
fgic->SetQRadpsIC(0.0);
@ -358,7 +357,7 @@ bool FGTrim::DoTrim(void) {
for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
}
fdmex->GetOutput()->Enable();
fdmex->EnableOutput();
return !trim_failed;
}

View file

@ -72,9 +72,8 @@ FORWARD DECLARATIONS
namespace JSBSim {
typedef enum { tLongitudinal, tFull, tGround, tPullup,
tCustom, tNone, tTurn
} TrimMode;
typedef enum { tLongitudinal=0, tFull, tGround, tPullup,
tCustom, tTurn, tNone } TrimMode;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION

View file

@ -36,20 +36,16 @@ INCLUDES
# pragma warning (disable : 4786)
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string>
#include <stdlib.h>
#include "FGFDMExec.h"
#include "FGAtmosphere.h"
#include <FGFDMExec.h>
#include <models/FGAtmosphere.h>
#include "FGInitialCondition.h"
#include "FGTrimAxis.h"
#include "FGAircraft.h"
#include "FGPropulsion.h"
#include "FGAerodynamics.h"
#include <models/FGAircraft.h>
#include <models/FGPropulsion.h>
#include <models/FGAerodynamics.h>
namespace JSBSim {

View file

@ -0,0 +1,7 @@
noinst_LIBRARIES = libInit.a
libInit_a_SOURCES = FGInitialCondition.cpp FGTrim.cpp FGTrimAxis.cpp
noinst_HEADERS = FGInitialCondition.h FGTrim.h FGTrimAxis.h
INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim

View file

@ -0,0 +1,74 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGGroundCallback.cpp
Author: Mathias Froehlich
Date started: 05/21/04
------ Copyright (C) 2004 Mathias Froehlich (Mathias.Froehlich@web.de) -------
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.
HISTORY
-------------------------------------------------------------------------------
05/21/00 MF Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <math/FGColumnVector3.h>
#include <math/FGLocation.h>
#include "FGGroundCallback.h"
namespace JSBSim {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGGroundCallback::FGGroundCallback()
{
mReferenceRadius = 20925650.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGGroundCallback::~FGGroundCallback()
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGGroundCallback::GetAltitude(const FGLocation& loc) const
{
return loc.GetRadius() - mReferenceRadius;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGGroundCallback::GetAGLevel(double t, const FGLocation& loc,
FGLocation& contact, FGColumnVector3& normal,
FGColumnVector3& vel) const
{
vel = FGColumnVector3(0.0, 0.0, 0.0);
normal = (-1/FGColumnVector3(loc).Magnitude())*FGColumnVector3(loc);
double radius = loc.GetRadius();
double agl = GetAltitude(loc);
contact = ((radius-agl)/radius)*FGColumnVector3(loc);
return agl;
}
}

View file

@ -0,0 +1,87 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGGroundCallback.h
Author: Mathias Froehlich
Date started: 05/21/04
------ Copyright (C) 2004 Mathias Froehlich (Mathias.Froehlich@web.de) -------
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.
HISTORY
-------------------------------------------------------------------------------
05/21/00 MF Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGGROUNDCALLBACK_H
#define FGGROUNDCALLBACK_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <math/FGColumnVector3.h>
#include <math/FGLocation.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_GROUNDCALLBACK "$Id$"
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** This class provides callback slots to get ground specific data like
ground elevation and such.
There is a default implementation, which returns values for a
ball formed earth.
@author Mathias Froehlich
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGGroundCallback : public FGJSBBase
{
public:
FGGroundCallback();
virtual ~FGGroundCallback();
/** Compute the altitude above sealevel. */
virtual double GetAltitude(const FGLocation& l) const;
/** Compute the altitude above ground. Defaults to sealevel altitude. */
virtual double GetAGLevel(double t, const FGLocation& l, FGLocation& cont,
FGColumnVector3& n, FGColumnVector3& v) const;
private:
/// Reference radius.
double mReferenceRadius;
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -61,11 +61,12 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
else if( isspace(name[i]) )
name[i]='-';
}
/*
for(i=0;i<name.length();i++) {
if( name[i] == '/' )
name.erase(i,1);
}
*/
return name;
}
@ -75,9 +76,9 @@ FGPropertyManager*
FGPropertyManager::GetNode (const string &path, bool create)
{
SGPropertyNode* node=this->getNode(path.c_str(), create);
//if(node == 0)
// cout << "FGPropertyManager::GetNode() No node found for "
// << path << endl;
if (node == 0 && !suppress_warning)
cout << "FGPropertyManager::GetNode() No node found for "
<< path << endl;
return (FGPropertyManager*)node;
}
@ -94,7 +95,11 @@ FGPropertyManager::GetNode (const string &relpath, int index, bool create)
bool FGPropertyManager::HasNode (const string &path)
{
return (GetNode(path, false) != 0);
// Checking if a node exists shouldn't write a warning if it doesn't exist
suppress_warning = true;
bool has_node = (GetNode(path, false) != 0);
suppress_warning = false;
return has_node;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -264,10 +269,10 @@ void FGPropertyManager::Untie (const string &name)
void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
{
if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer),
useDefault))
cout <<
"Failed to tie property " << name << " to a pointer" << endl;
if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer), useDefault))
cout << "Failed to tie property " << name << " to a pointer" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -275,10 +280,10 @@ void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
void FGPropertyManager::Tie (const string &name, int *pointer,
bool useDefault )
{
if (!tie(name.c_str(), SGRawValuePointer<int>(pointer),
useDefault))
cout <<
"Failed to tie property " << name << " to a pointer" << endl;
if (!tie(name.c_str(), SGRawValuePointer<int>(pointer), useDefault))
cout << "Failed to tie property " << name << " to a pointer" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -286,10 +291,10 @@ void FGPropertyManager::Tie (const string &name, int *pointer,
void FGPropertyManager::Tie (const string &name, long *pointer,
bool useDefault )
{
if (!tie(name.c_str(), SGRawValuePointer<long>(pointer),
useDefault))
cout <<
"Failed to tie property " << name << " to a pointer" << endl;
if (!tie(name.c_str(), SGRawValuePointer<long>(pointer), useDefault))
cout << "Failed to tie property " << name << " to a pointer" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -297,21 +302,20 @@ void FGPropertyManager::Tie (const string &name, long *pointer,
void FGPropertyManager::Tie (const string &name, float *pointer,
bool useDefault )
{
if (!tie(name.c_str(), SGRawValuePointer<float>(pointer),
useDefault))
cout <<
"Failed to tie property " << name << " to a pointer" << endl;
if (!tie(name.c_str(), SGRawValuePointer<float>(pointer), useDefault))
cout << "Failed to tie property " << name << " to a pointer" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Tie (const string &name, double *pointer,
bool useDefault)
void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault)
{
if (!tie(name.c_str(), SGRawValuePointer<double>(pointer),
useDefault))
cout <<
"Failed to tie property " << name << " to a pointer" << endl;
if (!tie(name.c_str(), SGRawValuePointer<double>(pointer), useDefault))
cout << "Failed to tie property " << name << " to a pointer" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
} // namespace JSBSim

View file

@ -37,11 +37,13 @@ INCLUDES
#include <string>
#ifdef FGFS
#include <simgear/props/props.hxx>
# include <simgear/props/props.hxx>
#else
#include "simgear/props/props.hxx"
# include "simgear/props/props.hxx"
#endif
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -68,10 +70,13 @@ CLASS DOCUMENTATION
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGPropertyManager : public SGPropertyNode {
class FGPropertyManager : public SGPropertyNode, public FGJSBBase
{
private:
bool suppress_warning;
public:
/// Constructor
FGPropertyManager(void) {}
FGPropertyManager(void) {suppress_warning = false;}
/// Destructor
~FGPropertyManager(void) {}
@ -500,15 +505,12 @@ class FGPropertyManager : public SGPropertyNode {
*/
template <class V> inline void
Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
bool useDefault = true)
Tie (const string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter),
useDefault))
{
cout <<
"Failed to tie property " << name << " to functions" << endl;
}
if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter), useDefault))
cout << "Failed to tie property " << name << " to functions" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
@ -527,19 +529,16 @@ class FGPropertyManager : public SGPropertyNode {
* @param getter The getter function, or 0 if the value is unreadable.
* @param setter The setter function, or 0 if the value is unmodifiable.
* @param useDefault true if the setter should be invoked with any existing
* property value should be; false if the old value should be
* property value should there be one; false if the old value should be
* discarded; defaults to true.
*/
template <class V> inline void Tie (const string &name,
int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true)
template <class V> inline void Tie (const string &name, int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(),
SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
{
cout <<
"Failed to tie property " << name << " to indexed functions" << endl;
}
if (!tie(name.c_str(), SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
cout << "Failed to tie property " << name << " to indexed functions" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
@ -566,12 +565,10 @@ class FGPropertyManager : public SGPropertyNode {
Tie (const string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(),
SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
{
cout <<
"Failed to tie property " << name << " to object methods" << endl;
}
if (!tie(name.c_str(), SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
cout << "Failed to tie property " << name << " to object methods" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
/**
@ -594,16 +591,13 @@ class FGPropertyManager : public SGPropertyNode {
* discarded; defaults to true.
*/
template <class T, class V> inline void
Tie (const string &name, T * obj, int index,
V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
bool useDefault = true)
Tie (const string &name, T * obj, int index, V (T::*getter)(int) const,
void (T::*setter)(int, V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(),
SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
{
cout <<
"Failed to tie property " << name << " to indexed object methods" << endl;
}
if (!tie(name.c_str(), SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
cout << "Failed to tie property " << name << " to indexed object methods" << endl;
else if (debug_lvl & 0x20)
cout << name << endl;
}
};
}

View file

@ -41,10 +41,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef FGFS
# include <simgear/compiler.h>
# include STL_IOSTREAM
@ -59,8 +55,8 @@ INCLUDES
#endif
#include "FGScript.h"
#include "FGConfigFile.h"
#include "FGTrim.h"
#include "FGXMLParse.h"
#include <initialization/FGTrim.h>
namespace JSBSim {
@ -95,134 +91,126 @@ FGScript::~FGScript()
bool FGScript::LoadScript( string script )
{
FGConfigFile Script(script);
string token="";
string aircraft="";
string initialize="";
string prop_name;
string aircraft="", initialize="", comparison = "", prop_name="";
Element *document=0, *element=0, *run_element=0, *when_element=0;
Element *parameter_element=0, *set_element=0;
bool result = false;
double dt = 0.0;
double dt = 0.0, value = 0.0;
FGXMLParse script_file_parser;
struct condition *newCondition;
ifstream script_file(script.c_str());
if (!Script.IsOpen()) return false;
if ( !script_file ) return false;
Script.GetNextConfigLine();
if (Script.GetValue("runscript").length() <= 0) {
readXML(script_file, script_file_parser);
document = script_file_parser.GetDocument();
if (document->GetName() != string("runscript")) {
cerr << "File: " << script << " is not a script file" << endl;
delete FDMExec;
return false;
}
ScriptName = Script.GetValue("name");
Scripted = true;
if (debug_lvl > 0) cout << "Reading and running from script file " << ScriptName << endl << endl;
// read aircraft and initialization files
while (Script.GetNextConfigLine() != string("EOF") && Script.GetValue() != string("/runscript")) {
token = Script.GetValue();
if (token == "use") {
if ((token = Script.GetValue("aircraft")) != string("")) {
aircraft = token;
result = FDMExec->LoadModel(aircraft);
if (!result) {
cerr << "Aircraft file " << aircraft << " was not found" << endl;
exit(-1);
}
if (debug_lvl > 0) cout << " Use aircraft: " << token << endl;
} else if ((token = Script.GetValue("initialize")) != string("")) {
initialize = token;
if (debug_lvl > 0) cout << " Use reset file: " << token << endl;
} else {
cerr << "Unknown 'use' keyword: \"" << token << "\"" << endl;
}
} else if (token == "run") {
StartTime = strtod(Script.GetValue("start").c_str(), NULL);
State->Setsim_time(StartTime);
EndTime = strtod(Script.GetValue("end").c_str(), NULL);
dt = strtod(Script.GetValue("dt").c_str(), NULL);
State->Setdt(dt);
Script.GetNextConfigLine();
token = Script.GetValue();
while (token != string("/run")) {
if (token == "when") {
Script.GetNextConfigLine();
token = Script.GetValue();
newCondition = new struct condition();
while (token != string("/when")) {
if (token == "parameter") {
prop_name = Script.GetValue("name");
newCondition->TestParam.push_back( PropertyManager->GetNode(prop_name) );
newCondition->TestValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
newCondition->Comparison.push_back(Script.GetValue("comparison"));
} else if (token == "set") {
prop_name = Script.GetValue("name");
newCondition->SetParam.push_back( PropertyManager->GetNode(prop_name) );
newCondition->SetValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
newCondition->Triggered.push_back(false);
newCondition->OriginalValue.push_back(0.0);
newCondition->newValue.push_back(0.0);
newCondition->StartTime.push_back(0.0);
newCondition->EndTime.push_back(0.0);
string tempCompare = Script.GetValue("type");
if (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);
else if (tempCompare == "FG_BOOL") newCondition->Type.push_back(FG_BOOL);
else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);
else newCondition->Type.push_back((eType)0);
tempCompare = Script.GetValue("action");
if (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);
else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);
else if (tempCompare == "FG_EXP") newCondition->Action.push_back(FG_EXP);
else newCondition->Action.push_back((eAction)0);
if (Script.GetValue("persistent") == "true")
newCondition->Persistent.push_back(true);
else
newCondition->Persistent.push_back(false);
newCondition->TC.push_back(strtod(Script.GetValue("tc").c_str(), NULL));
} else {
cerr << "Unrecognized keyword in script file: \" [when] " << token << "\"" << endl;
}
Script.GetNextConfigLine();
token = Script.GetValue();
}
Conditions.push_back(*newCondition);
Script.GetNextConfigLine();
token = Script.GetValue();
} else {
cerr << "Error reading script file: expected \"when\", got \"" << token << "\"" << endl;
}
}
} else if (token.empty()) {
// do nothing
element = document->FindElement("use");
if (element) {
aircraft = element->GetAttributeValue("aircraft");
if (!aircraft.empty()) {
result = FDMExec->LoadModel(aircraft);
if (!result) return false;
} else {
cerr << "Unrecognized keyword in script file: \"" << token << "\" [runscript] " << endl;
cerr << "Aircraft must be specified first in script file." << endl;
return false;
}
element = document->FindNextElement("use");
initialize = element->GetAttributeValue("initialize");
} else {
cerr << "No \"use\" directives in the script file." << endl;
return false;
}
if (aircraft == "") {
cerr << "Aircraft file not loaded in script" << endl;
exit(-1);
run_element = document->FindElement("run");
if (!run_element) {
cerr << "No \"run\" element found in script." << endl;
return false;
}
// Set sim timing
StartTime = run_element->GetAttributeValueAsNumber("start");
State->Setsim_time(StartTime);
EndTime = run_element->GetAttributeValueAsNumber("end");
dt = run_element->GetAttributeValueAsNumber("dt");
State->Setdt(dt);
// read "when" tests from script
when_element = run_element->FindElement("when");
while (when_element) { // "when" processing
newCondition = new struct condition();
// read parameters
parameter_element = when_element->FindElement("parameter");
while (parameter_element) {
prop_name = parameter_element->GetAttributeValue("name");
newCondition->TestParam.push_back( PropertyManager->GetNode(prop_name) );
value = parameter_element->GetAttributeValueAsNumber("value");
newCondition->TestValue.push_back(value);
comparison = parameter_element->GetAttributeValue("comparison");
newCondition->Comparison.push_back(comparison);
parameter_element = when_element->FindNextElement("parameter");
}
// read set definitions
set_element = when_element->FindElement("set");
while (set_element) {
prop_name = set_element->GetAttributeValue("name");
newCondition->SetParam.push_back( PropertyManager->GetNode(prop_name) );
value = set_element->GetAttributeValueAsNumber("value");
newCondition->SetValue.push_back(value);
newCondition->Triggered.push_back(false);
newCondition->OriginalValue.push_back(0.0);
newCondition->newValue.push_back(0.0);
newCondition->StartTime.push_back(0.0);
newCondition->EndTime.push_back(0.0);
string tempCompare = set_element->GetAttributeValue("type");
if (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);
else if (tempCompare == "FG_BOOL") newCondition->Type.push_back(FG_BOOL);
else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);
else newCondition->Type.push_back(FG_VALUE); // DEFAULT
tempCompare = set_element->GetAttributeValue("action");
if (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);
else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);
else if (tempCompare == "FG_EXP") newCondition->Action.push_back(FG_EXP);
else newCondition->Action.push_back(FG_STEP); // DEFAULT
if (set_element->GetAttributeValue("persistent") == "true")
newCondition->Persistent.push_back(true);
else
newCondition->Persistent.push_back(false); // DEFAULT
if (!set_element->GetAttributeValue("tc").empty())
newCondition->TC.push_back(set_element->GetAttributeValueAsNumber("tc"));
else
newCondition->TC.push_back(1.0); // DEFAULT
set_element = when_element->FindNextElement("set");
}
Conditions.push_back(*newCondition);
when_element = run_element->FindNextElement("when");
}
Debug(4);
FGInitialCondition *IC=FDMExec->GetIC();
if ( ! IC->Load( initialize )) {
cerr << "Initialization unsuccessful" << endl;
exit(-1);
}
/* comment this out for conversion capability
FGTrim fgt(FDMExec, tFull);
if ( !fgt.DoTrim() ) {
cout << "Trim Failed" << endl;
}
fgt.Report();
*/
return true;
}
@ -289,18 +277,21 @@ bool FGScript::RunScript(void)
iC->StartTime[i] = currentTime;
}
double time_span = currentTime - iC->StartTime[i];
double value_span = iC->newValue[i] - iC->OriginalValue[i];
switch (iC->Action[i]) {
case FG_RAMP:
newSetValue = (currentTime - iC->StartTime[i])/(iC->TC[i])
* (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
if (newSetValue > iC->newValue[i]) newSetValue = iC->newValue[i];
if (time_span <= iC->TC[i])
newSetValue = time_span/iC->TC[i] * value_span + iC->OriginalValue[i];
else
newSetValue = iC->newValue[i];
break;
case FG_STEP:
newSetValue = iC->newValue[i];
break;
case FG_EXP:
newSetValue = (1 - exp(-(currentTime - iC->StartTime[i])/(iC->TC[i])))
* (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
newSetValue = (1 - exp( -time_span/iC->TC[i] )) * value_span + iC->OriginalValue[i];
break;
default:
cerr << "Invalid Action specified" << endl;

View file

@ -0,0 +1,417 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Author: Jon Berndt
Date started: 09/28/2004
Purpose: XML element class
Called by: FGXMLParse
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGXMLElement.h"
#ifdef FGFS
# ifndef __BORLANDC__
# include <simgear/compiler.h>
# endif
# ifdef SG_HAVE_STD_INCLUDES
# include <cmath>
# include <cstdlib>
# else
# include <math.h>
# include <stdlib.h>
# endif
#else
# if defined (sgi) && !defined(__GNUC__)
# include <math.h>
# include <stdlib.h>
# else
# include <cmath>
# include <cstdlib>
# endif
#endif
#include <stdlib.h>
#include <math.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_XMLELEMENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
Element::Element(string nm)
{
name = nm;
parent = 0L;
element_index = 0;
// convert ["from"]["to"] = factor, so: from * factor = to
convert["M"]["FT"] = 3.2808399;
convert["FT"]["M"] = 1.0/convert["M"]["FT"];
convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
convert["FT"]["IN"] = 12.0;
convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
convert["LBS"]["KG"] = 0.45359237;
convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
convert["SLUG*FT2"]["KG*M2"] = 1.35594;
convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
convert["LBS/FT"]["N/M"] = 14.5939;
convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
convert["WATTS"]["HP"] = 0.001341022;
convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
convert["N"]["LBS"] = 0.22482;
convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
convert["KTS"]["FT/SEC"] = 1.68781;
convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
convert["FT*LBS"]["N*M"] = 1.35581795;
convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
convert["M"]["M"] = 1.00;
convert["FT"]["FT"] = 1.00;
convert["IN"]["IN"] = 1.00;
convert["IN3"]["IN3"] = 1.00;
convert["DEG"]["DEG"] = 1.00;
convert["RAD"]["RAD"] = 1.00;
convert["M2"]["M2"] = 1.00;
convert["FT2"]["FT2"] = 1.00;
convert["KG*M2"]["KG*M2"] = 1.00;
convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
convert["KG"]["KG"] = 1.00;
convert["LBS"]["LBS"] = 1.00;
convert["LBS/FT"]["LBS/FT"] = 1.00;
convert["LBS/SEC"]["LBS/SEC"] = 1.00;
convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
convert["N/M"]["N/M"] = 1.00;
convert["N/M/SEC"]["N/M/SEC"] = 1.00;
convert["PSI"]["PSI"] = 1.00;
convert["PSF"]["PSF"] = 1.00;
convert["INHG"]["INHG"] = 1.00;
convert["HP"]["HP"] = 1.00;
convert["N"]["N"] = 1.00;
convert["WATTS"]["WATTS"] = 1.00;
convert["LBS/SEC"]["LBS/SEC"] = 1.00;
convert["FT/SEC"]["FT/SEC"] = 1.00;
convert["KTS"]["KTS"] = 1.00;
convert["FT*LBS"]["FT*LBS"] = 1.00;
convert["N*M"]["N*M"] = 1.00;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Element::~Element(void)
{
for (int i=0; i<children.size(); i++) delete children[i];
data_lines.clear();
attributes.clear();
attribute_key.clear();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string Element::GetAttributeValue(string attr)
{
int select=-1;
for (int i=0; i<attribute_key.size(); i++) {
if (attribute_key[i] == attr) select = i;
}
if (select < 0) return string("");
else return attributes[attr];
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double Element::GetAttributeValueAsNumber(string attr)
{
string attribute = GetAttributeValue(attr);
if (attribute.empty()) return 99e99;
else return (atof(attribute.c_str()));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Element* Element::GetElement(int el)
{
if (children.size() > el) {
element_index = el;
return children[el];
}
else {
element_index = 0;
return 0L;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Element* Element::GetNextElement(void)
{
if (children.size() > element_index+1) {
element_index++;
return children[element_index];
} else {
element_index = 0;
return 0L;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string Element::GetDataLine(int i)
{
if (data_lines.size() > 0) return data_lines[i];
else return string("");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double Element::GetDataAsNumber(void)
{
if (data_lines.size() == 1) {
return atof(data_lines[0].c_str());
} else {
return 99e99;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int Element::GetNumElements(string element_name)
{
int number_of_elements=0;
Element* el=FindElement(element_name);
while (el) {
number_of_elements++;
el=FindNextElement(element_name);
}
return number_of_elements;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Element* Element::FindElement(string el)
{
if (el.empty() && children.size() >= 1) {
element_index = 1;
return children[0];
}
for (int i=0; i<children.size(); i++) {
if (el == children[i]->GetName()) {
element_index = i+1;
return children[i];
}
}
element_index = 0;
return 0L;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Element* Element::FindNextElement(string el)
{
if (el.empty()) {
if (element_index < children.size()) {
return children[element_index++];
} else {
element_index = 0;
return 0L;
}
}
for (int i=element_index; i<children.size(); i++) {
if (el == children[i]->GetName()) {
element_index = i+1;
return children[i];
}
}
element_index = 0;
return 0L;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double Element::FindElementValueAsNumber(string el)
{
Element* element = FindElement(el);
if (element) {
return element->GetDataAsNumber();
} else {
return 99e99;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string Element::FindElementValue(string el)
{
Element* element = FindElement(el);
if (element) {
return element->GetDataLine();
} else {
return "";
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
{
Element* element = FindElement(el);
double value;
string supplied_units="";
if (element) {
value = element->GetDataAsNumber();
supplied_units = element->GetAttributeValue("unit");
if (!supplied_units.empty()) {
if (convert.find(supplied_units) != convert.end()) {
if (convert[supplied_units].find(target_units) != convert[supplied_units].end()) {
value *= convert[supplied_units][target_units];
} else {
cerr << endl << "Target unit: \"" << target_units << "\" does not exist (typo?). Add new unit"
<< " conversion in FGXMLElement.cpp." << endl;
exit(-1);
}
} else {
cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
<< " conversion in FGXMLElement.cpp." << endl;
exit(-1);
}
}
} else {
return 99e99;
}
return value;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double Element::FindElementValueAsNumberConvertFromTo( string el,
string supplied_units,
string target_units)
{
Element* element = FindElement(el);
double value;
if (element) {
value = element->GetDataAsNumber();
if (!supplied_units.empty()) {
if (convert.find(supplied_units) != convert.end()) {
if (convert[supplied_units].find(target_units) != convert[supplied_units].end()) {
value *= convert[supplied_units][target_units];
} else {
cerr << endl << "Target unit: \"" << target_units << "\" does not exist (typo?). Add new unit"
<< " conversion in FGXMLElement.cpp." << endl;
exit(-1);
}
} else {
cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
<< " conversion in FGXMLElement.cpp." << endl;
exit(-1);
}
}
} else {
return 99e99;
}
return value;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
{
FGColumnVector3 triplet;
Element* item;
double value=0.0;
string supplied_units = GetAttributeValue("unit");
item = FindElement("x");
if (!item) item = FindElement("roll");
if (item) {
value = item->GetDataAsNumber();
if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
} else {
value = 0.0;
cerr << "Could not find an X triplet item for this column vector." << endl;
}
triplet(1) = value;
item = FindElement("y");
if (!item) item = FindElement("pitch");
if (item) {
value = item->GetDataAsNumber();
if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
} else {
value = 0.0;
cerr << "Could not find a Y triplet item for this column vector." << endl;
}
triplet(2) = value;
item = FindElement("z");
if (!item) item = FindElement("yaw");
if (item) {
value = item->GetDataAsNumber();
if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
} else {
value = 0.0;
cerr << "Could not find a Z triplet item for this column vector." << endl;
}
triplet(3) = value;
return triplet;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void Element::Print(int level)
{
int i, spaces;
level+=2;
for (int spaces=0; spaces<=level; spaces++) cout << " "; // format output
cout << "Element Name: " << name;
for (int i=0; i<attributes.size(); i++) {
cout << " " << attribute_key[i] << " = " << attributes[attribute_key[i]];
}
cout << endl;
for (i=0; i<data_lines.size(); i++) {
for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
cout << data_lines[i] << endl;
}
for (i=0; i<children.size(); i++) {
children[i]->Print(level);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void Element::AddAttribute(string name, string value)
{
attribute_key.push_back(name);
attributes[name] = value;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void Element::AddData(string d)
{
int string_start = d.find_first_not_of(" ");
if (string_start > 0) d.erase(0,string_start-1);
data_lines.push_back(d);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} // end namespace JSBSim

View file

@ -0,0 +1,354 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
File: FGXMLElement.h
Author: Jon S. Berndt
Date started: 9/28/04
------------- Copyright (C) 2004 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.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef XMLELEMENT_H
#define XMLELEMENT_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
# include <string>
# include <vector>
# include <iostream>
# include <map>
# else
# include <vector.h>
# include <string>
# include <iostream.h>
# include <map.h>
# endif
#else
# include <string>
# include <map>
# include <iostream>
# include <vector>
using std::string;
using std::map;
using std::vector;
using std::cout;
using std::endl;
#endif
using std::string;
using std::map;
using std::vector;
using std::cout;
using std::endl;
#include <math/FGColumnVector3.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_XMLELEMENT "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Encapsulates an XML element.
This class handles the creation, storage, and manipulation of XML elements.
This class also can convert supplied values as follows:
convert ["from"]["to"] = factor, so: from * factor = to
- convert["M"]["FT"] = 3.2808399;
- convert["FT"]["M"] = 1.0/convert["M"]["FT"];
- convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
- convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
- convert["FT"]["IN"] = 12.0;
- convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
- convert["LBS"]["KG"] = 0.45359237;
- convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
- convert["SLUG*FT2"]["KG*M2"] = 1.35594;
- convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
- convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
- convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
- convert["LBS/FT"]["N/M"] = 14.5939;
- convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
- convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
- convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
- convert["WATTS"]["HP"] = 0.001341022;
- convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
- convert["N"]["LBS"] = 0.22482;
- convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
- convert["KTS"]["FT/SEC"] = ktstofps;
- convert["M"]["M"] = 1.00;
- convert["FT"]["FT"] = 1.00;
- convert["IN"]["IN"] = 1.00;
- convert["DEG"]["DEG"] = 1.00;
- convert["RAD"]["RAD"] = 1.00;
- convert["M2"]["M2"] = 1.00;
- convert["FT2"]["FT2"] = 1.00;
- convert["KG*M2"]["KG*M2"] = 1.00;
- convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
- convert["KG"]["KG"] = 1.00;
- convert["LBS"]["LBS"] = 1.00;
- convert["LBS/FT"]["LBS/FT"] = 1.00;
- convert["N/M"]["N/M"] = 1.00;
- convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
- convert["N/M/SEC"]["N/M/SEC"] = 1.00;
- convert["PSI"]["PSI"] = 1.00;
- convert["INHG"]["INHG"] = 1.00;
- convert["HP"]["HP"] = 1.00;
- convert["N"]["N"] = 1.00;
- convert["WATTS"]["WATTS"] = 1.00;
- convert["KTS"]["KTS"] = 1.0;
- convert["FT/SEC"]["FT/SEC"] = 1.0;
Where:
- N = newtons
- M = meters
- M2 = meters squared
- KG = kilograms
- LBS = pounds force
- FT = feet
- FT2 = feet squared
- SEC = seconds
- SLUG = slug
- DEG = degrees
- RAD = radians
- WATTS = watts
@author Jon S. Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class Element {
public:
/** Constructor
@param nm the name of this element (if given)
*/
Element(string nm);
/// Destructor
~Element(void);
/** Retrieves an attribute.
@param key specifies the attribute key to retrieve the value of.
@return the key value (as a string), or the empty string if no such
attribute exists. */
string GetAttributeValue(string key);
/** Retrieves an attribute value as a double precision real number.
@param key specifies the attribute key to retrieve the value of.
@return the key value (as a number), or the HUGE_VAL if no such
attribute exists. */
double GetAttributeValueAsNumber(string key);
/** Retrieves the element name.
@return the element name, or the empty string if no name has been set.*/
string GetName(void) {return name;}
/** Gets a line of data belonging to an element.
@param i the index of the data line to return (0 by default).
@return a string representing the data line requested, or the empty string
if none exists.*/
string GetDataLine(int i=0);
/// Returns the number of lines of data stored
int GetNumDataLines(void) {return data_lines.size();}
/// Returns the number of child elements for this element.
int GetNumElements(void) {return children.size();}
/// Returns the number of named child elements for this element.
int GetNumElements(string);
/** Converts the element data to a number.
This function attempts to convert the first (and presumably only) line of
data "owned" by the element into a real number. If there is not exactly one
line of data owned by the element, then HUGE_VAL is returned.
@return the numeric value of the data owned by the element.*/
double GetDataAsNumber(void);
/** Returns a pointer to the element requested by index.
This function also resets an internal counter to the index, so that
subsequent calls to GetNextElement() will return the following
elements sequentially, until the last element is reached. At that point,
GetNextElement() will return NULL.
@param el the index of the requested element (0 by default)
@return a pointer to the Element, or 0 if no valid element exists. */
Element* GetElement(int el=0);
/** Returns a pointer to the next element in the list.
The function GetElement() must be called first to be sure that this
function will return the correct element. The call to GetElement() resets
the internal counter to zero. Subsequent calls to GetNextElement() return
a pointer to subsequent elements in the list. When the final element is
reached, 0 is returned.
@return a pointer to the next Element in the sequence, or 0 if no valid
Element is present. */
Element* GetNextElement(void);
/** Returns a pointer to the parent of an element.
@return a pointer to the parent Element, or 0 if this is the top level Element. */
Element* GetParent(void) {return parent;}
/** Searches for a specified element.
Finds the first element that matches the supplied string, or simply the first
element if no search string is supplied. This function call resets the internal
element counter to the first element.
@param el the search string (empty string by default).
@return a pointer to the first element that matches the supplied search string. */
Element* FindElement(string el="");
/** Searches for the next element as specified.
This function would be called after FindElement() is first called (in order to
reset the internal counter). If no argument is supplied (or the empty string)
a pointer to the very next element is returned. Otherwise, the next occurence
of the named element is returned. If the end of the list is reached, 0 is
returned.
@param el the name of the next element to find.
@return the pointer to the found element, or 0 if no appropriate element us
found.*/
Element* FindNextElement(string el="");
/** Searches for the named element and returns the string data belonging to it.
This function allows the data belonging to a named element to be returned
as a string. If no element is found, the empty string is returned. If no
argument is supplied, the data string for the first element is returned.
@param el the name of the element being searched for (the empty string by
default)
@return the data value for the named element as a string, or the empty
string if the element cannot be found. */
string FindElementValue(string el="");
/** Searches for the named element and returns the data belonging to it as a number.
This function allows the data belonging to a named element to be returned
as a double. If no element is found, HUGE_VAL is returned. If no
argument is supplied, the data for the first element is returned.
@param el the name of the element being searched for (the empty string by
default)
@return the data value for the named element as a double, or HUGE_VAL if the
data is missing. */
double FindElementValueAsNumber(string el="");
/** Searches for the named element and converts and returns the data belonging to it.
This function allows the data belonging to a named element to be returned
as a double. If no element is found, HUGE_VAL is returned. If no
argument is supplied, the data for the first element is returned. Additionally,
this function converts the value from the units specified in the config file (via
the UNITS="" attribute in the element definition) to the native units used by
JSBSim itself, as specified by the target_units parameter. The currently
allowable unit conversions are seen in the source file FGXMLElement.cpp.
Also, see above in the main documentation for this class.
@param el the name of the element being searched for (the empty string by
default)
@param target_units the string representing the native units used by JSBSim
to which the value returned will be converted.
@return the unit-converted data value for the named element as a double,
or HUGE_VAL if the data is missing. */
double FindElementValueAsNumberConvertTo(string el, string target_units);
/** Searches for the named element and converts and returns the data belonging to it.
This function allows the data belonging to a named element to be returned
as a double. If no element is found, HUGE_VAL is returned. If no
argument is supplied, the data for the first element is returned. Additionally,
this function converts the value from the units specified in the supplied_units
parameter to the units specified in the target_units parameter. JSBSim itself,
as specified by the target_units parameter. The currently allowable unit
conversions are seen in the source file FGXMLElement.cpp. Also, see above
in the main documentation for this class.
@param el the name of the element being searched for (the empty string by
default)
@param supplied_units the string representing the units of the value as
supplied by the config file.
@param target_units the string representing the native units used by JSBSim
to which the value returned will be converted.
@return the unit-converted data value for the named element as a double,
or HUGE_VAL if the data is missing. */
double FindElementValueAsNumberConvertFromTo( string el,
string supplied_units,
string target_units);
/** Composes a 3-element column vector for the supplied location or orientation.
This function processes a LOCATION or ORIENTATION construct, returning a
filled-out 3-element column vector containing the X, Y, Z or ROLL, PITCH,
YAW elements found in the supplied element. If one of the mentioned components
is not found, that component is set to zero and a warning message is printed.
All three elements should be supplied.
@param target_units the string representing the native units used by JSBSim
to which the value returned will be converted.
@return a column vector object built from the LOCATION or ORIENT components. */
FGColumnVector3 FindElementTripletConvertTo( string target_units);
/** This function sets the value of the parent class attribute to the supplied
Element pointer.
@param p pointer to the parent Element. */
void SetParent(Element* p) {parent = p;}
/** Adds a child element to the list of children stored for this element.
* @param el Child element to add. */
void AddChildElement(Element* el) {children.push_back(el);}
/** Stores an attribute belonging to this element.
* @param name The string name of the attribute.
* @param value The string value of the attribute. */
void AddAttribute(string name, string value);
/** Stores data belonging to this element.
* @param d the data to store. */
void AddData(string d);
/** Prints the element.
* Prints this element and calls the Print routine for child elements.
* @param d The tab level. A level corresponds to a single space. */
void Print(int level=0);
private:
string name;
map <string, string> attributes;
vector <string> data_lines;
vector <Element*> children;
vector <string> attribute_key;
Element *parent;
int element_index;
typedef map <string, map <string, double> > tMapConvert;
tMapConvert convert;
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,146 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGXMLParse.h
Author: Jon Berndt
Date started: 08/20/2004
Purpose: Config file read-in class and XML parser
Called by: Various
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGXMLParse.h"
#include <stdlib.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_XMLPARSE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGXMLParse.h"
using namespace std;
FGXMLParse::FGXMLParse(void)
{
first_element_read = false;
current_element = document = 0L;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGXMLParse::~FGXMLParse(void)
{
if (document) delete document;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::startXML(void)
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::reset(void)
{
if (document) delete document;
first_element_read = false;
current_element = document = 0L;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::endXML(void)
{
// At this point, document should equal current_element ?
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::startElement (const char * name, const XMLAttributes &atts)
{
string Name(name);
Element *temp_element;
working_string.erase();
if (!first_element_read) {
document = new Element(Name);
current_element = document;
first_element_read = true;
} else {
temp_element = new Element(Name);
temp_element->SetParent(current_element);
current_element->AddChildElement(temp_element);
current_element = temp_element;
}
if (current_element == 0L) {
cerr << "No current element read (no top-level element in XML file?)" << endl;
exit (-1);
}
for (int i=0; i<atts.size();i++) {
current_element->AddAttribute(atts.getName(i), atts.getValue(i));
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::endElement (const char * name)
{
int size, pos;
string local_work_string;
while (!working_string.empty()) {
// clear leading newlines and spaces
while (working_string[0] == '\n' || working_string[0] == ' ')
working_string.erase(0,1);
// remove spaces (only) from end of string
size = working_string.size();
while (working_string[size-1] == ' ')
{
working_string.erase(size-1,1);
size = working_string.size();
}
if (!working_string.empty()) {
pos = working_string.find("\n");
if (pos != string::npos) local_work_string = working_string.substr(0,pos);
else local_work_string = working_string;
current_element->AddData(local_work_string);
working_string.erase(0, pos);
}
}
current_element = current_element->GetParent();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::data (const char * s, int length)
{
working_string += string(s, length);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::pi (const char * target, const char * data)
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGXMLParse::warning (const char * message, int line, int column)
{
cerr << "Warning: " << message << " line: " << line << " column: " << column << endl;
}
} // end namespace JSBSim

View file

@ -0,0 +1,106 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGXMLParse.h
Author: Jon S. Berndt
Date started: 8/20/04
------------- Copyright (C) 2004 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.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGXMLPARSE_H
#define FGXMLPARSE_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# include STL_STRING
#else
# include <string>
# include <iostream>
using std::string;
using std::cout;
using std::cerr;
using std::endl;
#endif
#include "FGXMLElement.h"
#include "simgear/xml/easyxml.hxx"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_XMLPARSE "$Id$"
#define VALID_CHARS """`!@#$%^&*()_+`1234567890-={}[];':,.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Encapsulates an XML parser based on the EasyXML parser from the SimGear library.
@author Jon S. Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGXMLParse : public XMLVisitor
{
public:
FGXMLParse(void);
virtual ~FGXMLParse(void);
Element* GetDocument(void) {return document;}
void startXML();
void endXML();
void startElement (const char * name, const XMLAttributes &atts);
void endElement (const char * name);
void data (const char * s, int length);
void pi (const char * target, const char * data);
void warning (const char * message, int line, int column);
void reset(void);
private:
bool first_element_read;
mutable string working_string;
Element *document;
Element *current_element;
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -37,10 +37,6 @@ HISTORY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGfdmSocket.h"
namespace JSBSim {
@ -54,7 +50,7 @@ CLASS IMPLEMENTATION
FGfdmSocket::FGfdmSocket(string address, int port)
{
size = 0;
sckt = sckt_in = size = 0;
connected = false;
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
@ -100,12 +96,61 @@ FGfdmSocket::FGfdmSocket(string address, int port)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGfdmSocket::FGfdmSocket(int port)
{
size = 0;
connected = false;
unsigned long NoBlock = true;
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
WSADATA wsaData;
int wsaReturnCode;
wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
else cerr << "Winsock DLL not initialized ..." << endl;
#endif
sckt = socket(AF_INET, SOCK_STREAM, 0);
if (sckt >= 0) { // successful
memset(&scktName, 0, sizeof(struct sockaddr_in));
scktName.sin_family = AF_INET;
scktName.sin_port = htons(port);
// memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
int len = sizeof(struct sockaddr_in);
if (bind(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful
cout << "Successfully bound to socket ..." << endl;
if (listen(sckt, 5) >= 0) { // successful listen()
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
ioctlsocket(sckt, FIONBIO, &NoBlock);
sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
#else
ioctl(sckt, FIONBIO, &NoBlock);
sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
#endif
} else {
cerr << "Could not listen ..." << endl;
}
connected = true;
} else { // unsuccessful
cerr << "Could not bind to socket ..." << endl;
}
} else { // unsuccessful
cerr << "Could not create socket for FDM, error = " << errno << endl;
}
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGfdmSocket::~FGfdmSocket()
{
#ifndef macintosh
if (sckt) shutdown(sckt,2);
if (sckt_in) shutdown(sckt_in,2);
#endif
#ifdef __BORLANDC__
WSACleanup();
#endif
@ -114,6 +159,80 @@ FGfdmSocket::~FGfdmSocket()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGfdmSocket::Receive(void)
{
char buf[1024];
int len = sizeof(struct sockaddr_in);
int num_chars=0;
int total_chars = 0;
unsigned long NoBlock = true;
string data = ""; // todo: should allocate this with a standard size as a
// class attribute and pass as a reference?
if (sckt_in <= 0) {
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
#else
sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
#endif
if (sckt_in > 0) {
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
ioctlsocket(sckt_in, FIONBIO,&NoBlock);
#else
ioctl(sckt_in, FIONBIO, &NoBlock);
#endif
send(sckt_in, "Connected to JSBSim server\nJSBSim> ", 35, 0);
}
}
if (sckt_in > 0) {
while ((num_chars = recv(sckt_in, buf, 1024, 0)) > 0) {
data += string(buf).substr(0,num_chars);
total_chars += num_chars;
}
#if defined(_MSC_VER)
// when nothing received and the error isn't "would block"
// then assume that the client has closed the socket.
if (num_chars == 0) {
DWORD err = WSAGetLastError ();
if (err != WSAEWOULDBLOCK) {
printf ("Socket Closed. back to listening\n");
closesocket (sckt_in);
sckt_in = -1;
}
}
#endif
}
return data.substr(0, total_chars);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int FGfdmSocket::Reply(string text)
{
int num_chars_sent=0;
if (sckt_in >= 0) {
num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0);
send(sckt_in, "JSBSim> ", 8, 0);
} else {
cerr << "Socket reply must be to a valid socket" << endl;
return -1;
}
return num_chars_sent;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGfdmSocket::Close(void)
{
close(sckt_in);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGfdmSocket::Clear(void)
{
buffer = "";
@ -122,6 +241,14 @@ void FGfdmSocket::Clear(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGfdmSocket::Clear(string s)
{
buffer = s + " ";
size = buffer.size();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGfdmSocket::Append(const char* item)
{
if (size == 0) buffer += string(item);

View file

@ -65,11 +65,14 @@ INCLUDES
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
#include <winsock.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <sys/ioctl.h>
#endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -96,21 +99,29 @@ CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
using std::string;
using std::cerr;
class FGfdmSocket : public FGJSBBase
{
public:
FGfdmSocket(string, int);
FGfdmSocket(int);
~FGfdmSocket();
void Send(void);
string Receive(void);
int Reply(string text);
void Append(const string s) {Append(s.c_str());}
void Append(const char*);
void Append(double);
void Append(long);
void Clear(void);
void Clear(string s);
void Close(void);
bool GetConnectStatus(void) {return connected;}
private:
int sckt;
int sckt_in;
int size;
struct sockaddr_in scktName;
struct hostent *host;

View file

@ -0,0 +1,7 @@
noinst_LIBRARIES = libInputOutput.a
libInputOutput_a_SOURCES = FGGroundCallback.cpp FGPropertyManager.cpp FGScript.cpp FGXMLElement.cpp FGXMLParse.cpp FGfdmSocket.cpp
noinst_HEADERS = FGGroundCallback.h FGPropertyManager.h FGScript.h FGXMLElement.h FGXMLParse.h FGfdmSocket.h
INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim

View file

@ -0,0 +1,155 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGColumnVector3.cpp
Author: Originally by Tony Peden [formatted here (and broken??) by JSB]
Date started: 1998
Purpose: FGColumnVector3 class
Called by: Various
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
??/??/?? TP Created
03/16/2000 JSB Added exception throwing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGColumnVector3.h"
#include <stdio.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_COLUMNVECTOR3;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGColumnVector3::FGColumnVector3(void)
{
data[0] = data[1] = data[2] = 0.0;
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGColumnVector3::Dump(string delimeter) const
{
char buffer[256];
sprintf(buffer, "%f%s%f%s%f", Entry(1), delimeter.c_str(), Entry(2), delimeter.c_str(), Entry(3));
return string(buffer);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ostream& operator<<(ostream& os, const FGColumnVector3& col)
{
os << col(1) << " , " << col(2) << " , " << col(3);
return os;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3 FGColumnVector3::operator/(const double scalar) const
{
if (scalar != 0.0)
return operator*( 1.0/scalar );
cerr << "Attempt to divide by zero in method \
FGColumnVector3::operator/(const double scalar), \
object " << data[0] << " , " << data[1] << " , " << data[2] << endl;
return FGColumnVector3();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3& FGColumnVector3::operator/=(const double scalar)
{
if (scalar != 0.0)
operator*=( 1.0/scalar );
else
cerr << "Attempt to divide by zero in method \
FGColumnVector3::operator/=(const double scalar), \
object " << data[0] << " , " << data[1] << " , " << data[2] << endl;
return *this;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGColumnVector3::Magnitude(void) const
{
if (Entry(1) == 0.0 && Entry(2) == 0.0 && Entry(3) == 0.0)
return 0.0;
else
return sqrt( Entry(1)*Entry(1) + Entry(2)*Entry(2) + Entry(3)*Entry(3) );
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3& FGColumnVector3::Normalize(void)
{
double Mag = Magnitude();
if (Mag != 0.0)
operator*=( 1.0/Mag );
return *this;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3 FGColumnVector3::multElementWise(const FGColumnVector3& V) const
{
return FGColumnVector3(Entry(1) * V(1), Entry(2) * V(2), Entry(3) * V(3));
}
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGColumnVector3::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGColumnVector3" << endl;
if (from == 1) cout << "Destroyed: FGColumnVector3" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,308 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGColumnVector3.h
Author: Originally by Tony Peden [formatted and adapted here by Jon Berndt]
Date started: Unknown
HISTORY
--------------------------------------------------------------------------------
??/??/???? ?? Initial version and more.
03/06/2004 MF Rework, document and do much inlineing.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGCOLUMNVECTOR3_H
#define FGCOLUMNVECTOR3_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <stdlib.h>
#ifdef FGFS
# include <math.h>
# include <simgear/compiler.h>
# include STL_STRING
# include STL_FSTREAM
# include STL_IOSTREAM
SG_USING_STD(string);
SG_USING_STD(ostream);
SG_USING_STD(istream);
SG_USING_STD(cerr);
SG_USING_STD(cout);
SG_USING_STD(endl);
#else
# include <string>
# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
# include <fstream.h>
# include <iostream.h>
# include <math.h>
# else
# include <fstream>
# include <iostream>
# if defined(sgi) && !defined(__GNUC__)
# include <math.h>
# else
# include <cmath>
# endif
using std::ostream;
using std::istream;
using std::cerr;
using std::cout;
using std::endl;
# if !(defined(_MSC_VER) && _MSC_VER <= 1200)
using std::sqrt;
# endif
# endif
using std::string;
#endif
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_COLUMNVECTOR3 "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** This class implements a 3 dimensional vector.
@author Jon S. Berndt, Tony Peden, et. al.
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGColumnVector3 : public FGJSBBase
{
public:
/** Default initializer.
Create a zero vector. */
FGColumnVector3(void);
/** Initialization by given values.
@param X value of the x-conponent.
@param Y value of the y-conponent.
@param Z value of the z-conponent.
Create a vector from the doubles given in the arguments. */
FGColumnVector3(double X, double Y, double Z) {
data[0] = X;
data[1] = Y;
data[2] = Z;
Debug(0);
}
/** Copy constructor.
@param v Vector which is used for initialization.
Create copy of the vector given in the argument. */
FGColumnVector3(const FGColumnVector3& v) {
data[0] = v.data[0];
data[1] = v.data[1];
data[2] = v.data[2];
Debug(0);
}
/// Destructor.
~FGColumnVector3(void) { Debug(1); }
/** Read access the entries of the vector.
@param idx the component index.
Return the value of the matrix entry at the given index.
Indices are counted starting with 1.
Note that the index given in the argument is unchecked. */
double operator()(unsigned int idx) const { return Entry(idx); }
/** Write access the entries of the vector.
@param idx the component index.
Return a reference to the vector entry at the given index.
Indices are counted starting with 1.
Note that the index given in the argument is unchecked. */
double& operator()(unsigned int idx) { return Entry(idx); }
/** Read access the entries of the vector.
@param idx the component index.
Return the value of the matrix entry at the given index.
Indices are counted starting with 1.
This function is just a shortcut for the @ref double
operator()(unsigned int idx) const function. It is
used internally to access the elements in a more convenient way.
Note that the index given in the argument is unchecked. */
double Entry(unsigned int idx) const { return data[idx-1]; }
/** Write access the entries of the vector.
@param idx the component index.
Return a reference to the vector entry at the given index.
Indices are counted starting with 1.
This function is just a shortcut for the @ref double&
operator()(unsigned int idx) function. It is
used internally to access the elements in a more convenient way.
Note that the index given in the argument is unchecked. */
double& Entry(unsigned int idx) { return data[idx-1]; }
/** Prints the contents of the vector
@param delimeter the item separator (tab or comma)
@return a string with the delimeter-separated contents of the vector */
string Dump(string delimeter) const;
/** Assignment operator.
@param b source vector.
Copy the content of the vector given in the argument into *this. */
FGColumnVector3& operator=(const FGColumnVector3& b) {
data[0] = b.data[0];
data[1] = b.data[1];
data[2] = b.data[2];
return *this;
}
/** Comparison operator.
@param b other vector.
Returns true if both vectors are exactly the same. */
bool operator==(const FGColumnVector3& b) const {
return data[0] == b.data[0] && data[1] == b.data[1] && data[2] == b.data[2];
}
/** Comparison operator.
@param b other vector.
Returns false if both vectors are exactly the same. */
bool operator!=(const FGColumnVector3& b) const { return ! operator==(b); }
/** Multiplication by a scalar.
@param scalar scalar value to multiply the vector with.
@return The resulting vector from the multiplication with that scalar.
Multiply the vector with the scalar given in the argument. */
FGColumnVector3 operator*(const double scalar) const {
return FGColumnVector3(scalar*Entry(1), scalar*Entry(2), scalar*Entry(3));
}
/** Multiply by 1/scalar.
@param scalar scalar value to devide the vector through.
@return The resulting vector from the division through that scalar.
Multiply the vector with the 1/scalar given in the argument. */
FGColumnVector3 operator/(const double scalar) const;
/** Cross product multiplication.
@param v vector to multiply with.
@return The resulting vector from the cross product multiplication.
Compute and return the cross product of the current vector with
the given argument. */
FGColumnVector3 operator*(const FGColumnVector3& V) const {
return FGColumnVector3( Entry(2) * V(3) - Entry(3) * V(2),
Entry(3) * V(1) - Entry(1) * V(3),
Entry(1) * V(2) - Entry(2) * V(1) );
}
/// Addition operator.
FGColumnVector3 operator+(const FGColumnVector3& B) const {
return FGColumnVector3( Entry(1) + B(1), Entry(2) + B(2), Entry(3) + B(3) );
}
/// Subtraction operator.
FGColumnVector3 operator-(const FGColumnVector3& B) const {
return FGColumnVector3( Entry(1) - B(1), Entry(2) - B(2), Entry(3) - B(3) );
}
/// Subtract an other vector.
FGColumnVector3& operator-=(const FGColumnVector3 &B) {
Entry(1) -= B(1);
Entry(2) -= B(2);
Entry(3) -= B(3);
return *this;
}
/// Add an other vector.
FGColumnVector3& operator+=(const FGColumnVector3 &B) {
Entry(1) += B(1);
Entry(2) += B(2);
Entry(3) += B(3);
return *this;
}
/// Scale by a scalar.
FGColumnVector3& operator*=(const double scalar) {
Entry(1) *= scalar;
Entry(2) *= scalar;
Entry(3) *= scalar;
return *this;
}
/// Scale by a 1/scalar.
FGColumnVector3& operator/=(const double scalar);
void InitMatrix(void) { data[0] = data[1] = data[2] = 0.0; }
void InitMatrix(double a) { data[0] = data[1] = data[2] = a; }
void InitMatrix(double a, double b, double c) {
data[0]=a; data[1]=b; data[2]=c;
}
/** Length of the vector.
Compute and return the euclidean norm of this vector. */
double Magnitude(void) const;
/** Length of the vector in a coordinate axis plane.
Compute and return the euclidean norm of this vector projected into
the coordinate axis plane idx1-idx2. */
double Magnitude(int idx1, int idx2) const {
return sqrt( Entry(idx1)*Entry(idx1) + Entry(idx2)*Entry(idx2) );
}
/** Normalize.
Normalize the vector to have the Magnitude() == 1.0. If the vector
is equal to zero it is left untouched. */
FGColumnVector3& Normalize(void);
// ??? Is this something sensible ??
FGColumnVector3 multElementWise(const FGColumnVector3& V) const;
// little trick here.
struct AssignRef {
AssignRef(FGColumnVector3& r, int i) : Ref(r), idx(i) {}
AssignRef operator<<(const double ff) {
Ref.Entry(idx) = ff;
return AssignRef(Ref, idx+1);
}
FGColumnVector3& Ref;
int idx;
};
AssignRef operator<<(const double ff) {
Entry(1) = ff;
return AssignRef(*this, 2);
}
private:
double data[3];
void Debug(int from);
};
/** Scalar multiplication.
@param scalar scalar value to multiply with.
@param A Vector to multiply.
Multiply the Vector with a scalar value.*/
inline FGColumnVector3 operator*(double scalar, const FGColumnVector3& A) {
// use already defined operation.
return A*scalar;
}
/** Write vector to a stream.
@param os Stream to write to.
@param M Matrix to write.
Write the matrix to a stream.*/
ostream& operator<<(ostream& os, const FGColumnVector3& col);
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,257 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGFunction.cpp
Author: Jon Berndt
Date started: 8/25/2004
Purpose: Stores various parameter types for functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <stdio.h>
#include "FGFunction.h"
#include "FGTable.h"
#include "FGPropertyValue.h"
#include "FGRealValue.h"
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FUNCTION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
: PropertyManager(propMan), Prefix(prefix)
{
int i;
Element* element;
string operation, property_name;
int size = el->GetNumElements();
cached = false;
cachedValue = -HUGE_VAL;
Name = el->GetAttributeValue("name");
operation = el->GetName();
if (operation == string("function")) {
Type = eTopLevel;
bind();
} else if (operation == string("product")) {
Type = eProduct;
} else if (operation == string("difference")) {
Type = eDifference;
} else if (operation == string("sum")) {
Type = eSum;
} else if (operation == string("quotient")) {
Type = eQuotient;
} else if (operation == string("pow")) {
Type = ePow;
} else if (operation == string("abs")) {
Type = eAbs;
} else if (operation == string("sin")) {
Type = eSin;
} else if (operation == string("cos")) {
Type = eCos;
} else if (operation == string("tan")) {
Type = eTan;
} else if (operation == string("asin")) {
Type = eASin;
} else if (operation == string("acos")) {
Type = eACos;
} else if (operation == string("atan")) {
Type = eATan;
} else if (operation == string("atan2")) {
Type = eATan2;
} else if (operation != string("description")) {
cerr << "Bad operation " << operation << " detected in configuration file" << endl;
}
element = el->GetElement();
while (element) {
operation = element->GetName();
// data types
if (operation == string("property")) {
property_name = element->GetDataLine();
Parameters.push_back(new FGPropertyValue(PropertyManager->GetNode(property_name)));
} else if (operation == string("value")) {
Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
} else if (operation == string("table")) {
Parameters.push_back(new FGTable(PropertyManager, element));
// operations
} else if (operation == string("product") ||
operation == string("difference") ||
operation == string("sum") ||
operation == string("quotient") ||
operation == string("pow") ||
operation == string("abs") ||
operation == string("sin") ||
operation == string("cos") ||
operation == string("tan") ||
operation == string("asin") ||
operation == string("acos") ||
operation == string("atan") ||
operation == string("atan2"))
{
Parameters.push_back(new FGFunction(PropertyManager, element));
} else if (operation != string("description")) {
cerr << "Bad operation " << operation << " detected in configuration file" << endl;
}
element = el->GetNextElement();
}
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGFunction::~FGFunction(void)
{
string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
PropertyManager->Untie(tmp);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFunction::cacheValue(bool cache)
{
cached = false; // Must set cached to false prior to calling GetValue(), else
// it will _never_ calculate the value;
if (cache) {
cachedValue = GetValue();
cached = true;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGFunction::GetValue(void) const
{
int i;
if (cached) return cachedValue;
double temp = Parameters[0]->GetValue();
switch (Type) {
case eTopLevel:
break;
case eProduct:
for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
break;
case eDifference:
for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
break;
case eSum:
for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
break;
case eQuotient:
temp /= Parameters[1]->GetValue();
break;
case ePow:
temp = pow(temp,Parameters[1]->GetValue());
break;
case eAbs:
temp = abs(temp);
break;
case eSin:
temp = sin(temp);
break;
case eCos:
temp = cos(temp);
break;
case eTan:
temp = tan(temp);
break;
case eACos:
temp = acos(temp);
break;
case eASin:
temp = asin(temp);
break;
case eATan:
temp = atan(temp);
break;
case eATan2:
temp = atan2(temp, Parameters[1]->GetValue());
break;
default:
cerr << "Unknown function operation type" << endl;
break;
}
return temp;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGFunction::GetValueAsString(void) const
{
char buffer[20];
string value;
sprintf(buffer,"%9.6f",GetValue());
value = string(buffer);
return value;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFunction::bind(void)
{
string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGFunction::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (Type == eTopLevel)
cout << " Function: " << Name << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
if (from == 1) cout << "Destroyed: FGGroundReactions" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
}

View file

@ -0,0 +1,75 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGFunction.h
Author: Jon Berndt
Date started: August 25 2004
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGFUNCTION_H
#define FGFUNCTION_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <vector>
#include <string>
#include "FGParameter.h"
#include <input_output/FGXMLElement.h>
#include <input_output/FGPropertyManager.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FUNCTION "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Represents various types of parameters.
@author Jon Berndt
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGFunction
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFunction : public FGParameter
{
public:
FGFunction(FGPropertyManager* propMan, Element* el, string prefix="");
~FGFunction();
double GetValue(void) const;
string GetValueAsString(void) const;
string GetName(void) const {return Name;}
void cacheValue(bool);
private:
vector <FGParameter*> Parameters;
FGPropertyManager* const PropertyManager;
bool cached;
string Prefix;
double cachedValue;
enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow,
eAbs, eSin, eCos, eTan, eASin, eACos, eATan, eATan2} Type;
string Name;
void bind(void);
void Debug(int from);
};
} // namespace JSBSim
#endif

View file

@ -0,0 +1,221 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGLocation.cpp
Author: Jon S. Berndt
Date started: 04/04/2004
Purpose: Store an arbitrary location on the globe
------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) ------------------
------- (C) 2004 Mathias Froehlich (Mathias.Froehlich@web.de) ----
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 encapsulates an arbitrary position in the globe with its accessors.
It has vector properties, so you can add multiply ....
HISTORY
------------------------------------------------------------------------------
04/04/2004 MF Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
# include <cmath>
# else
# include <math.h>
# endif
#else
# if defined(sgi) && !defined(__GNUC__)
# include <math.h>
# else
# include <cmath>
# endif
#endif
#include "FGLocation.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_LOCATION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGLocation::FGLocation(double lon, double lat, double radius)
{
mCacheValid = false;
double sinLat = sin(lat);
double cosLat = cos(lat);
double sinLon = sin(lon);
double cosLon = cos(lon);
mECLoc = FGColumnVector3( radius*cosLat*cosLon,
radius*cosLat*sinLon,
radius*sinLat );
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::SetLongitude(double longitude)
{
double rtmp = mECLoc.Magnitude(eX, eY);
// Check if we have zero radius.
// If so set it to 1, so that we can set a position
if (0.0 == mECLoc.Magnitude())
rtmp = 1.0;
// Fast return if we are on the north or south pole ...
if (rtmp == 0.0)
return;
mCacheValid = false;
mECLoc(eX) = rtmp*cos(longitude);
mECLoc(eY) = rtmp*sin(longitude);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::SetLatitude(double latitude)
{
mCacheValid = false;
double r = mECLoc.Magnitude();
if (r == 0.0) {
mECLoc(eX) = 1.0;
r = 1.0;
}
double rtmp = mECLoc.Magnitude(eX, eY);
if (rtmp != 0.0) {
double fac = r/rtmp*cos(latitude);
mECLoc(eX) *= fac;
mECLoc(eY) *= fac;
} else {
mECLoc(eX) = r*cos(latitude);
mECLoc(eY) = 0.0;
}
mECLoc(eZ) = r*sin(latitude);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::SetRadius(double radius)
{
mCacheValid = false;
double rold = mECLoc.Magnitude();
if (rold == 0.0)
mECLoc(eX) = radius;
else
mECLoc *= radius/rold;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::ComputeDerivedUnconditional(void) const
{
// The radius is just the Euclidean norm of the vector.
mRadius = mECLoc.Magnitude();
// The distance of the location to the y-axis, which is the axis
// through the poles.
double rxy = sqrt(mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY));
// Compute the sin/cos values of the longitude
double sinLon, cosLon;
if (rxy == 0.0) {
sinLon = 0.0;
cosLon = 1.0;
} else {
sinLon = mECLoc(eY)/rxy;
cosLon = mECLoc(eX)/rxy;
}
// Compute the sin/cos values of the latitude
double sinLat, cosLat;
if (mRadius == 0.0) {
sinLat = 0.0;
cosLat = 1.0;
} else {
sinLat = mECLoc(eZ)/mRadius;
cosLat = rxy/mRadius;
}
// Compute the longitude and latitude itself
if ( mECLoc( eX ) == 0.0 && mECLoc( eY ) == 0.0 )
mLon = 0.0;
else
mLon = atan2( mECLoc( eY ), mECLoc( eX ) );
if ( rxy == 0.0 && mECLoc( eZ ) == 0.0 )
mLat = 0.0;
else
mLat = atan2( mECLoc(eZ), rxy );
// Compute the transform matrices from and to the earth centered frame.
// see Durham Chapter 4, problem 1, page 52
mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat, cosLat,
-sinLon , cosLon , 0.0 ,
-cosLon*cosLat, -sinLon*cosLat, -sinLat );
mTl2ec = mTec2l.Transposed();
// Mark the cached values as valid
mCacheValid = true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::bind(FGPropertyManager* PropertyManager, const string& prefix) const
{
PropertyManager->Tie(prefix + "lat-gc-rad", (FGLocation*)this,
&FGLocation::GetLatitude);
PropertyManager->Tie(prefix + "lat-gc-deg", (FGLocation*)this,
&FGLocation::GetLatitudeDeg);
PropertyManager->Tie(prefix + "long-gc-rad", (FGLocation*)this,
&FGLocation::GetLongitude);
PropertyManager->Tie(prefix + "long-gc-deg", (FGLocation*)this,
&FGLocation::GetLongitudeDeg);
PropertyManager->Tie(prefix + "radius-ft", (FGLocation*)this,
&FGLocation::GetRadius);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLocation::unbind(FGPropertyManager* PropertyManager, const string& prefix) const
{
PropertyManager->Untie(prefix + "lat-gc-rad");
PropertyManager->Untie(prefix + "lat-gc-deg");
PropertyManager->Untie(prefix + "long-gc-rad");
PropertyManager->Untie(prefix + "long-gc-deg");
PropertyManager->Untie(prefix + "radius-ft");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} // namespace JSBSim

View file

@ -39,8 +39,8 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include "FGPropertyManager.h"
#include <FGJSBBase.h>
#include <input_output/FGPropertyManager.h>
#include "FGColumnVector3.h"
#include "FGMatrix33.h"

View file

@ -18,10 +18,6 @@ HISTORY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGMatrix33.h"
#include "FGColumnVector3.h"

View file

@ -113,12 +113,17 @@ public:
};
/** Default initializer.
Create a zero matrix. */
Create a zero matrix.
*/
FGMatrix33(void);
/** Copy constructor.
@param M Matrix which is used for initialization.
Create copy of the matrix given in the argument. */
Create copy of the matrix given in the argument.
*/
FGMatrix33(const FGMatrix33& M) {
Entry(1,1) = M.Entry(1,1);
Entry(2,1) = M.Entry(2,1);
@ -134,6 +139,7 @@ public:
}
/** Initialization by given values.
@param m11 value of the 1,1 Matrix element.
@param m12 value of the 1,2 Matrix element.
@param m13 value of the 1,3 Matrix element.
@ -143,7 +149,9 @@ public:
@param m31 value of the 3,1 Matrix element.
@param m32 value of the 3,2 Matrix element.
@param m33 value of the 3,3 Matrix element.
Create a matrix from the doubles given in the arguments. */
Create a matrix from the doubles given in the arguments.
*/
FGMatrix33(double m11, double m12, double m13,
double m21, double m22, double m23,
double m31, double m32, double m33) {
@ -160,24 +168,30 @@ public:
Debug(0);
}
/// Destructor.
/** Destructor.
*/
~FGMatrix33(void) { Debug(1); }
/** Read access the entries of the matrix.
@param row Row index.
@param col Column index.
@return the value of the matrix entry at the given row and
column indices. Indices are counted starting with 1. */
column indices. Indices are counted starting with 1.
*/
double operator()(unsigned int row, unsigned int col) const {
return Entry(row, col);
}
/** Write access the entries of the matrix.
Note that the indices given in the arguments are unchecked.
@param row Row index.
@param col Column index.
@return a reference to the matrix entry at the given row and
column indices. Indices are counted starting with 1. */
column indices. Indices are counted starting with 1.
*/
double& operator()(unsigned int row, unsigned int col) {
return Entry(row, col);
}
@ -186,11 +200,15 @@ public:
This function is just a shortcut for the @ref double&
operator()(unsigned int row, unsigned int col) function. It is
used internally to access the elements in a more convenient way.
Note that the indices given in the arguments are unchecked.
@param row Row index.
@param col Column index.
@return the value of the matrix entry at the given row and
column indices. Indices are counted starting with 1. */
column indices. Indices are counted starting with 1.
*/
double Entry(unsigned int row, unsigned int col) const {
return data[(col-1)*eRows+row-1];
}
@ -199,27 +217,34 @@ public:
This function is just a shortcut for the @ref double&
operator()(unsigned int row, unsigned int col) function. It is
used internally to access the elements in a more convenient way.
Note that the indices given in the arguments are unchecked.
@param row Row index.
@param col Column index.
@return a reference to the matrix entry at the given row and
column indices. Indices are counted starting with 1. */
column indices. Indices are counted starting with 1.
*/
double& Entry(unsigned int row, unsigned int col) {
return data[(col-1)*eRows+row-1];
}
/** Number of rows in the matrix.
@return the number of rows in the matrix. */
@return the number of rows in the matrix.
*/
unsigned int Rows(void) const { return eRows; }
/** Number of cloumns in the matrix.
@return the number of columns in the matrix. */
@return the number of columns in the matrix.
*/
unsigned int Cols(void) const { return eColumns; }
/** Transposed matrix.
This function only returns the transpose of this matrix. This matrix itself
remains unchanged.
@return the transposed matrix. */
@return the transposed matrix.
*/
FGMatrix33 Transposed(void) const {
return FGMatrix33( Entry(1,1), Entry(2,1), Entry(3,1),
Entry(1,2), Entry(2,2), Entry(3,2),
@ -227,15 +252,18 @@ public:
}
/** Transposes this matrix.
This function only transposes this matrix. Nothing is returned. */
This function only transposes this matrix. Nothing is returned.
*/
void T(void);
/** Initialize the matrix.
This function initializes a matrix to all 0.0. */
This function initializes a matrix to all 0.0.
*/
void InitMatrix(void);
/** Initialize the matrix.
This function initializes a matrix to user specified values. */
This function initializes a matrix to user specified values.
*/
void InitMatrix(double m11, double m12, double m13,
double m21, double m22, double m23,
double m31, double m32, double m33) {
@ -251,7 +279,8 @@ public:
}
/** Determinant of the matrix.
@return the determinant of the matrix. */
@return the determinant of the matrix.
*/
double Determinant(void) const;
/** Return if the matrix is invertible.
@ -259,19 +288,24 @@ public:
invertible. This is done by simply computing the determinant and
check if it is zero. Note that this test does not cover any
instabilities caused by nearly singular matirces using finite
arithmetics. It only checks exact singularity. */
arithmetics. It only checks exact singularity.
*/
bool Invertible(void) const { return 0.0 != Determinant(); }
/** Return the inverse of the matrix.
Computes and returns if the inverse of the matrix. It is computed
by Cramers Rule. Also there are no checks performed if the matrix
is invertible. If you are not sure that it really is check this
with the @ref Invertible() call before. */
with the @ref Invertible() call before.
*/
FGMatrix33 Inverse(void) const;
/** Assignment operator.
@param A source matrix.
Copy the content of the matrix given in the argument into *this. */
Copy the content of the matrix given in the argument into *this.
*/
FGMatrix33& operator=(const FGMatrix33& A) {
data[0] = A.data[0];
data[1] = A.data[1];
@ -286,80 +320,113 @@ public:
}
/** Matrix vector multiplication.
@param v vector to multiply with.
@return matric vector product.
Compute and return the product of the current matrix with the
vector given in the argument. */
vector given in the argument.
*/
FGColumnVector3 operator*(const FGColumnVector3& v) const;
/** Matrix subtraction.
@param B matrix to add to.
@return difference of the matrices.
Compute and return the sum of the current matrix and the matrix
B given in the argument. */
B given in the argument.
*/
FGMatrix33 operator-(const FGMatrix33& B) const;
/** Matrix addition.
@param B matrix to add to.
@return sum of the matrices.
Compute and return the sum of the current matrix and the matrix
B given in the argument. */
B given in the argument.
*/
FGMatrix33 operator+(const FGMatrix33& B) const;
/** Matrix product.
@param B matrix to add to.
@return product of the matrices.
Compute and return the product of the current matrix and the matrix
B given in the argument. */
B given in the argument.
*/
FGMatrix33 operator*(const FGMatrix33& B) const;
/** Multiply the matrix with a scalar.
@param scalar scalar factor to multiply with.
@return scaled matrix.
Compute and return the product of the current matrix with the
scalar value scalar given in the argument. */
scalar value scalar given in the argument.
*/
FGMatrix33 operator*(const double scalar) const;
/** Multiply the matrix with 1.0/scalar.
@param scalar scalar factor to divide through.
@return scaled matrix.
Compute and return the product of the current matrix with the
scalar value 1.0/scalar, where scalar is given in the argument. */
scalar value 1.0/scalar, where scalar is given in the argument.
*/
FGMatrix33 operator/(const double scalar) const;
/** In place matrix subtraction.
@param B matrix to subtract.
@return reference to the current matrix.
Compute the diffence from the current matrix and the matrix B
given in the argument. */
given in the argument.
*/
FGMatrix33& operator-=(const FGMatrix33 &B);
/** In place matrix addition.
@param B matrix to add.
@return reference to the current matrix.
Compute the sum of the current matrix and the matrix B
given in the argument. */
given in the argument.
*/
FGMatrix33& operator+=(const FGMatrix33 &B);
/** In place matrix multiplication.
@param B matrix to multiply with.
@return reference to the current matrix.
Compute the product of the current matrix and the matrix B
given in the argument. */
given in the argument.
*/
FGMatrix33& operator*=(const FGMatrix33 &B);
/** In place matrix scale.
@param scalar scalar value to multiply with.
@return reference to the current matrix.
Compute the product of the current matrix and the scalar value scalar
given in the argument. */
given in the argument.
*/
FGMatrix33& operator*=(const double scalar);
/** In place matrix scale.
@param scalar scalar value to divide through.
@return reference to the current matrix.
Compute the product of the current matrix and the scalar value
1.0/scalar, where scalar is given in the argument. */
1.0/scalar, where scalar is given in the argument.
*/
FGMatrix33& operator/=(const double scalar);
private:
@ -369,24 +436,33 @@ private:
};
/** Scalar multiplication.
@param scalar scalar value to multiply with.
@param A Matrix to multiply.
Multiply the Matrix with a scalar value.*/
Multiply the Matrix with a scalar value.
*/
inline FGMatrix33 operator*(double scalar, const FGMatrix33& A) {
// use already defined operation.
return A*scalar;
}
/** Write matrix to a stream.
@param os Stream to write to.
@param M Matrix to write.
Write the matrix to a stream.*/
Write the matrix to a stream.
*/
ostream& operator<<(ostream& os, const FGMatrix33& M);
/** Read matrix from a stream.
@param os Stream to read from.
@param M Matrix to initialize with the values from the stream.
Read matrix from a stream.*/
Read matrix from a stream.
*/
istream& operator>>(istream& is, FGMatrix33& M);
} // namespace JSBSim

View file

@ -0,0 +1,55 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGParameter.h
Author: Jon Berndt
Date started: August 25 2004
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGPARAMETER_H
#define FGPARAMETER_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PARAMETER "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Represents various types of parameters.
@author Jon Berndt
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGParameter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGParameter : public FGJSBBase
{
public:
virtual double GetValue(void) const = 0;
protected:
};
} // namespace JSBSim
#endif

View file

@ -0,0 +1,34 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGPropertyValue.cpp
Author: Jon Berndt
Date started: 12/10/2004
Purpose: Stores property values
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGPropertyValue.h"
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_PROPERTYVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode) : PropertyManager(propNode)
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGPropertyValue::GetValue(void) const
{
return PropertyManager->getDoubleValue();
}
}

View file

@ -0,0 +1,60 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGPropertyValue.h
Author: Jon Berndt
Date started: December 10 2004
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGPROPERTYVALUE_H
#define FGPROPERTYVALUE_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGParameter.h"
#include <input_output/FGPropertyManager.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPERTYVALUE "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Represents a property value
@author Jon Berndt
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGPropertyValue
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGPropertyValue : public FGParameter
{
public:
FGPropertyValue(FGPropertyManager* propNode);
~FGPropertyValue() {};
double GetValue(void) const;
private:
FGPropertyManager* PropertyManager;
};
} // namespace JSBSim
#endif

View file

@ -38,10 +38,6 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef FGFS
# include <math.h>
# include <simgear/compiler.h>

View file

@ -40,10 +40,10 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include <FGJSBBase.h>
#include "FGMatrix33.h"
#include "FGColumnVector3.h"
#include "FGPropertyManager.h"
#include <input_output/FGPropertyManager.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS

View file

@ -0,0 +1,34 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGRealValue.cpp
Author: Jon Berndt
Date started: 12/10/2004
Purpose: Stores real values
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGRealValue.h"
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_REALVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGRealValue::FGRealValue(double value) : Value(value)
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGRealValue::GetValue(void) const
{
return Value;
}
}

View file

@ -0,0 +1,59 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGRealValue.h
Author: Jon Berndt
Date started: December 10 2004
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGREALVALUE_H
#define FGREALVALUE_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGParameter.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_REALVALUE "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Represents a real value
@author Jon Berndt
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGRealValue
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGRealValue : public FGParameter
{
public:
FGRealValue(double val);
~FGRealValue() {};
double GetValue(void) const;
private:
double Value;
};
} // namespace JSBSim
#endif

View file

@ -36,16 +36,12 @@ JSB 1/9/00 Created
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGTable.h"
#if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
#include <iomanip.h>
# include <iomanip.h>
#else
#include <iomanip>
# include <iomanip>
#endif
using namespace std;
@ -59,50 +55,12 @@ static const char *IdHdr = ID_TABLE;
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGTable::FGTable(int NRows, int NCols, int NTables)
: nRows(NTables), nCols(1), nTables(NTables)
{
Type = tt3D;
colCounter = 1;
rowCounter = 1;
Data = Allocate(); // this data array will contain the keys for the associated tables
Tables.reserve(nTables);
for (int i=0; i<nTables; i++) Tables.push_back(FGTable(NRows, NCols));
lastRowIndex=lastColumnIndex=2;
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols)
{
if (NCols > 1) {
Type = tt2D;
colCounter = 1;
rowCounter = 0;
} else if (NCols == 1) {
Type = tt1D;
colCounter = 0;
rowCounter = 1;
} else {
cerr << "FGTable cannot accept 'Rows=0'" << endl;
}
Data = Allocate();
lastRowIndex=lastColumnIndex=2;
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTable::FGTable(int NRows) : nRows(NRows), nCols(1)
FGTable::FGTable(int NRows) : nRows(NRows), nCols(1), PropertyManager(0)
{
Type = tt1D;
colCounter = 0;
rowCounter = 1;
nTables = 0;
Data = Allocate();
Debug(0);
@ -111,16 +69,17 @@ FGTable::FGTable(int NRows) : nRows(NRows), nCols(1)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTable::FGTable(const FGTable& t)
FGTable::FGTable(const FGTable& t) : PropertyManager(t.PropertyManager)
{
Type = t.Type;
colCounter = t.colCounter;
rowCounter = t.rowCounter;
tableCounter = t.tableCounter;
nRows = t.nRows;
nCols = t.nCols;
nTables = t.nTables;
dimension = t.dimension;
internal = t.internal;
Tables = t.Tables;
Data = Allocate();
@ -136,6 +95,168 @@ FGTable::FGTable(const FGTable& t)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(propMan)
{
int i;
stringstream buf;
string property_string;
string lookup_axis;
string call_type;
string parent_type;
FGPropertyManager* node;
Element *tableData;
Element *parent_element;
Element *axisElement;
string operation_types = "function, product, sum, difference, quotient,"
"pow, abs, sin, cos, asin, acos, tan, atan, table";
nTables = 0;
// Is this an internal lookup table?
internal = false;
call_type = el->GetAttributeValue("type");
if (call_type == string("internal")) {
parent_element = el->GetParent();
parent_type = parent_element->GetName();
if (operation_types.find(parent_type) == string::npos) {
internal = true;
} else {
// internal table is a child element of a restricted type
cerr << endl << fgred << " An internal table cannot be nested within another type," << endl;
cerr << " such as a function. The 'internal' keyword is ignored." << fgdef << endl << endl;
}
} else if (!call_type.empty()) {
cerr << endl << fgred << " An unknown table type attribute is listed: " << call_type
<< ". Execution cannot continue." << fgdef << endl << endl;
abort();
}
// Determine and store the lookup properties for this table unless this table
// is part of a 3D table, in which case its independentVar property indexes will
// be set by a call from the owning table during creation
dimension = 0;
axisElement = el->FindElement("independentVar");
if (axisElement) {
// The 'internal' attribute of the table element cannot be specified
// at the same time that independentVars are specified.
if (internal) {
cerr << endl << fgred << " This table specifies both 'internal' call type" << endl;
cerr << " and specific lookup properties via the 'independentVar' element." << endl;
cerr << " These are mutually exclusive specifications. The 'internal'" << endl;
cerr << " attribute will be ignored." << fgdef << endl << endl;
internal = false;
}
for (i=0; i<3; i++) lookupProperty[i] = 0;
while (axisElement) {
property_string = axisElement->GetDataLine();
node = PropertyManager->GetNode(property_string);
lookup_axis = axisElement->GetAttributeValue("lookup");
if (lookup_axis == string("row")) {
lookupProperty[eRow] = node;
} else if (lookup_axis == string("column")) {
lookupProperty[eColumn] = node;
} else if (lookup_axis == string("table")) {
lookupProperty[eTable] = node;
} else { // assumed single dimension table; row lookup
lookupProperty[eRow] = node;
}
dimension++;
axisElement = el->FindNextElement("independentVar");
}
} else if (internal) { // This table is an internal table
// determine how many rows, columns, and tables in this table (dimension).
if (el->GetNumElements("tableData") > 1) {
dimension = 3; // this is a 3D table
} else {
tableData = el->FindElement("tableData");
string test_line = tableData->GetDataLine(1); // examine second line in table for dimension
if (FindNumColumns(test_line) == 2) dimension = 1; // 1D table
else if (FindNumColumns(test_line) > 2) dimension = 2; // 2D table
else {
cerr << "Invalid number of columns in table" << endl;
}
}
} else { // no independentVars found, and table is not marked as internal
cerr << endl << fgred << "No independent variable found for table." << fgdef << endl << endl;
abort();
}
// end lookup property code
tableData = el->FindElement("tableData");
for (int i=0; i<tableData->GetNumDataLines(); i++) {
buf << tableData->GetDataLine(i) << string(" ");
}
switch (dimension) {
case 1:
nRows = tableData->GetNumDataLines();
nCols = 1;
Type = tt1D;
colCounter = 0;
rowCounter = 1;
Data = Allocate();
Debug(0);
lastRowIndex = lastColumnIndex = 2;
*this << buf;
break;
case 2:
nRows = tableData->GetNumDataLines()-1;
if (nRows >= 2) nCols = FindNumColumns(tableData->GetDataLine(0));
else {
cerr << endl << fgred << "Not enough rows in this table." << fgdef << endl;
abort();
}
Type = tt2D;
colCounter = 1;
rowCounter = 0;
Data = Allocate();
lastRowIndex = lastColumnIndex = 2;
*this << buf;
break;
case 3:
nTables = el->GetNumElements("tableData");
nRows = nTables;
nCols = 1;
Type = tt3D;
colCounter = 1;
rowCounter = 1;
Data = Allocate(); // this data array will contain the keys for the associated tables
Tables.reserve(nTables); // necessary?
tableData = el->FindElement("tableData");
for (i=0; i<nTables; i++) {
Tables.push_back(new FGTable(PropertyManager, tableData));
Data[i+1][1] = tableData->GetAttributeValueAsNumber("breakPoint");
Tables[i]->SetRowIndexProperty(lookupProperty[eRow]);
Tables[i]->SetColumnIndexProperty(lookupProperty[eColumn]);
tableData = el->FindNextElement("tableData");
}
Debug(0);
break;
default:
cout << "No dimension given" << endl;
break;
}
if (debug_lvl & 1) Print();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double** FGTable::Allocate(void)
{
Data = new double*[nRows+1];
@ -152,7 +273,11 @@ double** FGTable::Allocate(void)
FGTable::~FGTable()
{
if (nTables > 0) Tables.clear();
if (nTables > 0) {
cout << "nTables = " << nTables << endl;
for (int i=0; i<nTables; i++) delete Tables[i];
Tables.clear();
}
for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r];
if (Data) delete[] Data;
Debug(1);
@ -160,7 +285,46 @@ FGTable::~FGTable()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGTable::GetValue(double key)
int FGTable::FindNumColumns(string test_line)
{
// determine number of data columns in table (first column is row lookup - don't count)
int position=0;
int nCols=0;
while ((position = test_line.find_first_not_of(" \t", position)) != string::npos) {
nCols++;
position = test_line.find_first_of(" \t", position);
}
return nCols;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGTable::GetValue(void) const
{
double temp = 0;
double temp2 = 0;
switch (Type) {
case tt1D:
temp = lookupProperty[eRow]->getDoubleValue();
temp2 = GetValue(temp);
return temp2;
case tt2D:
return GetValue(lookupProperty[eRow]->getDoubleValue(),
lookupProperty[eColumn]->getDoubleValue());
case tt3D:
return GetValue(lookupProperty[eRow]->getDoubleValue(),
lookupProperty[eColumn]->getDoubleValue(),
lookupProperty[eTable]->getDoubleValue());
default:
cerr << "Attempted to GetValue() for invalid/unknown table type" << endl;
throw(string("Attempted to GetValue() for invalid/unknown table type"));
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGTable::GetValue(double key) const
{
double Factor, Value, Span;
int r=lastRowIndex;
@ -205,8 +369,7 @@ double FGTable::GetValue(double key)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGTable::GetValue(double rowKey, double colKey)
double FGTable::GetValue(double rowKey, double colKey) const
{
double rFactor, cFactor, col1temp, col2temp, Value;
int r=lastRowIndex;
@ -215,7 +378,6 @@ double FGTable::GetValue(double rowKey, double colKey)
if ( r > 2 && Data[r-1][0] > rowKey ) {
while ( Data[r-1][0] > rowKey && r > 2) { r--; }
} else if ( Data[r][0] < rowKey ) {
// cout << Data[r][0] << endl;
while ( r <= nRows && Data[r][0] <= rowKey ) { r++; }
if ( r > nRows ) r = nRows;
}
@ -249,7 +411,7 @@ double FGTable::GetValue(double rowKey, double colKey)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGTable::GetValue(double rowKey, double colKey, double tableKey)
double FGTable::GetValue(double rowKey, double colKey, double tableKey) const
{
double Factor, Value, Span;
int r=lastRowIndex;
@ -259,10 +421,10 @@ double FGTable::GetValue(double rowKey, double colKey, double tableKey)
if( tableKey <= Data[1][1] ) {
lastRowIndex=2;
return Tables[0].GetValue(rowKey, colKey);
return Tables[0]->GetValue(rowKey, colKey);
} else if ( tableKey >= Data[nRows][1] ) {
lastRowIndex=nRows;
return Tables[nRows-1].GetValue(rowKey, colKey);
return Tables[nRows-1]->GetValue(rowKey, colKey);
}
// the key is somewhere in the middle, search for the right breakpoint
@ -286,19 +448,18 @@ double FGTable::GetValue(double rowKey, double colKey, double tableKey)
Factor = 1.0;
}
Value = Factor*(Tables[r-1].GetValue(rowKey, colKey) - Tables[r-2].GetValue(rowKey, colKey))
+ Tables[r-2].GetValue(rowKey, colKey);
Value = Factor*(Tables[r-1]->GetValue(rowKey, colKey) - Tables[r-2]->GetValue(rowKey, colKey))
+ Tables[r-2]->GetValue(rowKey, colKey);
return Value;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTable::operator<<(FGConfigFile& infile)
void FGTable::operator<<(stringstream& in_stream)
{
int startRow=0;
int startCol=0;
int tableCtr=0;
if (Type == tt1D || Type == tt3D) startRow = 1;
if (Type == tt3D) startCol = 1;
@ -306,11 +467,7 @@ void FGTable::operator<<(FGConfigFile& infile)
for (int r=startRow; r<=nRows; r++) {
for (int c=startCol; c<=nCols; c++) {
if (r != 0 || c != 0) {
infile >> Data[r][c];
if (Type == tt3D) {
Tables[tableCtr] << infile;
tableCtr++;
}
in_stream >> Data[r][c];
}
}
}
@ -340,9 +497,8 @@ FGTable& FGTable::operator<<(const int n)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTable::Print(int spaces)
void FGTable::Print(void)
{
string tabspace;
int startRow=0;
int startCol=0;
@ -355,11 +511,22 @@ void FGTable::Print(int spaces)
ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream
#endif
for (int i=0;i<spaces;i++) tabspace+=" ";
switch(Type) {
case tt1D:
cout << " 1 dimensional table with " << nRows << " rows." << endl;
break;
case tt2D:
cout << " 2 dimensional table with " << nRows << " rows, " << nCols << " columns." << endl;
break;
case tt3D:
cout << " 3 dimensional table with " << nRows << " rows, "
<< nCols << " columns "
<< nTables << " tables." << endl;
break;
}
cout.precision(4);
for (int r=startRow; r<=nRows; r++) {
cout << tabspace;
cout << " ";
for (int c=startCol; c<=nCols; c++) {
if (r == 0 && c == 0) {
cout << " ";
@ -367,7 +534,7 @@ void FGTable::Print(int spaces)
cout << Data[r][c] << " ";
if (Type == tt3D) {
cout << endl;
Tables[r-1].Print(spaces);
Tables[r-1]->Print();
}
}
}

View file

@ -38,8 +38,10 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGConfigFile.h"
#include "FGJSBBase.h"
#include <input_output/FGXMLElement.h>
#include "FGParameter.h"
#include <input_output/FGPropertyManager.h>
#include <sstream>
#include <vector>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -53,6 +55,7 @@ FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
using std::vector;
using std::stringstream;
namespace JSBSim {
@ -199,7 +202,7 @@ CLASS DOCUMENTATION
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGTable : public FGJSBBase
class FGTable : public FGParameter
{
public:
/// Destructor
@ -209,14 +212,13 @@ public:
@param table a const reference to a table.*/
FGTable(const FGTable& table);
/** The constructor for a VECTOR table
@param nRows the number of rows in this VECTOR table. */
FGTable(int nRows);
FGTable(int nRows, int nCols);
FGTable(int nRows, int nCols, int numTables);
double GetValue(double key);
double GetValue(double rowKey, double colKey);
double GetValue(double rowKey, double colKey, double TableKey);
/// The constructor for a table
FGTable (FGPropertyManager* propMan, Element* el);
FGTable (int );
double GetValue(void) const;
double GetValue(double key) const;
double GetValue(double rowKey, double colKey) const;
double GetValue(double rowKey, double colKey, double TableKey) const;
/** Read the table in.
Data in the config file should be in matrix format with the row
independents as the first column and the column independents in
@ -239,21 +241,32 @@ public:
</pre>
*/
void operator<<(FGConfigFile&);
void operator<<(stringstream&);
FGTable& operator<<(const double n);
FGTable& operator<<(const int n);
inline double GetElement(int r, int c) {return Data[r][c];}
inline double GetElement(int r, int c, int t);
void Print(int spaces=0);
void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;}
void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;}
void Print(void);
private:
enum type {tt1D, tt2D, tt3D} Type;
enum axis {eRow=0, eColumn, eTable};
bool internal;
FGPropertyManager *lookupProperty[3];
double** Data;
vector <FGTable> Tables;
int nRows, nCols, nTables;
vector <FGTable*> Tables;
int FindNumColumns(string);
int nRows, nCols, nTables, dimension;
int colCounter, rowCounter, tableCounter;
int lastRowIndex, lastColumnIndex, lastTableIndex;
mutable int lastRowIndex, lastColumnIndex, lastTableIndex;
double** Allocate(void);
FGPropertyManager* const PropertyManager;
void Debug(int from);
};
}

View file

@ -0,0 +1,9 @@
noinst_LIBRARIES = libMath.a
libMath_a_SOURCES = FGColumnVector3.cpp FGFunction.cpp FGLocation.cpp FGMatrix33.cpp \
FGPropertyValue.cpp FGQuaternion.cpp FGRealValue.cpp FGTable.cpp
noinst_HEADERS = FGColumnVector3.h FGFunction.h FGLocation.h FGMatrix33.h \
FGParameter.h FGPropertyValue.h FGQuaternion.h FGRealValue.h FGTable.h
INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim

View file

@ -0,0 +1,403 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGAerodynamics.cpp
Author: Jon S. Berndt
Date started: 09/13/00
Purpose: Encapsulates the aerodynamic forces
------------- Copyright (C) 2000 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
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
09/13/00 JSB Created
04/22/01 JSB Moved code into here from FGAircraft
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGAerodynamics.h"
#include "FGPropagate.h"
#include "FGAircraft.h"
#include "FGState.h"
#include "FGMassBalance.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_AERODYNAMICS;
const unsigned NAxes=6;
const char* AxisNames[] = { "drag", "side-force", "lift", "rolling-moment",
"pitching-moment","yawing-moment" };
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
{
Name = "FGAerodynamics";
AxisIdx["DRAG"] = 0;
AxisIdx["SIDE"] = 1;
AxisIdx["LIFT"] = 2;
AxisIdx["ROLL"] = 3;
AxisIdx["PITCH"] = 4;
AxisIdx["YAW"] = 5;
Coeff = new CoeffArray[6];
impending_stall = stall_hyst = 0.0;
alphaclmin = alphaclmax = 0.0;
alphahystmin = alphahystmax = 0.0;
clsq = lod = 0.0;
alphaw = 0.0;
bi2vel = ci2vel = 0.0;
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGAerodynamics::~FGAerodynamics()
{
unsigned int i,j;
unbind();
for (i=0; i<6; i++)
for (j=0; j<Coeff[i].size(); j++)
delete Coeff[i][j];
delete[] Coeff;
for (i=0; i<variables.size(); i++)
delete variables[i];
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAerodynamics::Run(void)
{
unsigned int axis_ctr, ctr, i;
double alpha, twovel;
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false; // if paused don't execute
// calculate some oft-used quantities for speed
twovel = 2*Auxiliary->GetVt();
if (twovel != 0) {
bi2vel = Aircraft->GetWingSpan() / twovel;
ci2vel = Aircraft->Getcbar() / twovel;
}
alphaw = Auxiliary->Getalpha() + Aircraft->GetWingIncidence();
alpha = Auxiliary->Getalpha();
qbar_area = Aircraft->GetWingArea() * Auxiliary->Getqbar();
if (alphaclmax != 0) {
if (alpha > 0.85*alphaclmax) {
impending_stall = 10*(alpha/alphaclmax - 0.85);
} else {
impending_stall = 0;
}
}
if (alphahystmax != 0.0 && alphahystmin != 0.0) {
if (alpha > alphahystmax) {
stall_hyst = 1;
} else if (alpha < alphahystmin) {
stall_hyst = 0;
}
}
vLastFs = vFs;
vFs.InitMatrix();
// Tell the variable functions to cache their values, so while the aerodynamic
// functions are being calculated for each axis, these functions do not get
// calculated each time, but instead use the values that have already
// been calculated for this frame.
for (i=0; i<variables.size(); i++) variables[i]->cacheValue(true);
for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) {
vFs(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue();
}
}
// calculate lift coefficient squared
if ( Auxiliary->Getqbar() > 0) {
clsq = vFs(eLift) / (Aircraft->GetWingArea()*Auxiliary->Getqbar());
clsq *= clsq;
}
if ( vFs(eDrag) > 0) {
lod = vFs(eLift) / vFs(eDrag);
}
//correct signs of drag and lift to wind axes convention
//positive forward, right, down
vFs(eDrag)*=-1; vFs(eLift)*=-1;
// transform stability axis forces into body axes
vForces = State->GetTs2b()*vFs;
vDXYZcg = MassBalance->StructuralToBody(Aircraft->GetXYZrp());
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++) {
vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->GetValue();
}
}
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAerodynamics::Load(Element *element)
{
string parameter, axis, scratch;
Element *temp_element, *axis_element, *function_element;
Debug(2);
if (temp_element = element->FindElement("alphalimits")) {
alphaclmin = temp_element->FindElementValueAsNumberConvertTo("min", "DEG");
alphaclmax = temp_element->FindElementValueAsNumberConvertTo("max", "DEG");
}
if (temp_element = element->FindElement("hysteresis_limits")) {
alphahystmin = temp_element->FindElementValueAsNumberConvertTo("min", "DEG");
alphahystmax = temp_element->FindElementValueAsNumberConvertTo("max", "DEG");
}
function_element = element->FindElement("function");
while (function_element) {
variables.push_back( new FGFunction(PropertyManager, function_element) );
function_element = element->FindNextElement("function");
}
axis_element = element->FindElement("axis");
while (axis_element) {
CoeffArray ca;
axis = axis_element->GetAttributeValue("name");
function_element = axis_element->FindElement("function");
while (function_element) {
ca.push_back( new FGFunction(PropertyManager, function_element) );
function_element = axis_element->FindNextElement("function");
}
Coeff[AxisIdx[axis]] = ca;
axis_element = element->FindNextElement("axis");
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGAerodynamics::GetCoefficientStrings(string delimeter)
{
string CoeffStrings = "";
bool firstime = true;
unsigned int axis, sd;
for (sd = 0; sd < variables.size(); sd++) {
if (firstime) {
firstime = false;
} else {
CoeffStrings += delimeter;
}
CoeffStrings += variables[sd]->GetName();
}
for (axis = 0; axis < 6; axis++) {
for (sd = 0; sd < Coeff[axis].size(); sd++) {
CoeffStrings += delimeter;
CoeffStrings += Coeff[axis][sd]->GetName();
}
}
return CoeffStrings;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGAerodynamics::GetCoefficientValues(string delimeter)
{
string SDValues = "";
bool firstime = true;
unsigned int sd;
for (sd = 0; sd < variables.size(); sd++) {
if (firstime) {
firstime = false;
} else {
SDValues += delimeter;
}
SDValues += variables[sd]->GetValueAsString();
}
for (unsigned int axis = 0; axis < 6; axis++) {
for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
SDValues += delimeter;
SDValues += Coeff[axis][sd]->GetValueAsString();
}
}
return SDValues;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAerodynamics::bind(void)
{
typedef double (FGAerodynamics::*PMF)(int) const;
PropertyManager->Tie("forces/fbx-aero-lbs", this,1,
(PMF)&FGAerodynamics::GetForces);
PropertyManager->Tie("forces/fby-aero-lbs", this,2,
(PMF)&FGAerodynamics::GetForces);
PropertyManager->Tie("forces/fbz-aero-lbs", this,3,
(PMF)&FGAerodynamics::GetForces);
PropertyManager->Tie("moments/l-aero-lbsft", this,1,
(PMF)&FGAerodynamics::GetMoments);
PropertyManager->Tie("moments/m-aero-lbsft", this,2,
(PMF)&FGAerodynamics::GetMoments);
PropertyManager->Tie("moments/n-aero-lbsft", this,3,
(PMF)&FGAerodynamics::GetMoments);
PropertyManager->Tie("forces/fwx-aero-lbs", this,1,
(PMF)&FGAerodynamics::GetvFs);
PropertyManager->Tie("forces/fwy-aero-lbs", this,2,
(PMF)&FGAerodynamics::GetvFs);
PropertyManager->Tie("forces/fwz-aero-lbs", this,3,
(PMF)&FGAerodynamics::GetvFs);
PropertyManager->Tie("forces/lod-norm", this,
&FGAerodynamics::GetLoD);
PropertyManager->Tie("aero/cl-squared", this,
&FGAerodynamics::GetClSquared);
PropertyManager->Tie("aero/qbar-area", &qbar_area);
PropertyManager->Tie("aero/alpha-max-deg", this,
&FGAerodynamics::GetAlphaCLMax,
&FGAerodynamics::SetAlphaCLMax,
true);
PropertyManager->Tie("aero/alpha-min-deg", this,
&FGAerodynamics::GetAlphaCLMin,
&FGAerodynamics::SetAlphaCLMin,
true);
PropertyManager->Tie("aero/bi2vel", this,
&FGAerodynamics::GetBI2Vel);
PropertyManager->Tie("aero/ci2vel", this,
&FGAerodynamics::GetCI2Vel);
PropertyManager->Tie("aero/alpha-wing-rad", this,
&FGAerodynamics::GetAlphaW);
PropertyManager->Tie("systems/stall-warn-norm", this,
&FGAerodynamics::GetStallWarn);
PropertyManager->Tie("aero/stall-hyst-norm", this,
&FGAerodynamics::GetHysteresisParm);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAerodynamics::unbind(void)
{
unsigned i,j;
PropertyManager->Untie("forces/fbx-aero-lbs");
PropertyManager->Untie("forces/fby-aero-lbs");
PropertyManager->Untie("forces/fbz-aero-lbs");
PropertyManager->Untie("moments/l-aero-lbsft");
PropertyManager->Untie("moments/m-aero-lbsft");
PropertyManager->Untie("moments/n-aero-lbsft");
PropertyManager->Untie("forces/fwx-aero-lbs");
PropertyManager->Untie("forces/fwy-aero-lbs");
PropertyManager->Untie("forces/fwz-aero-lbs");
PropertyManager->Untie("forces/lod-norm");
PropertyManager->Untie("aero/cl-squared");
PropertyManager->Untie("aero/qbar-area");
PropertyManager->Untie("aero/alpha-max-deg");
PropertyManager->Untie("aero/alpha-min-deg");
PropertyManager->Untie("aero/bi2vel");
PropertyManager->Untie("aero/ci2vel");
PropertyManager->Untie("aero/alpha-wing-rad");
PropertyManager->Untie("aero/stall-hyst-norm");
PropertyManager->Untie("systems/stall-warn-norm");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGAerodynamics::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 2) { // Loader
cout << endl << " Aerodynamics: " << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGAerodynamics" << endl;
if (from == 1) cout << "Destroyed: FGAerodynamics" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,196 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGAerodynamics.h
Author: Jon S. Berndt
Date started: 09/13/00
------------- 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.
HISTORY
--------------------------------------------------------------------------------
09/13/00 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGAERODYNAMICS_H
#define FGAERODYNAMICS_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
# include <vector>
# include <map>
# else
# include <vector.h>
# include <map.h>
# endif
#else
# include <vector>
# include <map>
#endif
#include "FGModel.h"
#include <math/FGFunction.h>
#include <math/FGColumnVector3.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AERODYNAMICS "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Encapsulates the aerodynamic calculations.
This class owns and contains the list of coefficients that define the
aerodynamic properties of this aircraft. Here also, such unique phenomena
as ground effect and maximum lift curve tailoff are handled.
@config
<pre>
\<AERODYNAMICS>
\<AXIS NAME="{LIFT|DRAG|SIDE|ROLL|PITCH|YAW}">
{Coefficient definitions}
\</AXIS>
{Additional axis definitions}
\</AERODYNAMICS> </pre>
@author Jon S. Berndt, Tony Peden
$Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGAerodynamics : public FGModel {
public:
/** Constructor
@param Executive a pointer to the parent executive object */
FGAerodynamics(FGFDMExec* Executive);
/// Destructor
~FGAerodynamics();
/** Runs the Aerodynamics model; called by the Executive
@return false if no error */
bool Run(void);
/** Loads the Aerodynamics model.
The Load function for this class expects the XML parser to
have found the AERODYNAMICS keyword in the configuration file.
@param element pointer to the current XML element for aerodynamics parameters.
@return true if successful */
bool Load(Element* element);
/** Gets the total aerodynamic force vector.
@return a force vector reference. */
FGColumnVector3& GetForces(void) {return vForces;}
/** Gets the aerodynamic force for an axis.
@param n Axis index. This could be 0, 1, or 2, or one of the
axis enums: eX, eY, eZ.
@return the force acting on an axis */
double GetForces(int n) const {return vForces(n);}
/** Gets the total aerodynamic moment vector.
@return a moment vector reference. */
FGColumnVector3& GetMoments(void) {return vMoments;}
/** Gets the aerodynamic moment for an axis.
@return the moment about a single axis (as described also in the
similar call to GetForces(int n).*/
double GetMoments(int n) const {return vMoments(n);}
FGColumnVector3& GetvLastFs(void) { return vLastFs; }
double GetvLastFs(int axis) const { return vLastFs(axis); }
FGColumnVector3& GetvFs(void) { return vFs; }
double GetvFs(int axis) const { return vFs(axis); }
inline double GetLoD(void) const { return lod; }
inline double GetClSquared(void) const { return clsq; }
inline double GetAlphaCLMax(void) const { return alphaclmax; }
inline double GetAlphaCLMin(void) const { return alphaclmin; }
inline double GetAlphaHystMax(void) const { return alphahystmax; }
inline double GetAlphaHystMin(void) const { return alphahystmin; }
inline double GetHysteresisParm(void) const { return stall_hyst; }
inline double GetStallWarn(void) const { return impending_stall; }
double GetAlphaW(void) const { return alphaw; }
double GetBI2Vel(void) const { return bi2vel; }
double GetCI2Vel(void) const { return ci2vel; }
inline void SetAlphaCLMax(double tt) { alphaclmax=tt; }
inline void SetAlphaCLMin(double tt) { alphaclmin=tt; }
/** Gets the strings for the current set of coefficients.
@param delimeter either a tab or comma string depending on output type
@return a string containing the descriptive names for all coefficients */
string GetCoefficientStrings(string delimeter);
/** Gets the coefficient values.
@param delimeter either a tab or comma string depending on output type
@return a string containing the numeric values for the current set of
coefficients */
string GetCoefficientValues(string delimeter);
void bind(void);
void unbind(void);
private:
typedef map<string,int> AxisIndex;
AxisIndex AxisIdx;
vector <FGFunction*> variables;
typedef vector <FGFunction*> CoeffArray;
CoeffArray* Coeff;
FGColumnVector3 vFs;
FGColumnVector3 vForces;
FGColumnVector3 vMoments;
FGColumnVector3 vLastFs;
FGColumnVector3 vDXYZcg;
double alphaclmax, alphaclmin;
double alphahystmax, alphahystmin;
double impending_stall, stall_hyst;
double bi2vel, ci2vel,alphaw;
double clsq, lod, qbar_area;
typedef double (FGAerodynamics::*PMF)(int) const;
void Debug(int from);
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,324 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGAircraft.cpp
Author: Jon S. Berndt
Date started: 12/12/98
Purpose: Encapsulates an aircraft
Called by: FGFDMExec
------------- 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
--------------------------------------------------------------------------------
Models the aircraft reactions and forces. This class is instantiated by the
FGFDMExec class and scheduled as an FDM entry.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <sys/stat.h>
#include <sys/types.h>
#ifdef FGFS
# ifndef __BORLANDC__
# include <simgear/compiler.h>
# endif
# ifdef SG_HAVE_STD_INCLUDES
# include <cmath>
# else
# include <math.h>
# endif
#else
# 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 <FGState.h>
#include <FGFDMExec.h>
#include "FGPropagate.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_AIRCRAFT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex)
{
Name = "FGAircraft";
WingSpan = 0.0;
HTailArea = VTailArea = 0.0;
HTailArm = VTailArm = 0.0;
lbarh = lbarv = 0.0;
vbarh = vbarv = 0.0;
WingIncidence = 0.0;
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGAircraft::~FGAircraft()
{
unbind();
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAircraft::Run(void)
{
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
vForces.InitMatrix();
vForces += Aerodynamics->GetForces();
vForces += Propulsion->GetForces();
vForces += GroundReactions->GetForces();
vMoments.InitMatrix();
vMoments += Aerodynamics->GetMoments();
vMoments += Propulsion->GetMoments();
vMoments += GroundReactions->GetMoments();
// printf("%s:%i\n", __FILE__, __LINE__);
vBodyAccel = vForces/MassBalance->GetMass();
// printf("%s:%i\n", __FILE__, __LINE__);
vNcg = vBodyAccel/Inertial->gravity();
vNwcg = State->GetTb2s() * vNcg;
vNwcg(3) = -1*vNwcg(3) + 1;
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGAircraft::GetNlf(void)
{
return -1*Aerodynamics->GetvFs(3)/MassBalance->GetWeight();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAircraft::Load(Element* el)
{
string element_name;
Element* element;
if (el->FindElement("wingarea"))
WingArea = el->FindElementValueAsNumberConvertTo("wingarea", "FT2");
if (el->FindElement("wingspan"))
WingSpan = el->FindElementValueAsNumberConvertTo("wingspan", "FT");
if (el->FindElement("chord"))
cbar = el->FindElementValueAsNumberConvertTo("chord", "FT");
if (el->FindElement("wing_incidence"))
WingIncidence = el->FindElementValueAsNumberConvertTo("wing_incidence", "DEG");
if (el->FindElement("htailarea"))
HTailArea = el->FindElementValueAsNumberConvertTo("htailarea", "FT2");
if (el->FindElement("htailarm"))
HTailArm = el->FindElementValueAsNumberConvertTo("htailarm", "FT");
if (el->FindElement("vtailarea"))
VTailArea = el->FindElementValueAsNumberConvertTo("vtailarea", "FT2");
if (el->FindElement("vtailarm"))
VTailArm = el->FindElementValueAsNumberConvertTo("vtailarm", "FT");
// Find all LOCATION elements that descend from this METRICS branch of the
// config file. This would be CG location, eyepoint, etc.
element = el->FindElement("location");
while (element) {
element_name = element->GetAttributeValue("name");
if (element_name == "AERORP") vXYZrp = element->FindElementTripletConvertTo("IN");
else if (element_name == "EYEPOINT") vXYZep = element->FindElementTripletConvertTo("IN");
else if (element_name == "VRP") vXYZvrp = element->FindElementTripletConvertTo("IN");
element = el->FindNextElement("location");
}
// 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);
}
}
Debug(2);
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::bind(void)
{
typedef double (FGAircraft::*PMF)(int) const;
PropertyManager->Tie("metrics/Sw-sqft", this, &FGAircraft::GetWingArea);
PropertyManager->Tie("metrics/bw-ft", this, &FGAircraft::GetWingSpan);
PropertyManager->Tie("metrics/cbarw-ft", this, &FGAircraft::Getcbar);
PropertyManager->Tie("metrics/iw-deg", this, &FGAircraft::GetWingIncidence);
PropertyManager->Tie("metrics/Sh-sqft", this, &FGAircraft::GetHTailArea);
PropertyManager->Tie("metrics/lh-ft", this, &FGAircraft::GetHTailArm);
PropertyManager->Tie("metrics/Sv-sqft", this, &FGAircraft::GetVTailArea);
PropertyManager->Tie("metrics/lv-ft", this, &FGAircraft::GetVTailArm);
PropertyManager->Tie("metrics/lh-norm", this, &FGAircraft::Getlbarh);
PropertyManager->Tie("metrics/lv-norm", this, &FGAircraft::Getlbarv);
PropertyManager->Tie("metrics/vbarh-norm", this, &FGAircraft::Getvbarh);
PropertyManager->Tie("metrics/vbarv-norm", this, &FGAircraft::Getvbarv);
PropertyManager->Tie("moments/l-total-lbsft", this, eL, (PMF)&FGAircraft::GetMoments);
PropertyManager->Tie("moments/m-total-lbsft", this, eM, (PMF)&FGAircraft::GetMoments);
PropertyManager->Tie("moments/n-total-lbsft", this, eN, (PMF)&FGAircraft::GetMoments);
PropertyManager->Tie("forces/fbx-total-lbs", this, eX, (PMF)&FGAircraft::GetForces);
PropertyManager->Tie("forces/fby-total-lbs", this, eY, (PMF)&FGAircraft::GetForces);
PropertyManager->Tie("forces/fbz-total-lbs", this, eZ, (PMF)&FGAircraft::GetForces);
PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp);
PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp);
PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp);
PropertyManager->Tie("metrics/eyepoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZep);
PropertyManager->Tie("metrics/eyepoint-y-in", this, eY,(PMF)&FGAircraft::GetXYZep);
PropertyManager->Tie("metrics/eyepoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZep);
PropertyManager->Tie("metrics/visualrefpoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZvrp);
PropertyManager->Tie("metrics/visualrefpoint-y-in", this, eY, (PMF)&FGAircraft::GetXYZvrp);
PropertyManager->Tie("metrics/visualrefpoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZvrp);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAircraft::unbind(void)
{
PropertyManager->Untie("metrics/Sw-sqft");
PropertyManager->Untie("metrics/bw-ft");
PropertyManager->Untie("metrics/cbarw-ft");
PropertyManager->Untie("metrics/iw-deg");
PropertyManager->Untie("metrics/Sh-sqft");
PropertyManager->Untie("metrics/lh-ft");
PropertyManager->Untie("metrics/Sv-sqft");
PropertyManager->Untie("metrics/lv-ft");
PropertyManager->Untie("metrics/lh-norm");
PropertyManager->Untie("metrics/lv-norm");
PropertyManager->Untie("metrics/vbarh-norm");
PropertyManager->Untie("metrics/vbarv-norm");
PropertyManager->Untie("moments/l-total-lbsft");
PropertyManager->Untie("moments/m-total-lbsft");
PropertyManager->Untie("moments/n-total-lbsft");
PropertyManager->Untie("forces/fbx-total-lbs");
PropertyManager->Untie("forces/fby-total-lbs");
PropertyManager->Untie("forces/fbz-total-lbs");
PropertyManager->Untie("metrics/aero-rp-x-in");
PropertyManager->Untie("metrics/aero-rp-y-in");
PropertyManager->Untie("metrics/aero-rp-z-in");
PropertyManager->Untie("metrics/eyepoint-x-in");
PropertyManager->Untie("metrics/eyepoint-y-in");
PropertyManager->Untie("metrics/eyepoint-z-in");
PropertyManager->Untie("metrics/visualrefpoint-x-in");
PropertyManager->Untie("metrics/visualrefpoint-y-in");
PropertyManager->Untie("metrics/visualrefpoint-z-in");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGAircraft::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 2) { // Loading
cout << endl << " Aircraft Metrics:" << endl;
cout << " WingArea: " << WingArea << endl;
cout << " WingSpan: " << WingSpan << endl;
cout << " Incidence: " << WingIncidence << endl;
cout << " Chord: " << cbar << endl;
cout << " H. Tail Area: " << HTailArea << endl;
cout << " H. Tail Arm: " << HTailArm << endl;
cout << " V. Tail Area: " << VTailArea << endl;
cout << " V. Tail Arm: " << VTailArm << endl;
cout << " Eyepoint (x, y, z): " << vXYZep << endl;
cout << " Ref Pt (x, y, z): " << vXYZrp << endl;
cout << " Visual Ref Pt (x, y, z): " << vXYZvrp << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGAircraft" << endl;
if (from == 1) cout << "Destroyed: FGAircraft" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,184 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGAircraft.h
Author: Jon S. Berndt
Date started: 12/12/98
------------- 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.
HISTORY
--------------------------------------------------------------------------------
12/12/98 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGAIRCRAFT_H
#define FGAIRCRAFT_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
# include <vector>
# include <iterator>
# else
# include <vector.h>
# include <iterator.h>
# endif
#else
# include <vector>
# include <iterator>
#endif
#include "FGModel.h"
#include <input_output/FGXMLElement.h>
#include <math/FGColumnVector3.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AIRCRAFT "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Encapsulates an Aircraft and its systems.
Owns all the parts (other classes) which make up this aircraft. This includes
the Engines, Tanks, Propellers, Nozzles, Aerodynamic and Mass properties,
landing gear, etc. These constituent parts may actually run as separate
JSBSim models themselves, but the responsibility for initializing them and
for retrieving their force and moment contributions falls to FGAircraft.
@author Jon S. Berndt
@version $Id$
@see 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
@see D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
JSC 12960, July 1977
@see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
NASA-Ames", NASA CR-2497, January 1975
@see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
Wiley & Sons, 1979 ISBN 0-471-03032-5
@see Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
1982 ISBN 0-471-08936-2
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGAircraft : public FGModel {
public:
/** Constructor
@param Executive a pointer to the parent executive object */
FGAircraft(FGFDMExec *Executive);
/// Destructor
~FGAircraft();
/** Runs the Aircraft model; called by the Executive
@see JSBSim.cpp documentation
@return false if no error */
bool Run(void);
/** Loads the aircraft.
The executive calls this method to load the aircraft into JSBSim.
@param el a pointer to the element tree
@return true if successful */
bool Load(Element* el);
/** Gets the aircraft name
@return the name of the aircraft as a string type */
inline string GetAircraftName(void) { return AircraftName; }
/// Gets the wing area
double GetWingArea(void) const { return WingArea; }
/// Gets the wing span
double GetWingSpan(void) const { return WingSpan; }
/// Gets the average wing chord
double Getcbar(void) const { return cbar; }
inline double GetWingIncidence(void) const { return WingIncidence; }
inline double GetHTailArea(void) const { return HTailArea; }
inline double GetHTailArm(void) const { return HTailArm; }
inline double GetVTailArea(void) const { return VTailArea; }
inline double GetVTailArm(void) const { return VTailArm; }
inline double Getlbarh(void) const { return lbarh; } // HTailArm / cbar
inline double Getlbarv(void) const { return lbarv; } // VTailArm / cbar
inline double Getvbarh(void) const { return vbarh; } // H. Tail Volume
inline double Getvbarv(void) const { return vbarv; } // V. Tail Volume
inline FGColumnVector3& GetMoments(void) { return vMoments; }
inline double GetMoments(int idx) const { return vMoments(idx); }
inline FGColumnVector3& GetForces(void) { return vForces; }
inline double GetForces(int idx) const { return vForces(idx); }
inline FGColumnVector3& GetBodyAccel(void) { return vBodyAccel; }
inline double GetBodyAccel(int idx) { return vBodyAccel(idx); }
inline FGColumnVector3& GetNcg (void) { return vNcg; }
inline double GetNcg(int idx) { return vNcg(idx); }
inline FGColumnVector3& GetXYZrp(void) { return vXYZrp; }
inline FGColumnVector3& GetXYZvrp(void) { return vXYZvrp; }
inline FGColumnVector3& GetXYZep(void) { return vXYZep; }
inline double GetXYZrp(int idx) const { return vXYZrp(idx); }
inline double GetXYZvrp(int idx) const { return vXYZvrp(idx); }
inline double GetXYZep(int idx) const { return vXYZep(idx); }
inline void SetAircraftName(string name) {AircraftName = name;}
double GetNlf(void);
inline FGColumnVector3& GetNwcg(void) { return vNwcg; }
void bind(void);
void unbind(void);
private:
FGColumnVector3 vMoments;
FGColumnVector3 vForces;
FGColumnVector3 vXYZrp;
FGColumnVector3 vXYZvrp;
FGColumnVector3 vXYZep;
FGColumnVector3 vDXYZcg;
FGColumnVector3 vBodyAccel;
FGColumnVector3 vNcg;
FGColumnVector3 vNwcg;
double WingArea, WingSpan, cbar, WingIncidence;
double HTailArea, VTailArea, HTailArm, VTailArm;
double lbarh,lbarv,vbarh,vbarv;
string AircraftName;
void Debug(int from);
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,582 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGAtmosphere.cpp
Author: Jon Berndt
Implementation of 1959 Standard Atmosphere added by Tony Peden
Date started: 11/24/98
Purpose: Models the atmosphere
Called by: FGSimExec
------------- 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
--------------------------------------------------------------------------------
Models the atmosphere. The equation used below was determined by a third order
curve fit using Excel. The data is from the ICAO atmosphere model.
HISTORY
--------------------------------------------------------------------------------
11/24/98 JSB Created
07/23/99 TP Added implementation of 1959 Standard Atmosphere
Moved calculation of Mach number to FGPropagate
Later updated to '76 model
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[1] Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGAtmosphere.h"
#include <FGState.h>
#include <FGFDMExec.h>
#include "FGAircraft.h"
#include "FGPropagate.h"
#include "FGInertial.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
{
Name = "FGAtmosphere";
lastIndex = 0;
h = 0.0;
psiw = 0.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.
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
// turbType = ttNone;
turbType = ttStandard;
// turbType = ttBerndt;
TurbGain = 0.0;
TurbRate = 1.0;
T_dev_sl = T_dev = delta_T = 0.0;
StandardTempOnly = false;
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGAtmosphere::~FGAtmosphere()
{
unbind();
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAtmosphere::InitModel(void)
{
FGModel::InitModel();
UseInternal(); // this is the default
Calculate(h);
StdSLtemperature = SLtemperature = 518.67;
StdSLpressure = SLpressure = 2116.22;
StdSLdensity = SLdensity = 0.00237767;
StdSLsoundspeed = SLsoundspeed = sqrt(SHRatio*Reng*StdSLtemperature);
rSLtemperature = 1.0/StdSLtemperature;
rSLpressure = 1.0/StdSLpressure;
rSLdensity = 1.0/StdSLdensity;
rSLsoundspeed = 1.0/StdSLsoundspeed;
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAtmosphere::Run(void)
{
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
T_dev = 0.0;
h = Propagate->Geth();
if (!useExternal) {
Calculate(h);
CalculateDerived();
} else {
CalculateDerived();
}
Debug(2);
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// See reference 1
void FGAtmosphere::Calculate(double altitude)
{
double slope, reftemp, refpress;
int i = 0;
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 1: // 36089 ft.
slope = 0;
reftemp = 389.97;
refpress = 472.452;
//refdens = 0.000706032;
break;
case 2: // 65616 ft.
slope = 0.00054864;
reftemp = 389.97;
refpress = 114.636;
//refdens = 0.000171306;
break;
case 3: // 104986 ft.
slope = 0.00153619;
reftemp = 411.57;
refpress = 8.36364;
//refdens = 1.18422e-05;
break;
case 4: // 154199 ft.
slope = 0;
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: // 200131 ft.
slope = -0.00219456;
reftemp = 454.17;
refpress = 0.00684986;
//refdens = 8.77702e-9;
break;
case 7: // 259186 ft.
slope = 0;
reftemp = 325.17;
refpress = 0.000122276;
//refdens = 2.19541e-10;
break;
case 0:
default: // sea level
slope = -0.00356616; // R/ft.
reftemp = 518.67; // R
refpress = 2116.22; // psf
//refdens = 0.00237767; // slugs/cubic ft.
break;
}
// If delta_T is set, then that is our temperature deviation at any altitude.
// If not, then we'll estimate a deviation based on the sea level deviation (if set).
if(!StandardTempOnly) {
T_dev = 0.0;
if (delta_T != 0.0) {
T_dev = delta_T;
} else {
if ((altitude < 36089.239) && (T_dev_sl != 0.0)) {
T_dev = T_dev_sl * ( 1.0 - (altitude/36089.239));
}
}
reftemp+=T_dev;
}
if (slope == 0) {
intTemperature = reftemp;
intPressure = refpress*exp(-Inertial->SLgravity()/(reftemp*Reng)*(altitude-htab[i]));
intDensity = intPressure/(Reng*intTemperature);
} else {
intTemperature = reftemp+slope*(altitude-htab[i]);
intPressure = refpress*pow(intTemperature/reftemp,-Inertial->SLgravity()/(slope*Reng));
intDensity = intPressure/(Reng*intTemperature);
}
lastIndex=i;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Calculate parameters derived from T, P and rho
void FGAtmosphere::CalculateDerived(void)
{
T_dev = (*temperature) - GetTemperature(h);
density_altitude = h + T_dev * 66.7;
if (turbType != ttStandard) {
Turbulence();
vWindNED += vTurbulence;
}
if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) );
if (psiw < 0) psiw += 2*M_PI;
soundspeed = sqrt(SHRatio*Reng*(*temperature));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the standard atmospheric properties at a specified altitude
void FGAtmosphere::GetStdAtmosphere(double altitude) {
StandardTempOnly = true;
Calculate(altitude);
StandardTempOnly = false;
atmosphere.Temperature = intTemperature;
atmosphere.Pressure = intPressure;
atmosphere.Density = intDensity;
// Reset the internal atmospheric state
Calculate(h);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the standard pressure at a specified altitude
double FGAtmosphere::GetPressure(double altitude) {
GetStdAtmosphere(altitude);
return atmosphere.Pressure;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the standard temperature at a specified altitude
double FGAtmosphere::GetTemperature(double altitude) {
GetStdAtmosphere(altitude);
return atmosphere.Temperature;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Get the standard density at a specified altitude
double FGAtmosphere::GetDensity(double altitude) {
GetStdAtmosphere(altitude);
return atmosphere.Density;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// square a value, but preserve the original sign
static inline double square_signed (double value)
{
if (value < 0)
return value * value * -1;
else
return value * value;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAtmosphere::Turbulence(void)
{
switch (turbType) {
case ttStandard: {
vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
// Scale the magnitude so that it moves
// away from the peaks
MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
(1 + fabs(Magnitude)));
MagnitudeAccel += MagnitudedAccelDt*rate*TurbRate*State->Getdt();
Magnitude += MagnitudeAccel*rate*State->Getdt();
vDirectiondAccelDt.Normalize();
// deemphasise non-vertical forces
vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX));
vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY));
vDirectionAccel += vDirectiondAccelDt*rate*TurbRate*State->Getdt();
vDirectionAccel.Normalize();
vDirection += vDirectionAccel*rate*State->Getdt();
vDirection.Normalize();
// Diminish turbulence within three wingspans
// of the ground
vTurbulence = TurbGain * Magnitude * vDirection;
double HOverBMAC = Auxiliary->GetHOverBMAC();
if (HOverBMAC < 3.0)
vTurbulence *= (HOverBMAC / 3.0) * (HOverBMAC / 3.0);
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
if (Aircraft->GetWingSpan() > 0) {
vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
} else {
vTurbPQR(eP) = vBodyTurbGrad(eY)/30.0;
}
// if (Aircraft->GetHTailArm() != 0.0)
// vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
// else
// vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
if (Aircraft->GetVTailArm() > 0)
vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
else
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
// Clear the horizontal forces
// actually felt by the plane, now
// that we've used them to calculate
// moments.
vTurbulence(eX) = 0.0;
vTurbulence(eY) = 0.0;
break;
}
case ttBerndt: {
vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
MagnitudeAccel += MagnitudedAccelDt*rate*State->Getdt();
Magnitude += MagnitudeAccel*rate*State->Getdt();
vDirectiondAccelDt.Normalize();
vDirectionAccel += vDirectiondAccelDt*rate*State->Getdt();
vDirectionAccel.Normalize();
vDirection += vDirectionAccel*rate*State->Getdt();
// Diminish z-vector within two wingspans
// of the ground
double HOverBMAC = Auxiliary->GetHOverBMAC();
if (HOverBMAC < 2.0)
vDirection(eZ) *= HOverBMAC / 2.0;
vDirection.Normalize();
vTurbulence = TurbGain*Magnitude * vDirection;
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
if (Aircraft->GetHTailArm() > 0)
vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
else
vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
if (Aircraft->GetVTailArm() > 0)
vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
else
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
break;
}
default:
break;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAtmosphere::UseExternal(void)
{
temperature=&exTemperature;
pressure=&exPressure;
density=&exDensity;
useExternal=true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAtmosphere::UseInternal(void)
{
temperature=&intTemperature;
pressure=&intPressure;
density=&intDensity;
useExternal=false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAtmosphere::bind(void)
{
typedef double (FGAtmosphere::*PMF)(int) const;
PropertyManager->Tie("atmosphere/T-R", this,
&FGAtmosphere::GetTemperature);
PropertyManager->Tie("atmosphere/rho-slugs_ft3", this,
&FGAtmosphere::GetDensity);
// PropertyManager->Tie("atmosphere/P-psf", this,
// &FGAtmosphere::GetPressure);
PropertyManager->Tie("atmosphere/a-fps", this,
&FGAtmosphere::GetSoundSpeed);
PropertyManager->Tie("atmosphere/T-sl-R", this,
&FGAtmosphere::GetTemperatureSL);
PropertyManager->Tie("atmosphere/rho-sl-slugs_ft3", this,
&FGAtmosphere::GetDensitySL);
PropertyManager->Tie("atmosphere/P-sl-psf", this,
&FGAtmosphere::GetPressureSL);
PropertyManager->Tie("atmosphere/a-sl-fps", this,
&FGAtmosphere::GetSoundSpeedSL);
PropertyManager->Tie("atmosphere/theta", this,
&FGAtmosphere::GetTemperatureRatio);
PropertyManager->Tie("atmosphere/sigma", this,
&FGAtmosphere::GetDensityRatio);
PropertyManager->Tie("atmosphere/delta", this,
&FGAtmosphere::GetPressureRatio);
PropertyManager->Tie("atmosphere/a-ratio", this,
&FGAtmosphere::GetSoundSpeedRatio);
PropertyManager->Tie("atmosphere/psiw-rad", this,
&FGAtmosphere::GetWindPsi);
PropertyManager->Tie("atmosphere/delta-T", this,
&FGAtmosphere::GetDeltaT, &FGAtmosphere::SetDeltaT);
PropertyManager->Tie("atmosphere/T-sl-dev-F", this,
&FGAtmosphere::GetSLTempDev, &FGAtmosphere::SetSLTempDev);
PropertyManager->Tie("atmosphere/density-altitude", this,
&FGAtmosphere::GetDensityAltitude);
PropertyManager->Tie("atmosphere/p-turb-rad_sec", this,1,
(PMF)&FGAtmosphere::GetTurbPQR);
PropertyManager->Tie("atmosphere/q-turb-rad_sec", this,2,
(PMF)&FGAtmosphere::GetTurbPQR);
PropertyManager->Tie("atmosphere/r-turb-rad_sec", this,3,
(PMF)&FGAtmosphere::GetTurbPQR);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAtmosphere::unbind(void)
{
PropertyManager->Untie("atmosphere/T-R");
PropertyManager->Untie("atmosphere/rho-slugs_ft3");
// PropertyManager->Untie("atmosphere/P-psf");
PropertyManager->Untie("atmosphere/a-fps");
PropertyManager->Untie("atmosphere/T-sl-R");
PropertyManager->Untie("atmosphere/rho-sl-slugs_ft3");
PropertyManager->Untie("atmosphere/P-sl-psf");
PropertyManager->Untie("atmosphere/a-sl-fps");
PropertyManager->Untie("atmosphere/delta-T");
PropertyManager->Untie("atmosphere/T-sl-dev-F");
PropertyManager->Untie("atmosphere/density-altitude");
PropertyManager->Untie("atmosphere/theta");
PropertyManager->Untie("atmosphere/sigma");
PropertyManager->Untie("atmosphere/delta");
PropertyManager->Untie("atmosphere/a-ratio");
PropertyManager->Untie("atmosphere/psiw-rad");
PropertyManager->Untie("atmosphere/p-turb-rad_sec");
PropertyManager->Untie("atmosphere/q-turb-rad_sec");
PropertyManager->Untie("atmosphere/r-turb-rad_sec");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGAtmosphere::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGAtmosphere" << endl;
if (from == 1) cout << "Destroyed: FGAtmosphere" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 128) { // Turbulence
if (frame == 0 && from == 2) {
cout << "vTurbulence(X), vTurbulence(Y), vTurbulence(Z), "
<< "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), "
<< "vDirection(X), vDirection(Y), vDirection(Z), "
<< "Magnitude, "
<< "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl;
} else if (from == 2) {
cout << vTurbulence << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl;
}
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,217 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGAtmosphere.h
Author: Jon Berndt
Implementation of 1959 Standard Atmosphere added by Tony Peden
Date started: 11/24/98
------------- 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.
HISTORY
--------------------------------------------------------------------------------
11/24/98 JSB Created
07/23/99 TP Added implementation of 1959 Standard Atmosphere
Moved calculation of Mach number to FGPropagate
Updated to '76 model
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGAtmosphere_H
#define FGAtmosphere_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
#include <math/FGColumnVector3.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ATMOSPHERE "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models the standard atmosphere.
@author Tony Peden, Jon Berndt
@version $Id$
@see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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);
bool InitModel(void);
/// Returns the temperature in degrees Rankine.
inline double GetTemperature(void) const {return *temperature;}
/** Returns the density in slugs/ft^3.
<i>This function may <b>only</b> be used if Run() is called first.</i> */
inline double GetDensity(void) const {return *density;}
/// Returns the pressure in psf.
inline double GetPressure(void) const {return *pressure;}
/// Returns the standard pressure at a specified altitude
double GetPressure(double altitude);
/// Returns the standard temperature at a specified altitude
double GetTemperature(double altitude);
/// Returns the standard density at a specified altitude
double GetDensity(double altitude);
/// Returns the speed of sound in ft/sec.
inline double GetSoundSpeed(void) const {return soundspeed;}
/// Returns the sea level temperature in degrees Rankine.
inline double GetTemperatureSL(void) const { return SLtemperature; }
/// Returns the sea level density in slugs/ft^3
inline double GetDensitySL(void) const { return SLdensity; }
/// Returns the sea level pressure in psf.
inline double GetPressureSL(void) const { return SLpressure; }
/// Returns the sea level speed of sound in ft/sec.
inline double GetSoundSpeedSL(void) const { return SLsoundspeed; }
/// Returns the ratio of at-altitude temperature over the sea level value.
inline double GetTemperatureRatio(void) const { return (*temperature)*rSLtemperature; }
/// Returns the ratio of at-altitude density over the sea level value.
inline double GetDensityRatio(void) const { return (*density)*rSLdensity; }
/// Returns the ratio of at-altitude pressure over the sea level value.
inline double GetPressureRatio(void) const { return (*pressure)*rSLpressure; }
/// Returns the ratio of at-altitude sound speed over the sea level value.
inline double GetSoundSpeedRatio(void) const { return soundspeed*rSLsoundspeed; }
/// Tells the simulator to use an externally calculated atmosphere model.
void UseExternal(void);
/// Tells the simulator to use the internal atmosphere model.
void UseInternal(void); //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(double t) { exTemperature=t; }
/// Provides the external atmosphere model with an interface to set the density.
inline void SetExDensity(double d) { exDensity=d; }
/// Provides the external atmosphere model with an interface to set the pressure.
inline void SetExPressure(double p) { exPressure=p; }
/// Sets the temperature deviation at sea-level in degrees Fahrenheit
inline void SetSLTempDev(double d) { T_dev_sl = d; }
/// Gets the temperature deviation at sea-level in degrees Fahrenheit
inline double GetSLTempDev(void) const { return T_dev_sl; }
/// Sets the current delta-T in degrees Fahrenheit
inline void SetDeltaT(double d) { delta_T = d; }
/// Gets the current delta-T in degrees Fahrenheit
inline double GetDeltaT(void) const { return delta_T; }
/// Gets the at-altitude temperature deviation in degrees Fahrenheit
inline double GetTempDev(void) const { return T_dev; }
/// Gets the density altitude in feet
inline double GetDensityAltitude(void) const { return density_altitude; }
/// Sets the wind components in NED frame.
inline void SetWindNED(double wN, double wE, double wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;}
/// 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 double GetWindPsi(void) const { return psiw; }
inline void SetTurbGain(double tt) {TurbGain = tt;}
inline void SetTurbRate(double tt) {TurbRate = tt;}
inline double GetTurbPQR(int idx) const {return vTurbPQR(idx);}
inline FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;}
void bind(void);
void unbind(void);
protected:
double rho;
enum tType {ttStandard, ttBerndt, ttNone} turbType;
struct atmType {double Temperature; double Pressure; double Density;};
int lastIndex;
double h;
double htab[8];
double StdSLtemperature,StdSLdensity,StdSLpressure,StdSLsoundspeed;
double rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
double SLtemperature,SLdensity,SLpressure,SLsoundspeed;
double *temperature,*density,*pressure;
double soundspeed;
bool useExternal;
double exTemperature,exDensity,exPressure;
double intTemperature, intDensity, intPressure;
double T_dev_sl, T_dev, delta_T, density_altitude;
atmType atmosphere;
bool StandardTempOnly;
double MagnitudedAccelDt, MagnitudeAccel, Magnitude;
double TurbGain;
double TurbRate;
FGColumnVector3 vDirectiondAccelDt;
FGColumnVector3 vDirectionAccel;
FGColumnVector3 vDirection;
FGColumnVector3 vTurbulence;
FGColumnVector3 vTurbulenceGrad;
FGColumnVector3 vBodyTurbGrad;
FGColumnVector3 vTurbPQR;
FGColumnVector3 vWindNED;
double psiw;
/// Calculate the atmosphere for the given altitude, including effects of temperature deviation.
void Calculate(double altitude);
/// Calculate atmospheric properties other than the basic T, P and rho.
void CalculateDerived(void);
/// Get T, P and rho for a standard atmosphere at the given altitude.
void GetStdAtmosphere(double altitude);
void Turbulence(void);
void Debug(int from);
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,428 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGAuxiliary.cpp
Author: Tony Peden, Jon Berndt
Date started: 01/26/99
Purpose: Calculates additional parameters needed by the visual system, etc.
Called by: FGSimExec
------------- 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 calculates various auxiliary parameters.
REFERENCES
Anderson, John D. "Introduction to Flight", 3rd Edition, McGraw-Hill, 1989
pgs. 112-126
HISTORY
--------------------------------------------------------------------------------
01/26/99 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGAuxiliary.h"
#include "FGAerodynamics.h"
#include "FGPropagate.h"
#include "FGAtmosphere.h"
#include <FGState.h>
#include <FGFDMExec.h>
#include "FGAircraft.h"
#include "FGInertial.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_AUXILIARY;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
{
Name = "FGAuxiliary";
vcas = veas = pt = tat = 0;
psl = rhosl = 1;
earthPosAngle = 0.0;
qbar = 0;
qbarUW = 0.0;
qbarUV = 0.0;
Mach = 0.0;
alpha = beta = 0.0;
adot = bdot = 0.0;
gamma = Vt = Vground = 0.0;
psigt = 0.0;
day_of_year = 1;
seconds_in_day = 0.0;
hoverbmac = hoverbcg = 0.0;
vPilotAccel.InitMatrix();
vPilotAccelN.InitMatrix();
vToEyePt.InitMatrix();
vAeroPQR.InitMatrix();
vEulerRates.InitMatrix();
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGAuxiliary::~FGAuxiliary()
{
unbind();
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGAuxiliary::Run()
{
double A,B,D, hdot_Vt;
const FGColumnVector3& vPQR = Propagate->GetPQR();
const FGColumnVector3& vUVW = Propagate->GetUVW();
const FGColumnVector3& vUVWdot = Propagate->GetUVWdot();
const FGColumnVector3& vVel = Propagate->GetVel();
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
p = Atmosphere->GetPressure();
rhosl = Atmosphere->GetDensitySL();
psl = Atmosphere->GetPressureSL();
sat = Atmosphere->GetTemperature();
// Rotation
double cTht = Propagate->GetCosEuler(eTht);
double cPhi = Propagate->GetCosEuler(ePhi);
double sPhi = Propagate->GetSinEuler(ePhi);
vEulerRates(eTht) = vPQR(eQ)*cPhi - vPQR(eR)*sPhi;
if (cTht != 0.0) {
vEulerRates(ePsi) = (vPQR(eQ)*sPhi + vPQR(eR)*cPhi)/cTht;
vEulerRates(ePhi) = vPQR(eP) + vEulerRates(ePsi)*sPhi;
}
// 12/16/2005, JSB: For ground handling purposes, at this time, let's ramp
// in the effects of wind from 10 fps to 30 fps when there is weight on the
// landing gear wheels.
if (GroundReactions->GetWOW() && vUVW(eU) < 10) {
vAeroPQR = vPQR;
vAeroUVW = vUVW;
} else if (GroundReactions->GetWOW() && vUVW(eU) < 30) {
double factor = (vUVW(eU) - 10.0)/20.0;
vAeroPQR = vPQR + factor*Atmosphere->GetTurbPQR();
vAeroUVW = vUVW + factor*Propagate->GetTl2b()*Atmosphere->GetWindNED();
} else {
vAeroPQR = vPQR + Atmosphere->GetTurbPQR();
vAeroUVW = vUVW + Propagate->GetTl2b()*Atmosphere->GetWindNED();
}
Vt = vAeroUVW.Magnitude();
if ( Vt > 0.05) {
if (vAeroUVW(eW) != 0.0)
alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
if (vAeroUVW(eV) != 0.0)
beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV),
sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
double signU=1;
if (vAeroUVW(eU) != 0.0)
signU = vAeroUVW(eU)/fabs(vAeroUVW(eU));
if ( (mUW == 0.0) || (Vt == 0.0) ) {
adot = 0.0;
bdot = 0.0;
} else {
adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW;
bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU)
+ vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
}
} else {
alpha = beta = adot = bdot = 0;
}
qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt;
qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
Mach = Vt / Atmosphere->GetSoundSpeed();
MachU = vMachUVW(eU) = vAeroUVW(eU) / Atmosphere->GetSoundSpeed();
vMachUVW(eV) = vAeroUVW(eV) / Atmosphere->GetSoundSpeed();
vMachUVW(eW) = vAeroUVW(eW) / Atmosphere->GetSoundSpeed();
// Position
Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) );
if (vVel(eNorth) == 0) psigt = 0;
else psigt = atan2(vVel(eEast), vVel(eNorth));
if (psigt < 0.0) psigt += 2*M_PI;
if (Vt != 0) {
hdot_Vt = -vVel(eDown)/Vt;
if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);
} else {
gamma = 0.0;
}
tat = sat*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow
tatc = RankineToCelsius(tat);
if (MachU < 1) { // Calculate total pressure assuming isentropic flow
pt = p*pow((1 + 0.2*MachU*MachU),3.5);
} else {
// Use Rayleigh pitot tube formula for normal shock in front of pitot tube
B = 5.76*MachU*MachU/(5.6*MachU*MachU - 0.8);
D = (2.8*MachU*MachU-0.4)*0.4167;
pt = p*pow(B,3.5)*D;
}
A = pow(((pt-p)/psl+1),0.28571);
if (MachU > 0.0) {
vcas = sqrt(7*psl/rhosl*(A-1));
veas = sqrt(2*qbar/rhosl);
} else {
vcas = veas = 0.0;
}
vPilotAccel.InitMatrix();
if ( Vt > 1.0 ) {
vPilotAccel = Aerodynamics->GetForces()
+ Propulsion->GetForces()
+ GroundReactions->GetForces();
vPilotAccel /= MassBalance->GetMass();
vToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep());
vPilotAccel += Propagate->GetPQRdot() * vToEyePt;
vPilotAccel += vPQR * (vPQR * vToEyePt);
} else {
vPilotAccel = Propagate->GetTl2b() * FGColumnVector3( 0.0, 0.0, Inertial->gravity() );
}
vPilotAccelN = vPilotAccel/Inertial->gravity();
earthPosAngle += State->Getdt()*Inertial->omega();
// VRP computation
const FGLocation& vLocation = Propagate->GetLocation();
FGColumnVector3 vrpStructural = Aircraft->GetXYZvrp();
FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural );
FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody;
vLocationVRP = vLocation.LocalToLocation( vrpLocal );
// Recompute some derived values now that we know the dependent parameters values ...
hoverbcg = Propagate->GetDistanceAGL() / Aircraft->GetWingSpan();
FGColumnVector3 vMac = Propagate->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp());
hoverbmac = (Propagate->GetDistanceAGL() + vMac(3)) / Aircraft->GetWingSpan();
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGAuxiliary::GetHeadWind(void)
{
double psiw,vw;
psiw = Atmosphere->GetWindPsi();
vw = Atmosphere->GetWindNED().Magnitude();
return vw*cos(psiw - Propagate->GetEuler(ePsi));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGAuxiliary::GetCrossWind(void)
{
double psiw,vw;
psiw = Atmosphere->GetWindPsi();
vw = Atmosphere->GetWindNED().Magnitude();
return vw*sin(psiw - Propagate->GetEuler(ePsi));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAuxiliary::bind(void)
{
typedef double (FGAuxiliary::*PMF)(int) const;
typedef double (FGAuxiliary::*PF)(void) const;
PropertyManager->Tie("velocities/vc-fps", this, &FGAuxiliary::GetVcalibratedFPS);
PropertyManager->Tie("velocities/vc-kts", this, &FGAuxiliary::GetVcalibratedKTS);
PropertyManager->Tie("velocities/ve-fps", this, &FGAuxiliary::GetVequivalentFPS);
PropertyManager->Tie("velocities/ve-kts", this, &FGAuxiliary::GetVequivalentKTS);
PropertyManager->Tie("velocities/machU", this, &FGAuxiliary::GetMachU);
PropertyManager->Tie("velocities/tat-r", this, &FGAuxiliary::GetTotalTemperature);
PropertyManager->Tie("velocities/tat-c", this, &FGAuxiliary::GetTAT_C);
PropertyManager->Tie("velocities/pt-lbs_sqft", this, &FGAuxiliary::GetTotalPressure);
PropertyManager->Tie("velocities/p-aero-rad_sec", this, eX, (PMF)&FGAuxiliary::GetAeroPQR);
PropertyManager->Tie("velocities/q-aero-rad_sec", this, eY, (PMF)&FGAuxiliary::GetAeroPQR);
PropertyManager->Tie("velocities/r-aero-rad_sec", this, eZ, (PMF)&FGAuxiliary::GetAeroPQR);
PropertyManager->Tie("velocities/phidot-rad_sec", this, ePhi, (PMF)&FGAuxiliary::GetEulerRates);
PropertyManager->Tie("velocities/thetadot-rad_sec", this, eTht, (PMF)&FGAuxiliary::GetEulerRates);
PropertyManager->Tie("velocities/psidot-rad_sec", this, ePsi, (PMF)&FGAuxiliary::GetEulerRates);
PropertyManager->Tie("velocities/u-aero-fps", this, eU, (PMF)&FGAuxiliary::GetAeroUVW);
PropertyManager->Tie("velocities/v-aero-fps", this, eV, (PMF)&FGAuxiliary::GetAeroUVW);
PropertyManager->Tie("velocities/w-aero-fps", this, eW, (PMF)&FGAuxiliary::GetAeroUVW);
PropertyManager->Tie("velocities/vt-fps", this, &FGAuxiliary::GetVt, &FGAuxiliary::SetVt, true);
PropertyManager->Tie("velocities/mach", this, &FGAuxiliary::GetMach, &FGAuxiliary::SetMach, true);
PropertyManager->Tie("velocities/vg-fps", this, &FGAuxiliary::GetVground);
PropertyManager->Tie("accelerations/a-pilot-x-ft_sec2", this, eX, (PMF)&FGAuxiliary::GetPilotAccel);
PropertyManager->Tie("accelerations/a-pilot-y-ft_sec2", this, eY, (PMF)&FGAuxiliary::GetPilotAccel);
PropertyManager->Tie("accelerations/a-pilot-z-ft_sec2", this, eZ, (PMF)&FGAuxiliary::GetPilotAccel);
PropertyManager->Tie("accelerations/n-pilot-x-norm", this, eX, (PMF)&FGAuxiliary::GetNpilot);
PropertyManager->Tie("accelerations/n-pilot-y-norm", this, eY, (PMF)&FGAuxiliary::GetNpilot);
PropertyManager->Tie("accelerations/n-pilot-z-norm", this, eZ, (PMF)&FGAuxiliary::GetNpilot);
PropertyManager->Tie("position/epa-rad", this, &FGAuxiliary::GetEarthPositionAngle);
/* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true);
PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */
PropertyManager->Tie("aero/alpha-rad", this, (PF)&FGAuxiliary::Getalpha, &FGAuxiliary::Setalpha, true);
PropertyManager->Tie("aero/beta-rad", this, (PF)&FGAuxiliary::Getbeta, &FGAuxiliary::Setbeta, true);
PropertyManager->Tie("aero/mag-beta-rad", this, (PF)&FGAuxiliary::GetMagBeta);
PropertyManager->Tie("aero/alpha-deg", this, inDegrees, (PMF)&FGAuxiliary::Getalpha);
PropertyManager->Tie("aero/beta-deg", this, inDegrees, (PMF)&FGAuxiliary::Getbeta);
PropertyManager->Tie("aero/mag-beta-deg", this, inDegrees, (PMF)&FGAuxiliary::GetMagBeta);
PropertyManager->Tie("aero/qbar-psf", this, &FGAuxiliary::Getqbar, &FGAuxiliary::Setqbar, true);
PropertyManager->Tie("aero/qbarUW-psf", this, &FGAuxiliary::GetqbarUW, &FGAuxiliary::SetqbarUW, true);
PropertyManager->Tie("aero/qbarUV-psf", this, &FGAuxiliary::GetqbarUV, &FGAuxiliary::SetqbarUV, true);
PropertyManager->Tie("aero/alphadot-rad_sec", this, (PF)&FGAuxiliary::Getadot, &FGAuxiliary::Setadot, true);
PropertyManager->Tie("aero/betadot-rad_sec", this, (PF)&FGAuxiliary::Getbdot, &FGAuxiliary::Setbdot, true);
PropertyManager->Tie("aero/alphadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getadot);
PropertyManager->Tie("aero/betadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getbdot);
PropertyManager->Tie("aero/h_b-cg-ft", this, &FGAuxiliary::GetHOverBCG);
PropertyManager->Tie("aero/h_b-mac-ft", this, &FGAuxiliary::GetHOverBMAC);
PropertyManager->Tie("flight-path/gamma-rad", this, &FGAuxiliary::GetGamma, &FGAuxiliary::SetGamma);
PropertyManager->Tie("flight-path/psi-gt-rad", this, &FGAuxiliary::GetGroundTrack);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAuxiliary::unbind(void)
{
PropertyManager->Untie("velocities/vc-fps");
PropertyManager->Untie("velocities/vc-kts");
PropertyManager->Untie("velocities/ve-fps");
PropertyManager->Untie("velocities/ve-kts");
PropertyManager->Untie("velocities/machU");
PropertyManager->Untie("velocities/tat-r");
PropertyManager->Untie("velocities/tat-c");
PropertyManager->Untie("velocities/p-aero-rad_sec");
PropertyManager->Untie("velocities/q-aero-rad_sec");
PropertyManager->Untie("velocities/r-aero-rad_sec");
PropertyManager->Untie("velocities/pt-lbs_sqft");
PropertyManager->Untie("velocities/phidot-rad_sec");
PropertyManager->Untie("velocities/thetadot-rad_sec");
PropertyManager->Untie("velocities/psidot-rad_sec");
PropertyManager->Untie("velocities/u-aero-fps");
PropertyManager->Untie("velocities/v-aero-fps");
PropertyManager->Untie("velocities/w-aero-fps");
PropertyManager->Untie("velocities/vt-fps");
PropertyManager->Untie("velocities/mach");
PropertyManager->Untie("velocities/vg-fps");
PropertyManager->Untie("accelerations/a-pilot-x-ft_sec2");
PropertyManager->Untie("accelerations/a-pilot-y-ft_sec2");
PropertyManager->Untie("accelerations/a-pilot-z-ft_sec2");
PropertyManager->Untie("accelerations/n-pilot-x-norm");
PropertyManager->Untie("accelerations/n-pilot-y-norm");
PropertyManager->Untie("accelerations/n-pilot-z-norm");
PropertyManager->Untie("position/epa-rad");
/* PropertyManager->Untie("atmosphere/headwind-fps");
PropertyManager->Untie("atmosphere/crosswind-fps"); */
PropertyManager->Untie("aero/qbar-psf");
PropertyManager->Untie("aero/qbarUW-psf");
PropertyManager->Untie("aero/qbarUV-psf");
PropertyManager->Untie("aero/alpha-rad");
PropertyManager->Untie("aero/beta-rad");
PropertyManager->Untie("aero/alpha-deg");
PropertyManager->Untie("aero/beta-deg");
PropertyManager->Untie("aero/alphadot-rad_sec");
PropertyManager->Untie("aero/betadot-rad_sec");
PropertyManager->Untie("aero/mag-beta-rad");
PropertyManager->Untie("aero/alphadot-deg_sec");
PropertyManager->Untie("aero/betadot-deg_sec");
PropertyManager->Untie("aero/mag-beta-deg");
PropertyManager->Untie("aero/h_b-cg-ft");
PropertyManager->Untie("aero/h_b-mac-ft");
PropertyManager->Untie("flight-path/gamma-rad");
PropertyManager->Untie("flight-path/psi-gt-rad");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGAuxiliary::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGAuxiliary" << endl;
if (from == 1) cout << "Destroyed: FGAuxiliary" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
if (Mach > 100 || Mach < 0.00)
cout << "FGPropagate::Mach is out of bounds: " << Mach << endl;
if (qbar > 1e6 || qbar < 0.00)
cout << "FGPropagate::qbar is out of bounds: " << qbar << endl;
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,245 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGAuxiliary.h
Author: Jon Berndt
Date started: 01/26/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.
HISTORY
--------------------------------------------------------------------------------
11/22/98 JSB Created
1/1/00 TP Added calcs and getters for VTAS, VCAS, VEAS, Vground, in knots
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGAUXILIARY_H
#define FGAUXILIARY_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
#include <math/FGColumnVector3.h>
#include <math/FGLocation.h>
#include "FGPropagate.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AUXILIARY "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Encapsulates various uncategorized scheduled functions.
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.
@author Tony Peden, Jon Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGAuxiliary : public FGModel {
public:
/** Constructor
@param Executive a pointer to the parent executive object */
FGAuxiliary(FGFDMExec* Executive);
/// Destructor
~FGAuxiliary();
/** Runs the Auxiliary routines; called by the Executive
@return false if no error */
bool Run(void);
// GET functions
// Atmospheric parameters GET functions
double GetVcalibratedFPS(void) const { return vcas; }
double GetVcalibratedKTS(void) const { return vcas*fpstokts; }
double GetVequivalentFPS(void) const { return veas; }
double GetVequivalentKTS(void) const { return veas*fpstokts; }
// total pressure above is freestream total pressure for subsonic only
// for supersonic it is the 1D total pressure behind a normal shock
double GetTotalPressure(void) const { return pt; }
double GetTotalTemperature(void) const { return tat; }
double GetTAT_C(void) const { return tatc; }
double GetPilotAccel(int idx) const { return vPilotAccel(idx); }
double GetNpilot(int idx) const { return vPilotAccelN(idx); }
double GetAeroPQR(int axis) const { return vAeroPQR(axis); }
double GetEulerRates(int axis) const { return vEulerRates(axis); }
const FGColumnVector3& GetPilotAccel (void) const { return vPilotAccel; }
const FGColumnVector3& GetNpilot (void) const { return vPilotAccelN; }
const FGColumnVector3& GetAeroPQR (void) const { return vAeroPQR; }
const FGColumnVector3& GetEulerRates (void) const { return vEulerRates; }
const FGColumnVector3& GetAeroUVW (void) const { return vAeroUVW; }
const FGLocation& GetLocationVRP(void) const { return vLocationVRP; }
double GethVRP(void) const { return vLocationVRP.GetRadius() - Propagate->GetSeaLevelRadius(); }
double GetAeroUVW (int idx) const { return vAeroUVW(idx); }
double Getalpha (void) const { return alpha; }
double Getbeta (void) const { return beta; }
double Getadot (void) const { return adot; }
double Getbdot (void) const { return bdot; }
double GetMagBeta (void) const { return fabs(beta); }
double Getalpha (int unit) const { if (unit == inDegrees) return alpha*radtodeg;
else cerr << "Bad units" << endl; return 0.0;}
double Getbeta (int unit) const { if (unit == inDegrees) return beta*radtodeg;
else cerr << "Bad units" << endl; return 0.0;}
double Getadot (int unit) const { if (unit == inDegrees) return adot*radtodeg;
else cerr << "Bad units" << endl; return 0.0;}
double Getbdot (int unit) const { if (unit == inDegrees) return bdot*radtodeg;
else cerr << "Bad units" << endl; return 0.0;}
double GetMagBeta (int unit) const { if (unit == inDegrees) return fabs(beta)*radtodeg;
else cerr << "Bad units" << endl; return 0.0;}
double Getqbar (void) const { return qbar; }
double GetqbarUW (void) const { return qbarUW; }
double GetqbarUV (void) const { return qbarUV; }
double GetVt (void) const { return Vt; }
double GetVground (void) const { return Vground; }
double GetMach (void) const { return Mach; }
double GetMachU (void) const { return MachU; }
double GetHOverBCG(void) const { return hoverbcg; }
double GetHOverBMAC(void) const { return hoverbmac; }
double GetGamma(void) const { return gamma; }
double GetGroundTrack(void) const { return psigt; }
double GetEarthPositionAngle(void) const { return earthPosAngle; }
double GetHeadWind(void);
double GetCrossWind(void);
// SET functions
void SetAeroUVW(FGColumnVector3 tt) { vAeroUVW = tt; }
void Setalpha (double tt) { alpha = tt; }
void Setbeta (double tt) { beta = tt; }
void Setqbar (double tt) { qbar = tt; }
void SetqbarUW (double tt) { qbarUW = tt; }
void SetqbarUV (double tt) { qbarUV = tt; }
void SetVt (double tt) { Vt = tt; }
void SetMach (double tt) { Mach=tt; }
void Setadot (double tt) { adot = tt; }
void Setbdot (double tt) { bdot = tt; }
void SetAB (double t1, double t2) { alpha=t1; beta=t2; }
void SetGamma (double tt) { gamma = tt; }
// Time routines, SET and GET functions
void SetDayOfYear (int doy) { day_of_year = doy; }
void SetSecondsInDay (double sid) { seconds_in_day = sid; }
int GetDayOfYear (void) const { return day_of_year; }
double GetSecondsInDay (void) const { return seconds_in_day; }
void bind(void);
void unbind(void);
private:
double vcas, veas;
double rhosl, rho, p, psl, pt, tat, sat, tatc; // Don't add a getter for pt!
FGColumnVector3 vPilotAccel;
FGColumnVector3 vPilotAccelN;
FGColumnVector3 vToEyePt;
FGColumnVector3 vAeroPQR;
FGColumnVector3 vAeroUVW;
FGColumnVector3 vEuler;
FGColumnVector3 vEulerRates;
FGColumnVector3 vMachUVW;
FGLocation vLocationVRP;
double Vt, Vground, Mach, MachU;
double qbar, qbarUW, qbarUV;
double alpha, beta;
double adot,bdot;
double psigt, gamma;
double seconds_in_day; // seconds since current GMT day began
int day_of_year; // GMT day, 1 .. 366
double earthPosAngle;
double hoverbcg, hoverbmac;
void Debug(int from);
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,844 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 "FGFCS.h"
#include <FGFDMExec.h>
#include <input_output/FGPropertyManager.h>
#include <fstream>
#include <models/flight_control/FGFilter.h>
#include <models/flight_control/FGDeadBand.h>
#include <models/flight_control/FGGain.h>
#include <models/flight_control/FGGradient.h>
#include <models/flight_control/FGSwitch.h>
#include <models/flight_control/FGSummer.h>
#include <models/flight_control/FGKinemat.h>
#include <models/flight_control/FGFCSFunction.h>
#include <models/flight_control/FGSensor.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FCS;
#if defined(WIN32) && !defined(__CYGWIN__)
#define snprintf _snprintf
#endif
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)
{
int i;
Name = "FGFCS";
DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0;
PTrimCmd = YTrimCmd = RTrimCmd = 0.0;
GearCmd = GearPos = 1; // default to gear down
LeftBrake = RightBrake = CenterBrake = 0.0;
bind();
for (i=0;i<=NForms;i++) {
DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
DfPos[i] = DsbPos[i] = DspPos[i] = 0.0;
}
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGFCS::~FGFCS()
{
if (PropertyManager->HasNode("fcs")) unbind( PropertyManager->GetNode("fcs") );
if (PropertyManager->HasNode("ap")) unbind( PropertyManager->GetNode("ap") );
PropertyManager->Untie( "gear/gear-cmd-norm" );
PropertyManager->Untie( "gear/gear-pos-norm" );
ThrottleCmd.clear();
ThrottlePos.clear();
MixtureCmd.clear();
MixturePos.clear();
PropAdvanceCmd.clear();
PropAdvance.clear();
SteerPosDeg.clear();
PropFeatherCmd.clear();
PropFeather.clear();
unsigned int i;
for (i=0;i<APComponents.size();i++) delete APComponents[i];
for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i];
for (i=0;i<sensors.size();i++) delete sensors[i];
APComponents.clear();
FCSComponents.clear();
sensors.clear();
interface_properties.clear();
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Notes: In this logic the default engine commands are set. This is simply a
// sort of safe-mode method in case the user has not defined control laws for
// throttle, mixture, and prop-advance. The throttle, mixture, and prop advance
// positions are set equal to the respective commands. Any control logic that is
// actually present in the flight_control or autopilot section will override
// these simple assignments.
bool FGFCS::Run(void)
{
unsigned int i;
if (FGModel::Run()) return true; // fast exit if nothing to do
if (FDMExec->Holding()) return false;
for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
for (i=0; i<PropFeather.size(); i++) PropFeather[i] = PropFeatherCmd[i];
// Set the default steering angle
for (i=0; i<SteerPosDeg.size(); i++) {
FGLGear* gear = GroundReactions->GetGearUnit(i);
SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() );
}
// Cycle through the sensor, autopilot, and flight control components
for (i=0; i<sensors.size(); i++) sensors[i]->Run();
for (i=0; i<APComponents.size(); i++) APComponents[i]->Run();
for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run();
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetDaLPos( int form , double pos )
{
switch(form) {
case ofRad:
DaLPos[ofRad] = pos;
DaLPos[ofDeg] = pos*radtodeg;
break;
case ofDeg:
DaLPos[ofRad] = pos*degtorad;
DaLPos[ofDeg] = pos;
break;
case ofNorm:
DaLPos[ofNorm] = pos;
}
DaLPos[ofMag] = fabs(DaLPos[ofRad]);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetDaRPos( int form , double pos )
{
switch(form) {
case ofRad:
DaRPos[ofRad] = pos;
DaRPos[ofDeg] = pos*radtodeg;
break;
case ofDeg:
DaRPos[ofRad] = pos*degtorad;
DaRPos[ofDeg] = pos;
break;
case ofNorm:
DaRPos[ofNorm] = pos;
}
DaRPos[ofMag] = fabs(DaRPos[ofRad]);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetDePos( int form , double pos )
{
switch(form) {
case ofRad:
DePos[ofRad] = pos;
DePos[ofDeg] = pos*radtodeg;
break;
case ofDeg:
DePos[ofRad] = pos*degtorad;
DePos[ofDeg] = pos;
break;
case ofNorm:
DePos[ofNorm] = pos;
}
DePos[ofMag] = fabs(DePos[ofRad]);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetDrPos( int form , double pos )
{
switch(form) {
case ofRad:
DrPos[ofRad] = pos;
DrPos[ofDeg] = pos*radtodeg;
break;
case ofDeg:
DrPos[ofRad] = pos*degtorad;
DrPos[ofDeg] = pos;
break;
case ofNorm:
DrPos[ofNorm] = pos;
}
DrPos[ofMag] = fabs(DrPos[ofRad]);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetDfPos( int form , double pos )
{
switch(form) {
case ofRad:
DfPos[ofRad] = pos;
DfPos[ofDeg] = pos*radtodeg;
break;
case ofDeg:
DfPos[ofRad] = pos*degtorad;
DfPos[ofDeg] = pos;
break;
case ofNorm:
DfPos[ofNorm] = pos;
}
DfPos[ofMag] = fabs(DfPos[ofRad]);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetDsbPos( int form , double pos )
{
switch(form) {
case ofRad:
DsbPos[ofRad] = pos;
DsbPos[ofDeg] = pos*radtodeg;
break;
case ofDeg:
DsbPos[ofRad] = pos*degtorad;
DsbPos[ofDeg] = pos;
break;
case ofNorm:
DsbPos[ofNorm] = pos;
}
DsbPos[ofMag] = fabs(DsbPos[ofRad]);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetDspPos( int form , double pos )
{
switch(form) {
case ofRad:
DspPos[ofRad] = pos;
DspPos[ofDeg] = pos*radtodeg;
break;
case ofDeg:
DspPos[ofRad] = pos*degtorad;
DspPos[ofDeg] = pos;
break;
case ofNorm:
DspPos[ofNorm] = pos;
}
DspPos[ofMag] = fabs(DspPos[ofRad]);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetThrottleCmd(int engineNum, double setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting;
} else {
ThrottleCmd[engineNum] = setting;
}
} else {
cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
<< " engines exist, but attempted throttle command is for engine "
<< engineNum << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetThrottlePos(int engineNum, double setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<ThrottlePos.size();ctr++) ThrottlePos[ctr] = setting;
} else {
ThrottlePos[engineNum] = setting;
}
} else {
cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
<< " engines exist, but attempted throttle position setting is for engine "
<< engineNum << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGFCS::GetThrottleCmd(int engineNum) const
{
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
cerr << "Cannot get throttle value for ALL engines" << endl;
} else {
return ThrottleCmd[engineNum];
}
} else {
cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
<< " engines exist, but throttle setting for engine " << engineNum
<< " is selected" << endl;
}
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGFCS::GetThrottlePos(int engineNum) const
{
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
cerr << "Cannot get throttle value for ALL engines" << endl;
} else {
return ThrottlePos[engineNum];
}
} else {
cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
<< " engines exist, but attempted throttle position setting is for engine "
<< engineNum << endl;
}
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetMixtureCmd(int engineNum, double setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<MixtureCmd.size();ctr++) MixtureCmd[ctr] = setting;
} else {
MixtureCmd[engineNum] = setting;
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetMixturePos(int engineNum, double setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<=MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr];
} else {
MixturePos[engineNum] = setting;
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetPropAdvanceCmd(int engineNum, double setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvanceCmd[ctr] = setting;
} else {
PropAdvanceCmd[engineNum] = setting;
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetPropAdvance(int engineNum, double setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<=PropAdvanceCmd.size();ctr++) PropAdvance[ctr] = PropAdvanceCmd[ctr];
} else {
PropAdvance[engineNum] = setting;
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetFeatherCmd(int engineNum, bool setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeatherCmd[ctr] = setting;
} else {
PropFeatherCmd[engineNum] = setting;
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::SetPropFeather(int engineNum, bool setting)
{
unsigned int ctr;
if (engineNum < (int)ThrottlePos.size()) {
if (engineNum < 0) {
for (ctr=0;ctr<=PropFeatherCmd.size();ctr++) PropFeather[ctr] = PropFeatherCmd[ctr];
} else {
PropFeather[engineNum] = setting;
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFCS::Load(Element* el)
{
string name, file, fname, comp_name, interface_property_string;
unsigned i;
vector <FGFCSComponent*> *Components;
Element *FCS_cfg, *document, *component_element, *property_element, *sensor_element;
Element *channel_element;
ifstream* controls_file = new ifstream();
FGXMLParse controls_file_parser;
Components=0;
// Determine if the FCS/Autopilot is defined inline in the aircraft configuration
// file or in a separate file. Set up the Element pointer as appropriate.
string separator = "/";
#ifdef macintosh
separator = ";";
#endif
name = el->GetAttributeValue("name");
if (name.empty()) {
fname = el->GetAttributeValue("file");
file = FDMExec->GetAircraftPath() + separator + FDMExec->GetModelName() + separator + fname + ".xml";
if (fname.empty()) {
cerr << "FCS/Autopilot does not appear to be defined inline nor in a file" << endl;
return false;
} else {
controls_file->open(file.c_str());
readXML(*controls_file, controls_file_parser);
delete controls_file;
document = controls_file_parser.GetDocument();
}
} else {
document = el;
}
if (document->GetName() == "autopilot") {
Components = &APComponents;
Name = "Autopilot: " + document->GetAttributeValue("name");
} else if (document->GetName() == "flight_control") {
Components = &FCSComponents;
Name = "FCS: " + document->GetAttributeValue("name");
}
Debug(2);
// ToDo: How do these get untied?
// ToDo: Consider having INPUT and OUTPUT interface properties. Would then
// have to duplicate this block of code after channel read code.
// Input properties could be write only (nah), and output could be read
// only.
if (document->GetName() == "flight_control") bindModel();
property_element = document->FindElement("property");
while (property_element) {
interface_properties.push_back(new double(0));
interface_property_string = property_element->GetDataLine();
PropertyManager->Tie(interface_property_string, interface_properties.back());
property_element = document->FindNextElement("property");
}
sensor_element = document->FindElement("sensor");
while (sensor_element) {
try {
sensors.push_back(new FGSensor(this, sensor_element));
} catch (string s) {
cerr << highint << fgred << endl << " " << s << endl;
return false;
}
sensor_element = document->FindNextElement("sensor");
}
channel_element = document->FindElement("channel");
while (channel_element) {
component_element = channel_element->FindElement("component");
if (component_element) {
cout << "This form of the component specification is being deprecated" << endl;
} else {
component_element = channel_element->GetElement();
}
while (component_element) {
comp_name = component_element->GetAttributeValue("type");
try {
if ((comp_name == "LAG_FILTER") ||
(comp_name == "LEAD_LAG_FILTER") ||
(comp_name == "SECOND_ORDER_FILTER") ||
(comp_name == "WASHOUT_FILTER") ||
(comp_name == "INTEGRATOR") ||
(component_element->GetName() == string("lag_filter")) ||
(component_element->GetName() == string("lead_lag_filter")) ||
(component_element->GetName() == string("washout_filter")) ||
(component_element->GetName() == string("second_order_filter")) ||
(component_element->GetName() == string("integrator")) )
{
Components->push_back(new FGFilter(this, component_element));
} else if ((comp_name == "PURE_GAIN") ||
(comp_name == "SCHEDULED_GAIN") ||
(comp_name == "AEROSURFACE_SCALE") ||
(component_element->GetName() == string("pure_gain")) ||
(component_element->GetName() == string("scheduled_gain")) ||
(component_element->GetName() == string("aerosurface_scale")))
{
Components->push_back(new FGGain(this, component_element));
} else if ((comp_name == "SUMMER") || (component_element->GetName() == string("summer"))) {
Components->push_back(new FGSummer(this, component_element));
} else if ((comp_name == "DEADBAND") || (component_element->GetName() == string("deadband"))) {
Components->push_back(new FGDeadBand(this, component_element));
} else if (comp_name == "GRADIENT") {
Components->push_back(new FGGradient(this, component_element));
} else if ((comp_name == "SWITCH") || (component_element->GetName() == string("switch"))) {
Components->push_back(new FGSwitch(this, component_element));
} else if ((comp_name == "KINEMAT") || (component_element->GetName() == string("kinematic"))) {
Components->push_back(new FGKinemat(this, component_element));
} else if ((comp_name == "FUNCTION") || (component_element->GetName() == string("fcs_function"))) {
Components->push_back(new FGFCSFunction(this, component_element));
} else {
cerr << "Unknown FCS component: " << comp_name << endl;
}
} catch(string s) {
cerr << highint << fgred << endl << " " << s << endl;
cerr << reset << endl;
return false;
}
if (comp_name.empty()) { // comp_name will be empty if using new format
component_element = channel_element->GetNextElement();
} else {
component_element = channel_element->FindNextElement("component");
}
}
channel_element = document->FindNextElement("channel");
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double 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(string delimeter)
{
unsigned int comp;
string CompStrings = "";
bool firstime = true;
for (comp = 0; comp < FCSComponents.size(); comp++) {
if (firstime) firstime = false;
else CompStrings += delimeter;
CompStrings += FCSComponents[comp]->GetName();
}
for (comp = 0; comp < APComponents.size(); comp++)
{
CompStrings += delimeter;
CompStrings += APComponents[comp]->GetName();
}
return CompStrings;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGFCS::GetComponentValues(string delimeter)
{
unsigned int comp;
string CompValues = "";
char buffer[12];
bool firstime = true;
for (comp = 0; comp < FCSComponents.size(); comp++) {
if (firstime) firstime = false;
else CompValues += delimeter;
sprintf(buffer, "%9.6f", FCSComponents[comp]->GetOutput());
CompValues += string(buffer);
}
for (comp = 0; comp < APComponents.size(); comp++) {
sprintf(buffer, "%s%9.6f", delimeter.c_str(), APComponents[comp]->GetOutput());
CompValues += string(buffer);
}
return CompValues;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::AddThrottle(void)
{
ThrottleCmd.push_back(0.0);
ThrottlePos.push_back(0.0);
MixtureCmd.push_back(0.0); // assume throttle and mixture are coupled
MixturePos.push_back(0.0);
PropAdvanceCmd.push_back(0.0); // assume throttle and prop pitch are coupled
PropAdvance.push_back(0.0);
PropFeatherCmd.push_back(false);
PropFeather.push_back(false);
unsigned int num = ThrottleCmd.size()-1;
bindThrottle(num);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::AddGear(void)
{
SteerPosDeg.push_back(0.0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::bind(void)
{
PropertyManager->Tie("fcs/aileron-cmd-norm", this, &FGFCS::GetDaCmd, &FGFCS::SetDaCmd);
PropertyManager->Tie("fcs/elevator-cmd-norm", this, &FGFCS::GetDeCmd, &FGFCS::SetDeCmd);
PropertyManager->Tie("fcs/rudder-cmd-norm", this, &FGFCS::GetDrCmd, &FGFCS::SetDrCmd);
PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGFCS::GetDsCmd, &FGFCS::SetDsCmd);
PropertyManager->Tie("fcs/flap-cmd-norm", this, &FGFCS::GetDfCmd, &FGFCS::SetDfCmd);
PropertyManager->Tie("fcs/speedbrake-cmd-norm", this, &FGFCS::GetDsbCmd, &FGFCS::SetDsbCmd);
PropertyManager->Tie("fcs/spoiler-cmd-norm", this, &FGFCS::GetDspCmd, &FGFCS::SetDspCmd);
PropertyManager->Tie("fcs/pitch-trim-cmd-norm", this, &FGFCS::GetPitchTrimCmd, &FGFCS::SetPitchTrimCmd);
PropertyManager->Tie("fcs/roll-trim-cmd-norm", this, &FGFCS::GetRollTrimCmd, &FGFCS::SetRollTrimCmd);
PropertyManager->Tie("fcs/yaw-trim-cmd-norm", this, &FGFCS::GetYawTrimCmd, &FGFCS::SetYawTrimCmd);
PropertyManager->Tie("gear/gear-cmd-norm", this, &FGFCS::GetGearCmd, &FGFCS::SetGearCmd);
PropertyManager->Tie("fcs/left-aileron-pos-rad", this, ofRad, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
PropertyManager->Tie("fcs/left-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
PropertyManager->Tie("fcs/left-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
PropertyManager->Tie("fcs/mag-left-aileron-pos-rad", this, ofMag, &FGFCS::GetDaLPos);
PropertyManager->Tie("fcs/right-aileron-pos-rad", this, ofRad, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
PropertyManager->Tie("fcs/right-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
PropertyManager->Tie("fcs/right-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
PropertyManager->Tie("fcs/mag-right-aileron-pos-rad", this, ofMag, &FGFCS::GetDaRPos);
PropertyManager->Tie("fcs/elevator-pos-rad", this, ofRad, &FGFCS::GetDePos, &FGFCS::SetDePos);
PropertyManager->Tie("fcs/elevator-pos-deg", this, ofDeg, &FGFCS::GetDePos, &FGFCS::SetDePos);
PropertyManager->Tie("fcs/elevator-pos-norm", this, ofNorm, &FGFCS::GetDePos, &FGFCS::SetDePos);
PropertyManager->Tie("fcs/mag-elevator-pos-rad", this, ofMag, &FGFCS::GetDePos);
PropertyManager->Tie("fcs/rudder-pos-rad", this,ofRad, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
PropertyManager->Tie("fcs/rudder-pos-deg", this,ofDeg, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
PropertyManager->Tie("fcs/rudder-pos-norm", this,ofNorm, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
PropertyManager->Tie("fcs/mag-rudder-pos-rad", this,ofMag, &FGFCS::GetDrPos);
PropertyManager->Tie("fcs/flap-pos-rad", this,ofRad, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
PropertyManager->Tie("fcs/flap-pos-deg", this,ofDeg, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
PropertyManager->Tie("fcs/flap-pos-norm", this,ofNorm, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
PropertyManager->Tie("fcs/speedbrake-pos-rad", this,ofRad, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
PropertyManager->Tie("fcs/speedbrake-pos-deg", this,ofDeg, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
PropertyManager->Tie("fcs/speedbrake-pos-norm", this,ofNorm, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
PropertyManager->Tie("fcs/mag-speedbrake-pos-rad", this,ofMag, &FGFCS::GetDsbPos);
PropertyManager->Tie("fcs/spoiler-pos-rad", this, ofRad, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
PropertyManager->Tie("fcs/spoiler-pos-deg", this, ofDeg, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
PropertyManager->Tie("fcs/spoiler-pos-norm", this, ofNorm, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
PropertyManager->Tie("fcs/mag-spoiler-pos-rad", this, ofMag, &FGFCS::GetDspPos);
PropertyManager->Tie("gear/gear-pos-norm", this, &FGFCS::GetGearPos, &FGFCS::SetGearPos);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Technically, this function should probably bind propulsion type specific controls
// rather than mixture and prop-advance.
//
void FGFCS::bindThrottle(unsigned int num)
{
char tmp[80];
snprintf(tmp, 80, "fcs/throttle-cmd-norm[%u]",num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetThrottleCmd,
&FGFCS::SetThrottleCmd);
snprintf(tmp, 80, "fcs/throttle-pos-norm[%u]",num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetThrottlePos,
&FGFCS::SetThrottlePos);
snprintf(tmp, 80, "fcs/mixture-cmd-norm[%u]",num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetMixtureCmd,
&FGFCS::SetMixtureCmd);
snprintf(tmp, 80, "fcs/mixture-pos-norm[%u]",num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetMixturePos,
&FGFCS::SetMixturePos);
snprintf(tmp, 80, "fcs/advance-cmd-norm[%u]",num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropAdvanceCmd,
&FGFCS::SetPropAdvanceCmd);
snprintf(tmp, 80, "fcs/advance-pos-norm[%u]", num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropAdvance,
&FGFCS::SetPropAdvance);
snprintf(tmp, 80, "fcs/feather-cmd-norm[%u]", num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetFeatherCmd,
&FGFCS::SetFeatherCmd);
snprintf(tmp, 80, "fcs/feather-pos-norm[%u]", num);
PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropFeather,
&FGFCS::SetPropFeather);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::bindModel(void)
{
unsigned int i;
char tmp[80];
for (i=0; i<SteerPosDeg.size(); i++) {
if (GroundReactions->GetGearUnit(i)->GetSteerable()) {
snprintf(tmp,80,"fcs/steer-pos-deg[%u]",i);
PropertyManager->Tie( tmp, this, i, &FGFCS::GetSteerPosDeg, &FGFCS::SetSteerPosDeg);
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::unbind(FGPropertyManager *node)
{
int N = node->nChildren();
for (int i=0; i<N; i++) {
if (node->getChild(i)->nChildren() ) {
unbind( (FGPropertyManager*)node->getChild(i) );
} else if ( node->getChild(i)->isTied() ) {
node->getChild(i)->untie();
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGFCS::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 2) { // Loader
cout << endl << " Flight Control (" << Name << ")" << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGFCS" << endl;
if (from == 1) cout << "Destroyed: FGFCS" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
}

View file

@ -0,0 +1,506 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGGFCS.h
Author: Jon S. Berndt
Date started: 12/12/98
------------- 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.
HISTORY
--------------------------------------------------------------------------------
12/12/98 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGFCS_H
#define FGFCS_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
# include <vector>
# else
# include <vector.h>
# endif
#else
# include <vector>
#endif
#include <string>
#include <models/flight_control/FGFCSComponent.h>
#include <models/FGModel.h>
#include <models/FGLGear.h>
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCS "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
typedef enum { ofRad=0, ofDeg, ofNorm, ofMag , NForms} OutputForm;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Encapsulates the Flight Control System (FCS) functionality.
This class owns and contains the list of FGFCSComponents
that define the control system for this aircraft. The config file for the
aircraft contains a description of the control path that starts at an input
or command and ends at an effector, e.g. an aerosurface. The FCS components
which comprise the control laws for an axis are defined sequentially in
the configuration file. For instance, for the X-15:
<pre>
\<flight_control name="X-15 SAS">
\<channel>
\<component name="Pitch Trim Sum" type="SUMMER">
<input> fcs/elevator-cmd-norm </input>
<input> fcs/pitch-trim-cmd-norm </input>
<clipto>
<min>-1</min>
<max>1</max>
</clipto>
\</component>
\<component name="Pitch Command Scale" TYPE="AEROSURFACE_SCALE">
<input> fcs/pitch-trim-sum </input>
<limit>
<min> -50 </min>
<max> 50 </max>
</limit>
\</component>
... etc.
</pre>
In the above case we can see the first few components of the pitch channel
defined. The input to the first component, as can be seen in the "Pitch trim
sum" component, is really the sum of two parameters: elevator command (from
the stick - a pilot input), and pitch trim. The type of this component is
"Summer".
The next component created is an aerosurface scale component - a type of
gain (see the LoadFCS() method for insight on how the various types of
components map into the actual component classes). This continues until the
final component for an axis when the
\<output> element specifies where the output is supposed to go. See the
individual components for more information on how they are mechanized.
Another option for the flight controls portion of the config file is that in
addition to using the "NAME" attribute in,
<pre>
\<flight_control name="X-15 SAS">
</pre>
one can also supply a filename:
<pre>
\<flight_control name="X-15 SAS" file="X15.xml">
\</flight_control>
</pre>
In this case, the FCS would be read in from another file.
@author Jon S. Berndt
@version $Id$
@see FGFCSComponent
@see FGXMLElement
@see FGGain
@see FGSummer
@see FGSwitch
@see FGGradient
@see FGFilter
@see FGDeadBand
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFCS : public FGModel {
public:
/** Constructor
@param Executive a pointer to the parent executive object */
FGFCS(FGFDMExec*);
/// Destructor
~FGFCS();
/** Runs the Flight Controls model; called by the Executive
@return false if no error */
bool Run(void);
/// @name Pilot input command retrieval
//@{
/** Gets the aileron command.
@return aileron command in range from -1.0 - 1.0 */
inline double GetDaCmd(void) const { return DaCmd; }
/** Gets the elevator command.
@return elevator command in range from -1.0 - 1.0 */
inline double GetDeCmd(void) const { return DeCmd; }
/** Gets the rudder command.
@return rudder command in range from -1.0 - 1.0 */
inline double GetDrCmd(void) const { return DrCmd; }
/** Gets the steering command.
@return steering command in range from -1.0 - 1.0 */
inline double GetDsCmd(void) const { return DsCmd; }
/** Gets the flaps command.
@return flaps command in range from 0 to 1.0 */
inline double GetDfCmd(void) const { return DfCmd; }
/** Gets the speedbrake command.
@return speedbrake command in range from 0 to 1.0 */
inline double GetDsbCmd(void) const { return DsbCmd; }
/** Gets the spoiler command.
@return spoiler command in range from 0 to 1.0 */
inline double GetDspCmd(void) const { return DspCmd; }
/** Gets the throttle command.
@param engine engine ID number
@return throttle command in range from 0 - 1.0 for the given engine */
double GetThrottleCmd(int engine) const;
/** Gets the mixture command.
@param engine engine ID number
@return mixture command in range from 0 - 1.0 for the given engine */
inline double GetMixtureCmd(int engine) const { return MixtureCmd[engine]; }
/** Gets the prop pitch command.
@param engine engine ID number
@return pitch command in range from 0.0 - 1.0 for the given engine */
inline double GetPropAdvanceCmd(int engine) const { return PropAdvanceCmd[engine]; }
/** Gets the prop feather command.
@param engine engine ID number
@return feather command for the given engine (on / off)*/
inline bool GetFeatherCmd(int engine) const { return PropFeatherCmd[engine]; }
/** Gets the pitch trim command.
@return pitch trim command in range from -1.0 to 1.0 */
inline double GetPitchTrimCmd(void) const { return PTrimCmd; }
/** Gets the rudder trim command.
@return rudder trim command in range from -1.0 - 1.0 */
inline double GetYawTrimCmd(void) const { return YTrimCmd; }
/** Gets the aileron trim command.
@return aileron trim command in range from -1.0 - 1.0 */
inline double GetRollTrimCmd(void) const { return RTrimCmd; }
/** Get the gear extend/retract command. 0 commands gear up, 1 down.
defaults to down.
@return the current value of the gear extend/retract command*/
inline double GetGearCmd(void) const { return GearCmd; }
//@}
/// @name Aerosurface position retrieval
//@{
/** Gets the left aileron position.
@return aileron position in radians */
inline double GetDaLPos( int form = ofRad )
const { return DaLPos[form]; }
/// @name Aerosurface position retrieval
//@{
/** Gets the right aileron position.
@return aileron position in radians */
inline double GetDaRPos( int form = ofRad )
const { return DaRPos[form]; }
/** Gets the elevator position.
@return elevator position in radians */
inline double GetDePos( int form = ofRad )
const { return DePos[form]; }
/** Gets the rudder position.
@return rudder position in radians */
inline double GetDrPos( int form = ofRad )
const { return DrPos[form]; }
/** Gets the speedbrake position.
@return speedbrake position in radians */
inline double GetDsbPos( int form = ofRad )
const { return DsbPos[form]; }
/** Gets the spoiler position.
@return spoiler position in radians */
inline double GetDspPos( int form = ofRad )
const { return DspPos[form]; }
/** Gets the flaps position.
@return flaps position in radians */
inline double GetDfPos( int form = ofRad )
const { return DfPos[form]; }
/** Gets the throttle position.
@param engine engine ID number
@return throttle position for the given engine in range from 0 - 1.0 */
double GetThrottlePos(int engine) const;
/** Gets the mixture position.
@param engine engine ID number
@return mixture position for the given engine in range from 0 - 1.0 */
inline double GetMixturePos(int engine) const { return MixturePos[engine]; }
/** Gets the steering position.
@return steering position in degrees */
double GetSteerPosDeg(int gear) const { return SteerPosDeg[gear]; }
/** Gets the gear position (0 up, 1 down), defaults to down
@return gear position (0 up, 1 down) */
inline double GetGearPos(void) const { return GearPos; }
/** Gets the prop pitch position.
@param engine engine ID number
@return prop pitch position for the given engine in range from 0 - 1.0 */
inline double GetPropAdvance(int engine) const { return PropAdvance[engine]; }
/** Gets the prop feather position.
@param engine engine ID number
@return prop fether for the given engine (on / off)*/
inline bool GetPropFeather(int engine) const { return PropFeather[engine]; }
//@}
/** Retrieves the State object pointer.
This is used by the FGFCS-owned components.
@return pointer to the State object */
inline FGState* GetState(void) { return State; }
/** Retrieves all component names for inclusion in output stream
@param delimeter either a tab or comma string depending on output type
@return a string containing the descriptive names for all components */
string GetComponentStrings(string delimeter);
/** Retrieves all component outputs for inclusion in output stream
@param delimeter either a tab or comma string depending on output type
@return a string containing the numeric values for the current set of
component outputs */
string GetComponentValues(string delimeter);
/// @name Pilot input command setting
//@{
/** Sets the aileron command
@param cmd aileron command */
inline void SetDaCmd( double cmd ) { DaCmd = cmd; }
/** Sets the elevator command
@param cmd elevator command in percent*/
inline void SetDeCmd(double cmd ) { DeCmd = cmd; }
/** Sets the rudder command
@param cmd rudder command in percent*/
inline void SetDrCmd(double cmd) { DrCmd = cmd; }
/** Sets the steering command
@param cmd steering command in percent*/
inline void SetDsCmd(double cmd) { DsCmd = cmd; }
/** Sets the flaps command
@param cmd flaps command in percent*/
inline void SetDfCmd(double cmd) { DfCmd = cmd; }
/** Sets the speedbrake command
@param cmd speedbrake command in percent*/
inline void SetDsbCmd(double cmd) { DsbCmd = cmd; }
/** Sets the spoilers command
@param cmd spoilers command in percent*/
inline void SetDspCmd(double cmd) { DspCmd = cmd; }
/** Sets the pitch trim command
@param cmd pitch trim command in percent*/
inline void SetPitchTrimCmd(double cmd) { PTrimCmd = cmd; }
/** Sets the rudder trim command
@param cmd rudder trim command in percent*/
inline void SetYawTrimCmd(double cmd) { YTrimCmd = cmd; }
/** Sets the aileron trim command
@param cmd aileron trim command in percent*/
inline void SetRollTrimCmd(double cmd) { RTrimCmd = cmd; }
/** Sets the throttle command for the specified engine
@param engine engine ID number
@param cmd throttle command in percent (0 - 100)*/
void SetThrottleCmd(int engine, double cmd);
/** Sets the mixture command for the specified engine
@param engine engine ID number
@param cmd mixture command in percent (0 - 100)*/
void SetMixtureCmd(int engine, double cmd);
/** Set the gear extend/retract command, defaults to down
@param gear command 0 for up, 1 for down */
void SetGearCmd(double gearcmd) { GearCmd = gearcmd; }
/** Sets the propeller pitch command for the specified engine
@param engine engine ID number
@param cmd mixture command in percent (0.0 - 1.0)*/
void SetPropAdvanceCmd(int engine, double cmd);
/** Sets the propeller feather command for the specified engine
@param engine engine ID number
@param cmd feather (bool)*/
void SetFeatherCmd(int engine, bool cmd);
//@}
/// @name Aerosurface position setting
//@{
/** Sets the left aileron position
@param cmd left aileron position in radians*/
inline void SetDaLPos( int form , double pos );
/** Sets the right aileron position
@param cmd right aileron position in radians*/
inline void SetDaRPos( int form , double pos );
/** Sets the elevator position
@param cmd elevator position in radians*/
inline void SetDePos( int form , double pos );
/** Sets the rudder position
@param cmd rudder position in radians*/
inline void SetDrPos( int form , double pos );
/** Sets the flaps position
@param cmd flaps position in radians*/
inline void SetDfPos( int form , double pos );
/** Sets the speedbrake position
@param cmd speedbrake position in radians*/
inline void SetDsbPos( int form , double pos );
/** Sets the spoiler position
@param cmd spoiler position in radians*/
inline void SetDspPos( int form , double pos );
/** Sets the actual throttle setting for the specified engine
@param engine engine ID number
@param cmd throttle setting in percent (0 - 100)*/
void SetThrottlePos(int engine, double cmd);
/** Sets the actual mixture setting for the specified engine
@param engine engine ID number
@param cmd mixture setting in percent (0 - 100)*/
void SetMixturePos(int engine, double cmd);
/** Sets the steering position
@param cmd steering position in degrees*/
void SetSteerPosDeg(int gear, double pos) { SteerPosDeg[gear] = pos; }
/** Set the gear extend/retract position, defaults to down
@param gear position 0 up, 1 down */
void SetGearPos(double gearpos) { GearPos = gearpos; }
/** Sets the actual prop pitch setting for the specified engine
@param engine engine ID number
@param cmd prop pitch setting in percent (0.0 - 1.0)*/
void SetPropAdvance(int engine, double cmd);
/** Sets the actual prop feather setting for the specified engine
@param engine engine ID number
@param cmd prop fether setting (bool)*/
void SetPropFeather(int engine, bool cmd);
//@}
/// @name Landing Gear brakes
//@{
/** Sets the left brake group
@param cmd brake setting in percent (0.0 - 1.0) */
void SetLBrake(double cmd) {LeftBrake = cmd;}
/** Sets the right brake group
@param cmd brake setting in percent (0.0 - 1.0) */
void SetRBrake(double cmd) {RightBrake = cmd;}
/** Sets the center brake group
@param cmd brake setting in percent (0.0 - 1.0) */
void SetCBrake(double cmd) {CenterBrake = cmd;}
/** Gets the brake for a specified group.
@param bg which brakegroup to retrieve the command for
@return the brake setting for the supplied brake group argument */
double GetBrake(FGLGear::BrakeGroup bg);
//@}
/** Loads the Flight Control System.
The FGAircraft instance is actually responsible for reading the config file
and calling the various Load() methods of the other systems, passing in
the XML Element instance pointer. Load() is called from FGAircraft.
@param el pointer to the Element instance
@return true if succesful */
bool Load(Element* el);
void AddThrottle(void);
void AddGear(void);
FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
private:
double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd;
double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms];
double DfPos[NForms], DsbPos[NForms], DspPos[NForms];
double PTrimCmd, YTrimCmd, RTrimCmd;
vector <double> ThrottleCmd;
vector <double> ThrottlePos;
vector <double> MixtureCmd;
vector <double> MixturePos;
vector <double> PropAdvanceCmd;
vector <double> PropAdvance;
vector <bool> PropFeatherCmd;
vector <bool> PropFeather;
vector <double> SteerPosDeg;
double LeftBrake, RightBrake, CenterBrake; // Brake settings
double GearCmd,GearPos;
vector <FGFCSComponent*> FCSComponents;
vector <FGFCSComponent*> APComponents;
vector <double*> interface_properties;
vector <FGFCSComponent*> sensors;
void bind(void);
void bindModel(void);
void bindThrottle(unsigned int);
void unbind(FGPropertyManager *node);
void Debug(int from);
};
}
#endif

View file

@ -0,0 +1,272 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGGroundReactions.cpp
Author: Jon S. Berndt
Date started: 09/13/00
Purpose: Encapsulates the ground reaction forces (gear and collision)
------------- Copyright (C) 2000 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
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
09/13/00 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <sstream>
#include <iomanip>
#include "FGGroundReactions.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_GROUNDREACTIONS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex)
{
Name = "FGGroundReactions";
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGGroundReactions::~FGGroundReactions(void)
{
for (int i=0; i<lGear.size();i++) lGear[i].unbind();
lGear.clear();
unbind();
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGGroundReactions::Run(void)
{
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
vForces.InitMatrix();
vMoments.InitMatrix();
if ( Propagate->GetDistanceAGL() < 300.0 ) { // Only execute gear code below 300 feet
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++;
}
}
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGGroundReactions::GetWOW(void)
{
bool result = false;
for (int i=0; i<lGear.size(); i++) {
if (lGear[i].IsBogey() && lGear[i].GetWOW()) {
result = true;
break;
}
}
return result;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGGroundReactions::Load(Element* el)
{
int num=0;
Debug(2);
Element* contact_element = el->FindElement("contact");
while (contact_element) {
lGear.push_back(FGLGear(contact_element, FDMExec, num++));
FCS->AddGear(); // make the FCS aware of the landing gear
contact_element = el->FindNextElement("contact");
}
for (int i=0; i<lGear.size();i++) lGear[i].bind();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGGroundReactions::GetGroundReactionStrings(string delimeter)
{
std::ostringstream buf;
for (unsigned int i=0;i<lGear.size();i++) {
string name = lGear[i].GetName();
buf << name << "_WOW" << delimeter
<< name << "_stroke" << delimeter
<< name << "_strokeVel" << delimeter
<< name << "_CompressForce" << delimeter
<< name << "_WhlSideForce" << delimeter
<< name << "_WhlVelVecX" << delimeter
<< name << "_WhlVelVecY" << delimeter
<< name << "_WhlRollForce" << delimeter
<< name << "_BodyXForce" << delimeter
<< name << "_BodyYForce" << delimeter
<< name << "_WhlSlipDegrees" << delimeter;
}
buf << "TotalGearForce_X" << delimeter
<< "TotalGearForce_Y" << delimeter
<< "TotalGearForce_Z" << delimeter
<< "TotalGearMoment_L" << delimeter
<< "TotalGearMoment_M" << delimeter
<< "TotalGearMoment_N";
return buf.str();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGGroundReactions::GetGroundReactionValues(string delimeter)
{
std::ostringstream buf;
for (unsigned int i=0;i<lGear.size();i++) {
FGLGear& gear = lGear[i];
buf << (gear.GetWOW() ? "1, " : "0, ")
<< setprecision(5) << gear.GetCompLen() << delimeter
<< setprecision(6) << gear.GetCompVel() << delimeter
<< setprecision(10) << gear.GetCompForce() << delimeter
<< setprecision(6) << gear.GetWheelVel(eX) << delimeter
<< gear.GetWheelVel(eY) << delimeter
<< gear.GetWheelSideForce() << delimeter
<< gear.GetWheelRollForce() << delimeter
<< gear.GetBodyXForce() << delimeter
<< gear.GetBodyYForce() << delimeter
<< gear.GetWheelSlipAngle() << delimeter;
}
buf << vForces(eX) << delimeter
<< vForces(eY) << delimeter
<< vForces(eZ) << delimeter
<< vMoments(eX) << delimeter
<< vMoments(eY) << delimeter
<< vMoments(eZ);
return buf.str();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGGroundReactions::bind(void)
{
typedef double (FGGroundReactions::*PMF)(int) const;
PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits);
PropertyManager->Tie("moments/l-gear-lbsft", this, eL, (PMF)&FGGroundReactions::GetMoments);
PropertyManager->Tie("moments/m-gear-lbsft", this, eM, (PMF)&FGGroundReactions::GetMoments);
PropertyManager->Tie("moments/n-gear-lbsft", this, eN, (PMF)&FGGroundReactions::GetMoments);
PropertyManager->Tie("forces/fbx-gear-lbs", this, eX, (PMF)&FGGroundReactions::GetForces);
PropertyManager->Tie("forces/fby-gear-lbs", this, eY, (PMF)&FGGroundReactions::GetForces);
PropertyManager->Tie("forces/fbz-gear-lbs", this, eZ, (PMF)&FGGroundReactions::GetForces);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGGroundReactions::unbind(void)
{
PropertyManager->Untie("gear/num-units");
PropertyManager->Untie("moments/l-gear-lbsft");
PropertyManager->Untie("moments/m-gear-lbsft");
PropertyManager->Untie("moments/n-gear-lbsft");
PropertyManager->Untie("forces/fbx-gear-lbs");
PropertyManager->Untie("forces/fby-gear-lbs");
PropertyManager->Untie("forces/fbz-gear-lbs");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGGroundReactions::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 2) { // Loading
cout << endl << " Ground Reactions: " << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
if (from == 1) cout << "Destroyed: FGGroundReactions" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
}

View file

@ -0,0 +1,114 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGGroundReactions.h
Author: Jon S. Berndt
Date started: 09/13/00
------------- 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.
HISTORY
--------------------------------------------------------------------------------
09/13/00 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGGROUNDREACTIONS_H
#define FGGROUNDREACTIONS_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
# include <vector>
# else
# include <vector.h>
# endif
#else
# include <vector>
#endif
#include "FGModel.h"
#include "FGLGear.h"
#include <math/FGColumnVector3.h>
#include <input_output/FGXMLElement.h>
#define ID_GROUNDREACTIONS "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Manages ground reactions modeling.
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGGroundReactions : public FGModel
{
public:
FGGroundReactions(FGFDMExec*);
~FGGroundReactions(void);
bool Run(void);
bool Load(Element* el);
FGColumnVector3& GetForces(void) {return vForces;}
double GetForces(int idx) const {return vForces(idx);}
FGColumnVector3& GetMoments(void) {return vMoments;}
double GetMoments(int idx) const {return vMoments(idx);}
string GetGroundReactionStrings(string delimeter);
string GetGroundReactionValues(string delimeter);
bool GetWOW(void);
inline int GetNumGearUnits(void) const { return lGear.size(); }
/** Gets a gear instance
@param gear index of gear instance
@return a pointer to the FGLGear instance of the gear unit requested */
inline FGLGear* GetGearUnit(int gear) { return &(lGear[gear]); }
void bind(void);
void unbind(void);
private:
vector <FGLGear> lGear;
FGColumnVector3 vForces;
FGColumnVector3 vMoments;
FGColumnVector3 vMaxStaticGrip;
FGColumnVector3 vMaxMomentResist;
void Debug(int from);
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,134 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGInertial.cpp
Author: Jon S. Berndt
Date started: 09/13/00
Purpose: Encapsulates the inertial frame forces (coriolis and centrifugal)
------------- Copyright (C) 2000 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
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
09/13/00 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGInertial.h"
#include "FGPropagate.h"
#include "FGState.h"
#include "FGMassBalance.h"
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_INERTIAL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex)
{
Name = "FGInertial";
// Defaults
RotationRate = 0.00007272205217;
GM = 14.06252720E15;
RadiusReference = 20925650.00;
gAccelReference = GM/(RadiusReference*RadiusReference);
gAccel = GM/(RadiusReference*RadiusReference);
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGInertial::~FGInertial(void)
{
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGInertial::Run(void)
{
// Fast return if we have nothing to do ...
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
// Gravitation accel
double r = Propagate->GetRadius();
gAccel = GetGAccel(r);
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGInertial::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGInertial" << endl;
if (from == 1) cout << "Destroyed: FGInertial" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
}

View file

@ -0,0 +1,101 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGInertial.h
Author: Jon S. Berndt
Date started: 09/13/00
------------- 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.
HISTORY
--------------------------------------------------------------------------------
09/13/00 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGINERTIAL_H
#define FGINERTIAL_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
# include <vector>
# else
# include <vector.h>
# endif
#else
# include <vector>
#endif
#include "FGModel.h"
#include <math/FGColumnVector3.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INERTIAL "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models inertial forces (e.g. centripetal and coriolis accelerations).
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGInertial : public FGModel {
public:
FGInertial(FGFDMExec*);
~FGInertial(void);
bool Run(void);
double SLgravity(void) const {return gAccelReference;}
double gravity(void) const {return gAccel;}
double omega(void) const {return RotationRate;}
double GetGAccel(double r) const { return GM/(r*r); }
double RefRadius(void) const {return RadiusReference;}
private:
double gAccel;
double gAccelReference;
double RadiusReference;
double RotationRate;
double GM;
void Debug(int from);
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

269
src/FDM/JSBSim/models/FGInput.cpp Executable file
View file

@ -0,0 +1,269 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGInput.cpp
Author: Jon Berndt
Date started: 12/02/98
Purpose: Manage output of sim parameters to file or stdout
Called by: FGSimExec
------------- 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 is the place where you create output routines to dump data for perusal
later.
HISTORY
--------------------------------------------------------------------------------
12/02/98 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGInput.h"
#include "FGState.h"
#include "FGFDMExec.h"
#include <fstream>
#include <iomanip>
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_INPUT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGInput::FGInput(FGFDMExec* fdmex) : FGModel(fdmex)
{
Name = "FGInput";
sFirstPass = dFirstPass = true;
socket = 0;
port = 0;
enabled = true;
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGInput::~FGInput()
{
if (socket) delete socket;
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// This function handles accepting input commands from the socket interface.
//
bool FGInput::Run(void)
{
string line, token, info_string;
int start=0, string_start=0, string_end=0;
int token_start=0, token_end=0;
char buf[100];
double value=0;
FGPropertyManager* node=0;
if (FGModel::Run()) return true; // fast exit if nothing to do
if (port == 0) return true; // Do nothing here if port not defined
// This model DOES execute if "Exec->Holding"
data = socket->Receive(); // get socket transmission if present
if (data.size() > 0) {
// parse lines
while (1) {
string_start = data.find_first_not_of("\r\n", start);
if (string_start == string::npos) break;
string_end = data.find_first_of("\r\n", string_start);
if (string_end == string::npos) break;
line = data.substr(string_start, string_end-string_start);
if (line.size() == 0) break;
// now parse individual line
token_start = line.find_first_not_of(" ", 0);
token_end = line.find_first_of(" ", token_start);
token = line.substr(token_start, token_end - token_start);
if (token == "set" || token == "SET" ) { // SET PROPERTY
token_start = line.find_first_not_of(" ", token_end);
token_end = line.find_first_of(" ", token_start);
token = line.substr(token_start, token_end-token_start);
node = PropertyManager->GetNode(token);
if (node == 0) socket->Reply("Unknown property\n");
else {
token_start = line.find_first_not_of(" ", token_end);
token_end = line.find_first_of(" ", token_start);
token = line.substr(token_start, token_end-token_start);
value = atof(token.c_str());
node->setDoubleValue(value);
}
} else if (token == "get" || token == "GET") { // GET PROPERTY
token_start = line.find_first_not_of(" ", token_end);
if (token_start == string::npos) {
socket->Reply("No property argument supplied.\n");
break;
} else {
token = line.substr(token_start, line.size()-token_start);
}
try {
node = PropertyManager->GetNode(token);
} catch(...) {
socket->Reply("Badly formed property query\n");
break;
}
if (node == 0) {
if (FDMExec->Holding()) { // if holding can query property list
string query = FDMExec->QueryPropertyCatalog(token);
socket->Reply(query);
} else {
socket->Reply("Must be in HOLD to search properties\n");
}
} else if (node > 0) {
sprintf(buf, "%s = %12.6f\n", token.c_str(), node->getDoubleValue());
socket->Reply(buf);
}
} else if (token == "hold" || token == "HOLD") { // PAUSE
FDMExec->Hold();
} else if (token == "resume" || token == "RESUME") { // RESUME
FDMExec->Resume();
} else if (token == "quit" || token == "QUIT") { // QUIT
// close the socket connection
socket->Reply("");
socket->Close();
} else if (token == "info" || token == "INFO") { // INFO
// get info about the sim run and/or aircraft, etc.
sprintf(buf, "%8.3f\0", State->Getsim_time());
info_string = "JSBSim version: " + JSBSim_version + "\n";
info_string += "Config File version: " + needed_cfg_version + "\n";
info_string += "Aircraft simulated: " + Aircraft->GetAircraftName() + "\n";
info_string += "Simulation time: " + string(buf) + "\n";
socket->Reply(info_string);
} else if (token == "help" || token == "HELP") { // HELP
socket->Reply(
" JSBSim Server commands:\n\n"
" get {property name}\n"
" set {property name} {value}\n"
" hold\n"
" resume\n"
" help\n"
" quit\n"
" info\n\n");
} else {
socket->Reply(string("Unknown command: ") + token + string("\n"));
}
start = string_end;
}
}
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGInput::Load(Element* element)
{
string type="", parameter="";
string name="", fname="";
string property;
port = element->GetAttributeValueAsNumber("port");
if (port == 0) {
cerr << endl << "No port assigned in input element" << endl;
} else {
socket = new FGfdmSocket(port);
}
Debug(2);
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGInput::Debug(int from)
{
string scratch="";
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
}
if (from == 2) {
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGInput" << endl;
if (from == 1) cout << "Destroyed: FGInput" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
}

107
src/FDM/JSBSim/models/FGInput.h Executable file
View file

@ -0,0 +1,107 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGInput.h
Author: Jon Berndt
Date started: 12/2/98
------------- 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.
HISTORY
--------------------------------------------------------------------------------
12/02/98 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGINPUT_H
#define FGINPUT_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
#ifdef FGFS
# include <simgear/compiler.h>
# include STL_IOSTREAM
# include STL_FSTREAM
#else
# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
# include <iostream.h>
# include <fstream.h>
# else
# include <iostream>
# include <fstream>
# endif
#endif
#include <input_output/FGfdmSocket.h>
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INPUT "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Handles simulation input.
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGInput : public FGModel
{
public:
FGInput(FGFDMExec*);
~FGInput();
bool Run(void);
void SetType(string);
inline void Enable(void) { enabled = true; }
inline void Disable(void) { enabled = false; }
inline bool Toggle(void) {enabled = !enabled; return enabled;}
bool Load(Element* el);
private:
bool sFirstPass, dFirstPass, enabled;
unsigned int port;
FGfdmSocket* socket;
string data;
void Debug(int from);
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,694 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGLGear.cpp
Author: Jon S. Berndt
Norman H. Princen
Date started: 11/18/99
Purpose: Encapsulates the landing gear elements
Called by: FGAircraft
------------- 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
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
11/18/99 JSB Created
01/30/01 NHP Extended gear model to properly simulate steering and braking
/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGLGear.h"
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_LGEAR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) : Exec(fdmex),
GearNumber(number)
{
Element *force_table=0;
string force_type="";
kSpring = bDamp = bDampRebound = dynamicFCoeff = staticFCoeff = rollingFCoeff = maxSteerAngle = 0;
sSteerType = sBrakeGroup = sSteerType = "";
isRetractable = 0;
name = el->GetAttributeValue("name");
sContactType = el->GetAttributeValue("type");
if (el->FindElement("spring_coeff"))
kSpring = el->FindElementValueAsNumberConvertTo("spring_coeff", "LBS/FT");
if (el->FindElement("damping_coeff"))
bDamp = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT/SEC");
if (el->FindElement("damping_coeff_rebound"))
bDampRebound = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT/SEC");
else
bDampRebound = bDamp;
if (el->FindElement("dynamic_friction"))
dynamicFCoeff = el->FindElementValueAsNumber("dynamic_friction");
if (el->FindElement("static_friction"))
staticFCoeff = el->FindElementValueAsNumber("static_friction");
if (el->FindElement("rolling_friction"))
rollingFCoeff = el->FindElementValueAsNumber("rolling_friction");
if (el->FindElement("max_steer"))
maxSteerAngle = el->FindElementValueAsNumberConvertTo("max_steer", "DEG");
if (el->FindElement("retractable"))
isRetractable = (int)el->FindElementValueAsNumber("retractable");
ForceY_Table = 0;
force_table = el->FindElement("table");
while (force_table) {
force_type = force_table->GetAttributeValue("type");
if (force_type == "CORNERING_COEFF") {
ForceY_Table = new FGTable(Exec->GetPropertyManager(), force_table);
} else {
cerr << "Undefined force table for " << name << " contact point" << endl;
}
force_table = el->FindNextElement("table");
}
sBrakeGroup = el->FindElementValue("brake_group");
if (maxSteerAngle == 360) sSteerType = "CASTERED";
else if (maxSteerAngle == 0.0) sSteerType = "FIXED";
else sSteerType = "STEERABLE";
Element* element = el->FindElement("location");
if (element) vXYZ = element->FindElementTripletConvertTo("IN");
else {cerr << "No location given for contact " << name << endl; exit(-1);}
if (sBrakeGroup == "LEFT" ) eBrakeGrp = bgLeft;
else if (sBrakeGroup == "RIGHT" ) eBrakeGrp = bgRight;
else if (sBrakeGroup == "CENTER") eBrakeGrp = bgCenter;
else if (sBrakeGroup == "NOSE" ) eBrakeGrp = bgNose;
else if (sBrakeGroup == "TAIL" ) eBrakeGrp = bgTail;
else if (sBrakeGroup == "NONE" ) eBrakeGrp = bgNone;
else if (sBrakeGroup.empty() ) {eBrakeGrp = bgNone;
sBrakeGroup = "NONE (defaulted)";}
else {
cerr << "Improper braking group specification in config file: "
<< sBrakeGroup << " is undefined." << endl;
}
if (sSteerType == "STEERABLE") eSteerType = stSteer;
else if (sSteerType == "FIXED" ) eSteerType = stFixed;
else if (sSteerType == "CASTERED" ) eSteerType = stCaster;
else if (sSteerType.empty() ) {eSteerType = stFixed;
sSteerType = "FIXED (defaulted)";}
else {
cerr << "Improper steering type specification in config file: "
<< sSteerType << " is undefined." << endl;
}
GearUp = false;
GearDown = true;
Servicable = true;
// Add some AI here to determine if gear is located properly according to its
// brake group type ??
State = Exec->GetState();
Aircraft = Exec->GetAircraft();
Propagate = Exec->GetPropagate();
Auxiliary = Exec->GetAuxiliary();
FCS = Exec->GetFCS();
MassBalance = Exec->GetMassBalance();
WOW = lastWOW = true; // should the value be initialized to true?
ReportEnable = true;
FirstContact = false;
StartedGroundRun = false;
TakeoffReported = LandingReported = false;
LandingDistanceTraveled = TakeoffDistanceTraveled = TakeoffDistanceTraveled50ft = 0.0;
MaximumStrutForce = MaximumStrutTravel = 0.0;
SideForce = RollingForce = 0.0;
SinkRate = GroundSpeed = 0.0;
vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);
vLocalGear = Propagate->GetTb2l() * vWhlBodyVec;
compressLength = 0.0;
compressSpeed = 0.0;
brakePct = 0.0;
maxCompLen = 0.0;
WheelSlip = last_WheelSlip = 0.0;
TirePressureNorm = 1.0;
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGLGear::FGLGear(const FGLGear& lgear)
{
GearNumber = lgear.GearNumber;
State = lgear.State;
Aircraft = lgear.Aircraft;
Propagate = lgear.Propagate;
Auxiliary = lgear.Auxiliary;
Exec = lgear.Exec;
FCS = lgear.FCS;
MassBalance = lgear.MassBalance;
vXYZ = lgear.vXYZ;
vMoment = lgear.vMoment;
vWhlBodyVec = lgear.vWhlBodyVec;
vLocalGear = lgear.vLocalGear;
WOW = lgear.WOW;
lastWOW = lgear.lastWOW;
ReportEnable = lgear.ReportEnable;
FirstContact = lgear.FirstContact;
StartedGroundRun = lgear.StartedGroundRun;
LandingDistanceTraveled = lgear.LandingDistanceTraveled;
TakeoffDistanceTraveled = lgear.TakeoffDistanceTraveled;
TakeoffDistanceTraveled50ft = lgear.TakeoffDistanceTraveled50ft;
MaximumStrutForce = lgear.MaximumStrutForce;
MaximumStrutTravel = lgear.MaximumStrutTravel;
SideForce = lgear.SideForce;
RollingForce = lgear.RollingForce;
kSpring = lgear.kSpring;
bDamp = lgear.bDamp;
bDampRebound = lgear.bDampRebound;
compressLength = lgear.compressLength;
compressSpeed = lgear.compressSpeed;
staticFCoeff = lgear.staticFCoeff;
dynamicFCoeff = lgear.dynamicFCoeff;
rollingFCoeff = lgear.rollingFCoeff;
brakePct = lgear.brakePct;
maxCompLen = lgear.maxCompLen;
SinkRate = lgear.SinkRate;
GroundSpeed = lgear.GroundSpeed;
LandingReported = lgear.LandingReported;
TakeoffReported = lgear.TakeoffReported;
name = lgear.name;
sSteerType = lgear.sSteerType;
sRetractable = lgear.sRetractable;
sContactType = lgear.sContactType;
sBrakeGroup = lgear.sBrakeGroup;
eSteerType = lgear.eSteerType;
eBrakeGrp = lgear.eBrakeGrp;
maxSteerAngle = lgear.maxSteerAngle;
isRetractable = lgear.isRetractable;
GearUp = lgear.GearUp;
GearDown = lgear.GearDown;
WheelSlip = lgear.WheelSlip;
TirePressureNorm = lgear.TirePressureNorm;
Servicable = lgear.Servicable;
ForceY_Table = lgear.ForceY_Table;
CosWheel = lgear.CosWheel;
SinWheel = lgear.SinWheel;
In = lgear.In;
prevIn = lgear.prevIn;
prevOut = lgear.prevOut;
slipIn = lgear.slipIn;
last_SlipIn = lgear.last_SlipIn;
last_WheelSlip = lgear.last_WheelSlip;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGLGear::~FGLGear()
{
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3& FGLGear::Force(void)
{
FGColumnVector3 normal, cvel;
FGLocation contact, gearLoc;
double t = Exec->GetState()->Getsim_time();
vForce.InitMatrix();
vMoment.InitMatrix();
if (isRetractable) ComputeRetractionState();
if (GearUp) return vForce;
vWhlBodyVec = MassBalance->StructuralToBody(vXYZ); // Get wheel in body frame
vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location
gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear);
compressLength = -Exec->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel);
// The compression length is measured in the Z-axis, only, at this time.
if (compressLength > 0.00) {
WOW = true;
// [The next equation should really use the vector to the contact patch of
// the tire including the strut compression and not the original vWhlBodyVec.]
vWhlVelVec = Propagate->GetTb2l() * (Propagate->GetPQR() * vWhlBodyVec);
vWhlVelVec += Propagate->GetVel() - cvel;
compressSpeed = vWhlVelVec(eZ);
InitializeReporting();
ComputeBrakeForceCoefficient();
ComputeSteeringAngle();
ComputeSlipAngle();
ComputeSideForceCoefficient();
ComputeVerticalStrutForce();
// Compute the forces in the wheel ground plane.
RollingForce = (1.0 - TirePressureNorm) * 30
+ vLocalForce(eZ) * BrakeFCoeff * (RollingWhlVel>=0?1.0:-1.0);
SideForce = vLocalForce(eZ) * FCoeff;
// Transform these forces back to the local reference frame.
vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel;
vLocalForce(eY) = SideForce*CosWheel + RollingForce*SinWheel;
// Transform the forces back to the body frame and compute the moment.
vForce = Propagate->GetTl2b() * vLocalForce;
// Lag and attenuate the XY-plane forces dependent on velocity
double RFRV = 0.015; // Rolling force relaxation velocity
double SFRV = 0.25; // Side force relaxation velocity
double dT = State->Getdt()*Exec->GetGroundReactions()->GetRate();
In = vForce;
vForce(eX) = (0.25)*(In(eX) + prevIn(eX)) + (0.50)*prevOut(eX);
vForce(eY) = (0.15)*(In(eY) + prevIn(eY)) + (0.70)*prevOut(eY);
prevOut = vForce;
prevIn = In;
if (fabs(RollingWhlVel) <= RFRV) vForce(eX) *= fabs(RollingWhlVel)/RFRV;
if (fabs(SideWhlVel) <= SFRV) vForce(eY) *= fabs(SideWhlVel)/SFRV;
vMoment = vWhlBodyVec * vForce;
} else { // Gear is NOT compressed
WOW = false;
compressLength = 0.0;
// Return to neutral position between 1.0 and 0.8 gear pos.
SteerAngle *= max(FCS->GetGearPos()-0.8, 0.0)/0.2;
ResetReporting();
}
ReportTakeoffOrLanding();
CrashDetect();
return vForce;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLGear::ComputeRetractionState(void)
{
if (FCS->GetGearPos() < 0.01) {
GearUp = true;
GearDown = false;
} else if (FCS->GetGearPos() > 0.99) {
GearDown = true;
GearUp = false;
} else {
GearUp = false;
GearDown = false;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLGear::ComputeSlipAngle(void)
{
double dT = State->Getdt()*Exec->GetGroundReactions()->GetRate();
// Transform the wheel velocities from the local axis system to the wheel axis system.
RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;
SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;
// Calculate tire slip angle.
if (fabs(RollingWhlVel) < 0.1 && fabs(SideWhlVel) < 0.01) {
WheelSlip = -SteerAngle*radtodeg;
} else {
WheelSlip = atan2(SideWhlVel, fabs(RollingWhlVel))*radtodeg;
}
slipIn = WheelSlip;
WheelSlip = (0.46)*(slipIn + last_SlipIn) + (0.08)*last_WheelSlip;
last_WheelSlip = WheelSlip;
last_SlipIn = slipIn;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Compute the steering angle in any case.
// This will also make sure that animations will look right.
void FGLGear::ComputeSteeringAngle(void)
{
switch (eSteerType) {
case stSteer:
SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber);
break;
case stFixed:
SteerAngle = 0.0;
break;
case stCaster:
// This is not correct for castering gear. Should make steer angle parallel
// to the actual velocity vector of the wheel, given aircraft velocity vector
// and omega.
SteerAngle = 0.0;
break;
default:
cerr << "Improper steering type membership detected for this gear." << endl;
break;
}
SinWheel = sin(Propagate->GetEuler(ePsi) + SteerAngle);
CosWheel = cos(Propagate->GetEuler(ePsi) + SteerAngle);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Reset reporting functionality after takeoff
void FGLGear::ResetReporting(void)
{
if (Propagate->GetDistanceAGL() > 200.0) {
FirstContact = false;
StartedGroundRun = false;
LandingReported = false;
LandingDistanceTraveled = 0.0;
MaximumStrutForce = MaximumStrutTravel = 0.0;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLGear::InitializeReporting(void)
{
// If this is the first time the wheel has made contact, remember some values
// for later printout.
if (!FirstContact) {
FirstContact = true;
SinkRate = compressSpeed;
GroundSpeed = Propagate->GetVel().Magnitude();
TakeoffReported = false;
}
// If the takeoff run is starting, initialize.
if ((Propagate->GetVel().Magnitude() > 0.1) &&
(FCS->GetBrake(bgLeft) == 0) &&
(FCS->GetBrake(bgRight) == 0) &&
(FCS->GetThrottlePos(0) == 1) && !StartedGroundRun)
{
TakeoffDistanceTraveled = 0;
TakeoffDistanceTraveled50ft = 0;
StartedGroundRun = true;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Takeoff and landing reporting functionality
void FGLGear::ReportTakeoffOrLanding(void)
{
double deltaT = State->Getdt()*Exec->GetGroundReactions()->GetRate();
if (FirstContact) LandingDistanceTraveled += Auxiliary->GetVground()*deltaT;
if (StartedGroundRun) {
TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*deltaT;
if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*deltaT;
}
if (ReportEnable && Auxiliary->GetVground() <= 0.05 && !LandingReported) {
if (debug_lvl > 0) Report(erLand);
}
if (ReportEnable && !TakeoffReported &&
(vLocalGear(eZ) - Propagate->GetDistanceAGL()) < -50.0)
{
if (debug_lvl > 0) Report(erTakeoff);
}
if (lastWOW != WOW) PutMessage("GEAR_CONTACT: " + name, WOW);
lastWOW = WOW;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Crash detection logic (really out-of-bounds detection)
void FGLGear::CrashDetect(void)
{
if (compressLength > 500.0 ||
vForce.Magnitude() > 100000000.0 ||
vMoment.Magnitude() > 5000000000.0 ||
SinkRate > 1.4666*30)
{
PutMessage("Crash Detected: Simulation FREEZE.");
State->SuspendIntegration();
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The following needs work regarding friction coefficients and braking and
// steering The BrakeFCoeff formula assumes that an anti-skid system is used.
// It also assumes that we won't be turning and braking at the same time.
// Will fix this later.
// [JSB] The braking force coefficients include normal rolling coefficient +
// a percentage of the static friction coefficient based on braking applied.
void FGLGear::ComputeBrakeForceCoefficient(void)
{
switch (eBrakeGrp) {
case bgLeft:
BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
staticFCoeff*FCS->GetBrake(bgLeft) );
break;
case bgRight:
BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
staticFCoeff*FCS->GetBrake(bgRight) );
break;
case bgCenter:
BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
staticFCoeff*FCS->GetBrake(bgCenter) );
break;
case bgNose:
BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
staticFCoeff*FCS->GetBrake(bgCenter) );
break;
case bgTail:
BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
staticFCoeff*FCS->GetBrake(bgCenter) );
break;
case bgNone:
BrakeFCoeff = rollingFCoeff;
break;
default:
cerr << "Improper brake group membership detected for this gear." << endl;
break;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Compute the sideforce coefficients using similar assumptions to LaRCSim for now.
// Allow a maximum of 10 degrees tire slip angle before wheel slides. At that point,
// transition from static to dynamic friction. There are more complicated formulations
// of this that avoid the discrete jump (similar to Pacejka). Will fix this later.
void FGLGear::ComputeSideForceCoefficient(void)
{
if (ForceY_Table) {
FCoeff = ForceY_Table->GetValue(WheelSlip);
} else {
if (fabs(WheelSlip) <= 10.0) {
FCoeff = staticFCoeff*WheelSlip/10.0;
} else if (fabs(WheelSlip) <= 40.0) {
FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 10.0)/10.0
+ staticFCoeff*(40.0 - fabs(WheelSlip))/10.0)*(WheelSlip>=0?1.0:-1.0);
} else {
FCoeff = dynamicFCoeff*(WheelSlip>=0?1.0:-1.0);
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Compute the vertical force on the wheel using square-law damping (per comment
// in paper AIAA-2000-4303 - see header prologue comments). We might consider
// allowing for both square and linear damping force calculation. Also need to
// possibly give a "rebound damping factor" that differs from the compression
// case.
void FGLGear::ComputeVerticalStrutForce(void)
{
double springForce = 0;
double dampForce = 0;
springForce = -compressLength * kSpring;
if (compressSpeed >= 0.0) {
dampForce = -compressSpeed * bDamp;
} else {
dampForce = -compressSpeed * bDampRebound;
}
vLocalForce(eZ) = min(springForce + dampForce, (double)0.0);
// Remember these values for reporting
MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));
MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLGear::bind(void)
{
char property_name[80];
snprintf(property_name, 80, "gear/unit[%d]/slip-angle-deg", GearNumber);
Exec->GetPropertyManager()->Tie( property_name, &WheelSlip );
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLGear::unbind(void)
{
char property_name[80];
snprintf(property_name, 80, "gear/unit[%d]/slip-angle-deg", GearNumber);
Exec->GetPropertyManager()->Untie( property_name );
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGLGear::Report(ReportType repType)
{
switch(repType) {
case erLand:
cout << endl << "Touchdown report for " << name << endl;
cout << " Sink rate at contact: " << SinkRate << " fps, "
<< SinkRate*0.3048 << " mps" << endl;
cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, "
<< GroundSpeed*0.3048 << " mps" << endl;
cout << " Maximum contact force: " << MaximumStrutForce << " lbs, "
<< MaximumStrutForce*4.448 << " Newtons" << endl;
cout << " Maximum strut travel: " << MaximumStrutTravel*12.0 << " inches, "
<< MaximumStrutTravel*30.48 << " cm" << endl;
cout << " Distance traveled: " << LandingDistanceTraveled << " ft, "
<< LandingDistanceTraveled*0.3048 << " meters" << endl;
LandingReported = true;
break;
case erTakeoff:
cout << endl << "Takeoff report for " << name << endl;
cout << " Distance traveled: " << TakeoffDistanceTraveled
<< " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl;
cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft
<< " ft, " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl;
TakeoffReported = true;
break;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGLGear::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor - loading and initialization
cout << " " << sContactType << " " << name << endl;
cout << " Location: " << vXYZ << endl;
cout << " Spring Constant: " << kSpring << endl;
cout << " Damping Constant: " << bDamp << endl;
cout << " Dynamic Friction: " << dynamicFCoeff << endl;
cout << " Static Friction: " << staticFCoeff << endl;
if (sContactType == "BOGEY") {
cout << " Rolling Friction: " << rollingFCoeff << endl;
cout << " Steering Type: " << sSteerType << endl;
cout << " Grouping: " << sBrakeGroup << endl;
cout << " Max Steer Angle: " << maxSteerAngle << endl;
cout << " Retractable: " << isRetractable << endl;
}
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGLGear" << endl;
if (from == 1) cout << "Destroyed: FGLGear" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,347 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGLGear.h
Author: Jon S. Berndt
Date started: 11/18/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.
HISTORY
--------------------------------------------------------------------------------
11/18/99 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGLGEAR_H
#define FGLGEAR_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef FGFS
# include <simgear/compiler.h>
#endif
#include <FGJSBBase.h>
#include <FGFDMExec.h>
#include <input_output/FGXMLElement.h>
#include <math/FGColumnVector3.h>
#include <math/FGTable.h>
#include <string>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_LGEAR "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
class FGAircraft;
class FGPropagate;
class FGFCS;
class FGState;
class FGMassBalance;
class FGAuxiliary;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Landing gear model.
Calculates forces and moments due to landing gear reactions. This is done in
several steps, and is dependent on what kind of gear is being modeled. Here
are the parameters that can be specified in the config file for modeling
landing gear:
<p>
<b><u>Physical Characteristics</u></b><br>
<ol>
<li>X, Y, Z location, in inches in structural coordinate frame</li>
<li>Spring constant, in lbs/ft</li>
<li>Damping coefficient, in lbs/ft/sec</li>
<li>Dynamic Friction Coefficient</li>
<li>Static Friction Coefficient</li>
</ol></p><p>
<b><u>Operational Properties</b></u><br>
<ol>
<li>Name</li>
<li>Steerability attribute {one of STEERABLE | FIXED | CASTERED}</li>
<li>Brake Group Membership {one of LEFT | CENTER | RIGHT | NOSE | TAIL | NONE}</li>
<li>Max Steer Angle, in degrees</li>
</ol></p>
<p>
<b><u>Algorithm and Approach to Modeling</u></b><br>
<ol>
<li>Find the location of the uncompressed landing gear relative to the CG of
the aircraft. Remember, the structural coordinate frame that the aircraft is
defined in is: X positive towards the tail, Y positive out the right side, Z
positive upwards. The locations of the various parts are given in inches in
the config file.</li>
<li>The vector giving the location of the gear (relative to the cg) is
rotated 180 degrees about the Y axis to put the coordinates in body frame (X
positive forwards, Y positive out the right side, Z positive downwards, with
the origin at the cg). The lengths are also now given in feet.</li>
<li>The new gear location is now transformed to the local coordinate frame
using the body-to-local matrix. (Mb2l).</li>
<li>Knowing the location of the center of gravity relative to the ground
(height above ground level or AGL) now enables gear deflection to be
calculated. The gear compression value is the local frame gear Z location
value minus the height AGL. [Currently, we make the assumption that the gear
is oriented - and the deflection occurs in - the Z axis only. Additionally,
the vector to the landing gear is currently not modified - which would
(correctly) move the point of contact to the actual compressed-gear point of
contact. Eventually, articulated gear may be modeled, but initially an
effort must be made to model a generic system.] As an example, say the
aircraft left main gear location (in local coordinates) is Z = 3 feet
(positive) and the height AGL is 2 feet. This tells us that the gear is
compressed 1 foot.</li>
<li>If the gear is compressed, a Weight-On-Wheels (WOW) flag is set.</li>
<li>With the compression length calculated, the compression velocity may now
be calculated. This will be used to determine the damping force in the
strut. The aircraft rotational rate is multiplied by the vector to the wheel
to get a wheel velocity in body frame. That velocity vector is then
transformed into the local coordinate frame.</li>
<li>The aircraft cg velocity in the local frame is added to the
just-calculated wheel velocity (due to rotation) to get a total wheel
velocity in the local frame.</li>
<li>The compression speed is the Z-component of the vector.</li>
<li>With the wheel velocity vector no longer needed, it is normalized and
multiplied by a -1 to reverse it. This will be used in the friction force
calculation.</li>
<li>Since the friction force takes place solely in the runway plane, the Z
coordinate of the normalized wheel velocity vector is set to zero.</li>
<li>The gear deflection force (the force on the aircraft acting along the
local frame Z axis) is now calculated given the spring and damper
coefficients, and the gear deflection speed and stroke length. Keep in mind
that gear forces always act in the negative direction (in both local and
body frames), and are not capable of generating a force in the positive
sense (one that would attract the aircraft to the ground). So, the gear
forces are always negative - they are limited to values of zero or less. The
gear force is simply the negative of the sum of the spring compression
length times the spring coefficient and the gear velocity times the damping
coefficient.</li>
<li>The lateral/directional force acting on the aircraft through the landing
gear (along the local frame X and Y axes) is calculated next. First, the
friction coefficient is multiplied by the recently calculated Z-force. This
is the friction force. It must be given direction in addition to magnitude.
We want the components in the local frame X and Y axes. From step 9, above,
the conditioned wheel velocity vector is taken and the X and Y parts are
multiplied by the friction force to get the X and Y components of friction.
</li>
<li>The wheel force in local frame is next converted to body frame.</li>
<li>The moment due to the gear force is calculated by multiplying r x F
(radius to wheel crossed into the wheel force). Both of these operands are
in body frame.</li>
</ol>
@author Jon S. Berndt
@version $Id$
@see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
NASA-Ames", NASA CR-2497, January 1975
@see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
Wiley & Sons, 1979 ISBN 0-471-03032-5
@see W. A. Ragsdale, "A Generic Landing Gear Dynamics Model for LASRS++",
AIAA-2000-4303
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGLGear : public FGJSBBase
{
public:
/// Brake grouping enumerators
enum BrakeGroup {bgNone=0, bgLeft, bgRight, bgCenter, bgNose, bgTail };
/// Steering group membership enumerators
enum SteerType {stSteer, stFixed, stCaster};
/// Report type enumerators
enum ReportType {erNone=0, erTakeoff, erLand};
/** Constructor
@param el a pointer to the XML element that contains the CONTACT info.
@param Executive a pointer to the parent executive object
@param File a pointer to the config file instance */
FGLGear(Element* el, FGFDMExec* Executive, int number);
/** Constructor
@param lgear a reference to an existing FGLGear object */
FGLGear(const FGLGear& lgear);
/// Destructor
~FGLGear();
/// The Force vector for this gear
FGColumnVector3& Force(void);
/// The Moment vector for this gear
FGColumnVector3& Moment(void) {return vMoment;}
/// Gets the location of the gear in Body axes
FGColumnVector3& GetBodyLocation(void) { return vWhlBodyVec; }
double GetBodyLocation(int idx) { return vWhlBodyVec(idx); }
FGColumnVector3& GetLocalGear(void) { return vLocalGear; }
double GetLocalGear(int idx) { return vLocalGear(idx); }
/// Gets the name of the gear
inline string GetName(void) {return name; }
/// Gets the Weight On Wheels flag value
inline bool GetWOW(void) {return WOW; }
/// Gets the current compressed length of the gear in feet
inline double GetCompLen(void) {return compressLength;}
/// Gets the current gear compression velocity in ft/sec
inline double GetCompVel(void) {return compressSpeed; }
/// Gets the gear compression force in pounds
inline double GetCompForce(void) {return Force()(3); }
inline double GetBrakeFCoeff(void) {return BrakeFCoeff;}
/// Gets the current normalized tire pressure
inline double GetTirePressure(void) { return TirePressureNorm; }
/// Sets the new normalized tire pressure
inline void SetTirePressure(double p) { TirePressureNorm = p; }
/// Sets the brake value in percent (0 - 100)
inline void SetBrake(double bp) {brakePct = bp;}
/** Set the console touchdown reporting feature
@param flag true turns on touchdown reporting, false turns it off */
inline void SetReport(bool flag) { ReportEnable = flag; }
/** Get the console touchdown reporting feature
@return true if reporting is turned on */
inline bool GetReport(void) { return ReportEnable; }
double GetSteerNorm(void) const { return radtodeg/maxSteerAngle*SteerAngle; }
double GetDefaultSteerAngle(double cmd) const { return cmd*maxSteerAngle; }
double GetstaticFCoeff(void) { return staticFCoeff; }
inline int GetBrakeGroup(void) { return (int)eBrakeGrp; }
inline int GetSteerType(void) { return (int)eSteerType; }
bool GetSteerable(void) const { return eSteerType != stFixed; }
inline bool GetRetractable(void) { return isRetractable; }
inline bool GetGearUnitUp(void) { return GearUp; }
inline bool GetGearUnitDown(void) { return GearDown; }
inline double GetWheelSideForce(void) { return SideForce; }
inline double GetWheelRollForce(void) { return RollingForce; }
inline double GetBodyXForce(void) { return vLocalForce(eX); }
inline double GetBodyYForce(void) { return vLocalForce(eY); }
inline double GetWheelSlipAngle(void) { return WheelSlip; }
double GetWheelVel(int axis) { return vWhlVelVec(axis);}
bool IsBogey(void) {return (sContactType == string("BOGEY"));}
void bind(void);
void unbind(void);
private:
int GearNumber;
FGColumnVector3 vXYZ;
FGColumnVector3 vMoment;
FGColumnVector3 vWhlBodyVec;
FGColumnVector3 vLocalGear;
FGColumnVector3 vForce;
FGColumnVector3 last_vForce; // remove this
FGColumnVector3 vLocalForce;
FGColumnVector3 vWhlVelVec; // Velocity of this wheel (Local)
FGColumnVector3 In;
FGColumnVector3 prevIn;
FGColumnVector3 prevOut;
FGTable *ForceY_Table;
double SteerAngle;
double kSpring;
double bDamp;
double bDampRebound;
double compressLength;
double compressSpeed;
double staticFCoeff, dynamicFCoeff, rollingFCoeff;
double brakePct;
double BrakeFCoeff;
double maxCompLen;
double SinkRate;
double GroundSpeed;
double TakeoffDistanceTraveled;
double TakeoffDistanceTraveled50ft;
double LandingDistanceTraveled;
double MaximumStrutForce;
double MaximumStrutTravel;
double SideWhlVel, RollingWhlVel;
double RollingForce, SideForce, FCoeff;
double WheelSlip;
double last_WheelSlip;
double slipIn;
double last_SlipIn;
double TirePressureNorm;
double SinWheel, CosWheel;
bool WOW;
bool lastWOW;
bool FirstContact;
bool StartedGroundRun;
bool LandingReported;
bool TakeoffReported;
bool ReportEnable;
bool isRetractable;
bool GearUp, GearDown;
bool Servicable;
string name;
string sSteerType;
string sBrakeGroup;
string sRetractable;
string sContactType;
BrakeGroup eBrakeGrp;
SteerType eSteerType;
double maxSteerAngle;
FGFDMExec* Exec;
FGState* State;
FGAircraft* Aircraft;
FGPropagate* Propagate;
FGAuxiliary* Auxiliary;
FGFCS* FCS;
FGMassBalance* MassBalance;
void ComputeRetractionState(void);
void ComputeBrakeForceCoefficient(void);
void ComputeSteeringAngle(void);
void ComputeSlipAngle(void);
void ComputeSideForceCoefficient(void);
void ComputeVerticalStrutForce(void);
void CrashDetect(void);
void InitializeReporting(void);
void ResetReporting(void);
void ReportTakeoffOrLanding(void);
void Report(ReportType rt);
void Debug(int from);
};
}
#include "FGAircraft.h"
#include "FGPropagate.h"
#include "FGAuxiliary.h"
#include "FGFCS.h"
#include "FGMassBalance.h"
#include "FGState.h"
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -40,7 +40,7 @@ INCLUDES
#include "FGMassBalance.h"
#include "FGPropulsion.h"
#include "FGPropertyManager.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
@ -73,76 +73,135 @@ FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex)
FGMassBalance::~FGMassBalance()
{
unbind();
PointMasses.clear();
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGMassBalance::Load(Element* el)
{
Element *element;
string element_name = "";
double bixx, biyy, bizz, bixy, bixz, biyz;
bixx = biyy = bizz = bixy = bixz = biyz = 0.0;
if (el->FindElement("ixx"))
bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
if (el->FindElement("iyy"))
biyy = el->FindElementValueAsNumberConvertTo("iyy", "SLUG*FT2");
if (el->FindElement("izz"))
bizz = el->FindElementValueAsNumberConvertTo("izz", "SLUG*FT2");
if (el->FindElement("ixy"))
bixy = el->FindElementValueAsNumberConvertTo("ixy", "SLUG*FT2");
if (el->FindElement("ixz"))
bixz = el->FindElementValueAsNumberConvertTo("ixz", "SLUG*FT2");
if (el->FindElement("iyz"))
biyz = el->FindElementValueAsNumberConvertTo("iyz", "SLUG*FT2");
SetAircraftBaseInertias(FGMatrix33( bixx, -bixy, -bixz,
-bixy, biyy, -biyz,
-bixz, -biyz, bizz ));
EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS");
element = el->FindElement("location");
while (element) {
element_name = element->GetAttributeValue("name");
if (element_name == "CG") vbaseXYZcg = element->FindElementTripletConvertTo("IN");
element = el->FindNextElement("location");
}
// Find all POINTMASS elements that descend from this METRICS branch of the
// config file.
element = el->FindElement("pointmass");
while (element) {
AddPointMass(element);
element = el->FindNextElement("pointmass");
}
Debug(2);
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGMassBalance::Run(void)
{
double denom, k1, k2, k3, k4, k5, k6;
double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
if (!FGModel::Run()) {
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetPointMassWeight();
Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetPointMassWeight();
Mass = lbtoslug*Weight;
Mass = lbtoslug*Weight;
// Calculate new CG
vXYZcg = (Propulsion->GetTanksMoment() + EmptyWeight*vbaseXYZcg
+ GetPointMassMoment() ) / Weight;
// printf("%s:%i\n", __FILE__, __LINE__);
vXYZcg = (Propulsion->GetTanksMoment() + EmptyWeight*vbaseXYZcg
+ GetPointMassMoment() ) / Weight;
// Calculate new total moments of inertia
// At first it is the base configuration inertia matrix ...
mJ = baseJ;
// ... with the additional term originating from the parallel axis theorem.
mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
// Then add the contributions from the additional pointmasses.
mJ += CalculatePMInertias();
mJ += Propulsion->CalculateTankInertias();
// At first it is the base configuration inertia matrix ...
mJ = baseJ;
// ... with the additional term originating from the parallel axis theorem.
mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
// Then add the contributions from the additional pointmasses.
mJ += CalculatePMInertias();
mJ += Propulsion->CalculateTankInertias();
Ixx = mJ(1,1);
Iyy = mJ(2,2);
Izz = mJ(3,3);
Ixy = -mJ(1,2);
Ixz = -mJ(1,3);
Iyz = -mJ(2,3);
Ixx = mJ(1,1);
Iyy = mJ(2,2);
Izz = mJ(3,3);
Ixy = -mJ(1,2);
Ixz = -mJ(1,3);
Iyz = -mJ(2,3);
// Calculate inertia matrix inverse (ref. Stevens and Lewis, "Flight Control & Simulation")
k1 = (Iyy*Izz - Iyz*Iyz);
k2 = (Iyz*Ixz + Ixy*Izz);
k3 = (Ixy*Iyz + Iyy*Ixz);
k1 = (Iyy*Izz - Iyz*Iyz);
k2 = (Iyz*Ixz + Ixy*Izz);
k3 = (Ixy*Iyz + Iyy*Ixz);
denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 );
k1 = k1*denom;
k2 = k2*denom;
k3 = k3*denom;
k4 = (Izz*Ixx - Ixz*Ixz)*denom;
k5 = (Ixy*Ixz + Iyz*Ixx)*denom;
k6 = (Ixx*Iyy - Ixy*Ixy)*denom;
denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 );
k1 = k1*denom;
k2 = k2*denom;
k3 = k3*denom;
k4 = (Izz*Ixx - Ixz*Ixz)*denom;
k5 = (Ixy*Ixz + Iyz*Ixx)*denom;
k6 = (Ixx*Iyy - Ixy*Ixy)*denom;
mJinv.InitMatrix( k1, k2, k3,
k2, k4, k5,
k3, k5, k6 );
mJinv.InitMatrix( k1, k2, k3,
k2, k4, k5,
k3, k5, k6 );
Debug(2);
Debug(0);
return false;
} else {
return true;
}
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGMassBalance::AddPointMass(double weight, double X, double Y, double Z)
void FGMassBalance::AddPointMass(Element* el)
{
PointMassLoc.push_back(FGColumnVector3(X, Y, Z));
PointMassWeight.push_back(weight);
Element* loc_element = el->FindElement("location");
string pointmass_name = el->GetAttributeValue("name");
if (!el) {
cerr << "Pointmass " << pointmass_name << "has no location." << endl;
exit(-1);
}
string loc_unit = loc_element->GetAttributeValue("unit");
double w, x, y, z;
w = el->FindElementValueAsNumberConvertTo("weight", "LBS");
x = loc_element->FindElementValueAsNumberConvertTo("x", loc_unit);
y = loc_element->FindElementValueAsNumberConvertTo("y", loc_unit);
z = loc_element->FindElementValueAsNumberConvertTo("z", loc_unit);
PointMasses.push_back(PointMass(w, x, y, z));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -151,8 +210,8 @@ double FGMassBalance::GetPointMassWeight(void)
{
double PM_total_weight = 0.0;
for (unsigned int i=0; i<PointMassWeight.size(); i++) {
PM_total_weight += PointMassWeight[i];
for (unsigned int i=0; i<PointMasses.size(); i++) {
PM_total_weight += PointMasses[i].Weight;
}
return PM_total_weight;
}
@ -163,8 +222,8 @@ FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
{
PointMassCG.InitMatrix();
for (unsigned int i=0; i<PointMassLoc.size(); i++) {
PointMassCG += PointMassWeight[i]*PointMassLoc[i];
for (unsigned int i=0; i<PointMasses.size(); i++) {
PointMassCG += PointMasses[i].Weight*PointMasses[i].Location;
}
return PointMassCG;
}
@ -175,13 +234,13 @@ FGMatrix33& FGMassBalance::CalculatePMInertias(void)
{
unsigned int size;
size = PointMassLoc.size();
size = PointMasses.size();
if (size == 0) return pmJ;
pmJ = FGMatrix33();
for (unsigned int i=0; i<size; i++)
pmJ += GetPointmassInertia( lbtoslug * PointMassWeight[i], PointMassLoc[i] );
pmJ += GetPointmassInertia( lbtoslug * PointMasses[i].Weight, PointMasses[i].Location );
return pmJ;
}
@ -271,8 +330,23 @@ void FGMassBalance::Debug(int from)
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (from == 2) { // Loading
cout << endl << " Mass and Balance:" << endl;
cout << " baseIxx: " << baseJ(1,1) << " slug-ft2" << endl;
cout << " baseIyy: " << baseJ(2,2) << " slug-ft2" << endl;
cout << " baseIzz: " << baseJ(3,3) << " slug-ft2" << endl;
cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl;
cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl;
cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl;
cout << " EmptyWeight: " << EmptyWeight << " lbm" << endl;
cout << " CG (x, y, z): " << vbaseXYZcg << endl;
// ToDo: Need to add point mass outputs here
for (int i=0; i<PointMasses.size(); i++) {
cout << " Point Mass Object: " << PointMasses[i].Weight << " lbs. at "
<< "X, Y, Z (in.): " << PointMasses[i].Location(eX) << " "
<< PointMasses[i].Location(eY) << " "
<< PointMasses[i].Location(eZ) << endl;
}
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification

View file

@ -39,8 +39,9 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
#include "FGColumnVector3.h"
#include "FGMatrix33.h"
#include <math/FGColumnVector3.h>
#include <math/FGMatrix33.h>
#include <input_output/FGXMLElement.h>
#include <vector>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -73,14 +74,14 @@ public:
FGMassBalance(FGFDMExec*);
~FGMassBalance();
bool Load(Element* el);
bool Run(void);
inline double GetMass(void) const {return Mass;}
inline double GetWeight(void) const {return Weight;}
inline double GetEmptyWeight(void) const {return EmptyWeight;}
inline FGColumnVector3& GetXYZcg(void) {return vXYZcg;}
inline double GetXYZcg(int axis) const {return vXYZcg(axis);}
inline double GetbaseXYZcg(int axis) const {return vbaseXYZcg(axis);}
/** Computes the inertia contribution of a pointmass.
Computes and returns the inertia matrix of a pointmass of mass
@ -119,17 +120,13 @@ public:
inline void SetEmptyWeight(double EW) { EmptyWeight = EW;}
inline void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = vXYZcg = CG;}
void AddPointMass(double weight, double X, double Y, double Z);
void AddPointMass(Element* el);
double GetPointMassWeight(void);
FGColumnVector3& GetPointMassMoment(void);
FGMatrix33& GetJ(void) {return mJ;}
FGMatrix33& GetJinv(void) {return mJinv;}
void SetAircraftBaseInertias(FGMatrix33 BaseJ) {baseJ = BaseJ;}
FGMatrix33& GetAircraftBaseInertias(void) {return baseJ;}
int GetNumPointMasses(void) {return PointMassLoc.size();}
FGColumnVector3& GetPointMassLoc(int i) {return PointMassLoc[i];}
double GetPointMassWeight(int i) {return PointMassWeight[i];}
void bind(void);
void unbind(void);
@ -145,11 +142,20 @@ private:
FGColumnVector3 vXYZtank;
FGColumnVector3 vbaseXYZcg;
FGColumnVector3 vPMxyz;
vector <FGColumnVector3> PointMassLoc;
vector <double> PointMassWeight;
FGColumnVector3 PointMassCG;
FGMatrix33& CalculatePMInertias(void);
struct PointMass {
PointMass(double w, double x, double y, double z) {
Weight = w;
Location.InitMatrix(x, y, z);
}
FGColumnVector3 Location;
double Weight;
};
vector <struct PointMass> PointMasses;
void Debug(int from);
};
}

View file

@ -51,7 +51,6 @@ INCLUDES
#include "FGAircraft.h"
#include "FGPropagate.h"
#include "FGAuxiliary.h"
#include "FGOutput.h"
namespace JSBSim {
@ -82,7 +81,6 @@ FGModel::FGModel(FGFDMExec* fdmex)
Aircraft = 0;
Propagate = 0;
Auxiliary = 0;
Output = 0;
//in order for FGModel derived classes to self-bind (that is, call
//their bind function in the constructor, the PropertyManager pointer
@ -117,7 +115,6 @@ bool FGModel::InitModel(void)
Aircraft = FDMExec->GetAircraft();
Propagate = FDMExec->GetPropagate();
Auxiliary = FDMExec->GetAuxiliary();
Output = FDMExec->GetOutput();
if (!State ||
!Atmosphere ||
@ -129,8 +126,7 @@ bool FGModel::InitModel(void)
!GroundReactions ||
!Aircraft ||
!Propagate ||
!Auxiliary ||
!Output) return(false);
!Auxiliary) return(false);
else return(true);
}

View file

@ -38,8 +38,9 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include "FGPropertyManager.h"
#include <FGJSBBase.h>
#include <input_output/FGPropertyManager.h>
#include <input_output/FGXMLElement.h>
#ifdef FGFS
# include <simgear/compiler.h>
@ -84,8 +85,6 @@ class FGGroundReactions;
class FGAircraft;
class FGPropagate;
class FGAuxiliary;
class FGOutput;
class FGConfigFile;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
@ -109,9 +108,9 @@ public:
virtual ~FGModel();
/** Loads this model.
@param Config a pointer to the config file instance
@param el a pointer to the element
@return true if model is successfully loaded*/
virtual bool Load(FGConfigFile* Config) {return true;}
virtual bool Load(Element* el) {return true;}
FGModel* NextModel;
string Name;
@ -144,7 +143,6 @@ protected:
FGAircraft* Aircraft;
FGPropagate* Propagate;
FGAuxiliary* Auxiliary;
FGOutput* Output;
FGPropertyManager* PropertyManager;
};
}

View file

@ -51,6 +51,7 @@ INCLUDES
#include "FGAuxiliary.h"
#include "FGInertial.h"
#include <fstream>
#include <iomanip>
namespace JSBSim {
@ -68,11 +69,10 @@ FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
sFirstPass = dFirstPass = true;
socket = 0;
Type = otNone;
Filename = "";
SubSystems = 0;
enabled = true;
outputInFileName = "";
delimeter = ", ";
Filename = "";
Debug(0);
}
@ -82,7 +82,7 @@ FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
FGOutput::~FGOutput()
{
if (socket) delete socket;
for (unsigned int i=0; i<OutputProperties.size(); i++) delete OutputProperties[i];
OutputProperties.clear();
Debug(1);
}
@ -91,8 +91,9 @@ FGOutput::~FGOutput()
bool FGOutput::Run(void)
{
if (enabled) {
if (FGModel::Run()) return true;
if (FGModel::Run()) return true;
if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) {
if (Type == otSocket) {
SocketOutput();
} else if (Type == otCSV || Type == otTab) {
@ -187,6 +188,8 @@ void FGOutput::DelimitedOutput(string fname)
if (SubSystems & ssAtmosphere) {
outstream << delimeter;
outstream << "Rho" + delimeter;
outstream << "SL pressure" + delimeter;
outstream << "Ambient pressure" + delimeter;
outstream << "NWind" + delimeter + "EWind" + delimeter + "DWind";
}
if (SubSystems & ssMassProps) {
@ -281,6 +284,8 @@ void FGOutput::DelimitedOutput(string fname)
if (SubSystems & ssAtmosphere) {
outstream << delimeter;
outstream << Atmosphere->GetDensity() << delimeter;
outstream << Atmosphere->GetPressureSL() << delimeter;
outstream << Atmosphere->GetPressure() << delimeter;
outstream << Atmosphere->GetWindNED().Dump(delimeter);
}
if (SubSystems & ssMassProps) {
@ -329,99 +334,220 @@ void FGOutput::DelimitedOutput(string fname)
void FGOutput::SocketOutput(void)
{
string asciiData;
string asciiData, scratch;
if (socket == NULL) return;
if (!socket->GetConnectStatus()) return;
socket->Clear();
if (sFirstPass) {
socket->Append("<LABELS>");
socket->Clear("<LABELS>");
socket->Append("Time");
socket->Append("Altitude");
socket->Append("Phi");
socket->Append("Tht");
socket->Append("Psi");
socket->Append("Rho");
socket->Append("Vtotal");
socket->Append("UBody");
socket->Append("VBody");
socket->Append("WBody");
socket->Append("UAero");
socket->Append("VAero");
socket->Append("WAero");
socket->Append("Vn");
socket->Append("Ve");
socket->Append("Vd");
socket->Append("Udot");
socket->Append("Vdot");
socket->Append("Wdot");
socket->Append("P");
socket->Append("Q");
socket->Append("R");
socket->Append("PDot");
socket->Append("QDot");
socket->Append("RDot");
socket->Append("Fx");
socket->Append("Fy");
socket->Append("Fz");
socket->Append("Latitude (Deg)");
socket->Append("Longitude (Deg)");
socket->Append("QBar");
socket->Append("Alpha");
socket->Append("L");
socket->Append("M");
socket->Append("N");
socket->Append("Throttle Position");
socket->Append("Left Aileron Position");
socket->Append("Right Aileron Position");
socket->Append("Elevator Position");
socket->Append("Rudder Position");
if (SubSystems & ssAerosurfaces) {
socket->Append("Aileron Command");
socket->Append("Elevator Command");
socket->Append("Rudder Command");
socket->Append("Flap Command");
socket->Append("Left Aileron Position");
socket->Append("Right Aileron Position");
socket->Append("Elevator Position");
socket->Append("Rudder Position");
socket->Append("Flap Position");
}
if (SubSystems & ssRates) {
socket->Append("P");
socket->Append("Q");
socket->Append("R");
socket->Append("PDot");
socket->Append("QDot");
socket->Append("RDot");
}
if (SubSystems & ssVelocities) {
socket->Append("QBar");
socket->Append("Vtotal");
socket->Append("UBody");
socket->Append("VBody");
socket->Append("WBody");
socket->Append("UAero");
socket->Append("VAero");
socket->Append("WAero");
socket->Append("Vn");
socket->Append("Ve");
socket->Append("Vd");
}
if (SubSystems & ssForces) {
socket->Append("F_Drag");
socket->Append("F_Side");
socket->Append("F_Lift");
socket->Append("LoD");
socket->Append("Fx");
socket->Append("Fy");
socket->Append("Fz");
}
if (SubSystems & ssMoments) {
socket->Append("L");
socket->Append("M");
socket->Append("N");
}
if (SubSystems & ssAtmosphere) {
socket->Append("Rho");
socket->Append("SL pressure");
socket->Append("Ambient pressure");
socket->Append("NWind");
socket->Append("EWind");
socket->Append("DWind");
}
if (SubSystems & ssMassProps) {
socket->Append("Ixx");
socket->Append("Ixy");
socket->Append("Ixz");
socket->Append("Iyx");
socket->Append("Iyy");
socket->Append("Iyz");
socket->Append("Izx");
socket->Append("Izy");
socket->Append("Izz");
socket->Append("Mass");
socket->Append("Xcg");
socket->Append("Ycg");
socket->Append("Zcg");
}
if (SubSystems & ssPropagate) {
socket->Append("Altitude");
socket->Append("Phi");
socket->Append("Tht");
socket->Append("Psi");
socket->Append("Alpha");
socket->Append("Beta");
socket->Append("Latitude (Deg)");
socket->Append("Longitude (Deg)");
}
if (SubSystems & ssCoefficients) {
scratch = Aerodynamics->GetCoefficientStrings(",");
if (scratch.length() != 0) socket->Append(scratch);
}
if (SubSystems & ssFCS) {
scratch = FCS->GetComponentStrings(",");
if (scratch.length() != 0) socket->Append(scratch);
}
if (SubSystems & ssGroundReactions) {
socket->Append(GroundReactions->GetGroundReactionStrings(","));
}
if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
socket->Append(Propulsion->GetPropulsionStrings(","));
}
if (OutputProperties.size() > 0) {
for (unsigned int i=0;i<OutputProperties.size();i++) {
socket->Append(OutputProperties[i]->GetName());
}
}
sFirstPass = false;
socket->Send();
}
socket->Clear();
socket->Append(State->Getsim_time());
socket->Append(Propagate->Geth());
socket->Append(Propagate->GetEuler(ePhi));
socket->Append(Propagate->GetEuler(eTht));
socket->Append(Propagate->GetEuler(ePsi));
socket->Append(Atmosphere->GetDensity());
socket->Append(Auxiliary->GetVt());
socket->Append(Propagate->GetUVW(eU));
socket->Append(Propagate->GetUVW(eV));
socket->Append(Propagate->GetUVW(eW));
socket->Append(Auxiliary->GetAeroUVW(eU));
socket->Append(Auxiliary->GetAeroUVW(eV));
socket->Append(Auxiliary->GetAeroUVW(eW));
socket->Append(Propagate->GetVel(eNorth));
socket->Append(Propagate->GetVel(eEast));
socket->Append(Propagate->GetVel(eDown));
socket->Append(Propagate->GetUVWdot(eU));
socket->Append(Propagate->GetUVWdot(eV));
socket->Append(Propagate->GetUVWdot(eW));
socket->Append(Propagate->GetPQR(eP));
socket->Append(Propagate->GetPQR(eQ));
socket->Append(Propagate->GetPQR(eR));
socket->Append(Propagate->GetPQRdot(eP));
socket->Append(Propagate->GetPQRdot(eQ));
socket->Append(Propagate->GetPQRdot(eR));
socket->Append(Aircraft->GetForces(eX));
socket->Append(Aircraft->GetForces(eY));
socket->Append(Aircraft->GetForces(eZ));
socket->Append(Propagate->GetLocation().GetLatitudeDeg());
socket->Append(Propagate->GetLocation().GetLongitudeDeg());
socket->Append(Auxiliary->Getqbar());
socket->Append(Auxiliary->Getalpha(inDegrees));
socket->Append(Aircraft->GetMoments(eL));
socket->Append(Aircraft->GetMoments(eM));
socket->Append(Aircraft->GetMoments(eN));
socket->Append(FCS->GetThrottlePos(0));
socket->Append(FCS->GetDaLPos());
socket->Append(FCS->GetDaRPos());
socket->Append(FCS->GetDePos());
socket->Append(FCS->GetDrPos());
if (SubSystems & ssAerosurfaces) {
socket->Append(FCS->GetDaCmd());
socket->Append(FCS->GetDeCmd());
socket->Append(FCS->GetDrCmd());
socket->Append(FCS->GetDfCmd());
socket->Append(FCS->GetDaLPos());
socket->Append(FCS->GetDaRPos());
socket->Append(FCS->GetDePos());
socket->Append(FCS->GetDrPos());
socket->Append(FCS->GetDfPos());
}
if (SubSystems & ssRates) {
socket->Append(Propagate->GetPQR(eP));
socket->Append(Propagate->GetPQR(eQ));
socket->Append(Propagate->GetPQR(eR));
socket->Append(Propagate->GetPQRdot(eP));
socket->Append(Propagate->GetPQRdot(eQ));
socket->Append(Propagate->GetPQRdot(eR));
}
if (SubSystems & ssVelocities) {
socket->Append(Auxiliary->Getqbar());
socket->Append(Auxiliary->GetVt());
socket->Append(Propagate->GetUVW(eU));
socket->Append(Propagate->GetUVW(eV));
socket->Append(Propagate->GetUVW(eW));
socket->Append(Auxiliary->GetAeroUVW(eU));
socket->Append(Auxiliary->GetAeroUVW(eV));
socket->Append(Auxiliary->GetAeroUVW(eW));
socket->Append(Propagate->GetVel(eNorth));
socket->Append(Propagate->GetVel(eEast));
socket->Append(Propagate->GetVel(eDown));
}
if (SubSystems & ssForces) {
socket->Append(Aerodynamics->GetvFs()(eDrag));
socket->Append(Aerodynamics->GetvFs()(eSide));
socket->Append(Aerodynamics->GetvFs()(eLift));
socket->Append(Aerodynamics->GetLoD());
socket->Append(Aircraft->GetForces(eX));
socket->Append(Aircraft->GetForces(eY));
socket->Append(Aircraft->GetForces(eZ));
}
if (SubSystems & ssMoments) {
socket->Append(Aircraft->GetMoments(eL));
socket->Append(Aircraft->GetMoments(eM));
socket->Append(Aircraft->GetMoments(eN));
}
if (SubSystems & ssAtmosphere) {
socket->Append(Atmosphere->GetDensity());
socket->Append(Atmosphere->GetPressureSL());
socket->Append(Atmosphere->GetPressure());
socket->Append(Atmosphere->GetWindNED().Dump(","));
}
if (SubSystems & ssMassProps) {
socket->Append(MassBalance->GetJ()(1,1));
socket->Append(MassBalance->GetJ()(1,2));
socket->Append(MassBalance->GetJ()(1,3));
socket->Append(MassBalance->GetJ()(2,1));
socket->Append(MassBalance->GetJ()(2,2));
socket->Append(MassBalance->GetJ()(2,3));
socket->Append(MassBalance->GetJ()(3,1));
socket->Append(MassBalance->GetJ()(3,2));
socket->Append(MassBalance->GetJ()(3,3));
socket->Append(MassBalance->GetMass());
socket->Append(MassBalance->GetXYZcg()(eX));
socket->Append(MassBalance->GetXYZcg()(eY));
socket->Append(MassBalance->GetXYZcg()(eZ));
}
if (SubSystems & ssPropagate) {
socket->Append(Propagate->Geth());
socket->Append(Propagate->GetEuler(ePhi));
socket->Append(Propagate->GetEuler(eTht));
socket->Append(Propagate->GetEuler(ePsi));
socket->Append(Auxiliary->Getalpha(inDegrees));
socket->Append(Auxiliary->Getbeta(inDegrees));
socket->Append(Propagate->GetLocation().GetLatitudeDeg());
socket->Append(Propagate->GetLocation().GetLongitudeDeg());
}
if (SubSystems & ssCoefficients) {
scratch = Aerodynamics->GetCoefficientValues(",");
if (scratch.length() != 0) socket->Append(scratch);
}
if (SubSystems & ssFCS) {
scratch = FCS->GetComponentValues(",");
if (scratch.length() != 0) socket->Append(scratch);
}
if (SubSystems & ssGroundReactions) {
socket->Append(GroundReactions->GetGroundReactionValues(","));
}
if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
socket->Append(Propulsion->GetPropulsionValues(","));
}
for (unsigned int i=0;i<OutputProperties.size();i++) {
socket->Append(OutputProperties[i]->getDoubleValue());
}
socket->Send();
}
@ -441,108 +567,81 @@ void FGOutput::SocketStatusOutput(string out_str)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGOutput::Load(FGConfigFile* AC_cfg)
bool FGOutput::Load(Element* element)
{
string token="", parameter="", separator="";
string type="", parameter="";
string name="", fname="";
int OutRate = 0;
FGConfigFile* Output_cfg;
string property;
unsigned int port;
FGXMLParse output_file_parser;
Element *document, *property_element;
ifstream* output_file = new ifstream();
# ifndef macintosh
separator = "/";
# else
separator = ";";
string separator = "/";
# ifdef macintosh
separator = ";";
# endif
name = AC_cfg->GetValue("NAME");
fname = AC_cfg->GetValue("FILE");
token = AC_cfg->GetValue("TYPE");
port = atoi(AC_cfg->GetValue("PORT").c_str());
Output->SetType(token);
if (token == "SOCKET") {
socket = new FGfdmSocket(name,port);
}
fname = element->GetAttributeValue("file");
if (!fname.empty()) {
outputInFileName = FDMExec->GetAircraftPath() + separator
output_file_name = FDMExec->GetAircraftPath() + separator
+ FDMExec->GetModelName() + separator + fname + ".xml";
Output_cfg = new FGConfigFile(outputInFileName);
if (!Output_cfg->IsOpen()) {
cerr << "Could not open file: " << outputInFileName << endl;
return false;
}
output_file->open(output_file_name.c_str());
readXML(*output_file, output_file_parser);
delete output_file;
document = output_file_parser.GetDocument();
} else {
Output_cfg = AC_cfg;
document = element;
}
Output->SetFilename(name);
while ((token = Output_cfg->GetValue()) != string("/OUTPUT")) {
*Output_cfg >> parameter;
if (parameter == "RATE_IN_HZ") {
*Output_cfg >> OutRate;
}
if (parameter == "SIMULATION") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssSimulation;
}
if (parameter == "AEROSURFACES") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssAerosurfaces;
}
if (parameter == "RATES") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssRates;
}
if (parameter == "VELOCITIES") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssVelocities;
}
if (parameter == "FORCES") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssForces;
}
if (parameter == "MOMENTS") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssMoments;
}
if (parameter == "ATMOSPHERE") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssAtmosphere;
}
if (parameter == "MASSPROPS") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssMassProps;
}
if (parameter == "POSITION") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssPropagate;
}
if (parameter == "COEFFICIENTS") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssCoefficients;
}
if (parameter == "GROUND_REACTIONS") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssGroundReactions;
}
if (parameter == "FCS") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssFCS;
}
if (parameter == "PROPULSION") {
*Output_cfg >> parameter;
if (parameter == "ON") SubSystems += ssPropulsion;
}
if (parameter == "PROPERTY") {
*Output_cfg >> property;
OutputProperties.push_back(PropertyManager->GetNode(property));
}
name = document->GetAttributeValue("name");
type = document->GetAttributeValue("type");
SetType(type);
if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) {
port = atoi(document->GetAttributeValue("port").c_str());
socket = new FGfdmSocket(name, port);
} else {
Filename = name;
}
if (!document->GetAttributeValue("rate").empty()) {
OutRate = (int)document->GetAttributeValueAsNumber("rate");
} else {
OutRate = 1;
}
if (parameter == "EOF") break;
if (document->FindElementValue("simulation") == string("ON"))
SubSystems += ssSimulation;
if (document->FindElementValue("aerosurfaces") == string("ON"))
SubSystems += ssAerosurfaces;
if (document->FindElementValue("rates") == string("ON"))
SubSystems += ssRates;
if (document->FindElementValue("velocities") == string("ON"))
SubSystems += ssVelocities;
if (document->FindElementValue("forces") == string("ON"))
SubSystems += ssForces;
if (document->FindElementValue("moments") == string("ON"))
SubSystems += ssMoments;
if (document->FindElementValue("atmosphere") == string("ON"))
SubSystems += ssAtmosphere;
if (document->FindElementValue("massprops") == string("ON"))
SubSystems += ssMassProps;
if (document->FindElementValue("position") == string("ON"))
SubSystems += ssPropagate;
if (document->FindElementValue("coefficients") == string("ON"))
SubSystems += ssCoefficients;
if (document->FindElementValue("ground_reactions") == string("ON"))
SubSystems += ssGroundReactions;
if (document->FindElementValue("fcs") == string("ON"))
SubSystems += ssFCS;
if (document->FindElementValue("propulsion") == string("ON"))
SubSystems += ssPropulsion;
property_element = document->FindElement("property");
while (property_element) {
string property = property_element->GetDataLine();
OutputProperties.push_back(PropertyManager->GetNode(property));
property_element = document->FindNextElement("property");
}
OutRate = OutRate>120?120:(OutRate<0?0:OutRate);
@ -583,10 +682,10 @@ void FGOutput::Debug(int from)
}
if (from == 2) {
if (outputInFileName.empty())
if (output_file_name.empty())
cout << " " << "Output parameters read inline" << endl;
else
cout << " Output parameters read from file: " << outputInFileName << endl;
cout << " Output parameters read from file: " << output_file_name << endl;
if (Filename == "cout" || Filename == "COUT") {
scratch = " Log output goes to screen console";

View file

@ -54,7 +54,8 @@ INCLUDES
# endif
#endif
#include "FGfdmSocket.h"
#include <input_output/FGfdmSocket.h>
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -133,13 +134,12 @@ public:
void DelimitedOutput(string);
void SocketOutput(void);
void SocketStatusOutput(string);
void SetFilename(string fn) {Filename = fn;}
void SetType(string);
void SetSubsystems(int tt) {SubSystems = tt;}
inline void Enable(void) { enabled = true; }
inline void Disable(void) { enabled = false; }
inline bool Toggle(void) {enabled = !enabled; return enabled;}
bool Load(FGConfigFile* AC_cfg);
bool Load(Element* el);
/// Subsystem types for specifying which will be output in the FDM data logging
enum eSubSystems {
@ -161,7 +161,7 @@ public:
private:
bool sFirstPass, dFirstPass, enabled;
int SubSystems;
string Filename, outputInFileName, delimeter;
string output_file_name, delimeter, Filename;
enum {otNone, otCSV, otTab, otSocket, otTerminal, otUnknown} Type;
ofstream datafile;
FGfdmSocket* socket;

View file

@ -53,10 +53,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef FGFS
# include <simgear/compiler.h>
# ifdef SG_HAVE_STD_INCLUDES
@ -81,12 +77,12 @@ INCLUDES
#endif
#include "FGPropagate.h"
#include "FGState.h"
#include "FGFDMExec.h"
#include <FGState.h>
#include <FGFDMExec.h>
#include "FGAircraft.h"
#include "FGMassBalance.h"
#include "FGInertial.h"
#include "FGPropertyManager.h"
#include <input_output/FGPropertyManager.h>
namespace JSBSim {
@ -157,7 +153,7 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
// Compute some derived values.
vVel = VState.vQtrn.GetTInv()*VState.vUVW;
// Finaly make shure that the quaternion stays normalized.
// Finally, make sure that the quaternion stays normalized.
VState.vQtrn.Normalize();
// Recompute the RunwayRadius level.
@ -183,6 +179,7 @@ state values for (now + dt).
bool FGPropagate::Run(void)
{
if (FGModel::Run()) return true; // Fast return if we have nothing to do ...
if (FDMExec->Holding()) return false;
RecomputeRunwayRadius();
@ -224,9 +221,11 @@ bool FGPropagate::Run(void)
FGColumnVector3 ace = 2.0*omega*ecVel;
vUVWdot -= Tl2b*(Tec2l*ace);
// Centrifugal acceleration.
FGColumnVector3 aeec = omega*(omega*VState.vLocation);
vUVWdot -= Tl2b*(Tec2l*aeec);
if (!GroundReactions->GetWOW()) {
// Centrifugal acceleration.
FGColumnVector3 aeec = omega*(omega*VState.vLocation);
vUVWdot -= Tl2b*(Tec2l*aeec);
}
// Gravitation accel
vUVWdot += Tl2b*gAccel;
@ -257,8 +256,6 @@ bool FGPropagate::Run(void)
void FGPropagate::RecomputeRunwayRadius(void)
{
// Get the runway radius.
// Boring: this does not belong here, but since Jon placed the RunwayRadius
// value here it is better done here than somewhere else.
FGLocation contactloc;
FGColumnVector3 dv;
FGGroundCallback* gcb = FDMExec->GetGroundCallback();

View file

@ -38,11 +38,11 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
#include "FGColumnVector3.h"
#include "FGInitialCondition.h"
#include "FGLocation.h"
#include "FGQuaternion.h"
#include <models/FGModel.h>
#include <math/FGColumnVector3.h>
#include <initialization/FGInitialCondition.h>
#include <math/FGLocation.h>
#include <math/FGQuaternion.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -142,7 +142,6 @@ public:
void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
void SetDistanceAGL(double tt);
void SetInitialState(const FGInitialCondition *);
void RecomputeRunwayRadius(void);
void bind(void);

View file

@ -44,16 +44,15 @@ HISTORY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGPropulsion.h"
#include "FGRocket.h"
#include "FGTurbine.h"
#include "FGPiston.h"
#include "FGElectric.h"
#include "FGPropertyManager.h"
#include <models/propulsion/FGRocket.h>
#include <models/propulsion/FGTurbine.h>
#include <models/propulsion/FGPiston.h>
#include <models/propulsion/FGElectric.h>
#include <models/propulsion/FGTurboProp.h>
#include <input_output/FGPropertyManager.h>
#include <input_output/FGXMLParse.h>
#include <math/FGColumnVector3.h>
#include <sstream>
namespace JSBSim {
@ -79,8 +78,13 @@ FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
tankJ.InitMatrix();
refuel = false;
fuel_freeze = false;
bind();
TotalFuelQuantity = 0.0;
IsBound =
HavePistonEngine =
HaveTurbineEngine =
HaveRocketEngine =
HaveTurboPropEngine =
HaveElectricEngine = false;
Debug(0);
}
@ -102,6 +106,7 @@ bool FGPropulsion::Run(void)
unsigned int i;
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
double dt = State->Getdt();
@ -114,12 +119,16 @@ bool FGPropulsion::Run(void)
vMoments += Engines[i]->GetMoments(); // sum body frame moments
}
TotalFuelQuantity = 0.0;
for (i=0; i<numTanks; i++) {
Tanks[i]->Calculate( dt * rate );
if (Tanks[i]->GetType() == FGTank::ttFUEL) {
TotalFuelQuantity += Tanks[i]->GetContents();
}
}
if (refuel) DoRefuel( dt * rate );
return false;
}
@ -187,139 +196,80 @@ bool FGPropulsion::ICEngineStart(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropulsion::Load(FGConfigFile* AC_cfg)
bool FGPropulsion::Load(Element* el)
{
string token, fullpath, localpath;
string engineFileName, engType;
string parameter;
string enginePath = FDMExec->GetEnginePath();
string aircraftPath = FDMExec->GetAircraftPath();
double xLoc, yLoc, zLoc, Pitch, Yaw;
string type, engine_filename;
int Feed;
bool ThrottleAdded = false;
FGConfigFile* Cfg_ptr = 0;
Element* document;
FGXMLParse engine_file_parser;
ifstream* engine_file;
# ifndef macintosh
fullpath = enginePath + "/";
localpath = aircraftPath + "/Engines/";
# else
fullpath = enginePath + ";";
localpath = aircraftPath + ";Engines;";
# endif
Debug(2);
AC_cfg->GetNextConfigLine();
Element* engine_element = el->FindElement("engine");
while (engine_element) {
engine_filename = engine_element->GetAttributeValue("file");
while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
if (token == "AC_ENGINE") { // ============ READING ENGINES
engineFileName = AC_cfg->GetValue("FILE");
// Look in the Aircraft/Engines directory first
Cfg_ptr = 0;
FGConfigFile Local_cfg(localpath + engineFileName + ".xml");
FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
if (Local_cfg.IsOpen()) {
Cfg_ptr = &Local_cfg;
if (debug_lvl > 0) cout << "\n Reading engine from file: " << localpath
+ engineFileName + ".xml"<< endl;
} else {
if (Eng_cfg.IsOpen()) {
Cfg_ptr = &Eng_cfg;
if (debug_lvl > 0) cout << "\n Reading engine from file: " << fullpath
+ engineFileName + ".xml"<< endl;
}
}
if (Cfg_ptr) {
Cfg_ptr->GetNextConfigLine();
engType = Cfg_ptr->GetValue();
FCS->AddThrottle();
ThrottleAdded = true;
if (engType == "FG_ROCKET") {
Engines.push_back(new FGRocket(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_PISTON") {
Engines.push_back(new FGPiston(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_TURBINE") {
Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_SIMTURBINE") {
cerr << endl;
cerr << "The FG_SIMTURBINE engine type has been renamed to FG_TURBINE." << endl;
cerr << "To fix this problem, simply replace the FG_SIMTURBINE name " << endl;
cerr << "in your engine file to FG_TURBINE." << endl;
cerr << endl;
Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_ELECTRIC") {
Engines.push_back(new FGElectric(FDMExec, Cfg_ptr, numEngines));
} else {
cerr << fgred << " Unrecognized engine type: " << underon << engType
<< underoff << " found in config file." << fgdef << endl;
return false;
}
Engines.back()->SetEngineFileName(engineFileName);
AC_cfg->GetNextConfigLine();
while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
*AC_cfg >> token;
if (token == "XLOC") { *AC_cfg >> xLoc; }
else if (token == "YLOC") { *AC_cfg >> yLoc; }
else if (token == "ZLOC") { *AC_cfg >> zLoc; }
else if (token == "PITCH") { *AC_cfg >> Pitch;}
else if (token == "YAW") { *AC_cfg >> Yaw; }
else if (token.find("AC_THRUSTER") != string::npos) {
if (debug_lvl > 0) cout << "\n Reading thruster definition" << endl;
Engines.back()->LoadThruster(AC_cfg);
AC_cfg->GetNextConfigLine();
}
else if (token == "FEED") {
*AC_cfg >> Feed;
Engines[numEngines]->AddFeedTank(Feed);
if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
} else cerr << "Unknown identifier: " << token << " in engine file: "
<< engineFileName << endl;
}
if (debug_lvl > 0) {
cout << " X = " << xLoc << endl;
cout << " Y = " << yLoc << endl;
cout << " Z = " << zLoc << endl;
cout << " Pitch = " << Pitch << endl;
cout << " Yaw = " << Yaw << endl;
}
Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
numEngines++;
} else {
cerr << fgred << "\n Could not read engine config file: " << underon <<
engineFileName + ".xml" << underoff << fgdef << endl;
return false;
}
} else if (token == "AC_TANK") { // ============== READING TANKS
if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
Tanks.push_back(new FGTank(AC_cfg, FDMExec));
switch(Tanks[numTanks]->GetType()) {
case FGTank::ttFUEL:
numSelectedFuelTanks++;
numFuelTanks++;
break;
case FGTank::ttOXIDIZER:
numSelectedOxiTanks++;
numOxiTanks++;
break;
}
numTanks++;
if (engine_filename.empty()) {
cerr << "Engine definition did not supply an engine file." << endl;
return false;
}
AC_cfg->GetNextConfigLine();
engine_filename = FindEngineFullPathname(engine_filename);
readXML(engine_filename, engine_file_parser);
document = engine_file_parser.GetDocument(); // document holds the engine description
document->SetParent(engine_element);
type = document->GetName();
if (type == "piston_engine") {
HavePistonEngine = true;
if (!IsBound) bind();
Engines.push_back(new FGPiston(FDMExec, document, numEngines));
} else if (type == "turbine_engine") {
HaveTurbineEngine = true;
if (!IsBound) bind();
Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
} else if (type == "turboprop_engine") {
HaveTurboPropEngine = true;
if (!IsBound) bind();
Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
} else if (type == "rocket_engine") {
HaveRocketEngine = true;
if (!IsBound) bind();
Engines.push_back(new FGRocket(FDMExec, document, numEngines));
} else if (type == "electric_engine") {
HaveElectricEngine = true;
if (!IsBound) bind();
Engines.push_back(new FGElectric(FDMExec, document, numEngines));
} else {
cerr << "Unknown engine type: " << type << endl;
exit(-5);
}
FCS->AddThrottle();
ThrottleAdded = true;
numEngines++;
engine_element = el->FindNextElement("engine");
engine_file_parser.reset();
}
// Process tank definitions
Element* tank_element = el->FindElement("tank");
while (tank_element) {
Tanks.push_back(new FGTank(FDMExec, tank_element));
if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
else {cerr << "Unknown tank type specified." << endl; return false;}
numTanks++;
tank_element = el->FindNextElement("tank");
}
numSelectedFuelTanks = numFuelTanks;
numSelectedOxiTanks = numOxiTanks;
CalculateTankInertias();
if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
@ -328,6 +278,65 @@ bool FGPropulsion::Load(FGConfigFile* AC_cfg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropulsion::FindEngineFullPathname(string engine_filename)
{
string fullpath, localpath;
string enginePath = FDMExec->GetEnginePath();
string aircraftPath = FDMExec->GetAircraftPath();
ifstream* engine_file = new ifstream();
string separator = "/";
# ifdef macintosh
separator = ";";
# endif
fullpath = enginePath + separator;
localpath = aircraftPath + separator + "Engines" + separator;
engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
if ( !engine_file->is_open()) {
engine_file->open(string(localpath + engine_filename + ".xml").c_str());
if ( !engine_file->is_open()) {
cerr << " Could not open engine file: " << engine_filename << " in path "
<< fullpath << " or " << localpath << endl;
return string("");
} else {
return string(localpath + engine_filename + ".xml");
}
}
return string(fullpath + engine_filename + ".xml");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ifstream* FGPropulsion::FindEngineFile(string engine_filename)
{
string fullpath, localpath;
string enginePath = FDMExec->GetEnginePath();
string aircraftPath = FDMExec->GetAircraftPath();
ifstream* engine_file = new ifstream();
string separator = "/";
# ifdef macintosh
separator = ";";
# endif
fullpath = enginePath + separator;
localpath = aircraftPath + separator + "Engines" + separator;
engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
if ( !engine_file->is_open()) {
engine_file->open(string(localpath + engine_filename + ".xml").c_str());
if ( !engine_file->is_open()) {
cerr << " Could not open engine file: " << engine_filename << " in path "
<< fullpath << " or " << localpath << endl;
}
}
return engine_file;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropulsion::GetPropulsionStrings(string delimeter)
{
unsigned int i;
@ -427,6 +436,9 @@ void FGPropulsion::SetMagnetos(int setting)
{
if (ActiveEngine < 0) {
for (unsigned i=0; i<Engines.size(); i++) {
// ToDo: first need to make sure the engine Type is really appropriate:
// do a check to see if it is of type Piston. This should be done for
// all of this kind of possibly across-the-board settings.
((FGPiston*)Engines[i])->SetMagnetos(setting);
}
} else {
@ -505,15 +517,17 @@ double FGPropulsion::Transfer(int source, int target, double amount)
void FGPropulsion::DoRefuel(double time_slice)
{
unsigned int i;
double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
int TanksNotFull = 0;
for (unsigned int i=0; i<numTanks; i++) {
for (i=0; i<numTanks; i++) {
if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
}
if (TanksNotFull) {
for (unsigned int i=0; i<numTanks; i++) {
for (i=0; i<numTanks; i++) {
if (Tanks[i]->GetPctFull() < 99.99)
Transfer(-1, i, fillrate/TanksNotFull);
}
@ -522,14 +536,14 @@ void FGPropulsion::DoRefuel(double time_slice)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropulsion::SetFuelFreeze(bool f)
void FGPropulsion::SetFuelFreeze(bool f)
{
fuel_freeze = f;
for (unsigned int i=0; i<numEngines; i++) {
Engines[i]->SetFuelFreeze(f);
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropulsion::bind(void)
@ -537,44 +551,37 @@ void FGPropulsion::bind(void)
typedef double (FGPropulsion::*PMF)(int) const;
typedef int (FGPropulsion::*iPMF)(void) const;
PropertyManager->Tie("propulsion/magneto_cmd", this,
(iPMF)0, &FGPropulsion::SetMagnetos, true);
PropertyManager->Tie("propulsion/starter_cmd", this,
(iPMF)0, &FGPropulsion::SetStarter, true);
PropertyManager->Tie("propulsion/cutoff_cmd", this,
(iPMF)0, &FGPropulsion::SetCutoff, true);
IsBound = true;
PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
(PMF)&FGPropulsion::GetForces);
PropertyManager->Tie("forces/fby-prop-lbs", this,2,
(PMF)&FGPropulsion::GetForces);
PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
(PMF)&FGPropulsion::GetForces);
PropertyManager->Tie("moments/l-prop-lbsft", this,1,
(PMF)&FGPropulsion::GetMoments);
PropertyManager->Tie("moments/m-prop-lbsft", this,2,
(PMF)&FGPropulsion::GetMoments);
PropertyManager->Tie("moments/n-prop-lbsft", this,3,
(PMF)&FGPropulsion::GetMoments);
if (HaveTurbineEngine) {
PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
}
PropertyManager->Tie("propulsion/active_engine", this,
(iPMF)&FGPropulsion::GetActiveEngine, &FGPropulsion::SetActiveEngine, true);
if (HavePistonEngine) {
PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
}
PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
&FGPropulsion::SetActiveEngine, true);
PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropulsion::unbind(void)
{
PropertyManager->Untie("propulsion/magneto_cmd");
PropertyManager->Untie("propulsion/starter_cmd");
PropertyManager->Untie("propulsion/cutoff_cmd");
if (HaveTurbineEngine) {
PropertyManager->Untie("propulsion/starter_cmd");
PropertyManager->Untie("propulsion/cutoff_cmd");
}
if (HavePistonEngine) {
PropertyManager->Untie("propulsion/starter_cmd");
PropertyManager->Untie("propulsion/magneto_cmd");
}
PropertyManager->Untie("propulsion/active_engine");
PropertyManager->Untie("forces/fbx-prop-lbs");
PropertyManager->Untie("forces/fby-prop-lbs");
PropertyManager->Untie("forces/fbz-prop-lbs");
PropertyManager->Untie("moments/l-prop-lbsft");
PropertyManager->Untie("moments/m-prop-lbsft");
PropertyManager->Untie("moments/n-prop-lbsft");
PropertyManager->Untie("propulsion/total-fuel-lbs");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -601,8 +608,8 @@ void FGPropulsion::Debug(int from)
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (from == 2) { // Loader
cout << endl << " Propulsion:" << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification

View file

@ -43,19 +43,23 @@ INCLUDES
# ifdef SG_HAVE_STD_INCLUDES
# include <vector>
# include <iterator>
# include <fstream>
# else
# include <vector.h>
# include <iterator.h>
# include <fstream.h>
# endif
#else
# include <vector>
# include <iterator>
# include <fstream>
#endif
#include "FGModel.h"
#include "FGEngine.h"
#include "FGTank.h"
#include "FGMatrix33.h"
#include <models/propulsion/FGEngine.h>
#include <models/propulsion/FGTank.h>
#include <math/FGMatrix33.h>
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -110,10 +114,9 @@ public:
/** Loads the propulsion system (engine[s] and tank[s]).
Characteristics of the propulsion system are read in from the config file.
@param AC_cfg pointer to the config file instance that describes the
aircraft being modeled.
@param el pointer to an XML element that contains the engine information.
@return true if successfully loaded, otherwise false */
bool Load(FGConfigFile* AC_cfg);
bool Load(Element* el);
/// Retrieves the number of engines defined for the aircraft.
inline unsigned int GetNumEngines(void) const {return Engines.size();}
@ -159,26 +162,24 @@ public:
inline double GetMoments(int n) const {return vMoments(n);}
inline bool GetRefuel(void) {return refuel;}
inline void SetRefuel(bool setting) {refuel = setting;}
inline void SetRefuel(bool setting) {refuel = setting;}
double Transfer(int source, int target, double amount);
void DoRefuel(double time_slice);
FGColumnVector3& GetTanksMoment(void);
double GetTanksWeight(void);
inline int GetActiveEngine(void) const
{
return ActiveEngine;
}
inline int GetActiveEngine(void);
ifstream* FindEngineFile(string filename);
string FindEngineFullPathname(string engine_filename);
inline int GetActiveEngine(void) const {return ActiveEngine;}
inline bool GetFuelFreeze(void) {return fuel_freeze;}
double GetTotalFuelQuantity(void) const {return TotalFuelQuantity;}
void SetMagnetos(int setting);
void SetStarter(int setting);
void SetCutoff(int setting=0);
void SetActiveEngine(int engine);
void SetFuelFreeze(bool f);
void SetFuelFreeze(bool f);
FGMatrix33& CalculateTankInertias(void);
void bind();
@ -202,6 +203,13 @@ private:
FGMatrix33 tankJ;
bool refuel;
bool fuel_freeze;
double TotalFuelQuantity;
bool IsBound;
bool HavePistonEngine;
bool HaveTurbineEngine;
bool HaveTurboPropEngine;
bool HaveRocketEngine;
bool HaveElectricEngine;
void Debug(int from);
};

View file

@ -0,0 +1,14 @@
SUBDIRS = atmosphere propulsion flight_control
noinst_LIBRARIES = libModels.a
libModels_a_SOURCES = FGAerodynamics.cpp FGAircraft.cpp FGAtmosphere.cpp \
FGAuxiliary.cpp FGFCS.cpp FGGroundReactions.cpp FGInertial.cpp \
FGLGear.cpp FGMassBalance.cpp FGModel.cpp FGOutput.cpp \
FGPropagate.cpp FGPropulsion.cpp FGInput.cpp
noinst_HEADERS = FGAerodynamics.h FGAircraft.h FGAtmosphere.h FGAuxiliary.h \
FGFCS.h FGGroundReactions.h FGInertial.h FGLGear.h FGMassBalance.h \
FGModel.h FGOutput.h FGPropagate.h FGPropulsion.h FGInput.h
INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,209 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGMSIS.h
Description: MSIS-00 Atmosphere
Author: David Culp
Date started: 12/14/03
------------- Copyright (C) 2003 David P. Culp (davidculp2@comcast.net) ------
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.
HISTORY
--------------------------------------------------------------------------------
12/14/03 DPC Created
01/11/04 DPC Derive from FGAtmosphere
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGMSIS_H
#define FGMSIS_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <models/FGAtmosphere.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MSIS "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models the MSIS-00 atmosphere.
This is a wrapper for the NRL-MSIS-00 model 2001:
This C++ format model wraps the NRLMSISE-00 C source code package - release
20020503
The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and
Doug Drob. They also wrote a NRLMSISE-00 distribution package in
FORTRAN which is available at
http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm
Dominik Brodowski implemented and maintains this C version. You can
reach him at devel@brodo.de. See the file "DOCUMENTATION" for details,
and check http://www.brodo.de/english/pub/nrlmsise/index.html for
updated releases of this package.
@author David Culp
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
STRUCT DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
struct nrlmsise_flags {
int switches[24];
double sw[24];
double swc[24];
};
struct ap_array {
double a[7];
};
struct nrlmsise_input {
int year; /* year, currently ignored */
int doy; /* day of year */
double sec; /* seconds in day (UT) */
double alt; /* altitude in kilometers */
double g_lat; /* geodetic latitude */
double g_long; /* geodetic longitude */
double lst; /* local apparent solar time (hours), see note below */
double f107A; /* 81 day average of F10.7 flux (centered on DOY) */
double f107; /* daily F10.7 flux for previous day */
double ap; /* magnetic index(daily) */
struct ap_array *ap_a; /* see above */
};
struct nrlmsise_output {
double d[9]; /* densities */
double t[2]; /* temperatures */
};
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class MSIS : public FGAtmosphere
{
public:
/// Constructor
MSIS(FGFDMExec*);
/// Destructor
~MSIS();
/** Runs the MSIS-00 atmosphere model; called by the Executive
@return false if no error */
bool Run(void);
bool InitModel(void);
/// Does nothing. External control is not allowed.
void UseExternal(void);
private:
void Calculate(int day, // day of year (1 to 366)
double sec, // seconds in day (0.0 to 86400.0)
double alt, // altitude, feet
double lat, // geodetic latitude, degrees
double lon // geodetic longitude, degrees
);
void Debug(int from);
nrlmsise_flags flags;
nrlmsise_input input;
nrlmsise_output output;
ap_array aph;
/* PARMB */
double gsurf;
double re;
/* GTS3C */
double dd;
/* DMIX */
double dm04, dm16, dm28, dm32, dm40, dm01, dm14;
/* MESO7 */
double meso_tn1[5];
double meso_tn2[4];
double meso_tn3[3];
double meso_tgn1[2];
double meso_tgn2[2];
double meso_tgn3[2];
/* LPOLY */
double dfa;
double plg[4][9];
double ctloc, stloc;
double c2tloc, s2tloc;
double s3tloc, c3tloc;
double apdf, apt[4];
void tselec(struct nrlmsise_flags *flags);
void glatf(double lat, double *gv, double *reff);
double ccor(double alt, double r, double h1, double zh);
double ccor2(double alt, double r, double h1, double zh, double h2);
double scalh(double alt, double xm, double temp);
double dnet(double dd, double dm, double zhm, double xmm, double xm);
void splini(double *xa, double *ya, double *y2a, int n, double x, double *y);
void splint(double *xa, double *ya, double *y2a, int n, double x, double *y);
void spline(double *x, double *y, int n, double yp1, double ypn, double *y2);
double zeta(double zz, double zl);
double densm(double alt, double d0, double xm, double *tz, int mn3, double *zn3,
double *tn3, double *tgn3, int mn2, double *zn2, double *tn2,
double *tgn2);
double densu(double alt, double dlb, double tinf, double tlb, double xm,
double alpha, double *tz, double zlb, double s2, int mn1,
double *zn1, double *tn1, double *tgn1);
double g0(double a, double *p);
double sumex(double ex);
double sg0(double ex, double *p, double *ap);
double globe7(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
double glob7s(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
void gtd7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
void gtd7d(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
void ghp7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output, double press);
void gts7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,747 @@
// MSIS-00 Data
// Adapted for use in JSBSim
// David Culp, davidculp2@comcast.net
/* -------------------------------------------------------------------- */
/* --------- N R L M S I S E - 0 0 M O D E L 2 0 0 1 ---------- */
/* -------------------------------------------------------------------- */
/* This file is part of the NRLMSISE-00 C source code package - release
* 20020503
*
* The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and
* Doug Drob. They also wrote a NRLMSISE-00 distribution package in
* FORTRAN which is available at
* http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm
*
* Dominik Brodowski implemented and maintains this C version. You can
* reach him at devel@brodo.de. See the file "DOCUMENTATION" for details,
* and check http://www.brodo.de/english/pub/nrlmsise/index.html for
* updated releases of this package.
*/
/* ------------------------------------------------------------------- */
/* ------------------------ BLOCK DATA GTD7BK ------------------------ */
/* ------------------------------------------------------------------- */
namespace JSBSim {
/* TEMPERATURE */
double pt[150] = {
9.86573E-01, 1.62228E-02, 1.55270E-02,-1.04323E-01,-3.75801E-03,
-1.18538E-03,-1.24043E-01, 4.56820E-03, 8.76018E-03,-1.36235E-01,
-3.52427E-02, 8.84181E-03,-5.92127E-03,-8.61650E+00, 0.00000E+00,
1.28492E-02, 0.00000E+00, 1.30096E+02, 1.04567E-02, 1.65686E-03,
-5.53887E-06, 2.97810E-03, 0.00000E+00, 5.13122E-03, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.27026E-06,
0.00000E+00, 6.74494E+00, 4.93933E-03, 2.21656E-03, 2.50802E-03,
0.00000E+00, 0.00000E+00,-2.08841E-02,-1.79873E+00, 1.45103E-03,
2.81769E-04,-1.44703E-03,-5.16394E-05, 8.47001E-02, 1.70147E-01,
5.72562E-03, 5.07493E-05, 4.36148E-03, 1.17863E-04, 4.74364E-03,
6.61278E-03, 4.34292E-05, 1.44373E-03, 2.41470E-05, 2.84426E-03,
8.56560E-04, 2.04028E-03, 0.00000E+00,-3.15994E+03,-2.46423E-03,
1.13843E-03, 4.20512E-04, 0.00000E+00,-9.77214E+01, 6.77794E-03,
5.27499E-03, 1.14936E-03, 0.00000E+00,-6.61311E-03,-1.84255E-02,
-1.96259E-02, 2.98618E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
6.44574E+02, 8.84668E-04, 5.05066E-04, 0.00000E+00, 4.02881E+03,
-1.89503E-03, 0.00000E+00, 0.00000E+00, 8.21407E-04, 2.06780E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-1.20410E-02,-3.63963E-03, 9.92070E-05,-1.15284E-04,-6.33059E-05,
-6.05545E-01, 8.34218E-03,-9.13036E+01, 3.71042E-04, 0.00000E+00,
4.19000E-04, 2.70928E-03, 3.31507E-03,-4.44508E-03,-4.96334E-03,
-1.60449E-03, 3.95119E-03, 2.48924E-03, 5.09815E-04, 4.05302E-03,
2.24076E-03, 0.00000E+00, 6.84256E-03, 4.66354E-04, 0.00000E+00,
-3.68328E-04, 0.00000E+00, 0.00000E+00,-1.46870E+02, 0.00000E+00,
0.00000E+00, 1.09501E-03, 4.65156E-04, 5.62583E-04, 3.21596E+00,
6.43168E-04, 3.14860E-03, 3.40738E-03, 1.78481E-03, 9.62532E-04,
5.58171E-04, 3.43731E+00,-2.33195E-01, 5.10289E-04, 0.00000E+00,
0.00000E+00,-9.25347E+04, 0.00000E+00,-1.99639E-03, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
};
double pd[9][150] = {
/* HE DENSITY */ {
1.09979E+00,-4.88060E-02,-1.97501E-01,-9.10280E-02,-6.96558E-03,
2.42136E-02, 3.91333E-01,-7.20068E-03,-3.22718E-02, 1.41508E+00,
1.68194E-01, 1.85282E-02, 1.09384E-01,-7.24282E+00, 0.00000E+00,
2.96377E-01,-4.97210E-02, 1.04114E+02,-8.61108E-02,-7.29177E-04,
1.48998E-06, 1.08629E-03, 0.00000E+00, 0.00000E+00, 8.31090E-02,
1.12818E-01,-5.75005E-02,-1.29919E-02,-1.78849E-02,-2.86343E-06,
0.00000E+00,-1.51187E+02,-6.65902E-03, 0.00000E+00,-2.02069E-03,
0.00000E+00, 0.00000E+00, 4.32264E-02,-2.80444E+01,-3.26789E-03,
2.47461E-03, 0.00000E+00, 0.00000E+00, 9.82100E-02, 1.22714E-01,
-3.96450E-02, 0.00000E+00,-2.76489E-03, 0.00000E+00, 1.87723E-03,
-8.09813E-03, 4.34428E-05,-7.70932E-03, 0.00000E+00,-2.28894E-03,
-5.69070E-03,-5.22193E-03, 6.00692E-03,-7.80434E+03,-3.48336E-03,
-6.38362E-03,-1.82190E-03, 0.00000E+00,-7.58976E+01,-2.17875E-02,
-1.72524E-02,-9.06287E-03, 0.00000E+00, 2.44725E-02, 8.66040E-02,
1.05712E-01, 3.02543E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-6.01364E+03,-5.64668E-03,-2.54157E-03, 0.00000E+00, 3.15611E+02,
-5.69158E-03, 0.00000E+00, 0.00000E+00,-4.47216E-03,-4.49523E-03,
4.64428E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
4.51236E-02, 2.46520E-02, 6.17794E-03, 0.00000E+00, 0.00000E+00,
-3.62944E-01,-4.80022E-02,-7.57230E+01,-1.99656E-03, 0.00000E+00,
-5.18780E-03,-1.73990E-02,-9.03485E-03, 7.48465E-03, 1.53267E-02,
1.06296E-02, 1.18655E-02, 2.55569E-03, 1.69020E-03, 3.51936E-02,
-1.81242E-02, 0.00000E+00,-1.00529E-01,-5.10574E-03, 0.00000E+00,
2.10228E-03, 0.00000E+00, 0.00000E+00,-1.73255E+02, 5.07833E-01,
-2.41408E-01, 8.75414E-03, 2.77527E-03,-8.90353E-05,-5.25148E+00,
-5.83899E-03,-2.09122E-02,-9.63530E-03, 9.77164E-03, 4.07051E-03,
2.53555E-04,-5.52875E+00,-3.55993E-01,-2.49231E-03, 0.00000E+00,
0.00000E+00, 2.86026E+01, 0.00000E+00, 3.42722E-04, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* O DENSITY */ {
1.02315E+00,-1.59710E-01,-1.06630E-01,-1.77074E-02,-4.42726E-03,
3.44803E-02, 4.45613E-02,-3.33751E-02,-5.73598E-02, 3.50360E-01,
6.33053E-02, 2.16221E-02, 5.42577E-02,-5.74193E+00, 0.00000E+00,
1.90891E-01,-1.39194E-02, 1.01102E+02, 8.16363E-02, 1.33717E-04,
6.54403E-06, 3.10295E-03, 0.00000E+00, 0.00000E+00, 5.38205E-02,
1.23910E-01,-1.39831E-02, 0.00000E+00, 0.00000E+00,-3.95915E-06,
0.00000E+00,-7.14651E-01,-5.01027E-03, 0.00000E+00,-3.24756E-03,
0.00000E+00, 0.00000E+00, 4.42173E-02,-1.31598E+01,-3.15626E-03,
1.24574E-03,-1.47626E-03,-1.55461E-03, 6.40682E-02, 1.34898E-01,
-2.42415E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.13666E-04,
-5.40373E-03, 2.61635E-05,-3.33012E-03, 0.00000E+00,-3.08101E-03,
-2.42679E-03,-3.36086E-03, 0.00000E+00,-1.18979E+03,-5.04738E-02,
-2.61547E-03,-1.03132E-03, 1.91583E-04,-8.38132E+01,-1.40517E-02,
-1.14167E-02,-4.08012E-03, 1.73522E-04,-1.39644E-02,-6.64128E-02,
-6.85152E-02,-1.34414E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
6.07916E+02,-4.12220E-03,-2.20996E-03, 0.00000E+00, 1.70277E+03,
-4.63015E-03, 0.00000E+00, 0.00000E+00,-2.25360E-03,-2.96204E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
3.92786E-02, 1.31186E-02,-1.78086E-03, 0.00000E+00, 0.00000E+00,
-3.90083E-01,-2.84741E-02,-7.78400E+01,-1.02601E-03, 0.00000E+00,
-7.26485E-04,-5.42181E-03,-5.59305E-03, 1.22825E-02, 1.23868E-02,
6.68835E-03,-1.03303E-02,-9.51903E-03, 2.70021E-04,-2.57084E-02,
-1.32430E-02, 0.00000E+00,-3.81000E-02,-3.16810E-03, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-9.05762E-04,-2.14590E-03,-1.17824E-03, 3.66732E+00,
-3.79729E-04,-6.13966E-03,-5.09082E-03,-1.96332E-03,-3.08280E-03,
-9.75222E-04, 4.03315E+00,-2.52710E-01, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* N2 DENSITY */ {
1.16112E+00, 0.00000E+00, 0.00000E+00, 3.33725E-02, 0.00000E+00,
3.48637E-02,-5.44368E-03, 0.00000E+00,-6.73940E-02, 1.74754E-01,
0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00,
1.26733E-01, 0.00000E+00, 1.03154E+02, 5.52075E-02, 0.00000E+00,
0.00000E+00, 8.13525E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-2.50482E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.48894E-03,
6.16053E-04,-5.79716E-04, 2.95482E-03, 8.47001E-02, 1.70147E-01,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* TLB */ {
9.44846E-01, 0.00000E+00, 0.00000E+00,-3.08617E-02, 0.00000E+00,
-2.44019E-02, 6.48607E-03, 0.00000E+00, 3.08181E-02, 4.59392E-02,
0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00,
2.13260E-02, 0.00000E+00,-3.56958E+02, 0.00000E+00, 1.82278E-04,
0.00000E+00, 3.07472E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 3.83054E-03, 0.00000E+00, 0.00000E+00,
-1.93065E-03,-1.45090E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-1.23493E-03, 1.36736E-03, 8.47001E-02, 1.70147E-01,
3.71469E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
5.10250E-03, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 3.68756E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* O2 DENSITY */ {
1.35580E+00, 1.44816E-01, 0.00000E+00, 6.07767E-02, 0.00000E+00,
2.94777E-02, 7.46900E-02, 0.00000E+00,-9.23822E-02, 8.57342E-02,
0.00000E+00, 0.00000E+00, 0.00000E+00, 2.38636E+01, 0.00000E+00,
7.71653E-02, 0.00000E+00, 8.18751E+01, 1.87736E-02, 0.00000E+00,
0.00000E+00, 1.49667E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-3.67874E+02, 5.48158E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
1.22631E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
8.17187E-03, 3.71617E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.10826E-03,
-3.13640E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-7.35742E-02,-5.00266E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 1.94965E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* AR DENSITY */ {
1.04761E+00, 2.00165E-01, 2.37697E-01, 3.68552E-02, 0.00000E+00,
3.57202E-02,-2.14075E-01, 0.00000E+00,-1.08018E-01,-3.73981E-01,
0.00000E+00, 3.10022E-02,-1.16305E-03,-2.07596E+01, 0.00000E+00,
8.64502E-02, 0.00000E+00, 9.74908E+01, 5.16707E-02, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 3.46193E+02, 1.34297E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.48509E-03,
-1.54689E-04, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
1.47753E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
1.89320E-02, 3.68181E-05, 1.32570E-02, 0.00000E+00, 0.00000E+00,
3.59719E-03, 7.44328E-03,-1.00023E-03,-6.50528E+03, 0.00000E+00,
1.03485E-02,-1.00983E-03,-4.06916E-03,-6.60864E+01,-1.71533E-02,
1.10605E-02, 1.20300E-02,-5.20034E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-2.62769E+03, 7.13755E-03, 4.17999E-03, 0.00000E+00, 1.25910E+04,
0.00000E+00, 0.00000E+00, 0.00000E+00,-2.23595E-03, 4.60217E-03,
5.71794E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-3.18353E-02,-2.35526E-02,-1.36189E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.03522E-02,-6.67837E+01,-1.09724E-03, 0.00000E+00,
-1.38821E-02, 1.60468E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.51574E-02,
-5.44470E-04, 0.00000E+00, 7.28224E-02, 6.59413E-02, 0.00000E+00,
-5.15692E-03, 0.00000E+00, 0.00000E+00,-3.70367E+03, 0.00000E+00,
0.00000E+00, 1.36131E-02, 5.38153E-03, 0.00000E+00, 4.76285E+00,
-1.75677E-02, 2.26301E-02, 0.00000E+00, 1.76631E-02, 4.77162E-03,
0.00000E+00, 5.39354E+00, 0.00000E+00,-7.51710E-03, 0.00000E+00,
0.00000E+00,-8.82736E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* H DENSITY */ {
1.26376E+00,-2.14304E-01,-1.49984E-01, 2.30404E-01, 2.98237E-02,
2.68673E-02, 2.96228E-01, 2.21900E-02,-2.07655E-02, 4.52506E-01,
1.20105E-01, 3.24420E-02, 4.24816E-02,-9.14313E+00, 0.00000E+00,
2.47178E-02,-2.88229E-02, 8.12805E+01, 5.10380E-02,-5.80611E-03,
2.51236E-05,-1.24083E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02,
1.58727E-01,-3.48190E-02, 0.00000E+00, 0.00000E+00, 2.89885E-05,
0.00000E+00, 1.53595E+02,-1.68604E-02, 0.00000E+00, 1.01015E-02,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.84552E-04,
-1.22181E-03, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
-1.04927E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.91313E-03,
-2.30501E-02, 3.14758E-05, 0.00000E+00, 0.00000E+00, 1.26956E-02,
8.35489E-03, 3.10513E-04, 0.00000E+00, 3.42119E+03,-2.45017E-03,
-4.27154E-04, 5.45152E-04, 1.89896E-03, 2.89121E+01,-6.49973E-03,
-1.93855E-02,-1.48492E-02, 0.00000E+00,-5.10576E-02, 7.87306E-02,
9.51981E-02,-1.49422E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
2.65503E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 6.37110E-03, 3.24789E-04,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
6.14274E-02, 1.00376E-02,-8.41083E-04, 0.00000E+00, 0.00000E+00,
0.00000E+00,-1.27099E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-3.94077E-03,-1.28601E-02,-7.97616E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-6.71465E-03,-1.69799E-03, 1.93772E-03, 3.81140E+00,
-7.79290E-03,-1.82589E-02,-1.25860E-02,-1.04311E-02,-3.02465E-03,
2.43063E-03, 3.63237E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* N DENSITY */ {
7.09557E+01,-3.26740E-01, 0.00000E+00,-5.16829E-01,-1.71664E-03,
9.09310E-02,-6.71500E-01,-1.47771E-01,-9.27471E-02,-2.30862E-01,
-1.56410E-01, 1.34455E-02,-1.19717E-01, 2.52151E+00, 0.00000E+00,
-2.41582E-01, 5.92939E-02, 4.39756E+00, 9.15280E-02, 4.41292E-03,
0.00000E+00, 8.66807E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02,
1.58727E-01, 9.74701E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 6.70217E+01,-1.31660E-03, 0.00000E+00,-1.65317E-02,
0.00000E+00, 0.00000E+00, 8.50247E-02, 2.77428E+01, 4.98658E-03,
6.15115E-03, 9.50156E-03,-2.12723E-02, 8.47001E-02, 1.70147E-01,
-2.38645E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.37380E-03,
-8.41918E-03, 2.80145E-05, 7.12383E-03, 0.00000E+00,-1.66209E-02,
1.03533E-04,-1.68898E-02, 0.00000E+00, 3.64526E+03, 0.00000E+00,
6.54077E-03, 3.69130E-04, 9.94419E-04, 8.42803E+01,-1.16124E-02,
-7.74414E-03,-1.68844E-03, 1.42809E-03,-1.92955E-03, 1.17225E-01,
-2.41512E-02, 1.50521E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
1.60261E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00,-3.54403E-04,-1.87270E-02,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
2.76439E-02, 6.43207E-03,-3.54300E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00,-2.80221E-02, 8.11228E+01,-6.75255E-04, 0.00000E+00,
-1.05162E-02,-3.48292E-03,-6.97321E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-1.45546E-03,-1.31970E-02,-3.57751E-03,-1.09021E+00,
-1.50181E-02,-7.12841E-03,-6.64590E-03,-3.52610E-03,-1.87773E-02,
-2.22432E-03,-3.93895E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}, /* HOT O DENSITY */ {
6.04050E-02, 1.57034E+00, 2.99387E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.51018E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00,-8.61650E+00, 1.26454E-02,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 5.50878E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 6.23881E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
-9.45934E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
}};
/* S PARAM */
double ps[150] = {
9.56827E-01, 6.20637E-02, 3.18433E-02, 0.00000E+00, 0.00000E+00,
3.94900E-02, 0.00000E+00, 0.00000E+00,-9.24882E-03,-7.94023E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.74677E-03, 0.00000E+00, 1.54951E-02, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00,-6.99007E-04, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 1.24362E-02,-5.28756E-03, 8.47001E-02, 1.70147E-01,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
};
/* TURBO */
double pdl[2][25] = {
{ 1.09930E+00, 3.90631E+00, 3.07165E+00, 9.86161E-01, 1.63536E+01,
4.63830E+00, 1.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 1.28840E+00, 3.10302E-02, 1.18339E-01 },
{ 1.00000E+00, 7.00000E-01, 1.15020E+00, 3.44689E+00, 1.28840E+00,
1.00000E+00, 1.08738E+00, 1.22947E+00, 1.10016E+00, 7.34129E-01,
1.15241E+00, 2.22784E+00, 7.95046E-01, 4.01612E+00, 4.47749E+00,
1.23435E+02,-7.60535E-02, 1.68986E-06, 7.44294E-01, 1.03604E+00,
1.72783E+02, 1.15020E+00, 3.44689E+00,-7.46230E-01, 9.49154E-01 }
};
/* LOWER BOUNDARY */
double ptm[50] = {
1.04130E+03, 3.86000E+02, 1.95000E+02, 1.66728E+01, 2.13000E+02,
1.20000E+02, 2.40000E+02, 1.87000E+02,-2.00000E+00, 0.00000E+00
};
double pdm[8][10] = {
{ 2.45600E+07, 6.71072E-06, 1.00000E+02, 0.00000E+00, 1.10000E+02,
1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },\
{ 8.59400E+10, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02,
1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 },\
{ 2.81000E+11, 0.00000E+00, 1.05000E+02, 2.80000E+01, 2.89500E+01,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },
{ 3.30000E+10, 2.68270E-01, 1.05000E+02, 1.00000E+00, 1.10000E+02,
1.00000E+01, 1.10000E+02,-1.00000E+01, 0.00000E+00, 0.00000E+00 },
{ 1.33000E+09, 1.19615E-02, 1.05000E+02, 0.00000E+00, 1.10000E+02,
1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },
{ 1.76100E+05, 1.00000E+00, 9.50000E+01,-8.00000E+00, 1.10000E+02,
1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00, },
{ 1.00000E+07, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02,
1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 },
{ 1.00000E+06, 1.00000E+00, 1.05000E+02,-8.00000E+00, 5.50000E+02,
7.60000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 4.00000E+03 }};
double ptl[4][100] = {
/* TN1(2) */ {
1.00858E+00, 4.56011E-02,-2.22972E-02,-5.44388E-02, 5.23136E-04,
-1.88849E-02, 5.23707E-02,-9.43646E-03, 6.31707E-03,-7.80460E-02,
-4.88430E-02, 0.00000E+00, 0.00000E+00,-7.60250E+00, 0.00000E+00,
-1.44635E-02,-1.76843E-02,-1.21517E+02, 2.85647E-02, 0.00000E+00,
0.00000E+00, 6.31792E-04, 0.00000E+00, 5.77197E-03, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-8.90272E+03, 3.30611E-03, 3.02172E-03, 0.00000E+00,
-2.13673E-03,-3.20910E-04, 0.00000E+00, 0.00000E+00, 2.76034E-03,
2.82487E-03,-2.97592E-04,-4.21534E-03, 8.47001E-02, 1.70147E-01,
8.96456E-03, 0.00000E+00,-1.08596E-02, 0.00000E+00, 0.00000E+00,
5.57917E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 9.65405E-03, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN1(3) */ {
9.39664E-01, 8.56514E-02,-6.79989E-03, 2.65929E-02,-4.74283E-03,
1.21855E-02,-2.14905E-02, 6.49651E-03,-2.05477E-02,-4.24952E-02,
0.00000E+00, 0.00000E+00, 0.00000E+00, 1.19148E+01, 0.00000E+00,
1.18777E-02,-7.28230E-02,-8.15965E+01, 1.73887E-02, 0.00000E+00,
0.00000E+00, 0.00000E+00,-1.44691E-02, 2.80259E-04, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.16584E+02, 3.18713E-03, 7.37479E-03, 0.00000E+00,
-2.55018E-03,-3.92806E-03, 0.00000E+00, 0.00000E+00,-2.89757E-03,
-1.33549E-03, 1.02661E-03, 3.53775E-04, 8.47001E-02, 1.70147E-01,
-9.17497E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
3.56082E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-1.00902E-02, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN1(4) */ {
9.85982E-01,-4.55435E-02, 1.21106E-02, 2.04127E-02,-2.40836E-03,
1.11383E-02,-4.51926E-02, 1.35074E-02,-6.54139E-03, 1.15275E-01,
1.28247E-01, 0.00000E+00, 0.00000E+00,-5.30705E+00, 0.00000E+00,
-3.79332E-02,-6.24741E-02, 7.71062E-01, 2.96315E-02, 0.00000E+00,
0.00000E+00, 0.00000E+00, 6.81051E-03,-4.34767E-03, 8.66784E-02,
1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 1.07003E+01,-2.76907E-03, 4.32474E-04, 0.00000E+00,
1.31497E-03,-6.47517E-04, 0.00000E+00,-2.20621E+01,-1.10804E-03,
-8.09338E-04, 4.18184E-04, 4.29650E-03, 8.47001E-02, 1.70147E-01,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-4.04337E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-9.52550E-04,
8.56253E-04, 4.33114E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.21223E-03,
2.38694E-04, 9.15245E-04, 1.28385E-03, 8.67668E-04,-5.61425E-06,
1.04445E+00, 3.41112E+01, 0.00000E+00,-8.40704E-01,-2.39639E+02,
7.06668E-01,-2.05873E+01,-3.63696E-01, 2.39245E+01, 0.00000E+00,
-1.06657E-03,-7.67292E-04, 1.54534E-04, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN1(5) TN2(1) */ {
1.00320E+00, 3.83501E-02,-2.38983E-03, 2.83950E-03, 4.20956E-03,
5.86619E-04, 2.19054E-02,-1.00946E-02,-3.50259E-03, 4.17392E-02,
-8.44404E-03, 0.00000E+00, 0.00000E+00, 4.96949E+00, 0.00000E+00,
-7.06478E-03,-1.46494E-02, 3.13258E+01,-1.86493E-03, 0.00000E+00,
-1.67499E-02, 0.00000E+00, 0.00000E+00, 5.12686E-04, 8.66784E-02,
1.58727E-01,-4.64167E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
4.37353E-03,-1.99069E+02, 0.00000E+00,-5.34884E-03, 0.00000E+00,
1.62458E-03, 2.93016E-03, 2.67926E-03, 5.90449E+02, 0.00000E+00,
0.00000E+00,-1.17266E-03,-3.58890E-04, 8.47001E-02, 1.70147E-01,
0.00000E+00, 0.00000E+00, 1.38673E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.60571E-03,
6.28078E-04, 5.05469E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.57829E-03,
-4.00855E-04, 5.04077E-05,-1.39001E-03,-2.33406E-03,-4.81197E-04,
1.46758E+00, 6.20332E+00, 0.00000E+00, 3.66476E-01,-6.19760E+01,
3.09198E-01,-1.98999E+01, 0.00000E+00,-3.29933E+02, 0.00000E+00,
-1.10080E-03,-9.39310E-05, 1.39638E-04, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
} };
double pma[10][100] = {
/* TN2(2) */ {
9.81637E-01,-1.41317E-03, 3.87323E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.58707E-02,
-8.63658E-03, 0.00000E+00, 0.00000E+00,-2.02226E+00, 0.00000E+00,
-8.69424E-03,-1.91397E-02, 8.76779E+01, 4.52188E-03, 0.00000E+00,
2.23760E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-7.07572E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
-4.11210E-03, 3.50060E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00,-8.36657E-03, 1.61347E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00,-1.45130E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.24152E-03,
6.43365E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.33255E-03,
2.42657E-03, 1.60666E-03,-1.85728E-03,-1.46874E-03,-4.79163E-06,
1.22464E+00, 3.53510E+01, 0.00000E+00, 4.49223E-01,-4.77466E+01,
4.70681E-01, 8.41861E+00,-2.88198E-01, 1.67854E+02, 0.00000E+00,
7.11493E-04, 6.05601E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN2(3) */ {
1.00422E+00,-7.11212E-03, 5.24480E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.28914E-02,
-2.41301E-02, 0.00000E+00, 0.00000E+00,-2.12219E+01,-1.03830E-02,
-3.28077E-03, 1.65727E-02, 1.68564E+00,-6.68154E-03, 0.00000E+00,
1.45155E-02, 0.00000E+00, 8.42365E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00,-4.34645E-03, 0.00000E+00, 0.00000E+00, 2.16780E-02,
0.00000E+00,-1.38459E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 7.04573E-03,-4.73204E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 1.08767E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.08279E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.21769E-04,
-2.27387E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.26769E-03,
3.16901E-03, 4.60316E-04,-1.01431E-04, 1.02131E-03, 9.96601E-04,
1.25707E+00, 2.50114E+01, 0.00000E+00, 4.24472E-01,-2.77655E+01,
3.44625E-01, 2.75412E+01, 0.00000E+00, 7.94251E+02, 0.00000E+00,
2.45835E-03, 1.38871E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN2(4) TN3(1) */ {
1.01890E+00,-2.46603E-02, 1.00078E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.70977E-02,
-4.02286E-02, 0.00000E+00, 0.00000E+00,-2.29466E+01,-7.47019E-03,
2.26580E-03, 2.63931E-02, 3.72625E+01,-6.39041E-03, 0.00000E+00,
9.58383E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-1.85291E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 1.39717E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 9.19771E-03,-3.69121E+02, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00,-1.57067E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.07265E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.92953E-03,
-2.77739E-03,-4.40092E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.47280E-03,
2.95035E-04,-1.81246E-03, 2.81945E-03, 4.27296E-03, 9.78863E-04,
1.40545E+00,-6.19173E+00, 0.00000E+00, 0.00000E+00,-7.93632E+01,
4.44643E-01,-4.03085E+02, 0.00000E+00, 1.15603E+01, 0.00000E+00,
2.25068E-03, 8.48557E-04,-2.98493E-04, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN3(2) */ {
9.75801E-01, 3.80680E-02,-3.05198E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.85575E-02,
5.04057E-02, 0.00000E+00, 0.00000E+00,-1.76046E+02, 1.44594E-02,
-1.48297E-03,-3.68560E-03, 3.02185E+01,-3.23338E-03, 0.00000E+00,
1.53569E-02, 0.00000E+00,-1.15558E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 4.89620E-03, 0.00000E+00, 0.00000E+00,-1.00616E-02,
-8.21324E-03,-1.57757E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 6.63564E-03, 4.58410E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00,-2.51280E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 9.91215E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.73148E-04,
-1.29648E-03,-7.32026E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.68110E-03,
-4.66003E-03,-1.31567E-03,-7.39390E-04, 6.32499E-04,-4.65588E-04,
-1.29785E+00,-1.57139E+02, 0.00000E+00, 2.58350E-01,-3.69453E+01,
4.10672E-01, 9.78196E+00,-1.52064E-01,-3.85084E+03, 0.00000E+00,
-8.52706E-04,-1.40945E-03,-7.26786E-04, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN3(3) */ {
9.60722E-01, 7.03757E-02,-3.00266E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.22671E-02,
4.10423E-02, 0.00000E+00, 0.00000E+00,-1.63070E+02, 1.06073E-02,
5.40747E-04, 7.79481E-03, 1.44908E+02, 1.51484E-04, 0.00000E+00,
1.97547E-02, 0.00000E+00,-1.41844E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 5.77884E-03, 0.00000E+00, 0.00000E+00, 9.74319E-03,
0.00000E+00,-2.88015E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00,-4.44902E-03,-2.92760E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 2.34419E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.36685E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.65325E-04,
-5.50628E-04, 3.31465E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.06179E-03,
-3.08575E-03,-7.93589E-04,-1.08629E-04, 5.95511E-04,-9.05050E-04,
1.18997E+00, 4.15924E+01, 0.00000E+00,-4.72064E-01,-9.47150E+02,
3.98723E-01, 1.98304E+01, 0.00000E+00, 3.73219E+03, 0.00000E+00,
-1.50040E-03,-1.14933E-03,-1.56769E-04, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN3(4) */ {
1.03123E+00,-7.05124E-02, 8.71615E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.82621E-02,
-9.80975E-03, 0.00000E+00, 0.00000E+00, 2.89286E+01, 9.57341E-03,
0.00000E+00, 0.00000E+00, 8.66153E+01, 7.91938E-04, 0.00000E+00,
0.00000E+00, 0.00000E+00, 4.68917E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 7.86638E-03, 0.00000E+00, 0.00000E+00, 9.90827E-03,
0.00000E+00, 6.55573E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00,-4.00200E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 7.07457E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.72268E-03,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.04970E-04,
1.21560E-03,-8.05579E-06, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.49941E-03,
-4.57256E-04,-1.59311E-04, 2.96481E-04,-1.77318E-03,-6.37918E-04,
1.02395E+00, 1.28172E+01, 0.00000E+00, 1.49903E-01,-2.63818E+01,
0.00000E+00, 4.70628E+01,-2.22139E-01, 4.82292E-02, 0.00000E+00,
-8.67075E-04,-5.86479E-04, 5.32462E-04, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TN3(5) SURFACE TEMP TSL */ {
1.00828E+00,-9.10404E-02,-2.26549E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.32420E-02,
-9.08925E-03, 0.00000E+00, 0.00000E+00, 3.36105E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00,-1.24957E+01,-5.87939E-03, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.79765E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 2.01237E+03, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00,-1.75553E-02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.29699E-03,
1.26659E-03, 2.68402E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.17894E-03,
1.48746E-03, 1.06478E-04, 1.34743E-04,-2.20939E-03,-6.23523E-04,
6.36539E-01, 1.13621E+01, 0.00000E+00,-3.93777E-01, 2.38687E+03,
0.00000E+00, 6.61865E+02,-1.21434E-01, 9.27608E+00, 0.00000E+00,
1.68478E-04, 1.24892E-03, 1.71345E-03, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TGN3(2) SURFACE GRAD TSLG */ {
1.57293E+00,-6.78400E-01, 6.47500E-01, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.62974E-02,
-3.60423E-01, 0.00000E+00, 0.00000E+00, 1.28358E+02, 0.00000E+00,
0.00000E+00, 0.00000E+00, 4.68038E+01, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-1.67898E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.90994E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 3.15706E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TGN2(1) TGN1(2) */ {
8.60028E-01, 3.77052E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.17570E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 7.77757E-03, 0.00000E+00,
0.00000E+00, 0.00000E+00, 1.01024E+02, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 6.54251E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.56959E-02,
1.91001E-02, 3.15971E-02, 1.00982E-02,-6.71565E-03, 2.57693E-03,
1.38692E+00, 2.82132E-01, 0.00000E+00, 0.00000E+00, 3.81511E+02,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
}, /* TGN3(1) TGN2(2) */ {
1.06029E+00,-5.25231E-02, 3.73034E-01, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.31072E-02,
-3.88409E-01, 0.00000E+00, 0.00000E+00,-1.65295E+02,-2.13801E-01,
-4.38916E-02,-3.22716E-01,-8.82393E+01, 1.18458E-01, 0.00000E+00,
-4.35863E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00,-1.19782E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 2.62229E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00,-5.37443E+01, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00,-4.55788E-01, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.84009E-02,
3.96733E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.05494E-02,
7.39617E-02, 1.92200E-02,-8.46151E-03,-1.34244E-02, 1.96338E-02,
1.50421E+00, 1.88368E+01, 0.00000E+00, 0.00000E+00,-5.13114E+01,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
5.11923E-02, 3.61225E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
} };
/* SEMIANNUAL MULT SAM */
double sam[100] = {
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
};
/* MIDDLE ATMOSPHERE AVERAGES */
double pavgm[10] = {
2.61000E+02, 2.64000E+02, 2.29000E+02, 2.17000E+02, 2.17000E+02,
2.23000E+02, 2.86760E+02,-2.93940E+00, 2.50000E+00, 0.00000E+00 };
} // namespace

View file

@ -0,0 +1,331 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGMars.cpp
Author: Jon Berndt
Date started: 1/4/04
Purpose: Models the Martian atmosphere very simply
Called by: FGFDMExec
------------- Copyright (C) 2004 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
--------------------------------------------------------------------------------
Models the Martian atmosphere.
HISTORY
--------------------------------------------------------------------------------
1/04/2004 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGMars.h"
#include "FGState.h"
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_MARS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGMars::FGMars(FGFDMExec* fdmex) : FGAtmosphere(fdmex)
{
Name = "FGMars";
Reng = 53.5 * 44.01;
/*
lastIndex = 0;
h = 0.0;
psiw = 0.0;
MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
// turbType = ttNone;
turbType = ttStandard;
// turbType = ttBerndt;
TurbGain = 0.0;
TurbRate = 1.0;
*/
bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
FGMars::~FGMars()
{
unbind();
Debug(1);
}
*/
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGMars::InitModel(void)
{
FGModel::InitModel();
Calculate(h);
SLtemperature = intTemperature;
SLpressure = intPressure;
SLdensity = intDensity;
SLsoundspeed = sqrt(SHRatio*Reng*intTemperature);
rSLtemperature = 1.0/intTemperature;
rSLpressure = 1.0/intPressure;
rSLdensity = 1.0/intDensity;
rSLsoundspeed = 1.0/SLsoundspeed;
temperature = &intTemperature;
pressure = &intPressure;
density = &intDensity;
useExternal=false;
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGMars::Run(void)
{
if (FGModel::Run()) return true;
if (FDMExec->Holding()) return false;
//do temp, pressure, and density first
if (!useExternal) {
h = Propagate->Geth();
Calculate(h);
}
if (turbType != ttNone) {
Turbulence();
vWindNED += vTurbulence;
}
if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) );
if (psiw < 0) psiw += 2*M_PI;
soundspeed = sqrt(SHRatio*Reng*(*temperature));
Debug(2);
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGMars::Calculate(double altitude)
{
//Calculate reftemp, refpress, and density
// LIMIT the temperatures so they do not descend below absolute zero.
if (altitude < 22960.0) {
intTemperature = -25.68 - 0.000548*altitude; // Deg Fahrenheit
} else {
intTemperature = -10.34 - 0.001217*altitude; // Deg Fahrenheit
}
intPressure = 14.62*exp(-0.00003*altitude); // psf - 14.62 psf =~ 7 millibars
intDensity = intPressure/(Reng*intTemperature); // slugs/ft^3 (needs deg R. as input
//cout << "Atmosphere: h=" << altitude << " rho= " << intDensity << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// square a value, but preserve the original sign
static inline double
square_signed (double value)
{
if (value < 0)
return value * value * -1;
else
return value * value;
}
void FGMars::Turbulence(void)
{
switch (turbType) {
case ttStandard: {
vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
// Scale the magnitude so that it moves
// away from the peaks
MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
(1 + fabs(Magnitude)));
MagnitudeAccel += MagnitudedAccelDt*rate*TurbRate*State->Getdt();
Magnitude += MagnitudeAccel*rate*State->Getdt();
vDirectiondAccelDt.Normalize();
// deemphasise non-vertical forces
vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX));
vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY));
vDirectionAccel += vDirectiondAccelDt*rate*TurbRate*State->Getdt();
vDirectionAccel.Normalize();
vDirection += vDirectionAccel*rate*State->Getdt();
vDirection.Normalize();
// Diminish turbulence within three wingspans
// of the ground
vTurbulence = TurbGain * Magnitude * vDirection;
double HOverBMAC = Auxiliary->GetHOverBMAC();
if (HOverBMAC < 3.0)
vTurbulence *= (HOverBMAC / 3.0) * (HOverBMAC / 3.0);
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
// if (Aircraft->GetHTailArm() != 0.0)
// vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
// else
// vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
if (Aircraft->GetVTailArm())
vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
else
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
// Clear the horizontal forces
// actually felt by the plane, now
// that we've used them to calculate
// moments.
vTurbulence(eX) = 0.0;
vTurbulence(eY) = 0.0;
break;
}
case ttBerndt: {
vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
MagnitudeAccel += MagnitudedAccelDt*rate*State->Getdt();
Magnitude += MagnitudeAccel*rate*State->Getdt();
vDirectiondAccelDt.Normalize();
vDirectionAccel += vDirectiondAccelDt*rate*State->Getdt();
vDirectionAccel.Normalize();
vDirection += vDirectionAccel*rate*State->Getdt();
// Diminish z-vector within two wingspans
// of the ground
double HOverBMAC = Auxiliary->GetHOverBMAC();
if (HOverBMAC < 2.0)
vDirection(eZ) *= HOverBMAC / 2.0;
vDirection.Normalize();
vTurbulence = TurbGain*Magnitude * vDirection;
vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
if (Aircraft->GetHTailArm() != 0.0)
vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
else
vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
if (Aircraft->GetVTailArm())
vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
else
vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
break;
}
default:
break;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGMars::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGMars" << endl;
if (from == 1) cout << "Destroyed: FGMars" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 32) { // Turbulence
if (frame == 0 && from == 2) {
cout << "vTurbulence(X), vTurbulence(Y), vTurbulence(Z), "
<< "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), "
<< "vDirection(X), vDirection(Y), vDirection(Z), "
<< "Magnitude, "
<< "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl;
} else if (from == 2) {
cout << vTurbulence << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl;
}
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
} // namespace JSBSim

View file

@ -0,0 +1,182 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGMars.h
Author: Jon Berndt
Date started: 01/05/2004
------------- Copyright (C) 2004 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.
HISTORY
--------------------------------------------------------------------------------
01/05/2004 JSB Created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGMars_H
#define FGMars_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <models/FGAtmosphere.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MARS "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models the Martian atmosphere.
@author Jon Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGMars : public FGAtmosphere {
public:
/// Constructor
FGMars(FGFDMExec*);
/// Destructor
~FGMars();
/** Runs the Martian atmosphere model; called by the Executive
@return false if no error */
bool Run(void);
bool InitModel(void);
/// Returns the temperature in degrees Rankine.
inline double GetTemperature(void) const {return *temperature;}
/** Returns the density in slugs/ft^3.
<i>This function may <b>only</b> be used if Run() is called first.</i> */
inline double GetDensity(void) const {return *density;}
/// Returns the pressure in psf.
inline double GetPressure(void) const {return *pressure;}
/// Returns the speed of sound in ft/sec.
inline double GetSoundSpeed(void) const {return soundspeed;}
/// Returns the sea level temperature in degrees Rankine.
inline double GetTemperatureSL(void) const { return SLtemperature; }
/// Returns the sea level density in slugs/ft^3
inline double GetDensitySL(void) const { return SLdensity; }
/// Returns the sea level pressure in psf.
inline double GetPressureSL(void) const { return SLpressure; }
/// Returns the sea level speed of sound in ft/sec.
inline double GetSoundSpeedSL(void) const { return SLsoundspeed; }
/// Returns the ratio of at-altitude temperature over the sea level value.
inline double GetTemperatureRatio(void) const { return (*temperature)*rSLtemperature; }
/// Returns the ratio of at-altitude density over the sea level value.
inline double GetDensityRatio(void) const { return (*density)*rSLdensity; }
/// Returns the ratio of at-altitude pressure over the sea level value.
inline double GetPressureRatio(void) const { return (*pressure)*rSLpressure; }
/// Returns the ratio of at-altitude sound speed over the sea level value.
inline double GetSoundSpeedRatio(void) const { return soundspeed*rSLsoundspeed; }
/// Tells the simulator to use an externally calculated atmosphere model.
void UseExternal(void);
/// Tells the simulator to use the internal atmosphere model.
void UseInternal(void); //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(double t) { exTemperature=t; }
/// Provides the external atmosphere model with an interface to set the density.
inline void SetExDensity(double d) { exDensity=d; }
/// Provides the external atmosphere model with an interface to set the pressure.
inline void SetExPressure(double p) { exPressure=p; }
/// Sets the wind components in NED frame.
inline void SetWindNED(double wN, double wE, double wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;}
/// 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 double GetWindPsi(void) const { return psiw; }
inline void SetTurbGain(double tt) {TurbGain = tt;}
inline void SetTurbRate(double tt) {TurbRate = tt;}
inline double GetTurbPQR(int idx) const {return vTurbPQR(idx);}
inline FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;}
void bind(void);
void unbind(void);
private:
double rho;
enum tType {ttStandard, ttBerndt, ttNone} turbType;
int lastIndex;
double h;
double htab[8];
double SLtemperature,SLdensity,SLpressure,SLsoundspeed;
double rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
double *temperature,*density,*pressure;
double soundspeed;
bool useExternal;
double exTemperature,exDensity,exPressure;
double intTemperature, intDensity, intPressure;
double MagnitudedAccelDt, MagnitudeAccel, Magnitude;
double TurbGain;
double TurbRate;
FGColumnVector3 vDirectiondAccelDt;
FGColumnVector3 vDirectionAccel;
FGColumnVector3 vDirection;
FGColumnVector3 vTurbulence;
FGColumnVector3 vTurbulenceGrad;
FGColumnVector3 vBodyTurbGrad;
FGColumnVector3 vTurbPQR;
FGColumnVector3 vWindNED;
double psiw;
void Calculate(double altitude);
void Turbulence(void);
void Debug(int from);
};
} // namespace JSBSim
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -0,0 +1,7 @@
noinst_LIBRARIES = libAtmosphere.a
libAtmosphere_a_SOURCES = FGMSIS.cpp FGMSISData.cpp FGMars.cpp
noinst_HEADERS = FGMSIS.h FGMars.h
INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim

View file

@ -34,10 +34,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGCondition.h"
namespace JSBSim {
@ -52,21 +48,13 @@ CLASS IMPLEMENTATION
string FGCondition::indent = " ";
FGCondition::FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManager) :
PropertyManager(PropertyManager)
FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) :
PropertyManager(PropertyManager), isGroup(true)
{
mComparison["EQ"] = eEQ;
mComparison["NE"] = eNE;
mComparison["GT"] = eGT;
mComparison["GE"] = eGE;
mComparison["LT"] = eLT;
mComparison["LE"] = eLE;
mComparison["=="] = eEQ;
mComparison["!="] = eNE;
mComparison[">"] = eGT;
mComparison[">="] = eGE;
mComparison["<"] = eLT;
mComparison["<="] = eLE;
string property1, property2, logic;
Element* condition_element;
InitializeConditionals();
TestParam1 = TestParam2 = 0L;
TestValue = 0.0;
@ -74,31 +62,19 @@ FGCondition::FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManage
Logic = elUndef;
conditions.clear();
if (AC_cfg->GetValue("CONDITION_GROUP").empty()) { // define a condition
*AC_cfg >> property1 >> conditional >> property2;
TestParam1 = PropertyManager->GetNode(property1, true);
Comparison = mComparison[conditional];
if (property2.find_first_not_of("-.0123456789eE") == string::npos) {
TestValue = atof(property2.c_str());
} else {
TestParam2 = PropertyManager->GetNode(property2, true);
}
isGroup = false;
} else { // define a condition group
if (AC_cfg->GetValue("LOGIC") == "OR") Logic = eOR;
else if (AC_cfg->GetValue("LOGIC") == "AND") Logic = eAND;
AC_cfg->GetNextConfigLine();
while (AC_cfg->GetValue() != string("/CONDITION_GROUP")) {
conditions.push_back(FGCondition(AC_cfg, PropertyManager));
}
isGroup = true;
AC_cfg->GetNextConfigLine();
logic = element->GetAttributeValue("logic");
if (logic == "OR") Logic = eOR;
else if (logic == "AND") Logic = eAND;
else { // error
cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << logic << endl;
}
condition_element = element->GetElement();
while (condition_element) {
conditions.push_back(FGCondition(condition_element, PropertyManager));
condition_element = element->GetNextElement();
}
for (int i=0; i<element->GetNumDataLines(); i++) {
conditions.push_back(FGCondition(element->GetDataLine(i), PropertyManager));
}
Debug(0);
@ -106,6 +82,66 @@ FGCondition::FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManage
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) :
PropertyManager(PropertyManager), isGroup(false)
{
string property1, property2, compare_string;
Element* condition_element;
InitializeConditionals();
TestParam1 = TestParam2 = 0L;
TestValue = 0.0;
Comparison = ecUndef;
Logic = elUndef;
conditions.clear();
int start = 0, end = 0;
start = test.find_first_not_of(" ");
end = test.find_first_of(" ", start+1);
property1 = test.substr(start,end-start);
start = test.find_first_not_of(" ",end);
end = test.find_first_of(" ",start+1);
conditional = test.substr(start,end-start);
start = test.find_first_not_of(" ",end);
end = test.find_first_of(" ",start+1);
property2 = test.substr(start,end-start);
TestParam1 = PropertyManager->GetNode(property1, true);
Comparison = mComparison[conditional];
if (property2.find_first_not_of("-.0123456789eE") == string::npos) {
TestValue = atof(property2.c_str());
} else {
TestParam2 = PropertyManager->GetNode(property2, true);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGCondition::InitializeConditionals(void)
{
mComparison["EQ"] = eEQ;
mComparison["NE"] = eNE;
mComparison["GT"] = eGT;
mComparison["GE"] = eGE;
mComparison["LT"] = eLT;
mComparison["LE"] = eLE;
mComparison["eq"] = eEQ;
mComparison["ne"] = eNE;
mComparison["gt"] = eGT;
mComparison["ge"] = eGE;
mComparison["lt"] = eLT;
mComparison["le"] = eLE;
mComparison["=="] = eEQ;
mComparison["!="] = eNE;
mComparison[">"] = eGT;
mComparison[">="] = eGE;
mComparison["<"] = eLT;
mComparison["<="] = eLE;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGCondition::~FGCondition(void)
{
Debug(1);
@ -209,16 +245,6 @@ void FGCondition::PrintCondition(void )
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGCondition::convert(void)
{
if (conditions.empty())
cout << " " << property1 << " " << conditional << " " << property2 << endl;
else
for (int i; i<conditions.size(); i++) conditions[i].convert();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print

View file

@ -37,9 +37,10 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "../FGConfigFile.h"
#include <map>
#include "../FGPropertyManager.h"
#include <FGJSBBase.h>
#include <input_output/FGXMLElement.h>
#include <input_output/FGPropertyManager.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -59,7 +60,7 @@ CLASS DOCUMENTATION
/** Encapsulates a condition, which is used in parts of JSBSim including switches
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -67,16 +68,14 @@ CLASS DECLARATION
class FGCondition : public FGJSBBase
{
public:
FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManager);
FGCondition(Element* element, FGPropertyManager* PropertyManager);
FGCondition(string test, FGPropertyManager* PropertyManager);
~FGCondition(void);
bool Evaluate(void);
void PrintCondition(void);
void convert(void);
private:
FGConfigFile* AC_cfg;
enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE};
enum eLogic {elUndef=0, eAND, eOR};
map <string, eComparison> mComparison;
@ -87,11 +86,11 @@ private:
eComparison Comparison;
bool isGroup;
string conditional;
string property1, property2;
static string indent;
vector <FGCondition> conditions;
void InitializeConditionals(void);
void Debug(int from);
};

View file

@ -3,7 +3,7 @@
Module: FGDeadBand.cpp
Author: Jon S. Berndt
Date started: 11/1999
------------- Copyright (C) 2000 -------------
This program is free software; you can redistribute it and/or modify it under
@ -37,10 +37,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGDeadBand.h"
namespace JSBSim {
@ -54,40 +50,19 @@ CLASS IMPLEMENTATION
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGDeadBand::FGDeadBand(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
AC_cfg(AC_cfg)
FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
{
Type = AC_cfg->GetValue("TYPE");
Name = AC_cfg->GetValue("NAME");
AC_cfg->GetNextConfigLine();
string token;
clipmax = clipmin = 0.0;
clip = false;
gain = 1.0;
width = 0.0;
while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
*AC_cfg >> token;
if (token == "INPUT") {
if (InputNodes.size() > 0) {
cerr << "Deadband can only accept one input" << endl;
} else {
*AC_cfg >> token;
InputNodes.push_back(resolveSymbol(token));
}
} else if (token == "WIDTH") {
*AC_cfg >> width;
} else if (token == "CLIPTO") {
*AC_cfg >> clipmin >> clipmax;
if (clipmax > clipmin) clip = true;
} else if (token == "GAIN") {
*AC_cfg >> gain;
} else if (token == "OUTPUT") {
*AC_cfg >> token;
OutputNode = PropertyManager->GetNode(token);
}
if (element->FindElement("width")) {
width = element->FindElementValueAsNumber("width");
}
if (element->FindElement("gain")) {
gain = element->FindElementValueAsNumber("gain");
}
FGFCSComponent::bind();
Debug(0);
}
@ -103,9 +78,7 @@ FGDeadBand::~FGDeadBand()
bool FGDeadBand::Run(void )
{
FGFCSComponent::Run(); // call the base class for initialization of Input
Input = InputNodes[0]->getDoubleValue();
Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
if (Input < -width/2.0) {
Output = (Input + width/2.0)*gain;
@ -115,43 +88,13 @@ bool FGDeadBand::Run(void )
Output = 0.0;
}
if (clip) {
if (Output > clipmax) Output = clipmax;
else if (Output < clipmin) Output = clipmin;
}
Clip();
if (IsOutput) SetOutput();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGDeadBand::convert(void)
{
cout << endl;
cout << " <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
cout << " <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
if (gain != 1.0)
cout << " <gain>" << gain << "</gain>" << endl;
cout << " <width>" << width << "</width>" << endl;
if (clip) {
cout << " <clip>" << endl;
cout << " <min>" << clipmin << "</min>" << endl;
cout << " <max>" << clipmax << "</max>" << endl;
cout << " </clip>" << endl;
}
if (IsOutput)
cout << " <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
cout << " </component>" << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
@ -180,7 +123,7 @@ void FGDeadBand::Debug(int from)
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " DEADBAND WIDTH: " << width << endl;
cout << " GAIN: " << gain << endl;
if (clip) cout << " CLIPTO: " << clipmin
if (clip) cout << " CLIPTO: " << clipmin
<< ", " << clipmax << endl;
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
}

View file

@ -1,10 +1,10 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGDeadBand.h
Author:
Date started:
Author: Jon Berndt
Date started: 2001
------------- Copyright (C) -------------
------------- Copyright (C) 2001 Jon S. Berndt -------------
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
@ -38,7 +38,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFCSComponent.h"
#include "../FGConfigFile.h"
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -81,22 +81,18 @@ CLASS DOCUMENTATION
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGDeadBand : public FGFCSComponent
class FGDeadBand : public FGFCSComponent
{
public:
FGDeadBand(FGFCS* fcs, FGConfigFile* AC_cfg);
FGDeadBand(FGFCS* fcs, Element* element);
~FGDeadBand();
bool Run(void);
void convert(void);
private:
FGConfigFile* AC_cfg;
double width;
double clipmax, clipmin;
bool clip;
double gain;
void Debug(int from);
};
}

View file

@ -0,0 +1,245 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGFCSComponent.cpp
Author: Jon S. Berndt
Date started: 11/1999
------------- Copyright (C) 2000 -------------
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
--------------------------------------------------------------------------------
HISTORY
--------------------------------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFCSComponent.h"
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
{
Element *input_element, *clip_el;
Input = Output = clipmin = clipmax = 0.0;
OutputNode = treenode = 0;
ClipMinPropertyNode = ClipMaxPropertyNode = 0;
IsOutput = clip = false;
string input, clip_string;
PropertyManager = fcs->GetPropertyManager();
Type = element->GetAttributeValue("type"); // Old, deprecated format
if (Type.empty()) {
if (element->GetName() == string("lag_filter")) {
Type = "LAG_FILTER";
} else if (element->GetName() == string("lead_lag_filter")) {
Type = "LEAD_LAG_FILTER";
} else if (element->GetName() == string("washout_filter")) {
Type = "WASHOUT_FILTER";
} else if (element->GetName() == string("second_order_filter")) {
Type = "SECOND_ORDER_FILTER";
} else if (element->GetName() == string("integrator")) {
Type = "INTEGRATOR";
} else if (element->GetName() == string("summer")) {
Type = "SUMMER";
} else if (element->GetName() == string("pure_gain")) {
Type = "PURE_GAIN";
} else if (element->GetName() == string("scheduled_gain")) {
Type = "SCHEDULED_GAIN";
} else if (element->GetName() == string("aerosurface_scale")) {
Type = "AEROSURFACE_SCALE";
} else if (element->GetName() == string("switch")) {
Type = "SWITCH";
} else if (element->GetName() == string("kinematic")) {
Type = "KINEMATIC";
} else if (element->GetName() == string("deadband")) {
Type = "DEADBAND";
} else if (element->GetName() == string("fcs_function")) {
Type = "FCS_FUNCTION";
} else if (element->GetName() == string("sensor")) {
Type = "SENSOR";
} else { // illegal component in this channel
Type = "UNKNOWN";
}
}
Name = element->GetAttributeValue("name");
input_element = element->FindElement("input");
while (input_element) {
input = input_element->GetDataLine();
if (input[0] == '-') {
InputSigns.push_back(-1.0);
input.erase(0,1);
} else {
InputSigns.push_back( 1.0);
}
InputNodes.push_back( resolveSymbol(input) );
input_element = element->FindNextElement("input");
}
if (element->FindElement("output")) {
IsOutput = true;
OutputNode = PropertyManager->GetNode( element->FindElementValue("output") );
if (!OutputNode) {
cerr << endl << " Unable to process property: " << element->FindElementValue("output") << endl;
throw(string("Invalid output property name in flight control definition"));
}
}
clip_el = element->FindElement("clipto");
if (clip_el) {
clip_string = clip_el->FindElementValue("min");
if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property
ClipMinPropertyNode = PropertyManager->GetNode( clip_string );
} else {
clipmin = clip_el->FindElementValueAsNumber("min");
}
clip_string = clip_el->FindElementValue("max");
if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property
ClipMaxPropertyNode = PropertyManager->GetNode( clip_string );
} else {
clipmax = clip_el->FindElementValueAsNumber("max");
}
clip = true;
}
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGFCSComponent::~FGFCSComponent()
{
// string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
// PropertyManager->Untie( tmp);
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::SetOutput(void)
{
OutputNode->setDoubleValue(Output);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFCSComponent::Run(void)
{
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::Clip(void)
{
if (clip) {
if (ClipMinPropertyNode != 0) clipmin = ClipMinPropertyNode->getDoubleValue();
if (ClipMaxPropertyNode != 0) clipmax = ClipMaxPropertyNode->getDoubleValue();
if (Output > clipmax) Output = clipmax;
else if (Output < clipmin) Output = clipmin;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyManager* FGFCSComponent::resolveSymbol(string token)
{
string prop;
FGPropertyManager* tmp = PropertyManager->GetNode(token,false);
if (!tmp) {
if (token.find("/") == token.npos) prop = "model/" + token;
cerr << "Creating new property " << prop << endl;
tmp = PropertyManager->GetNode(token,true);
}
return tmp;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::bind(void)
{
string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
PropertyManager->Tie( tmp, this, &FGFCSComponent::GetOutput);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
// out the normally expected messages, essentially echoing
// the config files as they are read. If the environment
// variable is not set, debug_lvl is set to 1 internally
// 0: This requests JSBSim not to output any messages
// whatsoever.
// 1: This value explicity requests the normal JSBSim
// startup messages
// 2: This value asks for a message to be printed out when
// a class is instantiated
// 4: When this value is set, a message is displayed when a
// FGModel object executes its Run() method
// 8: When this value is set, various runtime state variables
// are printed out periodically
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGFCSComponent::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) {
cout << endl << " Loading Component \"" << Name
<< "\" of type: " << Type << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGFCSComponent" << endl;
if (from == 1) cout << "Destroyed: FGFCSComponent" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}
if (debug_lvl & 8 ) { // Runtime state variables
}
if (debug_lvl & 16) { // Sanity checking
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
}
}

View file

@ -43,8 +43,9 @@ INCLUDES
#include <string>
#include <vector>
#include "../FGJSBBase.h"
#include "../FGPropertyManager.h"
#include <FGJSBBase.h>
#include <input_output/FGPropertyManager.h>
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -78,11 +79,10 @@ CLASS DOCUMENTATION
- FGDeadBand
- FGSummer
- FGGradient
@author Jon S. Berndt
@version $Id$
@see Documentation for the FGFCS class, and for the configuration file class
FGConfigFile.
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -93,7 +93,7 @@ class FGFCSComponent : public FGJSBBase
{
public:
/// Constructor
FGFCSComponent(FGFCS*);
FGFCSComponent(FGFCS* fcs, Element* el);
/// Destructor
virtual ~FGFCSComponent();
@ -104,22 +104,28 @@ public:
inline string GetName(void) const {return Name;}
inline string GetType(void) const { return Type; }
virtual double GetOutputPct(void) const { return 0; }
virtual void convert(void) {};
virtual void bind();
FGPropertyManager* resolveSymbol(string token);
protected:
FGFCS* fcs;
FGPropertyManager* PropertyManager;
FGPropertyManager* treenode;
string Type;
string Name;
FGPropertyManager* OutputNode;
FGPropertyManager* ClipMinPropertyNode;
FGPropertyManager* ClipMaxPropertyNode;
vector <FGPropertyManager*> InputNodes;
vector <float> InputSigns;
string Type;
string Name;
double Input;
FGPropertyManager* OutputNode;
double Output;
double clipmax, clipmin;
bool IsOutput;
bool clip;
void Clip(void);
virtual void bind();
FGPropertyManager* resolveSymbol(string token);
virtual void Debug(int from);
};

View file

@ -1,10 +1,10 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGFCSComponent.cpp
Module: FGFCSFunction.cpp
Author: Jon S. Berndt
Date started: 11/1999
------------- Copyright (C) 2000 -------------
Date started: 6/2005
------------- Copyright (C) 2005 -------------
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
@ -37,87 +37,54 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGFCSComponent.h"
#include "FGFCSFunction.h"
namespace JSBSim {
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_FCSCOMPONENT;
static const char *IdHdr = ID_FCSFUNCTION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGFCSComponent::FGFCSComponent(FGFCS* _fcs) : fcs(_fcs)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGFCSFunction::FGFCSFunction(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
{
Type = "";
Input = 0.0;
Output = 0.0;
OutputNode = 0;
IsOutput = false;
PropertyManager=fcs->GetPropertyManager();
treenode = 0;
Element *function_element = element->FindElement("function");
function = new FGFunction(PropertyManager, function_element);
FGFCSComponent::bind();
Debug(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGFCSComponent::~FGFCSComponent()
FGFCSFunction::~FGFCSFunction()
{
Debug(1);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::SetOutput(void)
bool FGFCSFunction::Run(void )
{
OutputNode->setDoubleValue(Output);
}
Output = function->GetValue();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (InputNodes.size() > 0) {
Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
Output*= Input;
}
Clip();
if (IsOutput) SetOutput();
bool FGFCSComponent::Run(void)
{
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyManager* FGFCSComponent::resolveSymbol(string token)
{
string prop;
FGPropertyManager* tmp = PropertyManager->GetNode(token,false);
if (!tmp) {
if (token.find("/") == token.npos) prop = "model/" + token;
//cerr << "Creating new property " << prop << endl;
tmp = PropertyManager->GetNode(token,true);
}
return tmp;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::bind(void)
{
string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
FGPropertyManager *tmpn;
PropertyManager->Tie( tmp,this, &FGFCSComponent::GetOutput);
tmp = "fcs/components/" + PropertyManager->mkPropertyName(Name, true);
treenode = PropertyManager->GetNode( tmp, true );
for(unsigned i=0;i<InputNodes.size();i++) {
tmpn=treenode->GetNode( "input-property",(int)i,true );
tmpn->setStringValue( InputNodes[i]->GetName().c_str() );
}
if(OutputNode) treenode->SetString("output-property",OutputNode->GetName());
treenode->Tie("output-value",this,&FGFCSComponent::GetOutput);
treenode->SetString("type",Type);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
@ -137,15 +104,23 @@ void FGFCSComponent::bind(void)
// 16: When set various parameters are sanity checked and
// a message is printed out when they go out of bounds
void FGFCSComponent::Debug(int from)
void FGFCSFunction::Debug(int from)
{
if (debug_lvl <= 0) return;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (InputNodes.size()>0)
cout << " INPUT: " << InputNodes[0]->getName() << endl;
// cout << " Function: " << endl;
if (clip) cout << " CLIPTO: " << clipmin
<< ", " << clipmax << endl;
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
if (from == 0) cout << "Instantiated: FGFCSComponent" << endl;
if (from == 1) cout << "Destroyed: FGFCSComponent" << endl;
if (from == 0) cout << "Instantiated: FGFCSFunction" << endl;
if (from == 1) cout << "Destroyed: FGFCSFunction" << endl;
}
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
}

View file

@ -0,0 +1,87 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGFCSFunction.h
Author: Jon Berndt
Date started: 2005
------------- Copyright (C) 2005 Jon S. Berndt -------------
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.
HISTORY
--------------------------------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGFCSFUNCTION_H
#define FGFCSFUNCTION_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFCSComponent.h"
#include <input_output/FGXMLElement.h>
#include <math/FGFunction.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSFUNCTION "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
class FGFCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Models a FCSFunction object.
@author Jon S. Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFCSFunction : public FGFCSComponent
{
public:
FGFCSFunction(FGFCS* fcs, Element* element);
~FGFCSFunction();
bool Run(void);
private:
FGFunction* function;
void Debug(int from);
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#endif

View file

@ -37,10 +37,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGFilter.h"
namespace JSBSim {
@ -52,16 +48,10 @@ static const char *IdHdr = ID_FILTER;
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
AC_cfg(AC_cfg)
FGFilter::FGFilter(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
{
string token;
double denom;
string sOutputIdx;
Type = AC_cfg->GetValue("TYPE");
Name = AC_cfg->GetValue("NAME");
AC_cfg->GetNextConfigLine();
dt = fcs->GetState()->Getdt();
Trigger = 0;
@ -74,37 +64,14 @@ FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
else if (Type == "INTEGRATOR") FilterType = eIntegrator ;
else FilterType = eUnknown ;
while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
*AC_cfg >> token;
if (token == "C1") *AC_cfg >> C1;
else if (token == "C2") *AC_cfg >> C2;
else if (token == "C3") *AC_cfg >> C3;
else if (token == "C4") *AC_cfg >> C4;
else if (token == "C5") *AC_cfg >> C5;
else if (token == "C6") *AC_cfg >> C6;
else if (token == "TRIGGER")
{
token = AC_cfg->GetValue("TRIGGER");
*AC_cfg >> token;
Trigger = resolveSymbol(token);
}
else if (token == "INPUT")
{
token = AC_cfg->GetValue("INPUT");
if( InputNodes.size() > 0 ) {
cerr << "Filters can only accept one input" << endl;
} else {
*AC_cfg >> token;
InputNodes.push_back( resolveSymbol(token) );
}
}
else if (token == "OUTPUT")
{
IsOutput = true;
*AC_cfg >> sOutputIdx;
OutputNode = PropertyManager->GetNode( sOutputIdx );
}
else cerr << "Unknown filter type: " << token << endl;
if (element->FindElement("c1")) C1 = element->FindElementValueAsNumber("c1");
if (element->FindElement("c2")) C2 = element->FindElementValueAsNumber("c2");
if (element->FindElement("c3")) C3 = element->FindElementValueAsNumber("c3");
if (element->FindElement("c4")) C4 = element->FindElementValueAsNumber("c4");
if (element->FindElement("c5")) C5 = element->FindElementValueAsNumber("c5");
if (element->FindElement("c6")) C6 = element->FindElementValueAsNumber("c6");
if (element->FindElement("trigger")) {
Trigger = resolveSymbol(element->FindElementValue("trigger"));
}
Initialize = true;
@ -157,25 +124,16 @@ FGFilter::~FGFilter()
bool FGFilter::Run(void)
{
int test = 0;
FGFCSComponent::Run(); // call the base class for initialization of Input
double test = 0.0;
if (Initialize) {
PreviousOutput1 = PreviousInput1 = Output = Input;
Initialize = false;
} else if (Trigger != 0) {
test = Trigger->getIntValue();
if (test < 0) {
Input = PreviousInput1 = PreviousInput2 = 0.0;
} else {
Output = PreviousOutput1 = PreviousOutput2 = 0.0;
}
} else {
Input = InputNodes[0]->getDoubleValue();
Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
switch (FilterType) {
case eLag:
Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb;
@ -191,6 +149,12 @@ bool FGFilter::Run(void)
Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
break;
case eIntegrator:
if (Trigger != 0) {
test = Trigger->getDoubleValue();
if (fabs(test) > 0.000001) {
Input = PreviousInput1 = PreviousInput2 = 0.0;
}
}
Output = Input * ca + PreviousInput1 * ca + PreviousOutput1;
break;
case eUnknown:
@ -204,35 +168,12 @@ bool FGFilter::Run(void)
PreviousInput2 = PreviousInput1;
PreviousInput1 = Input;
Clip();
if (IsOutput) SetOutput();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFilter::convert(void)
{
cout << endl;
cout << " <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
cout << " <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
if (C1 != 0) cout << " <c1>" << C1 << "</c1>" << endl;
if (C2 != 0) cout << " <c2>" << C2 << "</c2>" << endl;
if (C3 != 0) cout << " <c3>" << C3 << "</c3>" << endl;
if (C4 != 0) cout << " <c4>" << C4 << "</c4>" << endl;
if (C5 != 0) cout << " <c5>" << C5 << "</c5>" << endl;
if (C6 != 0) cout << " <c6>" << C6 << "</c6>" << endl;
if (Trigger != 0) cout << " <trigger>" << Trigger << "</trigger>" << endl;
if (IsOutput)
cout << " <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
cout << " </component>" << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print

View file

@ -38,7 +38,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFCSComponent.h"
#include "../FGConfigFile.h"
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -62,75 +62,75 @@ Tustin substitution is used to take filter definitions from LaPlace space to the
time domain. The general format for a filter specification is:
<pre>
\<COMPONENT NAME="name" TYPE="type">
INPUT \<property>
C1 \<value>
[C2 \<value>]
[C3 \<value>]
[C4 \<value>]
[C5 \<value>]
[C6 \<value>]
[OUTPUT \<property>]
\</COMPONENT>
\<component name="name" type="type">
\<input> property \</input>
\<c1> value \<c/1>
[\<c2> value \<c/2>]
[\<c3> value \<c/3>]
[\<c4> value \<c/4>]
[\<c5> value \<c/5>]
[\<c6> value \<c/6>]
[\<output> property \<output>]
\</component>
</pre>
For a lag filter of the form,
<pre>
C1
------
s + C1
s + C1
</pre>
the corresponding filter definition is:
<pre>
\<COMPONENT NAME="name" TYPE="LAG_FILTER">
INPUT \<property>
C1 \<value>
[OUTPUT \<property>]
\</COMPONENT>
\<component name="name" type="LAG_FILTER">
\<input> property \</input>
\<c1> value \<c/1>
[\<output> property \<output>]
\</component>
</pre>
As an example, for the specific filter:
<pre>
600
------
s + 600
s + 600
</pre>
the corresponding filter definition could be:
<pre>
\<COMPONENT NAME="LAG_1" TYPE="LAG_FILTER">
INPUT aileron_cmd
C1 600
\</COMPONENT>
\<component name="Heading Roll Error Lag" type="LAG_FILTER">
\<input> fcs/heading-command \</input>
\<c1> 600 \</c1>
\</component>
</pre>
For a lead-lag filter of the form:
<pre>
C1*s + C2
---------
C3*s + C4
C3*s + C4
</pre>
The corresponding filter definition is:
<pre>
\<COMPONENT NAME="name" TYPE="LEAD_LAG_FILTER">
INPUT \<property>
C1 \<value>
C2 \<value>
C3 \<value>
C4 \<value>
[OUTPUT \<property>]
\</COMPONENT>
\<component name="name" type="LEAD_LAG_FILTER">
\<input> property \</input>
\<c1> value \<c/1>
\<c2> value \<c/2>
\<c3> value \<c/3>
\<c4> value \<c/4>
[\<output> property \<output>]
\</component>
</pre>
For a washout filter of the form:
<pre>
s
------
s + C1
s + C1
</pre>
The corresponding filter definition is:
<pre>
\<COMPONENT NAME="name" TYPE="WASHOUT_FILTER">
INPUT \<property>
C1 \<value>
[OUTPUT \<property>]
\</COMPONENT>
\<component name="name" type="WASHOUT_FILTER">
\<input> property \</input>
\<c1> value \</c1>
[\<output> property \<output>]
\</component>
</pre>
For a second order filter of the form:
<pre>
@ -140,16 +140,16 @@ C4*s^2 + C5*s + C6
</pre>
The corresponding filter definition is:
<pre>
\<COMPONENT NAME="name" TYPE="SECOND_ORDER_FILTER">
INPUT \<property>
C1 \<value>
C2 \<value>
C3 \<value>
C4 \<value>
C5 \<value>
C6 \<value>
[OUTPUT \<property>]
\</COMPONENT>
\<component name="name" type="SECOND_ORDER_FILTER">
\<input> property \</input>
\<c1> value \<c/1>
\<c2> value \<c/2>
\<c3> value \<c/3>
\<c4> value \<c/4>
\<c5> value \<c/5>
\<c6> value \<c/6>
[\<output> property \<output>]
\</component>
</pre>
For an integrator of the form:
<pre>
@ -159,35 +159,35 @@ For an integrator of the form:
</pre>
The corresponding filter definition is:
<pre>
\<COMPONENT NAME="name" TYPE="INTEGRATOR">
INPUT \<property>
C1 \<value>
[OUTPUT \<property>]
[TRIGGER \<property>]
\</COMPONENT>
\<component name="name" type="INTEGRATOR">
\<input> property \</input>
\<c1> value \<c/1>
[\<trigger> property \</trigger>]
[\<output> property \<output>]
\</component>
</pre>
For the integrator, the TRIGGER features the following behavior, if the TRIGGER
For the integrator, the trigger features the following behavior. If the trigger
property value is:
- -1 (or simply less than zero), all previous inputs and outputs are set to 0.0
- 0, no action is taken - the output is calculated normally
- +1 (or simply greater than zero), all previous outputs (only) will be set to 0.0
- 0: no action is taken - the output is calculated normally
- not 0: (or simply greater than zero), all current and previous inputs will
be set to 0.0
In all the filter specifications above, an [OUTPUT] keyword is also seen. This
In all the filter specifications above, an \<output> element is also seen. This
is so that the last component in a "string" can copy its value to the appropriate
output, such as the elevator, or speedbrake, etc.
@author Jon S. Berndt
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGFilter : public FGFCSComponent
class FGFilter : public FGFCSComponent
{
public:
FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg);
FGFilter(FGFCS* fcs, Element* element);
~FGFilter();
bool Run (void);
@ -195,7 +195,6 @@ public:
/** When true, causes previous values to be set to current values. This
is particularly useful for first pass. */
bool Initialize;
void convert(void);
enum {eLag, eLeadLag, eOrder2, eWashout, eIntegrator, eUnknown} FilterType;
@ -216,7 +215,6 @@ private:
double PreviousInput2;
double PreviousOutput1;
double PreviousOutput2;
FGConfigFile* AC_cfg;
FGPropertyManager* Trigger;
void Debug(int from);
};

View file

@ -37,10 +37,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGGain.h"
namespace JSBSim {
@ -52,81 +48,74 @@ static const char *IdHdr = ID_GAIN;
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
AC_cfg(AC_cfg)
FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
{
string token;
string strScheduledBy;
string sOutputIdx;
State = fcs->GetState();
Element *scale_element, *zero_centered;
string strScheduledBy, gain_string, sZeroCentered;
GainPropertyNode = 0;
Gain = 1.000;
Rows = 0;
Min = Max = 0.0;
OutputPct = 0;
invert = false;
ScheduledBy = 0;
clip = false;
clipmin = clipmax = 0.0;
Table = 0;
InMin = -1.0;
InMax = 1.0;
OutMin = OutMax = 0.0;
Type = AC_cfg->GetValue("TYPE");
Name = AC_cfg->GetValue("NAME");
AC_cfg->GetNextConfigLine();
if (Type == "PURE_GAIN") {
if ( !element->FindElement("gain") ) {
cout << highint << " No GAIN specified (default: 1.0)" << normint << endl;
}
}
while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
*AC_cfg >> token;
if (token == "INPUT") {
*AC_cfg >> token;
if (token[0] == '-') {
invert = true;
token.erase(0,1);
}
if (InputNodes.size() > 0) {
cerr << "Gains can only accept one input" << endl;
} else {
InputNodes.push_back( resolveSymbol(token) );
}
} else if (token == "GAIN") {
*AC_cfg >> Gain;
} else if (token == "MIN") {
*AC_cfg >> Min;
} else if (token == "MAX") {
*AC_cfg >> Max;
} else if (token == "CLIPTO") {
*AC_cfg >> clipmin >> clipmax;
if (clipmax > clipmin) {
clip = true;
}
} else if (token == "INVERT") {
invert = true;
cerr << endl << "The INVERT keyword is being deprecated and will not be "
"supported in the future. Please use a minus sign in front "
"of an input property in the future." << endl << endl;
} else if (token == "ROWS") {
*AC_cfg >> Rows;
Table = new FGTable(Rows);
} else if (token == "SCHEDULED_BY") {
token = AC_cfg->GetValue("SCHEDULED_BY");
*AC_cfg >> strScheduledBy;
ScheduledBy = PropertyManager->GetNode( strScheduledBy );
} else if (token == "OUTPUT") {
IsOutput = true;
*AC_cfg >> sOutputIdx;
OutputNode = PropertyManager->GetNode( sOutputIdx, true );
if ( element->FindElement("gain") ) {
gain_string = element->FindElementValue("gain");
if (gain_string.find_first_not_of("+-.0123456789") != string::npos) { // property
GainPropertyNode = PropertyManager->GetNode(gain_string);
} else {
AC_cfg->ResetLineIndexToZero();
*Table << *AC_cfg;
Gain = element->FindElementValueAsNumber("gain");
}
}
if (Type == "AEROSURFACE_SCALE") {
scale_element = element->FindElement("domain");
if (scale_element) {
if (scale_element->FindElement("max") && scale_element->FindElement("min") )
{
InMax = scale_element->FindElementValueAsNumber("max");
InMin = scale_element->FindElementValueAsNumber("min");
}
}
scale_element = element->FindElement("range");
if (!scale_element) throw(string("No range supplied for aerosurface scale component"));
if (scale_element->FindElement("max") && scale_element->FindElement("min") )
{
OutMax = scale_element->FindElementValueAsNumber("max");
OutMin = scale_element->FindElementValueAsNumber("min");
} else {
cerr << "Maximum and minimum output values must be supplied for the "
"aerosurface scale component" << endl;
exit(-1);
}
ZeroCentered = true;
zero_centered = element->FindElement("zero_centered");
if (zero_centered) {
sZeroCentered = zero_centered->FindElementValue("zero_centered");
if (sZeroCentered == string("0") || sZeroCentered == string("false")) {
ZeroCentered = false;
}
}
}
if (Type == "SCHEDULED_GAIN") {
if (element->FindElement("table")) {
Table = new FGTable(PropertyManager, element->FindElement("table"));
} else {
cerr << "A table must be provided for the scheduled gain component" << endl;
exit(-1);
}
}
FGFCSComponent::bind();
if (Type == "AEROSURFACE_SCALE")
treenode->Tie( "output-norm", this, &FGGain::GetOutputPct );
Debug(0);
}
@ -143,12 +132,10 @@ FGGain::~FGGain()
bool FGGain::Run(void )
{
double SchedGain = 1.0;
double LookupVal = 0;
FGFCSComponent::Run(); // call the base class for initialization of Input
Input = InputNodes[0]->getDoubleValue();
Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
if (invert) Input = -Input;
if (GainPropertyNode != 0) Gain = GainPropertyNode->getDoubleValue();
if (Type == "PURE_GAIN") { // PURE_GAIN
@ -156,72 +143,32 @@ bool FGGain::Run(void )
} else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN
LookupVal = ScheduledBy->getDoubleValue();
SchedGain = Table->GetValue(LookupVal);
SchedGain = Table->GetValue();
Output = Gain * SchedGain * Input;
} else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE
OutputPct = Input;
if (Input >= 0.0) Output = Input * Max;
else Output = Input * -Min;
if (ZeroCentered) {
if (Input == 0.0) {
Output = 0.0;
} else if (Input > 0) {
Output = (Input / InMax) * OutMax;
} else {
Output = (Input / InMin) * OutMin;
}
} else {
Output = OutMin + ((Input - InMin) / (InMax - InMin)) * (OutMax - OutMin);
}
Output *= Gain;
}
if (clip) {
if (Output > clipmax) Output = clipmax;
else if (Output < clipmin) Output = clipmin;
}
Clip();
if (IsOutput) SetOutput();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGGain::convert(void)
{
cout << endl;
cout << " <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
if (invert)
cout << " <input>-" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
else
cout << " <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
if (Gain != 1.0)
cout << " <gain>" << Gain << "</gain>" << endl;
if (Type == "PURE_GAIN") { // PURE_GAIN
} else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN
cout << " <table>" << endl;
cout << " <independentVar>" << ScheduledBy->GetFullyQualifiedName().substr(12) << "</independentVar>" << endl;
cout << " <tableData>" << endl;
Table->Print(20);
cout << " </tableData>" << endl;
cout << " </table>" << endl;
} else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE
cout << " <limit>" << endl;
cout << " <min>" << Min << "</min>" << endl;
cout << " <max>" << Max << "</max>" << endl;
cout << " </limit>" << endl;
}
if (clip) {
cout << " <clip>" << endl;
cout << " <min>" << clipmin << "</min>" << endl;
cout << " <max>" << clipmax << "</max>" << endl;
cout << " </clip>" << endl;
}
if (IsOutput)
cout << " <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
cout << " </component>" << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
@ -247,17 +194,22 @@ void FGGain::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
if (invert)
if (InputSigns[0] < 0)
cout << " INPUT: -" << InputNodes[0]->getName() << endl;
else
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " GAIN: " << Gain << endl;
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
cout << " MIN: " << Min << endl;
cout << " MAX: " << Max << endl;
if (ScheduledBy != 0) {
cout << " Scheduled by parameter: " << ScheduledBy->getName() << endl;
if (Type == "AEROSURFACE_SCALE") {
cout << " In/Out Mapping:" << endl;
cout << " Input MIN: " << InMin << endl;
cout << " Input MAX: " << InMax << endl;
cout << " Output MIN: " << OutMin << endl;
cout << " Output MAX: " << OutMax << endl;
}
if (Table != 0) {
cout << " Scheduled by table: " << endl;
Table->Print();
}
}

View file

@ -46,8 +46,8 @@ INCLUDES
#endif
#include "FGFCSComponent.h"
#include "../FGConfigFile.h"
#include "../FGTable.h"
#include <input_output/FGXMLElement.h>
#include <math/FGTable.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -71,11 +71,11 @@ CLASS DOCUMENTATION
The gain component merely multiplies the input by a gain. The form of the
gain component specification is:
<pre>
\<COMPONENT NAME="name" TYPE="PURE_GAIN">
INPUT \<property>
GAIN \<value>
[OUTPUT \<property>]
\</COMPONENT>
\<component name="name" type="PURE_GAIN">
\<input> property \</input>
\<gain> value \</gain>
[\<output> property \</output>]
\</component>
</pre>
Note: as is the case with the Summer component, the input property name may be
immediately preceded by a minus sign to invert that signal.
@ -169,24 +169,18 @@ CLASS DECLARATION
class FGGain : public FGFCSComponent
{
public:
FGGain(FGFCS* fcs, FGConfigFile* AC_cfg);
FGGain(FGFCS* fcs, Element* element);
~FGGain();
double GetOutputPct() const { return OutputPct; }
void convert(void);
bool Run (void);
private:
FGConfigFile* AC_cfg;
FGTable* Table;
FGState* State;
FGPropertyManager* GainPropertyNode;
double Gain;
double Min, Max;
double clipmin, clipmax;
double OutputPct;
bool invert, clip;
double InMin, InMax, OutMin, OutMax;
int Rows;
FGPropertyManager* ScheduledBy;
bool ZeroCentered;
void Debug(int from);
};

View file

@ -1,9 +1,9 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGGradient.cpp
Author:
Date started:
Author:
Date started:
------------- Copyright (C) 2000 -------------
This program is free software; you can redistribute it and/or modify it under
@ -37,10 +37,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGGradient.h"
namespace JSBSim {
@ -53,12 +49,8 @@ CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGGradient::FGGradient(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
AC_cfg(AC_cfg)
FGGradient::FGGradient(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
{
Type = AC_cfg->GetValue("TYPE");
Name = AC_cfg->GetValue("NAME");
FGFCSComponent::bind();
Debug(0);
@ -75,8 +67,6 @@ FGGradient::~FGGradient()
bool FGGradient::Run(void )
{
FGFCSComponent::Run(); // call the base class for initialization of Input
return true;
}

View file

@ -38,7 +38,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFCSComponent.h"
#include "../FGConfigFile.h"
#include <input_output/FGXMLElement.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
@ -68,13 +68,12 @@ CLASS DECLARATION
class FGGradient : public FGFCSComponent
{
public:
FGGradient(FGFCS* fcs, FGConfigFile* AC_cfg);
FGGradient(FGFCS* fcs, Element* element);
~FGGradient();
bool Run (void);
private:
FGConfigFile* AC_cfg;
void Debug(int from);
};
}

View file

@ -37,10 +37,6 @@ COMMENTS, REFERENCES, and NOTES
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <math.h>
#include <float.h>
@ -55,57 +51,39 @@ static const char *IdHdr = ID_FLAPS;
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGKinemat::FGKinemat(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
AC_cfg(AC_cfg)
FGKinemat::FGKinemat(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
{
string token,sOutputIdx;
Element *traverse_element, *setting_element;
double tmpDetent;
double tmpTime;
Detents.clear();
TransitionTimes.clear();
OutputPct=0;
Output = OutputPct = 0;
DoScale = true;
Type = AC_cfg->GetValue("TYPE");
Name = AC_cfg->GetValue("NAME");
AC_cfg->GetNextConfigLine();
if (element->FindElement("noscale")) DoScale = false;
while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
*AC_cfg >> token;
if (token == "INPUT") {
token = AC_cfg->GetValue("INPUT");
if( InputNodes.size() > 0 ) {
cerr << "Kinemat can only accept one input" << endl;
} else {
*AC_cfg >> token;
InputNodes.push_back( resolveSymbol(token) );
}
} else if ( token == "DETENTS" ) {
*AC_cfg >> NumDetents;
if (NumDetents < 2) {
cerr << "Kinemat must have at least 2 DETENTS" << endl;
}
for (int i=0;i<NumDetents;i++) {
*AC_cfg >> tmpDetent;
*AC_cfg >> tmpTime;
Detents.push_back(tmpDetent);
TransitionTimes.push_back(tmpTime);
}
} else if (token == "OUTPUT") {
IsOutput = true;
*AC_cfg >> sOutputIdx;
OutputNode = PropertyManager->GetNode(sOutputIdx, true);
} else if (token == "NOSCALE") {
DoScale = false;
}
traverse_element = element->FindElement("traverse");
setting_element = traverse_element->FindElement("setting");
while (setting_element) {
tmpDetent = setting_element->FindElementValueAsNumber("position");
tmpTime = setting_element->FindElementValueAsNumber("time");
Detents.push_back(tmpDetent);
TransitionTimes.push_back(tmpTime);
setting_element = traverse_element->FindNextElement("setting");
}
NumDetents = Detents.size();
if (NumDetents <= 1) {
cerr << "Kinematic component " << Name
<< " must have more than 1 setting element" << endl;
exit(-1);
}
FGFCSComponent::bind();
treenode->Tie("output-norm", this, &FGKinemat::GetOutputPct );
// treenode->Tie("output-norm", this, &FGKinemat::GetOutputPct );
Debug(0);
}
@ -123,11 +101,11 @@ bool FGKinemat::Run(void )
{
double dt = fcs->GetState()->Getdt();
Input = InputNodes[0]->getDoubleValue();
Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
if (DoScale) Input *= Detents[NumDetents-1];
Output = OutputNode->getDoubleValue();
if (IsOutput) Output = OutputNode->getDoubleValue();
if (Input < Detents[0])
Input = Detents[0];
@ -177,35 +155,12 @@ bool FGKinemat::Run(void )
OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]);
Clip();
if (IsOutput) SetOutput();
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGKinemat::convert(void)
{
cout << endl;
cout << " <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
cout << " <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
cout << " <traverse>" << endl;
for (int i=0; i<Detents.size(); i++) {
cout << " <setting>" << endl;
cout << " <position>" << Detents[i] << "</position>" << endl;
cout << " <time>" << TransitionTimes[i] << "</time>" << endl;
cout << " </setting>" << endl;
}
cout << " </traverse>" << endl;
if (IsOutput)
cout << " <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
cout << " </component>" << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print

Some files were not shown because too many files have changed in this diff Show more