From: ehofman Date: Thu, 12 Jan 2006 15:04:22 +0000 (+0000) Subject: sync. with JSBSim v. 2.0 X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=932b38a87e2870d23f9be9461b551f1e1fe556ba;p=flightgear.git sync. with JSBSim v. 2.0 --- diff --git a/configure.ac b/configure.ac index 38239fb46..336234287 100644 --- a/configure.ac +++ b/configure.ac @@ -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 \ diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index ab37dac38..536baeee8 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -41,10 +41,6 @@ COMMENTS, REFERENCES, and NOTES INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#ifdef HAVE_CONFIG_H -# include -#endif - #ifdef FGFS # include # 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include 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; iIncrTime(); + 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 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; - - 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; + ReadPrologue(document); + element = document->GetElement(); + + 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; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs) +{ + struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure; + int node_idx = 0; + char int_buf[10]; + + for (int i=0; inode->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; iFindElement("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(FGConfigFile* AC_cfg) +bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document element { - string token = AC_cfg->GetValue(); - string scratch; - string AircraftName; + bool result = true; // true for success + + if (!el) return false; - AircraftName = AC_cfg->GetValue("NAME"); + 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,82 +680,85 @@ 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; + return instance; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGFDMExec::ReadFlightControls(FGConfigFile* AC_cfg) +FGTrim* FGFDMExec::GetTrim(void) { - if (!FCS->Load(AC_cfg)) { - cerr << " Flight Controls not successfully loaded" << endl; - return false; - } - return true; + delete Trim; + Trim = new FGTrim(this,tNone); + return Trim; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGFDMExec::ReadAerodynamics(FGConfigFile* AC_cfg) +void FGFDMExec::DisableOutput(void) { - if (!Aerodynamics->Load(AC_cfg)) { - cerr << " Aerodynamics not successfully loaded" << endl; - return false; + for (int i=0; iDisable(); } - return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGFDMExec::ReadUndercarriage(FGConfigFile* AC_cfg) +void FGFDMExec::EnableOutput(void) { - if (!GroundReactions->Load(AC_cfg)) { - cerr << " Ground Reactions not successfully loaded" << endl; - return false; + for (int i=0; iEnable(); } - return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGFDMExec::ReadMetrics(FGConfigFile* AC_cfg) +void FGFDMExec::DoTrim(int mode) { - if (!Aircraft->Load(AC_cfg)) { - cerr << " Aircraft metrics not successfully loaded" << endl; - return false; - } - return true; -} + double saved_time; -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +cout << "DoTrim called" << endl; -bool FGFDMExec::ReadOutput(FGConfigFile* AC_cfg) -{ - if (!Output->Load(AC_cfg)) { - cerr << " Output not successfully loaded" << endl; - return false; + if (Constructing) return; + + if (mode < 0 || mode > JSBSim::tNone) { + cerr << endl << "Illegal trimming mode!" << endl << endl; + return; } - return true; + 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); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGPropertyManager* FGFDMExec::GetPropertyManager(void) { - return instance; +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; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGTrim* FGFDMExec::GetTrim(void) { - delete Trim; - Trim = new FGTrim(this,tNone); - return Trim; +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; +*/ } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -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) } } + diff --git a/src/FDM/JSBSim/FGFDMExec.h b/src/FDM/JSBSim/FGFDMExec.h index ae9edb999..e440ab763 100644 --- a/src/FDM/JSBSim/FGFDMExec.h +++ b/src/FDM/JSBSim/FGFDMExec.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -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).

JSBSim Debugging Directives

@@ -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 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 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 Outputs; FGInitialCondition* IC; FGTrim *Trim; vector 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); diff --git a/src/FDM/JSBSim/FGJSBBase.cpp b/src/FDM/JSBSim/FGJSBBase.cpp index 61669d179..c6fcc0f6c 100644 --- a/src/FDM/JSBSim/FGJSBBase.cpp +++ b/src/FDM/JSBSim/FGJSBBase.cpp @@ -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::Messages; FGJSBBase::Message FGJSBBase::localMsg; diff --git a/src/FDM/JSBSim/FGJSBBase.h b/src/FDM/JSBSim/FGJSBBase.h index 7b75f84c6..f47a779f6 100644 --- a/src/FDM/JSBSim/FGJSBBase.h +++ b/src/FDM/JSBSim/FGJSBBase.h @@ -42,18 +42,18 @@ INCLUDES #ifdef FGFS # include -# include # include # include # include STL_STRING SG_USING_STD(string); -# ifndef M_PI -# define M_PI SG_PI -# endif +# ifndef M_PI +# include +# define M_PI SG_PI +# endif -#else +#else // JSBSim section # include # include @@ -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 diff --git a/src/FDM/JSBSim/FGLocation.h b/src/FDM/JSBSim/FGLocation.h deleted file mode 100644 index d0c3eca8d..000000000 --- a/src/FDM/JSBSim/FGLocation.h +++ /dev/null @@ -1,444 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGLocation.h - Author: Jon S. Berndt, Mathias Froehlich - Date started: 04/04/2004 - - ------- 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. - -HISTORY -------------------------------------------------------------------------------- -04/04/2004 MF Created from code previously in the old positions class. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGLOCATION_H -#define FGLOCATION_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGJSBBase.h" -#include "FGPropertyManager.h" -#include "FGColumnVector3.h" -#include "FGMatrix33.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_LOCATION "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Holds an arbitrary location in the earth centered reference frame. - This coordinate frame has its center in the middle of the earth. - Its x-axis points from the center of the earth towards a location - with zero latitude and longitude on the earths surface. The y-axis - points from the center of the earth towards a location with zero - latitude and 90deg longitude on the earths surface. The z-axis - points from the earths center to the geographic north pole. - - This class provides access functions to set and get the location as - either the simple x, y and z values in ft or longitude/latitude and - the radial distance of the location from the earth center. - - It is common to associate a parent frame with a location. This - frame is usually called the local horizontal frame or simply the local - frame. This frame has its x/y plane parallel to the surface of the earth - (with the assumption of a spherical earth). The x-axis points - towards north, the y-axis points towards east and the z-axis - points to the center of the earth. - - Since this frame is determined by the location, this class also - provides the rotation matrices required to transform from the - earth centered frame to the local horizontal frame and back. There - are also conversion functions for conversion of position vectors - given in the one frame to positions in the other frame. - - The earth centered reference frame is *NOT* an inertial frame - since it rotates with the earth. - - The coordinates in the earth centered frame are the master values. - All other values are computed from these master values and are - cached as long as the location is changed by access through a - non-const member function. Values are cached to improve performance. - It is best practice to work with a natural set of master values. - Other parameters that are derived from these master values are calculated - only when needed, and IF they are needed and calculated, then they are - cached (stored and remembered) so they do not need to be re-calculated - until the master values they are derived from are themselves changed - (and become stale). - - Accuracy and round off: - - Given that we model a vehicle near the earth, the earths surface - radius is about 2*10^7, ft and that we use double values for the - representation of the location, we have an accuracy of about - 1e-16*2e7ft/1=2e-9ft left. This should be sufficient for our needs. - Note that this is the same relative accuracy we would have when we - compute directly with lon/lat/radius. For the radius value this - is clear. For the lon/lat pair this is easy to see. Take for - example KSFO located at about 37.61deg north 122.35deg west, which - corresponds to 0.65642rad north and 2.13541rad west. Both values - are of magnitude of about 1. But 1ft corresponds to about - 1/(2e7*2*pi)=7.9577e-09rad. So the left accuracy with this - representation is also about 1*1e-16/7.9577e-09=1.2566e-08 which - is of the same magnitude as the representation chosen here. - - The advantage of this representation is that it is a linear space - without singularities. The singularities are the north and south - pole and most notably the non-steady jump at -pi to pi. It is - harder to track this jump correctly especially when we need to - work with error norms and derivatives of the equations of motion - within the time-stepping code. Also, the rate of change is of the - same magnitude for all components in this representation which is - an advantage for numerical stability in implicit time-stepping too. - - Note: The latitude is a GEOCENTRIC value. FlightGear - converts latitude to a geodetic value and uses that. In order to get best - matching relative to a map, geocentric latitude must be converted to geodetic. - - @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 - - @author Mathias Froehlich - @version $Id$ - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGLocation : virtual FGJSBBase -{ -public: - /** Default constructor. */ - FGLocation() { mCacheValid = false; } - - /** Constructor to set the longitude, latitude and the distance - from the center of the earth. - @param lon longitude - @param lat GEOCENTRIC latitude - @param distance from center of earth to vehicle in feet*/ - FGLocation(double lon, double lat, double radius); - - /** Copy constructor. */ - FGLocation(const FGColumnVector3& lv) - : mECLoc(lv), mCacheValid(false) {} - - /** Copy constructor. */ - FGLocation(const FGLocation& l) - : mECLoc(l.mECLoc), mCacheValid(l.mCacheValid) { - if (!mCacheValid) - return; - - mLon = l.mLon; - mLat = l.mLat; - mRadius = l.mRadius; - - mTl2ec = l.mTl2ec; - mTec2l = l.mTec2l; - } - - /** Get the longitude. - @return the longitude in rad of the location represented with this - class instance. The returned values are in the range between - -pi <= lon <= pi. Longitude is positive east and negative west. */ - double GetLongitude() const { ComputeDerived(); return mLon; } - - /** Get the longitude. - @return the longitude in deg of the location represented with this - class instance. The returned values are in the range between - -180 <= lon <= 180. Longitude is positive east and negative west. */ - double GetLongitudeDeg() const { ComputeDerived(); return radtodeg*mLon; } - - /** Set the longitude. - @param longitude Longitude in rad to set. - Sets the longitude of the location represented with this class - instance to the value of the given argument. The value is meant - to be in rad. The latitude and the radius value are preserved - with this call with the exception of radius being equal to - zero. If the radius is previously set to zero it is changed to be - equal to 1.0 past this call. Longitude is positive east and negative west. */ - void SetLongitude(double longitude); - - /** Get the sine of Longitude. */ - double GetSinLongitude() const { ComputeDerived(); return -mTec2l(2,1); } - - /** Get the cosine of Longitude. */ - double GetCosLongitude() const { ComputeDerived(); return mTec2l(2,2); } - - /** Get the latitude. - @return the latitude in rad of the location represented with this - class instance. The returned values are in the range between - -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ - double GetLatitude() const { ComputeDerived(); return mLat; } - - /** Get the latitude. - @return the latitude in deg of the location represented with this - class instance. The returned values are in the range between - -90 <= lon <= 90. Latitude is positive north and negative south. */ - double GetLatitudeDeg() const { ComputeDerived(); return radtodeg*mLat; } - - /** Set the latitude. - @param latitude Latitude in rad to set. - Sets the latitude of the location represented with this class - instance to the value of the given argument. The value is meant - to be in rad. The longitude and the radius value are preserved - with this call with the exception of radius being equal to - zero. If the radius is previously set to zero it is changed to be - equal to 1.0 past this call. - Latitude is positive north and negative south. - The arguments should be within the bounds of -pi/2 <= lat <= pi/2. - The behavior of this function with arguments outside this range is - left as an exercise to the gentle reader ... */ - void SetLatitude(double latitude); - - /** Get the sine of Latitude. */ - double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); } - - /** Get the cosine of Latitude. */ - double GetCosLatitude() const { ComputeDerived(); return mTec2l(1,3); } - - /** Get the cosine of Latitude. */ - double GetTanLatitude() const { - ComputeDerived(); - double cLat = mTec2l(1,3); - if (cLat == 0.0) - return 0.0; - else - return -mTec2l(3,3)/cLat; - } - - /** Get the distance from the center of the earth. - @return the distance of the location represented with this class - instance to the center of the earth in ft. The radius value is - always positive. */ - double GetRadius() const { ComputeDerived(); return mRadius; } - - /** Set the distance from the center of the earth. - @param radius Radius in ft to set. - Sets the radius of the location represented with this class - instance to the value of the given argument. The value is meant - to be in ft. The latitude and longitude values are preserved - with this call with the exception of radius being equal to - zero. If the radius is previously set to zero, latitude and - longitude is set equal to zero past this call. - The argument should be positive. - The behavior of this function called with a negative argument is - left as an exercise to the gentle reader ... */ - void SetRadius(double radius); - - /** Transform matrix from local horizontal to earth centered frame. - Returns a const reference to the rotation matrix of the transform from - the local horizontal frame to the earth centered frame. */ - const FGMatrix33& GetTl2ec(void) const { ComputeDerived(); return mTl2ec; } - - /** Transform matrix from the earth centered to local horizontal frame. - Returns a const reference to the rotation matrix of the transform from - the earth centered frame to the local horizontal frame. */ - const FGMatrix33& GetTec2l(void) const { ComputeDerived(); return mTec2l; } - - /** Conversion from Local frame coordinates to a location in the - earth centered and fixed frame. - @parm lvec Vector in the local horizontal coordinate frame - @return The location in the earth centered and fixed frame */ - FGLocation LocalToLocation(const FGColumnVector3& lvec) const { - ComputeDerived(); return mTl2ec*lvec + mECLoc; - } - - /** Conversion from a location in the earth centered and fixed frame - to local horizontal frame coordinates. - @parm ecvec Vector in the earth centered and fixed frame - @return The vector in the local horizontal coordinate frame */ - FGColumnVector3 LocationToLocal(const FGColumnVector3& ecvec) const { - ComputeDerived(); return mTec2l*(ecvec - mECLoc); - } - - // For time-stepping, locations have vector properties... - - /** 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 mECLoc.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. - This function is just a shortcut for the 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) { - mCacheValid = false; return mECLoc.Entry(idx); - } - - const FGLocation& operator=(const FGLocation& l) { - mECLoc = l.mECLoc; - mCacheValid = l.mCacheValid; - if (!mCacheValid) - return *this; - - mLon = l.mLon; - mLat = l.mLat; - mRadius = l.mRadius; - - mTl2ec = l.mTl2ec; - mTec2l = l.mTec2l; - - return *this; - } - bool operator==(const FGLocation& l) const { - return mECLoc == l.mECLoc; - } - bool operator!=(const FGLocation& l) const { return ! operator==(l); } - const FGLocation& operator+=(const FGLocation &l) { - mCacheValid = false; - mECLoc += l.mECLoc; - return *this; - } - const FGLocation& operator-=(const FGLocation &l) { - mCacheValid = false; - mECLoc -= l.mECLoc; - return *this; - } - const FGLocation& operator*=(double scalar) { - mCacheValid = false; - mECLoc *= scalar; - return *this; - } - const FGLocation& operator/=(double scalar) { - return operator*=(1.0/scalar); - } - FGLocation operator+(const FGLocation& l) const { - return FGLocation(mECLoc + l.mECLoc); - } - FGLocation operator-(const FGLocation& l) const { - return FGLocation(mECLoc - l.mECLoc); - } - - FGLocation operator*(double scalar) const { - return FGLocation(scalar*mECLoc); - } - - /** Cast to a simple 3d vector */ - operator const FGColumnVector3&() const { - return mECLoc; - } - - /** Ties into the property tree. - Ties the variables represented by this class into the property tree. */ - void bind(FGPropertyManager*, const string&) const; - - /** Remove from property tree. - Unties the variables represented by this class into the property tree. */ - void unbind(FGPropertyManager*, const string&) const; - -private: - /** Computation of derived values. - This function re-computes the derived values like lat/lon and - transformation matrices. It does this unconditionally. */ - void ComputeDerivedUnconditional(void) const; - - /** Computation of derived values. - This function checks if the derived values like lat/lon and - transformation matrices are already computed. If so, it - returns. If they need to be computed this is done here. */ - void ComputeDerived(void) const { - if (!mCacheValid) - ComputeDerivedUnconditional(); - } - - /** The coordinates in the earth centered frame. This is the master copy. - The coordinate frame has its center in the middle of the earth. - Its x-axis points from the center of the earth towards a - location with zero latitude and longitude on the earths - surface. The y-axis points from the center of the earth towards a - location with zero latitude and 90deg longitude on the earths - surface. The z-axis points from the earths center to the - geographic north pole. - @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 */ - FGColumnVector3 mECLoc; - - /** The cached lon/lat/radius values. */ - mutable double mLon; - mutable double mLat; - mutable double mRadius; - - /** The cached rotation matrices from and to the associated frames. */ - mutable FGMatrix33 mTl2ec; - mutable FGMatrix33 mTec2l; - - /** A data validity flag. - This class implements caching of the derived values like the - orthogonal rotation matrices or the lon/lat/radius values. For caching we - carry a flag which signals if the values are valid or not. - The C++ keyword "mutable" tells the compiler that the data member is - allowed to change during a const member function. */ - mutable bool mCacheValid; -}; - -/** Scalar multiplication. - - @param scalar scalar value to multiply with. - @param l Vector to multiply. - - Multiply the Vector with a scalar value. */ -inline FGLocation operator*(double scalar, const FGLocation& l) -{ - return l.operator*(scalar); -} - -} // namespace JSBSim - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif diff --git a/src/FDM/JSBSim/FGMassBalance.cpp b/src/FDM/JSBSim/FGMassBalance.cpp deleted file mode 100644 index f925c8fcc..000000000 --- a/src/FDM/JSBSim/FGMassBalance.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGMassBalance.cpp - Author: Jon S. Berndt - Date started: 09/12/2000 - Purpose: This module models weight and balance - - ------------- 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 --------------------------------------------------------------------------------- - -This class models the change in weight and balance of the aircraft due to fuel -burnoff, etc. - -HISTORY --------------------------------------------------------------------------------- -09/12/2000 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGMassBalance.h" -#include "FGPropulsion.h" -#include "FGPropertyManager.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_MASSBALANCE; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex) -{ - Name = "FGMassBalance"; - Weight = EmptyWeight = Mass = 0.0; - - vbaseXYZcg.InitMatrix(0.0); - baseJ.InitMatrix(); - mJ.InitMatrix(); - mJinv.InitMatrix(); - pmJ.InitMatrix(); - - bind(); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMassBalance::~FGMassBalance() -{ - unbind(); - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGMassBalance::Run(void) -{ - double denom, k1, k2, k3, k4, k5, k6; - double Ixx, Iyy, Izz, Ixy, Ixz, Iyz; - - if (!FGModel::Run()) { - - Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetPointMassWeight(); - - Mass = lbtoslug*Weight; - -// Calculate new CG - - 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(); - - 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); - - 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 ); - - Debug(2); - - return false; - } else { - return true; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGMassBalance::AddPointMass(double weight, double X, double Y, double Z) -{ - PointMassLoc.push_back(FGColumnVector3(X, Y, Z)); - PointMassWeight.push_back(weight); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGMassBalance::GetPointMassWeight(void) -{ - double PM_total_weight = 0.0; - - for (unsigned int i=0; iTie("inertia/mass-slugs", this, - &FGMassBalance::GetMass); - PropertyManager->Tie("inertia/weight-lbs", this, - &FGMassBalance::GetWeight); - PropertyManager->Tie("inertia/cg-x-ft", this,1, - (PMF)&FGMassBalance::GetXYZcg); - PropertyManager->Tie("inertia/cg-y-ft", this,2, - (PMF)&FGMassBalance::GetXYZcg); - PropertyManager->Tie("inertia/cg-z-ft", this,3, - (PMF)&FGMassBalance::GetXYZcg); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGMassBalance::unbind(void) -{ - PropertyManager->Untie("inertia/mass-slugs"); - PropertyManager->Untie("inertia/weight-lbs"); - PropertyManager->Untie("inertia/cg-x-ft"); - PropertyManager->Untie("inertia/cg-y-ft"); - PropertyManager->Untie("inertia/cg-z-ft"); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGMassBalance::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: FGMassBalance" << endl; - if (from == 1) cout << "Destroyed: FGMassBalance" << 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 (from == 2) { - if (EmptyWeight <= 0.0 || EmptyWeight > 1e9) - cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl; - if (Weight <= 0.0 || Weight > 1e9) - cout << "MassBalance::Weight out of bounds: " << Weight << endl; - if (Mass <= 0.0 || Mass > 1e9) - cout << "MassBalance::Mass out of bounds: " << Mass << endl; - } - } - if (debug_lvl & 64) { - if (from == 0) { // Constructor - cout << IdSrc << endl; - cout << IdHdr << endl; - } - } -} -} diff --git a/src/FDM/JSBSim/FGMassBalance.h b/src/FDM/JSBSim/FGMassBalance.h deleted file mode 100644 index 14c11f0ca..000000000 --- a/src/FDM/JSBSim/FGMassBalance.h +++ /dev/null @@ -1,157 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGMassBalance.h - Author: Jon S. Berndt - Date started: 09/12/2000 - - ------------- 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. - -HISTORY --------------------------------------------------------------------------------- -09/12/2000 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGMASSBALANCE_H -#define FGMASSBALANCE_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGModel.h" -#include "FGColumnVector3.h" -#include "FGMatrix33.h" -#include - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_MASSBALANCE "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONSS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models weight and balance information. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGMassBalance : public FGModel -{ - -public: - FGMassBalance(FGFDMExec*); - ~FGMassBalance(); - - 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 - slugs at the given vector r in the structural frame. The units - should be for the mass in slug and the vector in the structural - frame as usual in inches. - @param slugs the mass of this single pointmass given in slugs - @param r the location of this single pointmass in the structural frame - */ - FGMatrix33 GetPointmassInertia(double slugs, const FGColumnVector3& r) const - { - FGColumnVector3 v = StructuralToBody( r ); - FGColumnVector3 sv = slugs*v; - double xx = sv(1)*v(1); - double yy = sv(2)*v(2); - double zz = sv(3)*v(3); - double xy = -sv(1)*v(2); - double xz = -sv(1)*v(3); - double yz = -sv(2)*v(3); - return FGMatrix33( yy+zz, xy, xz, - xy, xx+zz, yz, - xz, yz, xx+yy ); - } - - /** Conversion from the structural frame to the body frame. - Converts the location given in the structural frame - coordinate system to the body frame. The units of the structural - frame are assumed to be in inches. The unit of the result is in - ft. - @param r vector coordinate in the structural reference frame (X positive - aft, measurements in inches). - @return vector coordinate in the body frame, in feet. - */ - FGColumnVector3 StructuralToBody(const FGColumnVector3& r) const; - - 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); - 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); - -private: - double Weight; - double EmptyWeight; - double Mass; - FGMatrix33 mJ; - FGMatrix33 mJinv; - FGMatrix33 pmJ; - FGMatrix33 baseJ; - FGColumnVector3 vXYZcg; - FGColumnVector3 vXYZtank; - FGColumnVector3 vbaseXYZcg; - FGColumnVector3 vPMxyz; - vector PointMassLoc; - vector PointMassWeight; - FGColumnVector3 PointMassCG; - FGMatrix33& CalculatePMInertias(void); - - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif diff --git a/src/FDM/JSBSim/FGMatrix33.cpp b/src/FDM/JSBSim/FGMatrix33.cpp deleted file mode 100644 index 5027f4c73..000000000 --- a/src/FDM/JSBSim/FGMatrix33.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Module: FGMatrix33.cpp -Author: Tony Peden, Jon Berndt, Mathias Frolich -Date started: 1998 -Purpose: FGMatrix33 class -Called by: Various - -FUNCTIONAL DESCRIPTION --------------------------------------------------------------------------------- - -HISTORY --------------------------------------------------------------------------------- -??/??/?? TP Created -03/16/2000 JSB Added exception throwing - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGMatrix33.h" -#include "FGColumnVector3.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_MATRIX33; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33::FGMatrix33(void) -{ - data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = - data[6] = data[7] = data[8] = 0.0; - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -ostream& operator<<(ostream& os, const FGMatrix33& M) -{ - for (unsigned int i=1; i<=M.Rows(); i++) { - for (unsigned int j=1; j<=M.Cols(); j++) { - if (i == M.Rows() && j == M.Cols()) - os << M(i,j); - else - os << M(i,j) << ", "; - } - } - return os; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -istream& operator>>(istream& is, FGMatrix33& M) -{ - for (unsigned int i=1; i<=M.Rows(); i++) { - for (unsigned int j=1; j<=M.Cols(); j++) { - is >> M(i,j); - } - } - return is; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGMatrix33::Determinant(void) const { - return Entry(1,1)*Entry(2,2)*Entry(3,3) + Entry(1,2)*Entry(2,3)*Entry(3,1) - + Entry(1,3)*Entry(2,1)*Entry(3,2) - Entry(1,3)*Entry(2,2)*Entry(3,1) - - Entry(1,2)*Entry(2,1)*Entry(3,3) - Entry(2,3)*Entry(3,2)*Entry(1,1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33 FGMatrix33::Inverse(void) const { - // Compute the inverse of a general matrix using Cramers rule. - // I guess googling for cramers rule gives tons of references - // for this. :) - double rdet = 1.0/Determinant(); - - double i11 = rdet*(Entry(2,2)*Entry(3,3)-Entry(2,3)*Entry(3,2)); - double i21 = rdet*(Entry(2,3)*Entry(3,1)-Entry(2,1)*Entry(3,3)); - double i31 = rdet*(Entry(2,1)*Entry(3,2)-Entry(2,2)*Entry(3,1)); - double i12 = rdet*(Entry(1,3)*Entry(3,2)-Entry(1,2)*Entry(3,3)); - double i22 = rdet*(Entry(1,1)*Entry(3,3)-Entry(1,3)*Entry(3,1)); - double i32 = rdet*(Entry(1,2)*Entry(3,1)-Entry(1,1)*Entry(3,2)); - double i13 = rdet*(Entry(1,2)*Entry(2,3)-Entry(1,3)*Entry(2,2)); - double i23 = rdet*(Entry(1,3)*Entry(2,1)-Entry(1,1)*Entry(2,3)); - double i33 = rdet*(Entry(1,1)*Entry(2,2)-Entry(1,2)*Entry(2,1)); - - return FGMatrix33( i11, i12, i13, - i21, i22, i23, - i31, i32, i33 ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGMatrix33::InitMatrix(void) -{ - data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = - data[6] = data[7] = data[8] = 0.0; -} - -// ***************************************************************************** -// binary operators ************************************************************ -// ***************************************************************************** - -FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const -{ - return FGMatrix33( Entry(1,1) - M(1,1), - Entry(1,2) - M(1,2), - Entry(1,3) - M(1,3), - Entry(2,1) - M(2,1), - Entry(2,2) - M(2,2), - Entry(2,3) - M(2,3), - Entry(3,1) - M(3,1), - Entry(3,2) - M(3,2), - Entry(3,3) - M(3,3) ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M) -{ - data[0] -= M.data[0]; - data[1] -= M.data[1]; - data[2] -= M.data[2]; - data[3] -= M.data[3]; - data[4] -= M.data[4]; - data[5] -= M.data[5]; - data[6] -= M.data[6]; - data[7] -= M.data[7]; - data[8] -= M.data[8]; - - return *this; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const -{ - return FGMatrix33( Entry(1,1) + M(1,1), - Entry(1,2) + M(1,2), - Entry(1,3) + M(1,3), - Entry(2,1) + M(2,1), - Entry(2,2) + M(2,2), - Entry(2,3) + M(2,3), - Entry(3,1) + M(3,1), - Entry(3,2) + M(3,2), - Entry(3,3) + M(3,3) ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M) -{ - Entry(1,1) += M(1,1); - Entry(1,2) += M(1,2); - Entry(1,3) += M(1,3); - Entry(2,1) += M(2,1); - Entry(2,2) += M(2,2); - Entry(2,3) += M(2,3); - Entry(3,1) += M(3,1); - Entry(3,2) += M(3,2); - Entry(3,3) += M(3,3); - - return *this; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33 FGMatrix33::operator*(const double scalar) const -{ - return FGMatrix33( scalar * Entry(1,1), - scalar * Entry(1,2), - scalar * Entry(1,3), - scalar * Entry(2,1), - scalar * Entry(2,2), - scalar * Entry(2,3), - scalar * Entry(3,1), - scalar * Entry(3,2), - scalar * Entry(3,3) ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33 operator*(double scalar, FGMatrix33 &M) -{ - return FGMatrix33( scalar * M(1,1), - scalar * M(1,2), - scalar * M(1,3), - scalar * M(2,1), - scalar * M(2,2), - scalar * M(2,3), - scalar * M(3,1), - scalar * M(3,2), - scalar * M(3,3) ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33& FGMatrix33::operator*=(const double scalar) -{ - Entry(1,1) *= scalar; - Entry(1,2) *= scalar; - Entry(1,3) *= scalar; - Entry(2,1) *= scalar; - Entry(2,2) *= scalar; - Entry(2,3) *= scalar; - Entry(3,1) *= scalar; - Entry(3,2) *= scalar; - Entry(3,3) *= scalar; - - return *this; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const -{ - // FIXME: Make compiler friendlier - FGMatrix33 Product; - - Product(1,1) = Entry(1,1)*M(1,1) + Entry(1,2)*M(2,1) + Entry(1,3)*M(3,1); - Product(1,2) = Entry(1,1)*M(1,2) + Entry(1,2)*M(2,2) + Entry(1,3)*M(3,2); - Product(1,3) = Entry(1,1)*M(1,3) + Entry(1,2)*M(2,3) + Entry(1,3)*M(3,3); - Product(2,1) = Entry(2,1)*M(1,1) + Entry(2,2)*M(2,1) + Entry(2,3)*M(3,1); - Product(2,2) = Entry(2,1)*M(1,2) + Entry(2,2)*M(2,2) + Entry(2,3)*M(3,2); - Product(2,3) = Entry(2,1)*M(1,3) + Entry(2,2)*M(2,3) + Entry(2,3)*M(3,3); - Product(3,1) = Entry(3,1)*M(1,1) + Entry(3,2)*M(2,1) + Entry(3,3)*M(3,1); - Product(3,2) = Entry(3,1)*M(1,2) + Entry(3,2)*M(2,2) + Entry(3,3)*M(3,2); - Product(3,3) = Entry(3,1)*M(1,3) + Entry(3,2)*M(2,3) + Entry(3,3)*M(3,3); - - return Product; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M) -{ - // FIXME: Make compiler friendlier - double a,b,c; - - a = Entry(1,1); b=Entry(1,2); c=Entry(1,3); - Entry(1,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); - Entry(1,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); - Entry(1,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); - - a = Entry(2,1); b=Entry(2,2); c=Entry(2,3); - Entry(2,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); - Entry(2,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); - Entry(2,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); - - a = Entry(3,1); b=Entry(3,2); c=Entry(3,3); - Entry(3,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); - Entry(3,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); - Entry(3,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); - - return *this; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33 FGMatrix33::operator/(const double scalar) const -{ - FGMatrix33 Quot; - - if ( scalar != 0 ) { - double tmp = 1.0/scalar; - Quot(1,1) = Entry(1,1) * tmp; - Quot(1,2) = Entry(1,2) * tmp; - Quot(1,3) = Entry(1,3) * tmp; - Quot(2,1) = Entry(2,1) * tmp; - Quot(2,2) = Entry(2,2) * tmp; - Quot(2,3) = Entry(2,3) * tmp; - Quot(3,1) = Entry(3,1) * tmp; - Quot(3,2) = Entry(3,2) * tmp; - Quot(3,3) = Entry(3,3) * tmp; - } else { - MatrixException mE; - mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"; - throw mE; - } - return Quot; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33& FGMatrix33::operator/=(const double scalar) -{ - if ( scalar != 0 ) { - double tmp = 1.0/scalar; - Entry(1,1) *= tmp; - Entry(1,2) *= tmp; - Entry(1,3) *= tmp; - Entry(2,1) *= tmp; - Entry(2,2) *= tmp; - Entry(2,3) *= tmp; - Entry(3,1) *= tmp; - Entry(3,2) *= tmp; - Entry(3,3) *= tmp; - } else { - MatrixException mE; - mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"; - throw mE; - } - return *this; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGMatrix33::T(void) -{ - for (unsigned int i=1; i<=3; i++) { - for (unsigned int j=i+1; j<=3; j++) { - double tmp = Entry(i,j); - Entry(i,j) = Entry(j,i); - Entry(j,i) = tmp; - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const { - double tmp1 = v(1)*Entry(1,1); - double tmp2 = v(1)*Entry(2,1); - double tmp3 = v(1)*Entry(3,1); - - tmp1 += v(2)*Entry(1,2); - tmp2 += v(2)*Entry(2,2); - tmp3 += v(2)*Entry(3,2); - - tmp1 += v(3)*Entry(1,3); - tmp2 += v(3)*Entry(2,3); - tmp3 += v(3)*Entry(3,3); - - return FGColumnVector3( tmp1, tmp2, tmp3 ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGMatrix33::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: FGMatrix33" << endl; - if (from == 1) cout << "Destroyed: FGMatrix33" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGMatrix33.h b/src/FDM/JSBSim/FGMatrix33.h deleted file mode 100644 index 9bc78ee09..000000000 --- a/src/FDM/JSBSim/FGMatrix33.h +++ /dev/null @@ -1,394 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Header: FGMatrix33.h -Author: Tony Peden, Jon Berndt, Mathias Frolich -Date started: Unknown - -HISTORY --------------------------------------------------------------------------------- -??/??/?? TP Created -03/16/2000 JSB Added exception throwing -03/06/2004 MF Rework of the code to make it a bit compiler friendlier - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGMATRIX33_H -#define FGMATRIX33_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include -#ifdef FGFS -# include -# include -# 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 -# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) - include - include -# include -# else -# include -# include -# if defined(sgi) && !defined(__GNUC__) -# include -# else -# include -# endif - using std::ostream; - using std::istream; - using std::cerr; - using std::cout; - using std::endl; -# endif - using std::string; -#endif - -#include "FGColumnVector3.h" -#include "FGJSBBase.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_MATRIX33 "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -class FGColumnVector3; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Exception convenience class. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DECLARATION: MatrixException -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class MatrixException : public FGJSBBase -{ -public: - string Message; -}; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - /** Handles matrix math operations. - @author Tony Peden, Jon Berndt, Mathias Froelich - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DECLARATION: FGMatrix33 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGMatrix33 : public FGJSBBase -{ -public: - - enum { - eRows = 3, - eColumns = 3 - }; - - /** Default initializer. - 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. */ - FGMatrix33(const FGMatrix33& M) { - Entry(1,1) = M.Entry(1,1); - Entry(2,1) = M.Entry(2,1); - Entry(3,1) = M.Entry(3,1); - Entry(1,2) = M.Entry(1,2); - Entry(2,2) = M.Entry(2,2); - Entry(3,2) = M.Entry(3,2); - Entry(1,3) = M.Entry(1,3); - Entry(2,3) = M.Entry(2,3); - Entry(3,3) = M.Entry(3,3); - - Debug(0); - } - - /** 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. - @param m21 value of the 2,1 Matrix element. - @param m22 value of the 2,2 Matrix element. - @param m23 value of the 2,3 Matrix element. - @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. */ - FGMatrix33(double m11, double m12, double m13, - double m21, double m22, double m23, - double m31, double m32, double m33) { - Entry(1,1) = m11; - Entry(2,1) = m21; - Entry(3,1) = m31; - Entry(1,2) = m12; - Entry(2,2) = m22; - Entry(3,2) = m32; - Entry(1,3) = m13; - Entry(2,3) = m23; - Entry(3,3) = m33; - - Debug(0); - } - - /// 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. */ - 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. */ - double& operator()(unsigned int row, unsigned int col) { - return Entry(row, col); - } - - /** Read access the entries of the matrix. - 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. */ - double Entry(unsigned int row, unsigned int col) const { - return data[(col-1)*eRows+row-1]; - } - - /** Write access the entries of the matrix. - 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. */ - 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. */ - unsigned int Rows(void) const { return eRows; } - - /** Number of cloumns 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. */ - FGMatrix33 Transposed(void) const { - return FGMatrix33( Entry(1,1), Entry(2,1), Entry(3,1), - Entry(1,2), Entry(2,2), Entry(3,2), - Entry(1,3), Entry(2,3), Entry(3,3) ); - } - - /** Transposes this matrix. - This function only transposes this matrix. Nothing is returned. */ - void T(void); - -/** Initialize the matrix. - This function initializes a matrix to all 0.0. */ - void InitMatrix(void); - -/** Initialize the matrix. - 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) { - Entry(1,1) = m11; - Entry(2,1) = m21; - Entry(3,1) = m31; - Entry(1,2) = m12; - Entry(2,2) = m22; - Entry(3,2) = m32; - Entry(1,3) = m13; - Entry(2,3) = m23; - Entry(3,3) = m33; - } - - /** Determinant of the matrix. - @return the determinant of the matrix. */ - double Determinant(void) const; - - /** Return if the matrix is invertible. - Checks and returns if the matrix is nonsingular and thus - 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. */ - 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. */ - FGMatrix33 Inverse(void) const; - - /** Assignment operator. - @param A source matrix. - 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]; - data[2] = A.data[2]; - data[3] = A.data[3]; - data[4] = A.data[4]; - data[5] = A.data[5]; - data[6] = A.data[6]; - data[7] = A.data[7]; - data[8] = A.data[8]; - return *this; - } - - /** 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - FGMatrix33& operator/=(const double scalar); - -private: - double data[eRows*eColumns]; - - void Debug(int from); -}; - -/** Scalar multiplication. - @param scalar scalar value to multiply with. - @param A Matrix to multiply. - 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.*/ -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.*/ -istream& operator>>(istream& is, FGMatrix33& M); - -} // namespace JSBSim - -#endif diff --git a/src/FDM/JSBSim/FGModel.cpp b/src/FDM/JSBSim/FGModel.cpp deleted file mode 100644 index 3482baf52..000000000 --- a/src/FDM/JSBSim/FGModel.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGModel.cpp - Author: Jon Berndt - Date started: 11/11/98 - Purpose: Base class for all models - Called by: FGSimExec, et. al. - - ------------- 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 base class for the FGAerodynamics, FGPropagate, etc. classes defines methods -common to all models. - -HISTORY --------------------------------------------------------------------------------- -11/11/98 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGModel.h" -#include "FGState.h" -#include "FGFDMExec.h" -#include "FGAtmosphere.h" -#include "FGFCS.h" -#include "FGPropulsion.h" -#include "FGMassBalance.h" -#include "FGAerodynamics.h" -#include "FGInertial.h" -#include "FGGroundReactions.h" -#include "FGAircraft.h" -#include "FGPropagate.h" -#include "FGAuxiliary.h" -#include "FGOutput.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_MODEL; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -GLOBAL DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGModel::FGModel(FGFDMExec* fdmex) -{ - FDMExec = fdmex; - NextModel = 0L; - - State = 0; - Atmosphere = 0; - FCS = 0; - Propulsion = 0; - MassBalance = 0; - Aerodynamics = 0; - Inertial = 0; - GroundReactions = 0; - 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 - //must be brought up now. - PropertyManager = FDMExec->GetPropertyManager(); - - exe_ctr = 1; - rate = 1; - - if (debug_lvl & 2) cout << " FGModel Base Class" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGModel::~FGModel() -{ - if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGModel::InitModel(void) -{ - State = FDMExec->GetState(); - Atmosphere = FDMExec->GetAtmosphere(); - FCS = FDMExec->GetFCS(); - Propulsion = FDMExec->GetPropulsion(); - MassBalance = FDMExec->GetMassBalance(); - Aerodynamics = FDMExec->GetAerodynamics(); - Inertial = FDMExec->GetInertial(); - GroundReactions = FDMExec->GetGroundReactions(); - Aircraft = FDMExec->GetAircraft(); - Propagate = FDMExec->GetPropagate(); - Auxiliary = FDMExec->GetAuxiliary(); - Output = FDMExec->GetOutput(); - - if (!State || - !Atmosphere || - !FCS || - !Propulsion || - !MassBalance || - !Aerodynamics || - !Inertial || - !GroundReactions || - !Aircraft || - !Propagate || - !Auxiliary || - !Output) return(false); - else return(true); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGModel::Run() -{ - if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; - - if (exe_ctr == 1) { - if (exe_ctr++ >= rate) exe_ctr = 1; - return false; - } else { - if (exe_ctr++ >= rate) exe_ctr = 1; - 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 FGModel::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: FGModel" << endl; - if (from == 1) cout << "Destroyed: FGModel" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGModel.h b/src/FDM/JSBSim/FGModel.h deleted file mode 100644 index 6ae370731..000000000 --- a/src/FDM/JSBSim/FGModel.h +++ /dev/null @@ -1,153 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGModel.h - Author: Jon Berndt - Date started: 11/21/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/22/98 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGMODEL_H -#define FGMODEL_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGJSBBase.h" -#include "FGPropertyManager.h" - -#ifdef FGFS -# include -# ifdef SG_HAVE_STD_INCLUDES -# include -# else -# include -# endif -#else -# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) -# include -# else -# include -# endif -#endif - -#include - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_MODEL "$Id$" - -using namespace std; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -class FGFDMExec; -class FGState; -class FGAtmosphere; -class FGFCS; -class FGPropulsion; -class FGMassBalance; -class FGAerodynamics; -class FGInertial; -class FGGroundReactions; -class FGAircraft; -class FGPropagate; -class FGAuxiliary; -class FGOutput; -class FGConfigFile; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Base class for all scheduled JSBSim models - @author Jon S. Berndt - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGModel : public FGJSBBase -{ -public: - - /// Constructor - FGModel(FGFDMExec*); - /// Destructor - virtual ~FGModel(); - - /** Loads this model. - @param Config a pointer to the config file instance - @return true if model is successfully loaded*/ - virtual bool Load(FGConfigFile* Config) {return true;} - - FGModel* NextModel; - string Name; - - /** Runs the model; called by the Executive - @see JSBSim.cpp documentation - @return false if no error */ - virtual bool Run(void); - virtual bool InitModel(void); - virtual void SetRate(int tt) {rate = tt;} - virtual int GetRate(void) {return rate;} - - void SetPropertyManager(FGPropertyManager *fgpm) { PropertyManager=fgpm;} - -protected: - int exe_ctr; - int rate; - - virtual void Debug(int from); - - FGFDMExec* FDMExec; - FGState* State; - FGAtmosphere* Atmosphere; - FGFCS* FCS; - FGPropulsion* Propulsion; - FGMassBalance* MassBalance; - FGAerodynamics* Aerodynamics; - FGInertial* Inertial; - FGGroundReactions* GroundReactions; - FGAircraft* Aircraft; - FGPropagate* Propagate; - FGAuxiliary* Auxiliary; - FGOutput* Output; - FGPropertyManager* PropertyManager; -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGNozzle.cpp b/src/FDM/JSBSim/FGNozzle.cpp deleted file mode 100644 index fa047037f..000000000 --- a/src/FDM/JSBSim/FGNozzle.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGNozzle.cpp - Author: Jon S. Berndt - Date started: 08/24/00 - Purpose: Encapsulates the nozzle object - - ------------- 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 --------------------------------------------------------------------------------- -08/24/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "FGNozzle.h" -#include "FGAtmosphere.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_NOZZLE; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGNozzle::FGNozzle(FGFDMExec* FDMExec, FGConfigFile* Nzl_cfg, int num) : FGThruster(FDMExec) -{ - string token; - - Name = Nzl_cfg->GetValue("NAME"); - Nzl_cfg->GetNextConfigLine(); - while (Nzl_cfg->GetValue() != string("/FG_NOZZLE")) { - *Nzl_cfg >> token; - if (token == "PE") *Nzl_cfg >> PE; - else if (token == "EXPR") *Nzl_cfg >> ExpR; - else if (token == "NZL_EFF") *Nzl_cfg >> nzlEff; - else if (token == "DIAM") *Nzl_cfg >> Diameter; - else cerr << "Unhandled token in Nozzle config file: " << token << endl; - } - - Thrust = 0; - Type = ttNozzle; - Area2 = (Diameter*Diameter/4.0)*M_PI; - AreaT = Area2/ExpR; - - char property_name[80]; - snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); - PropertyManager->Tie( property_name, &ThrustCoeff ); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGNozzle::~FGNozzle() -{ - char property_name[80]; - snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); - PropertyManager->Untie( property_name ); - - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGNozzle::Calculate(double CfPc) -{ - double pAtm = fdmex->GetAtmosphere()->GetPressure(); - Thrust = max((double)0.0, (CfPc * AreaT + (PE - pAtm)*Area2) * nzlEff); - vFn(1) = Thrust; - - ThrustCoeff = max((double)0.0, CfPc / ((pAtm - PE) * Area2)); - - return Thrust; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGNozzle::GetPowerRequired(void) -{ - return PE; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGNozzle::GetThrusterLabels(int id, string delimeter) -{ - std::ostringstream buf; - - buf << Name << "_Thrust[" << id << ']'; - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGNozzle::GetThrusterValues(int id, string delimeter) -{ - std::ostringstream buf; - - buf << Thrust; - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGNozzle::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << " Nozzle Name: " << Name << endl; - cout << " Nozzle Exit Pressure = " << PE << endl; - cout << " Nozzle Expansion Ratio = " << ExpR << endl; - cout << " Nozzle Efficiency = " << nzlEff << endl; - cout << " Nozzle Diameter = " << Diameter << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGNozzle" << endl; - if (from == 1) cout << "Destroyed: FGNozzle" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGNozzle.h b/src/FDM/JSBSim/FGNozzle.h deleted file mode 100644 index d329fa1e1..000000000 --- a/src/FDM/JSBSim/FGNozzle.h +++ /dev/null @@ -1,94 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGNozzle.h - Author: Jon S. Berndt - Date started: 08/24/00 - - ------------- 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. - -HISTORY --------------------------------------------------------------------------------- -08/24/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGNOZZLE_H -#define FGNOZZLE_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGThruster.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_NOZZLE "$Id$"; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models a rocket nozzle. - @author Jon S. Berndt - @version $Id$ -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGNozzle : public FGThruster { - -public: - /// Constructor - FGNozzle(FGFDMExec* exec, FGConfigFile* AC_cfg, int num = 0); - /// Destructor - ~FGNozzle(); - - double Calculate(double CfPc); - double GetPowerRequired(void); - string GetThrusterLabels(int id, string delimeter); - string GetThrusterValues(int id, string delimeter); - -private: - - double PE; - double ExpR; - double nzlEff; - double Diameter; - double AreaT; - double Area2; - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGOutput.cpp b/src/FDM/JSBSim/FGOutput.cpp deleted file mode 100644 index dc3e43fac..000000000 --- a/src/FDM/JSBSim/FGOutput.cpp +++ /dev/null @@ -1,641 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGOutput.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 "FGOutput.h" -#include "FGState.h" -#include "FGFDMExec.h" -#include "FGAtmosphere.h" -#include "FGFCS.h" -#include "FGAerodynamics.h" -#include "FGGroundReactions.h" -#include "FGAircraft.h" -#include "FGMassBalance.h" -#include "FGPropagate.h" -#include "FGAuxiliary.h" -#include "FGInertial.h" - -#include - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_OUTPUT; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex) -{ - Name = "FGOutput"; - sFirstPass = dFirstPass = true; - socket = 0; - Type = otNone; - Filename = ""; - SubSystems = 0; - enabled = true; - outputInFileName = ""; - delimeter = ", "; - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGOutput::~FGOutput() -{ - if (socket) delete socket; - for (unsigned int i=0; iGetCoefficientStrings(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssFCS) { - scratch = FCS->GetComponentStrings(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssGroundReactions) { - outstream << delimeter; - outstream << GroundReactions->GetGroundReactionStrings(delimeter); - } - if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { - outstream << delimeter; - outstream << Propulsion->GetPropulsionStrings(delimeter); - } - if (OutputProperties.size() > 0) { - for (unsigned int i=0;iGetName(); - } - } - - outstream << endl; - dFirstPass = false; - } - - outstream << State->Getsim_time(); - if (SubSystems & ssSimulation) { - } - if (SubSystems & ssAerosurfaces) { - outstream << delimeter; - outstream << FCS->GetDaCmd() << delimeter; - outstream << FCS->GetDeCmd() << delimeter; - outstream << FCS->GetDrCmd() << delimeter; - outstream << FCS->GetDfCmd() << delimeter; - outstream << FCS->GetDaLPos() << delimeter; - outstream << FCS->GetDaRPos() << delimeter; - outstream << FCS->GetDePos() << delimeter; - outstream << FCS->GetDrPos() << delimeter; - outstream << FCS->GetDfPos(); - } - if (SubSystems & ssRates) { - outstream << delimeter; - outstream << Propagate->GetPQR().Dump(delimeter) << delimeter; - outstream << Propagate->GetPQRdot().Dump(delimeter); - } - if (SubSystems & ssVelocities) { - outstream << delimeter; - outstream << Auxiliary->Getqbar() << delimeter; - outstream << setprecision(12) << Auxiliary->GetVt() << delimeter; - outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter; - outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter; - outstream << Propagate->GetVel().Dump(delimeter); - } - if (SubSystems & ssForces) { - outstream << delimeter; - outstream << Aerodynamics->GetvFs() << delimeter; - outstream << Aerodynamics->GetLoD() << delimeter; - outstream << Aircraft->GetForces().Dump(delimeter); - } - if (SubSystems & ssMoments) { - outstream << delimeter; - outstream << Aircraft->GetMoments().Dump(delimeter); - } - if (SubSystems & ssAtmosphere) { - outstream << delimeter; - outstream << Atmosphere->GetDensity() << delimeter; - outstream << Atmosphere->GetWindNED().Dump(delimeter); - } - if (SubSystems & ssMassProps) { - outstream << delimeter; - outstream << MassBalance->GetJ() << delimeter; - outstream << MassBalance->GetMass() << delimeter; - outstream << MassBalance->GetXYZcg(); - } - if (SubSystems & ssPropagate) { - outstream << delimeter; - outstream << Propagate->Geth() << delimeter; - outstream << Propagate->GetEuler().Dump(delimeter) << delimeter; - outstream << Auxiliary->Getalpha(inDegrees) << delimeter; - outstream << Auxiliary->Getbeta(inDegrees) << delimeter; - outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter; - outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter; - outstream << Propagate->GetDistanceAGL() << delimeter; - outstream << Propagate->GetRunwayRadius(); - } - if (SubSystems & ssCoefficients) { - scratch = Aerodynamics->GetCoefficientValues(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssFCS) { - scratch = FCS->GetComponentValues(delimeter); - if (scratch.length() != 0) outstream << delimeter << scratch; - } - if (SubSystems & ssGroundReactions) { - outstream << delimeter; - outstream << GroundReactions->GetGroundReactionValues(delimeter); - } - if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { - outstream << delimeter; - outstream << Propulsion->GetPropulsionValues(delimeter); - } - - for (unsigned int i=0;igetDoubleValue(); - } - - outstream << endl; - outstream.flush(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGOutput::SocketOutput(void) -{ - string asciiData; - - if (socket == NULL) return; - if (!socket->GetConnectStatus()) return; - - socket->Clear(); - if (sFirstPass) { - socket->Append(""); - 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"); - 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()); - socket->Send(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGOutput::SocketStatusOutput(string out_str) -{ - string asciiData; - - if (socket == NULL) return; - - socket->Clear(); - asciiData = string("") + out_str; - socket->Append(asciiData.c_str()); - socket->Send(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGOutput::Load(FGConfigFile* AC_cfg) -{ - string token="", parameter="", separator=""; - string name="", fname=""; - int OutRate = 0; - FGConfigFile* Output_cfg; - string property; - unsigned int port; - -# ifndef macintosh - separator = "/"; -# else - 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); - } - - if (!fname.empty()) { - outputInFileName = 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; - } - } else { - Output_cfg = AC_cfg; - } - 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)); - } - - if (parameter == "EOF") break; - } - - OutRate = OutRate>120?120:(OutRate<0?0:OutRate); - rate = (int)(0.5 + 1.0/(State->Getdt()*OutRate)); - - 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 FGOutput::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 (outputInFileName.empty()) - cout << " " << "Output parameters read inline" << endl; - else - cout << " Output parameters read from file: " << outputInFileName << endl; - - if (Filename == "cout" || Filename == "COUT") { - scratch = " Log output goes to screen console"; - } else if (!Filename.empty()) { - scratch = " Log output goes to file: " + Filename; - } - switch (Type) { - case otCSV: - cout << scratch << " in CSV format output at rate " << 120/rate << " Hz" << endl; - break; - case otNone: - cout << " No log output" << endl; - break; - } - - if (SubSystems & ssSimulation) cout << " Simulation parameters logged" << endl; - if (SubSystems & ssAerosurfaces) cout << " Aerosurface parameters logged" << endl; - if (SubSystems & ssRates) cout << " Rate parameters logged" << endl; - if (SubSystems & ssVelocities) cout << " Velocity parameters logged" << endl; - if (SubSystems & ssForces) cout << " Force parameters logged" << endl; - if (SubSystems & ssMoments) cout << " Moments parameters logged" << endl; - if (SubSystems & ssAtmosphere) cout << " Atmosphere parameters logged" << endl; - if (SubSystems & ssMassProps) cout << " Mass parameters logged" << endl; - if (SubSystems & ssCoefficients) cout << " Coefficient parameters logged" << endl; - if (SubSystems & ssPropagate) cout << " Propagate parameters logged" << endl; - if (SubSystems & ssGroundReactions) cout << " Ground parameters logged" << endl; - if (SubSystems & ssFCS) cout << " FCS parameters logged" << endl; - if (SubSystems & ssPropulsion) cout << " Propulsion parameters logged" << endl; - if (OutputProperties.size() > 0) cout << " Properties logged:" << endl; - for (unsigned int i=0;iGetName() << endl; - } - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGOutput" << endl; - if (from == 1) cout << "Destroyed: FGOutput" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGOutput.h b/src/FDM/JSBSim/FGOutput.h deleted file mode 100644 index 410e62fcb..000000000 --- a/src/FDM/JSBSim/FGOutput.h +++ /dev/null @@ -1,174 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGOutput.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 FGOUTPUT_H -#define FGOUTPUT_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGModel.h" - -#ifdef FGFS -# include -# include STL_IOSTREAM -# include STL_FSTREAM -#else -# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) -# include -# include -# else -# include -# include -# endif -#endif - -#include "FGfdmSocket.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_OUTPUT "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Handles simulation output. - OUTPUT section definition - - The following specifies the way that JSBSim writes out data. - - NAME is the filename you want the output to go to - - TYPE can be: - CSV Comma separated data. If a filename is supplied then the data - goes to that file. If COUT or cout is specified, the data goes - to stdout. If the filename is a null filename the data goes to - stdout, as well. - SOCKET Will eventually send data to a socket output, where NAME - would then be the IP address of the machine the data should be - sent to. DON'T USE THIS YET! - TABULAR Columnar data. NOT IMPLEMENTED YET! - TERMINAL Output to terminal. NOT IMPLEMENTED YET! - NONE Specifies to do nothing. THis setting makes it easy to turn on and - off the data output without having to mess with anything else. - - The arguments that can be supplied, currently, are - - RATE_IN_HZ An integer rate in times-per-second that the data is output. This - value may not be *exactly* what you want, due to the dependence - on dt, the cycle rate for the FDM. - - The following parameters tell which subsystems of data to output: - - SIMULATION ON|OFF - ATMOSPHERE ON|OFF - MASSPROPS ON|OFF - AEROSURFACES ON|OFF - RATES ON|OFF - VELOCITIES ON|OFF - FORCES ON|OFF - MOMENTS ON|OFF - POSITION ON|OFF - COEFFICIENTS ON|OFF - GROUND_REACTIONS ON|OFF - FCS ON|OFF - PROPULSION ON|OFF - - NOTE that Time is always output with the data. - @version $Id$ - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGOutput : public FGModel -{ -public: - FGOutput(FGFDMExec*); - ~FGOutput(); - - bool Run(void); - - 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); - - /// Subsystem types for specifying which will be output in the FDM data logging - enum eSubSystems { - /** Subsystem: Simulation (= 1) */ ssSimulation = 1, - /** Subsystem: Aerosurfaces (= 2) */ ssAerosurfaces = 2, - /** Subsystem: Body rates (= 4) */ ssRates = 4, - /** Subsystem: Velocities (= 8) */ ssVelocities = 8, - /** Subsystem: Forces (= 16) */ ssForces = 16, - /** Subsystem: Moments (= 32) */ ssMoments = 32, - /** Subsystem: Atmosphere (= 64) */ ssAtmosphere = 64, - /** Subsystem: Mass Properties (= 128) */ ssMassProps = 128, - /** Subsystem: Coefficients (= 256) */ ssCoefficients = 256, - /** Subsystem: Propagate (= 512) */ ssPropagate = 512, - /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024, - /** Subsystem: FCS (= 2048) */ ssFCS = 2048, - /** Subsystem: Propulsion (= 4096) */ ssPropulsion = 4096 - } subsystems; - -private: - bool sFirstPass, dFirstPass, enabled; - int SubSystems; - string Filename, outputInFileName, delimeter; - enum {otNone, otCSV, otTab, otSocket, otTerminal, otUnknown} Type; - ofstream datafile; - FGfdmSocket* socket; - vector OutputProperties; - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGPiston.cpp b/src/FDM/JSBSim/FGPiston.cpp deleted file mode 100644 index 9c7530ea6..000000000 --- a/src/FDM/JSBSim/FGPiston.cpp +++ /dev/null @@ -1,808 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGPiston.cpp - Author: Jon S. Berndt, JSBSim framework - Dave Luff, Piston engine model - Date started: 09/12/2000 - Purpose: This module models a Piston engine - - ------------- 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 --------------------------------------------------------------------------------- - -This class descends from the FGEngine class and models a Piston engine based on -parameters given in the engine config file for this class - -HISTORY --------------------------------------------------------------------------------- -09/12/2000 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "FGPiston.h" -#include "FGPropulsion.h" -#include "FGPropeller.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_PISTON; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number) - : FGEngine(exec, engine_number), - R_air(287.3), - rho_fuel(800), // estimate - calorific_value_fuel(47.3e6), - Cp_air(1005), - Cp_fuel(1700) -{ - string token; - - Type = etPiston; - crank_counter = 0; - OilTemp_degK = 298; - MinManifoldPressure_inHg = 6.5; - MaxManifoldPressure_inHg = 28.5; - ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg - minMAP = 21950; - maxMAP = 96250; - MAP = Atmosphere->GetPressure() * 47.88; // psf to Pa - CylinderHeadTemp_degK = 0.0; - Displacement = 360; - MaxHP = 0; - Cycles = 2; - IdleRPM = 600; - Magnetos = 0; - ExhaustGasTemp_degK = 0.0; - EGT_degC = 0.0; - - dt = State->Getdt(); - - // Supercharging - BoostSpeeds = 0; // Default to no supercharging - BoostSpeed = 0; - Boosted = false; - BoostOverride = 0; - bBoostOverride = false; - bTakeoffBoost = false; - TakeoffBoost = 0.0; // Default to no extra takeoff-boost - int i; - for (i=0; iGetValue("NAME"); - Eng_cfg->GetNextConfigLine(); - while (Eng_cfg->GetValue() != string("/FG_PISTON")) { - *Eng_cfg >> token; - if (token == "MINMP") *Eng_cfg >> MinManifoldPressure_inHg; - else if (token == "MAXMP") *Eng_cfg >> MaxManifoldPressure_inHg; - else if (token == "DISPLACEMENT") *Eng_cfg >> Displacement; - else if (token == "MAXHP") *Eng_cfg >> MaxHP; - else if (token == "CYCLES") *Eng_cfg >> Cycles; - else if (token == "IDLERPM") *Eng_cfg >> IdleRPM; - else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle; - else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle; - else if (token == "NUMBOOSTSPEEDS") *Eng_cfg >> BoostSpeeds; - else if (token == "BOOSTOVERRIDE") *Eng_cfg >> BoostOverride; - else if (token == "TAKEOFFBOOST") *Eng_cfg >> TakeoffBoost; - else if (token == "RATEDBOOST1") *Eng_cfg >> RatedBoost[0]; - else if (token == "RATEDBOOST2") *Eng_cfg >> RatedBoost[1]; - else if (token == "RATEDBOOST3") *Eng_cfg >> RatedBoost[2]; - else if (token == "RATEDPOWER1") *Eng_cfg >> RatedPower[0]; - else if (token == "RATEDPOWER2") *Eng_cfg >> RatedPower[1]; - else if (token == "RATEDPOWER3") *Eng_cfg >> RatedPower[2]; - else if (token == "RATEDRPM1") *Eng_cfg >> RatedRPM[0]; - else if (token == "RATEDRPM2") *Eng_cfg >> RatedRPM[1]; - else if (token == "RATEDRPM3") *Eng_cfg >> RatedRPM[2]; - else if (token == "RATEDALTITUDE1") *Eng_cfg >> RatedAltitude[0]; - else if (token == "RATEDALTITUDE2") *Eng_cfg >> RatedAltitude[1]; - else if (token == "RATEDALTITUDE3") *Eng_cfg >> RatedAltitude[2]; - else cerr << "Unhandled token in Engine config file: " << token << endl; - } - - minMAP = MinManifoldPressure_inHg * 3376.85; // inHg to Pa - maxMAP = MaxManifoldPressure_inHg * 3376.85; - - // Set up and sanity-check the turbo/supercharging configuration based on the input values. - if(TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true; - for(i=0; i 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true; - if(bad) { - // We can't recover from the above - don't use this supercharger speed. - BoostSpeeds--; - // TODO - put out a massive error message! - break; - } - // Now sanity-check stuff that is recoverable. - if(i < BoostSpeeds - 1) { - if(BoostSwitchAltitude[i] < RatedAltitude[i]) { - // TODO - put out an error message - // But we can also make a reasonable estimate, as below. - BoostSwitchAltitude[i] = RatedAltitude[i] + 1000; - } - BoostSwitchPressure[i] = Atmosphere->GetPressure(BoostSwitchAltitude[i]) * 47.88; - //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n'; - // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now - BoostSwitchHysteresis = 1000; - } - // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude. - RatedMAP[i] = Atmosphere->GetPressureSL() * 47.88 + RatedBoost[i] * 6895; // psf*47.88 = Pa, psi*6895 = Pa. - // Sometimes a separate BCV setting for takeoff or extra power is fitted. - if(TakeoffBoost > RatedBoost[0]) { - // Assume that the effect on the BCV is the same whichever speed is in use. - TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895); - bTakeoffBoost = true; - } else { - TakeoffMAP[i] = RatedMAP[i]; - bTakeoffBoost = false; - } - BoostMul[i] = RatedMAP[i] / (Atmosphere->GetPressure(RatedAltitude[i]) * 47.88); - - // TODO - get rid of the debugging output before sending it to Jon - //cout << "Speed " << i+1 << '\n'; - //cout << "BoostMul = " << BoostMul[i] << ", RatedMAP = " << RatedMAP[i] << ", TakeoffMAP = " << TakeoffMAP[i] << '\n'; - } - - if(BoostSpeeds > 0) { - Boosted = true; - BoostSpeed = 0; - } - bBoostOverride = (BoostOverride == 1 ? true : false); - - //cout << "Engine is " << (Boosted ? "supercharged" : "naturally aspirated") << '\n'; - - Debug(0); // Call Debug() routine from constructor if needed -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGPiston::~FGPiston() -{ - Debug(1); // Call Debug() routine from constructor if needed -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGPiston::Calculate(void) -{ - if (FuelFlow_gph > 0.0) ConsumeFuel(); - - Throttle = FCS->GetThrottlePos(EngineNumber); - Mixture = FCS->GetMixturePos(EngineNumber); - - // - // Input values. - // - - p_amb = Atmosphere->GetPressure() * 47.88; // convert from lbs/ft2 to Pa - p_amb_sea_level = Atmosphere->GetPressureSL() * 47.88; - T_amb = Atmosphere->GetTemperature() * (5.0 / 9.0); // convert from Rankine to Kelvin - - RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); - - IAS = Auxiliary->GetVcalibratedKTS(); - - doEngineStartup(); - if(Boosted) doBoostControl(); - doMAP(); - doAirFlow(); - doFuelFlow(); - - //Now that the fuel flow is done check if the mixture is too lean to run the engine - //Assume lean limit at 22 AFR for now - thats a thi of 0.668 - //This might be a bit generous, but since there's currently no audiable warning of impending - //cutout in the form of misfiring and/or rough running its probably reasonable for now. - if (equivalence_ratio < 0.668) - Running = false; - - doEnginePower(); - doEGT(); - doCHT(); - doOilTemperature(); - doOilPressure(); - - if (Thruster->GetType() == FGThruster::ttPropeller) { - ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); - } - - PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); - - return Thrust = Thruster->Calculate(PowerAvailable); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Start or stop the engine. - */ - -void FGPiston::doEngineStartup(void) -{ - // Check parameters that may alter the operating state of the engine. - // (spark, fuel, starter motor etc) - bool spark; - bool fuel; - - // Check for spark - Magneto_Left = false; - Magneto_Right = false; - // Magneto positions: - // 0 -> off - // 1 -> left only - // 2 -> right only - // 3 -> both - if (Magnetos != 0) { - spark = true; - } else { - spark = false; - } // neglects battery voltage, master on switch, etc for now. - - if ((Magnetos == 1) || (Magnetos > 2)) Magneto_Left = true; - if (Magnetos > 1) Magneto_Right = true; - - // Assume we have fuel for now - fuel = !Starved; - - // Check if we are turning the starter motor - if (Cranking != Starter) { - // This check saves .../cranking from getting updated every loop - they - // only update when changed. - Cranking = Starter; - crank_counter = 0; - } - - if (Cranking) crank_counter++; //Check mode of engine operation - - if (!Running && spark && fuel) { // start the engine if revs high enough - if (Cranking) { - if ((RPM > 450) && (crank_counter > 175)) // Add a little delay to startup - Running = true; // on the starter - } else { - if (RPM > 450) // This allows us to in-air start - Running = true; // when windmilling - } - } - - // Cut the engine *power* - Note: the engine may continue to - // spin if the prop is in a moving airstream - - if ( Running && (!spark || !fuel) ) Running = false; - - // Check for stalling (RPM = 0). - if (Running) { - if (RPM == 0) { - Running = false; - } else if ((RPM <= 480) && (Cranking)) { - Running = false; - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -/** - * Calculate the Current Boost Speed - * - * This function calculates the current turbo/supercharger boost speed - * based on altitude and the (automatic) boost-speed control valve configuration. - * - * Inputs: p_amb, BoostSwitchPressure, BoostSwitchHysteresis - * - * Outputs: BoostSpeed - */ - -void FGPiston::doBoostControl(void) -{ - if(BoostSpeed < BoostSpeeds - 1) { - // Check if we need to change to a higher boost speed - if(p_amb < BoostSwitchPressure[BoostSpeed] - BoostSwitchHysteresis) { - BoostSpeed++; - } - } else if(BoostSpeed > 0) { - // Check if we need to change to a lower boost speed - if(p_amb > BoostSwitchPressure[BoostSpeed - 1] + BoostSwitchHysteresis) { - BoostSpeed--; - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -/** - * Calculate the manifold absolute pressure (MAP) in inches hg - * - * This function calculates manifold absolute pressure (MAP) - * from the throttle position, turbo/supercharger boost control - * system, engine speed and local ambient air density. - * - * TODO: changes in MP should not be instantaneous -- introduce - * a lag between throttle changes and MP changes, to allow pressure - * to build up or disperse. - * - * Inputs: minMAP, maxMAP, p_amb, Throttle - * - * Outputs: MAP, ManifoldPressure_inHg - */ - -void FGPiston::doMAP(void) -{ - if(RPM > 10) { - // Naturally aspirated - MAP = minMAP + (Throttle * (maxMAP - minMAP)); - MAP *= p_amb / p_amb_sea_level; - if(Boosted) { - // If takeoff boost is fitted, we currently assume the following throttle map: - // (In throttle % - actual input is 0 -> 1) - // 99 / 100 - Takeoff boost - // 96 / 97 / 98 - Rated boost - // 0 - 95 - Idle to Rated boost (MinManifoldPressure to MaxManifoldPressure) - // In real life, most planes would be fitted with a mechanical 'gate' between - // the rated boost and takeoff boost positions. - double T = Throttle; // processed throttle value. - bool bTakeoffPos = false; - if(bTakeoffBoost) { - if(Throttle > 0.98) { - //cout << "Takeoff Boost!!!!\n"; - bTakeoffPos = true; - } else if(Throttle <= 0.95) { - bTakeoffPos = false; - T *= 1.0 / 0.95; - } else { - bTakeoffPos = false; - //cout << "Rated Boost!!\n"; - T = 1.0; - } - } - // Boost the manifold pressure. - MAP *= BoostMul[BoostSpeed]; - // Now clip the manifold pressure to BCV or Wastegate setting. - if(bTakeoffPos) { - if(MAP > TakeoffMAP[BoostSpeed]) { - MAP = TakeoffMAP[BoostSpeed]; - } - } else { - if(MAP > RatedMAP[BoostSpeed]) { - MAP = RatedMAP[BoostSpeed]; - } - } - } - } else { - // rpm < 10 - effectively stopped. - // TODO - add a better variation of MAP with engine speed - MAP = Atmosphere->GetPressure() * 47.88; // psf to Pa - } - - // And set the value in American units as well - ManifoldPressure_inHg = MAP / 3376.85; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Calculate the air flow through the engine. - * Also calculates ambient air density - * (used in CHT calculation for air-cooled engines). - * - * Inputs: p_amb, R_air, T_amb, MAP, Displacement, - * RPM, volumetric_efficiency - * - * TODO: Model inlet manifold air temperature. - * - * Outputs: rho_air, m_dot_air - */ - -void FGPiston::doAirFlow(void) -{ - rho_air = p_amb / (R_air * T_amb); - double rho_air_manifold = MAP / (R_air * T_amb); - double displacement_SI = Displacement * in3tom3; - double swept_volume = (displacement_SI * (RPM/60)) / 2; - double v_dot_air = swept_volume * volumetric_efficiency; - m_dot_air = v_dot_air * rho_air_manifold; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Calculate the fuel flow into the engine. - * - * Inputs: Mixture, thi_sea_level, p_amb_sea_level, p_amb, m_dot_air - * - * Outputs: equivalence_ratio, m_dot_fuel - */ - -void FGPiston::doFuelFlow(void) -{ - double thi_sea_level = 1.3 * Mixture; - equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb; - m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio; - FuelFlow_gph = m_dot_fuel - * 3600 // seconds to hours - * 2.2046 // kg to lb - / 6.6; // lb to gal_us of kerosene -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Calculate the power produced by the engine. - * - * Currently, the JSBSim propellor model does not allow the - * engine to produce enough RPMs to get up to a high horsepower. - * When tested with sufficient RPM, it has no trouble reaching - * 200HP. - * - * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb, - * equivalence_ratio, Cycles, MaxHP - * - * Outputs: Percentage_Power, HP - */ - -void FGPiston::doEnginePower(void) -{ - if (Running) { - double T_amb_degF = KelvinToFahrenheit(T_amb); - double T_amb_sea_lev_degF = KelvinToFahrenheit(288); - - // FIXME: this needs to be generalized - double ManXRPM; // Convienience term for use in the calculations - if(Boosted) { - // Currently a simple linear fit. - // The zero crossing is moved up the speed-load range to reduce the idling power. - // This will change! - double zeroOffset = (minMAP / 2.0) * (IdleRPM / 2.0); - ManXRPM = MAP * (RPM > RatedRPM[BoostSpeed] ? RatedRPM[BoostSpeed] : RPM); - // The speed clip in the line above is deliberate. - Percentage_Power = ((ManXRPM - zeroOffset) / ((RatedMAP[BoostSpeed] * RatedRPM[BoostSpeed]) - zeroOffset)) * 107.0; - Percentage_Power -= 7.0; // Another idle power reduction offset - see line above with 107. - if (Percentage_Power < 0.0) Percentage_Power = 0.0; - // Note that %power is allowed to go over 100 for boosted powerplants - // such as for the BCV-override or takeoff power settings. - // TODO - currently no altitude effect (temperature & exhaust back-pressure) modelled - // for boosted engines. - } else { - ManXRPM = ManifoldPressure_inHg * RPM; // Note that inHg must be used for the following correlation. - Percentage_Power = (6e-9 * ManXRPM * ManXRPM) + (8e-4 * ManXRPM) - 1.0; - Percentage_Power += ((T_amb_sea_lev_degF - T_amb_degF) * 7 /120); - if (Percentage_Power < 0.0) Percentage_Power = 0.0; - else if (Percentage_Power > 100.0) Percentage_Power = 100.0; - } - - double Percentage_of_best_power_mixture_power = - Power_Mixture_Correlation->GetValue(14.7 / equivalence_ratio); - - Percentage_Power *= Percentage_of_best_power_mixture_power / 100.0; - - if(Boosted) { - HP = Percentage_Power * RatedPower[BoostSpeed] / 100.0; - } else { - HP = Percentage_Power * MaxHP / 100.0; - } - - } else { - - // Power output when the engine is not running - if (Cranking) { - if (RPM < 10) { - HP = 3.0; // This is a hack to prevent overshooting the idle rpm in - // the first time step. It may possibly need to be changed - // if the prop model is changed. - } else if (RPM < 480) { - HP = 3.0 + ((480 - RPM) / 10.0); - // This is a guess - would be nice to find a proper starter moter torque curve - } else { - HP = 3.0; - } - } else { - // Quick hack until we port the FMEP stuff - if (RPM > 0.0) - HP = -1.5; - else - HP = 0.0; - } - } - //cout << "Power = " << HP << '\n'; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Calculate the exhaust gas temperature. - * - * Inputs: equivalence_ratio, m_dot_fuel, calorific_value_fuel, - * Cp_air, m_dot_air, Cp_fuel, m_dot_fuel, T_amb, Percentage_Power - * - * Outputs: combustion_efficiency, ExhaustGasTemp_degK - */ - -void FGPiston::doEGT(void) -{ - double delta_T_exhaust; - double enthalpy_exhaust; - double heat_capacity_exhaust; - double dEGTdt; - - if ((Running) && (m_dot_air > 0.0)) { // do the energy balance - combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio); - enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * - combustion_efficiency * 0.33; - heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel); - delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust; - ExhaustGasTemp_degK = T_amb + delta_T_exhaust; - ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * Percentage_Power / 100.0); - } else { // Drop towards ambient - guess an appropriate time constant for now - dEGTdt = (298.0 - ExhaustGasTemp_degK) / 100.0; - delta_T_exhaust = dEGTdt * dt; - ExhaustGasTemp_degK += delta_T_exhaust; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Calculate the cylinder head temperature. - * - * Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel, - * combustion_efficiency, RPM - * - * Outputs: CylinderHeadTemp_degK - */ - -void FGPiston::doCHT(void) -{ - double h1 = -95.0; - double h2 = -3.95; - double h3 = -0.05; - - double arbitary_area = 1.0; - double CpCylinderHead = 800.0; - double MassCylinderHead = 8.0; - - double temperature_difference = CylinderHeadTemp_degK - T_amb; - double v_apparent = IAS * 0.5144444; - double v_dot_cooling_air = arbitary_area * v_apparent; - double m_dot_cooling_air = v_dot_cooling_air * rho_air; - double dqdt_from_combustion = - m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33; - double dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) + - (h3 * RPM * temperature_difference); - double dqdt_free = h1 * temperature_difference; - double dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free; - - double HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead; - - CylinderHeadTemp_degK += - (dqdt_cylinder_head / HeatCapacityCylinderHead) * dt; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Calculate the oil temperature. - * - * Inputs: Percentage_Power, running flag. - * - * Outputs: OilTemp_degK - */ - -void FGPiston::doOilTemperature(void) -{ - double idle_percentage_power = 2.3; // approximately - double target_oil_temp; // Steady state oil temp at the current engine conditions - double time_constant; // The time constant for the differential equation - - if (Running) { - target_oil_temp = 363; - time_constant = 500; // Time constant for engine-on idling. - if (Percentage_Power > idle_percentage_power) { - time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power - } - } else { - target_oil_temp = 298; - time_constant = 1000; // Time constant for engine-off; reflects the fact - // that oil is no longer getting circulated - } - - double dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant; - - OilTemp_degK += (dOilTempdt * dt); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/** - * Calculate the oil pressure. - * - * Inputs: RPM - * - * Outputs: OilPressure_psi - */ - -void FGPiston::doOilPressure(void) -{ - double Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine - double Oil_Press_RPM_Max = 1800; // FIXME: may vary by engine - double Design_Oil_Temp = 358; // degK; FIXME: may vary by engine - double Oil_Viscosity_Index = 0.25; - - OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM; - - if (OilPressure_psi >= Oil_Press_Relief_Valve) { - OilPressure_psi = Oil_Press_Relief_Valve; - } - - OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPiston::GetEngineLabels(string delimeter) -{ - std::ostringstream buf; - - buf << Name << "_PwrAvail[" << EngineNumber << "]" << delimeter - << Name << "_HP[" << EngineNumber << "]" << delimeter - << Name << "_equiv_ratio[" << EngineNumber << "]" << delimeter - << Name << "_MAP[" << EngineNumber << "]" << delimeter - << Thruster->GetThrusterLabels(EngineNumber, delimeter); - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPiston::GetEngineValues(string delimeter) -{ - std::ostringstream buf; - - buf << PowerAvailable << delimeter << HP << delimeter - << equivalence_ratio << delimeter << MAP << delimeter - << Thruster->GetThrusterValues(EngineNumber, delimeter); - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// -// 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 FGPiston::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - - cout << "\n Engine Name: " << Name << endl; - cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl; - cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl; - cout << " Displacement: " << Displacement << endl; - cout << " MaxHP: " << MaxHP << endl; - cout << " Cycles: " << Cycles << endl; - cout << " IdleRPM: " << IdleRPM << endl; - cout << " MaxThrottle: " << MaxThrottle << endl; - cout << " MinThrottle: " << MinThrottle << endl; - - cout << endl; - cout << " Combustion Efficiency table:" << endl; - Lookup_Combustion_Efficiency->Print(); - cout << endl; - - cout << endl; - cout << " Power Mixture Correlation table:" << endl; - Power_Mixture_Correlation->Print(); - cout << endl; - - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGPiston" << endl; - if (from == 1) cout << "Destroyed: FGPiston" << 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; - } - } -} - -double -FGPiston::CalcFuelNeed(void) -{ - return FuelFlow_gph / 3600 * 6 * State->Getdt() * Propulsion->GetRate(); -} - -} // namespace JSBSim diff --git a/src/FDM/JSBSim/FGPiston.h b/src/FDM/JSBSim/FGPiston.h deleted file mode 100644 index 7039aa4d7..000000000 --- a/src/FDM/JSBSim/FGPiston.h +++ /dev/null @@ -1,273 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGPiston.h - Author: Jon S. Berndt - Date started: 09/12/2000 - - ------------- 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. - -HISTORY --------------------------------------------------------------------------------- -09/12/2000 JSB Created -10/01/2001 DPM Modified to use equations from Dave Luff's piston model. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGPISTON_H -#define FGPISTON_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGEngine.h" -#include "FGConfigFile.h" -#include "FGTable.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_PISTON "$Id$"; -#define FG_MAX_BOOST_SPEEDS 3 - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models Dave Luff's Turbo/Supercharged Piston engine model. - Additional elements are required for a supercharged engine. These can be - left off a non-supercharged engine, ie. the changes are all backward - compatible at present. - - - NUMBOOSTSPEEDS - zero (or not present) for a naturally-aspirated engine, - either 1, 2 or 3 for a boosted engine. This corresponds to the number of - supercharger speeds. Merlin XII had 1 speed, Merlin 61 had 2, a late - Griffon engine apparently had 3. No known engine more than 3, although - some German engines apparently had a continuously variable-speed - supercharger. - - - BOOSTOVERRIDE - whether the boost pressure control system (either a boost - control valve for superchargers or wastegate for turbochargers) can be - overriden by the pilot. During wartime this was commonly possible, and - known as "War Emergency Power" by the Brits. 1 or 0 in the config file. - This isn't implemented in the model yet though, there would need to be - some way of getting the boost control cutout lever position (on or off) - from FlightGear first. - - - The next items are all appended with either 1, 2 or 3 depending on which - boost speed they refer to, eg RATEDBOOST1. The rated values seems to have - been a common convention at the time to express the maximum continuously - available power, and the conditions to attain that power. - - - RATEDBOOST[123] - the absolute rated boost above sea level ambient for a - given boost speed, in psi. Eg the Merlin XII had a rated boost of 9psi, - giving approximately 42inHg manifold pressure up to the rated altitude. - - - RATEDALTITUDE[123] - The altitude up to which rated boost can be - maintained. Up to this altitude the boost is maintained constant for a - given throttle position by the BCV or wastegate. Beyond this altitude the - manifold pressure must drop, since the supercharger is now at maximum - unregulated output. The actual pressure multiplier of the supercharger - system is calculated at initialisation from this value. - - - RATEDPOWER[123] - The power developed at rated boost at rated altitude at - rated rpm. - - - RATEDRPM[123] - The rpm at which rated power is developed. - - - TAKEOFFBOOST - Takeoff boost in psi above ambient. Many aircraft had an - extra boost setting beyond rated boost, but not totally uncontrolled as in - the already mentioned boost-control-cutout, typically attained by pushing - the throttle past a mechanical 'gate' preventing its inadvertant use. This - was typically used for takeoff, and emergency situations, generally for - not more than five minutes. This is a change in the boost control - setting, not the actual supercharger speed, and so would only give extra - power below the rated altitude. When TAKEOFFBOOST is specified in the - config file (and is above RATEDBOOST1), then the throttle position is - interpreted as: - - - 0 to 0.95 : idle manifold pressure to rated boost (where attainable) - - 0.96, 0.97, 0.98 : rated boost (where attainable). - - 0.99, 1.0 : takeoff boost (where attainable). - - A typical takeoff boost for an earlyish Merlin was about 12psi, compared - with a rated boost of 9psi. - - It is quite possible that other boost control settings could have been used - on some aircraft, or that takeoff/extra boost could have activated by other - means than pushing the throttle full forward through a gate, but this will - suffice for now. - - Note that MAXMP is still the non-boosted max manifold pressure even for - boosted engines - effectively this is simply a measure of the pressure drop - through the fully open throttle. - - @author Jon S. Berndt (Engine framework code and framework-related mods) - @author Dave Luff (engine operational code) - @author David Megginson (initial porting and additional code) - @version $Id$ - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGPiston : public FGEngine -{ -public: - /// Constructor - FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number); - /// Destructor - ~FGPiston(); - - string GetEngineLabels(string delimeter); - string GetEngineValues(string delimeter); - - double Calculate(void); - double GetPowerAvailable(void) {return PowerAvailable;} - double CalcFuelNeed(void); - - void SetMagnetos(int magnetos) {Magnetos = magnetos;} - - double GetEGT(void) { return EGT_degC; } - int GetMagnetos(void) {return Magnetos;} - - double getExhaustGasTemp_degF(void) {return KelvinToFahrenheit(ExhaustGasTemp_degK);} - double getManifoldPressure_inHg(void) const {return ManifoldPressure_inHg;} - double getCylinderHeadTemp_degF(void) {return KelvinToFahrenheit(CylinderHeadTemp_degK);} - double getOilPressure_psi(void) const {return OilPressure_psi;} - double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} - double getRPM(void) {return RPM;} - -private: - int crank_counter; - - double BrakeHorsePower; - double SpeedSlope; - double SpeedIntercept; - double AltitudeSlope; - double PowerAvailable; - - // timestep - double dt; - - void doEngineStartup(void); - void doBoostControl(void); - void doMAP(void); - void doAirFlow(void); - void doFuelFlow(void); - void doEnginePower(void); - void doEGT(void); - void doCHT(void); - void doOilPressure(void); - void doOilTemperature(void); - - // - // constants - // - - const double R_air; - const double rho_fuel; // kg/m^3 - const double calorific_value_fuel; // W/Kg (approximate) - const double Cp_air; // J/KgK - const double Cp_fuel; // J/KgK - - FGTable *Lookup_Combustion_Efficiency; - FGTable *Power_Mixture_Correlation; - - // - // Configuration - // - double MinManifoldPressure_inHg; // Inches Hg - double MaxManifoldPressure_inHg; // Inches Hg - double Displacement; // cubic inches - double MaxHP; // horsepower - double Cycles; // cycles/power stroke - double IdleRPM; // revolutions per minute - int BoostSpeeds; // Number of super/turbocharger boost speeds - zero implies no turbo/supercharging. - int BoostSpeed; // The current boost-speed (zero-based). - bool Boosted; // Set true for boosted engine. - int BoostOverride; // The raw value read in from the config file - should be 1 or 0 - see description below. - bool bBoostOverride; // Set true if pilot override of the boost regulator was fitted. - // (Typically called 'war emergency power'). - bool bTakeoffBoost; // Set true if extra takeoff / emergency boost above rated boost could be attained. - // (Typically by extra throttle movement past a mechanical 'gate'). - double TakeoffBoost; // Sea-level takeoff boost in psi. (if fitted). - double RatedBoost[FG_MAX_BOOST_SPEEDS]; // Sea-level rated boost in psi. - double RatedAltitude[FG_MAX_BOOST_SPEEDS]; // Altitude at which full boost is reached (boost regulation ends) - // and at which power starts to fall with altitude [ft]. - double RatedRPM[FG_MAX_BOOST_SPEEDS]; // Engine speed at which the rated power for each boost speed is delivered [rpm]. - double RatedPower[FG_MAX_BOOST_SPEEDS]; // Power at rated throttle position at rated altitude [HP]. - double BoostSwitchAltitude[FG_MAX_BOOST_SPEEDS - 1]; // Altitude at which switchover (currently assumed automatic) - // from one boost speed to next occurs [ft]. - double BoostSwitchPressure[FG_MAX_BOOST_SPEEDS - 1]; // Pressure at which boost speed switchover occurs [Pa] - double BoostMul[FG_MAX_BOOST_SPEEDS]; // Pressure multipier of unregulated supercharger - double RatedMAP[FG_MAX_BOOST_SPEEDS]; // Rated manifold absolute pressure [Pa] (BCV clamp) - double TakeoffMAP[FG_MAX_BOOST_SPEEDS]; // Takeoff setting manifold absolute pressure [Pa] (BCV clamp) - double BoostSwitchHysteresis; // Pa. - - double minMAP; // Pa - double maxMAP; // Pa - double MAP; // Pa - - // - // Inputs (in addition to those in FGEngine). - // - double p_amb; // Pascals - double p_amb_sea_level; // Pascals - double T_amb; // degrees Kelvin - double RPM; // revolutions per minute - double IAS; // knots - bool Magneto_Left; - bool Magneto_Right; - int Magnetos; - - // - // Outputs (in addition to those in FGEngine). - // - double rho_air; - double volumetric_efficiency; - double m_dot_air; - double equivalence_ratio; - double m_dot_fuel; - double Percentage_Power; - double HP; - double combustion_efficiency; - double ExhaustGasTemp_degK; - double EGT_degC; - double ManifoldPressure_inHg; - double CylinderHeadTemp_degK; - double OilPressure_psi; - double OilTemp_degK; - - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif diff --git a/src/FDM/JSBSim/FGPropagate.cpp b/src/FDM/JSBSim/FGPropagate.cpp deleted file mode 100644 index 4d5d67767..000000000 --- a/src/FDM/JSBSim/FGPropagate.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGPropagate.cpp - Author: Jon S. Berndt - Date started: 01/05/99 - Purpose: Integrate the EOM to determine instantaneous position - 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 --------------------------------------------------------------------------------- -This class encapsulates the integration of rates and accelerations to get the -current position of the aircraft. - -HISTORY --------------------------------------------------------------------------------- -01/05/99 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -COMMENTS, REFERENCES, and NOTES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling - Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate - School, January 1994 -[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices", - JSC 12960, July 1977 -[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at - NASA-Ames", NASA CR-2497, January 1975 -[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics", - Wiley & Sons, 1979 ISBN 0-471-03032-5 -[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons, - 1982 ISBN 0-471-08936-2 - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef FGFS -# include -# ifdef SG_HAVE_STD_INCLUDES -# include -# include -# else -# include -# include -# endif -#else -# if defined(sgi) && !defined(__GNUC__) -# include -# if (_COMPILER_VERSION < 740) -# include -# else -# include -# endif -# else -# include -# include -# endif -#endif - -#include "FGPropagate.h" -#include "FGState.h" -#include "FGFDMExec.h" -#include "FGAircraft.h" -#include "FGMassBalance.h" -#include "FGInertial.h" -#include "FGPropertyManager.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_PROPAGATE; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex) -{ - Name = "FGPropagate"; - - bind(); - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGPropagate::~FGPropagate(void) -{ - unbind(); - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropagate::InitModel(void) -{ - FGModel::InitModel(); - - SeaLevelRadius = Inertial->RefRadius(); // For initialization ONLY - RunwayRadius = SeaLevelRadius; - - VState.vLocation.SetRadius( SeaLevelRadius + 4.0 ); - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropagate::SetInitialState(const FGInitialCondition *FGIC) -{ - SeaLevelRadius = FGIC->GetSeaLevelRadiusFtIC(); - RunwayRadius = SeaLevelRadius; - - // Set the position lat/lon/radius - VState.vLocation = FGLocation( FGIC->GetLongitudeRadIC(), - FGIC->GetLatitudeRadIC(), - FGIC->GetAltitudeFtIC() + FGIC->GetSeaLevelRadiusFtIC() ); - - // Set the Orientation from the euler angles - VState.vQtrn = FGQuaternion( FGIC->GetPhiRadIC(), - FGIC->GetThetaRadIC(), - FGIC->GetPsiRadIC() ); - - // Set the velocities in the instantaneus body frame - VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(), - FGIC->GetVBodyFpsIC(), - FGIC->GetWBodyFpsIC() ); - - // Set the angular velocities in the instantaneus body frame. - VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(), - FGIC->GetQRadpsIC(), - FGIC->GetRRadpsIC() ); - - // Compute some derived values. - vVel = VState.vQtrn.GetTInv()*VState.vUVW; - - // Finaly make shure that the quaternion stays normalized. - VState.vQtrn.Normalize(); - - // Recompute the RunwayRadius level. - RecomputeRunwayRadius(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/* -Purpose: Called on a schedule to perform EOM integration -Notes: [JB] Run in standalone mode, SeaLevelRadius will be reference radius. - In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass. - -At the top of this Run() function, see several "shortcuts" (or, aliases) being -set up for use later, rather than using the longer class->function() notation. - -Here, propagation of state is done using a simple explicit Euler scheme (see the -bottom of the function). This propagation is done using the current state values -and current derivatives. Based on these values we compute an approximation to the -state values for (now + dt). - -*/ - -bool FGPropagate::Run(void) -{ - if (FGModel::Run()) return true; // Fast return if we have nothing to do ... - - RecomputeRunwayRadius(); - - double dt = State->Getdt()*rate; // The 'stepsize' - const FGColumnVector3 omega( 0.0, 0.0, Inertial->omega() ); // earth rotation - const FGColumnVector3& vForces = Aircraft->GetForces(); // current forces - const FGColumnVector3& vMoments = Aircraft->GetMoments(); // current moments - - double mass = MassBalance->GetMass(); // mass - const FGMatrix33& J = MassBalance->GetJ(); // inertia matrix - const FGMatrix33& Jinv = MassBalance->GetJinv(); // inertia matrix inverse - double r = GetRadius(); // radius - if (r == 0.0) {cerr << "radius = 0 !" << endl; r = 1e-16;} // radius check - double rInv = 1.0/r; - FGColumnVector3 gAccel( 0.0, 0.0, Inertial->GetGAccel(r) ); - - // The rotation matrices: - const FGMatrix33& Tl2b = GetTl2b(); // local to body frame - const FGMatrix33& Tb2l = GetTb2l(); // body to local frame - const FGMatrix33& Tec2l = VState.vLocation.GetTec2l(); // earth centered to local frame - const FGMatrix33& Tl2ec = VState.vLocation.GetTl2ec(); // local to earth centered frame - - // Inertial angular velocity measured in the body frame. - const FGColumnVector3 pqri = VState.vPQR + Tl2b*(Tec2l*omega); - - // Compute vehicle velocity wrt EC frame, expressed in Local horizontal frame. - vVel = Tb2l * VState.vUVW; - - // First compute the time derivatives of the vehicle state values: - - // Compute body frame rotational accelerations based on the current body moments - vPQRdot = Jinv*(vMoments - pqri*(J*pqri)); - - // Compute body frame accelerations based on the current body forces - vUVWdot = VState.vUVW*VState.vPQR + vForces/mass; - - // Coriolis acceleration. - FGColumnVector3 ecVel = Tl2ec*vVel; - FGColumnVector3 ace = 2.0*omega*ecVel; - vUVWdot -= Tl2b*(Tec2l*ace); - - // Centrifugal acceleration. - FGColumnVector3 aeec = omega*(omega*VState.vLocation); - vUVWdot -= Tl2b*(Tec2l*aeec); - - // Gravitation accel - vUVWdot += Tl2b*gAccel; - - // Compute vehicle velocity wrt EC frame, expressed in EC frame - FGColumnVector3 vLocationDot = Tl2ec * vVel; - - FGColumnVector3 omegaLocal( rInv*vVel(eEast), - -rInv*vVel(eNorth), - -rInv*vVel(eEast)*VState.vLocation.GetTanLatitude() ); - - // Compute quaternion orientation derivative on current body rates - FGQuaternion vQtrndot = VState.vQtrn.GetQDot( VState.vPQR - Tl2b*omegaLocal ); - - // Propagate velocities - VState.vPQR += dt*vPQRdot; - VState.vUVW += dt*vUVWdot; - - // Propagate positions - VState.vQtrn += dt*vQtrndot; - VState.vLocation += dt*vLocationDot; - - return false; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -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(); - double t = State->Getsim_time(); - gcb->GetAGLevel(t, VState.vLocation, contactloc, dv, dv); - RunwayRadius = contactloc.GetRadius(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropagate::Seth(double tt) -{ - VState.vLocation.SetRadius( tt + SeaLevelRadius ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGPropagate::GetRunwayRadius(void) const -{ - return RunwayRadius; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGPropagate::GetDistanceAGL(void) const -{ - return VState.vLocation.GetRadius() - RunwayRadius; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropagate::SetDistanceAGL(double tt) -{ - VState.vLocation.SetRadius( tt + RunwayRadius ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropagate::bind(void) -{ - typedef double (FGPropagate::*PMF)(int) const; - PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot); - - PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel); - PropertyManager->Tie("velocities/v-east-fps", this, eEast, (PMF)&FGPropagate::GetVel); - PropertyManager->Tie("velocities/v-down-fps", this, eDown, (PMF)&FGPropagate::GetVel); - - PropertyManager->Tie("velocities/u-fps", this, eU, (PMF)&FGPropagate::GetUVW); - PropertyManager->Tie("velocities/v-fps", this, eV, (PMF)&FGPropagate::GetUVW); - PropertyManager->Tie("velocities/w-fps", this, eW, (PMF)&FGPropagate::GetUVW); - - PropertyManager->Tie("velocities/p-rad_sec", this, eP, (PMF)&FGPropagate::GetPQR); - PropertyManager->Tie("velocities/q-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQR); - PropertyManager->Tie("velocities/r-rad_sec", this, eR, (PMF)&FGPropagate::GetPQR); - - PropertyManager->Tie("accelerations/pdot-rad_sec", this, eP, (PMF)&FGPropagate::GetPQRdot); - PropertyManager->Tie("accelerations/qdot-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQRdot); - PropertyManager->Tie("accelerations/rdot-rad_sec", this, eR, (PMF)&FGPropagate::GetPQRdot); - - PropertyManager->Tie("accelerations/udot-fps", this, eU, (PMF)&FGPropagate::GetUVWdot); - PropertyManager->Tie("accelerations/vdot-fps", this, eV, (PMF)&FGPropagate::GetUVWdot); - PropertyManager->Tie("accelerations/wdot-fps", this, eW, (PMF)&FGPropagate::GetUVWdot); - - PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::Geth, &FGPropagate::Seth, true); - PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude); - PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude); - PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL); - PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius); - - PropertyManager->Tie("metrics/runway-radius", this, &FGPropagate::GetRunwayRadius); - - PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); - - PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); - PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropagate::unbind(void) -{ - PropertyManager->Untie("velocities/v-north-fps"); - PropertyManager->Untie("velocities/v-east-fps"); - PropertyManager->Untie("velocities/v-down-fps"); - PropertyManager->Untie("velocities/h-dot-fps"); - PropertyManager->Untie("velocities/u-fps"); - PropertyManager->Untie("velocities/v-fps"); - PropertyManager->Untie("velocities/w-fps"); - PropertyManager->Untie("velocities/p-rad_sec"); - PropertyManager->Untie("velocities/q-rad_sec"); - PropertyManager->Untie("velocities/r-rad_sec"); - PropertyManager->Untie("accelerations/udot-fps"); - PropertyManager->Untie("accelerations/vdot-fps"); - PropertyManager->Untie("accelerations/wdot-fps"); - PropertyManager->Untie("accelerations/pdot-rad_sec"); - PropertyManager->Untie("accelerations/qdot-rad_sec"); - PropertyManager->Untie("accelerations/rdot-rad_sec"); - PropertyManager->Untie("position/h-sl-ft"); - PropertyManager->Untie("position/lat-gc-rad"); - PropertyManager->Untie("position/long-gc-rad"); - PropertyManager->Untie("position/h-agl-ft"); - PropertyManager->Untie("position/radius-to-vehicle-ft"); - PropertyManager->Untie("metrics/runway-radius"); - PropertyManager->Untie("attitude/phi-rad"); - PropertyManager->Untie("attitude/theta-rad"); - PropertyManager->Untie("attitude/psi-rad"); - PropertyManager->Untie("attitude/roll-rad"); - PropertyManager->Untie("attitude/pitch-rad"); - PropertyManager->Untie("attitude/heading-true-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 FGPropagate::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: FGPropagate" << endl; - if (from == 1) cout << "Destroyed: FGPropagate" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGPropagate.h b/src/FDM/JSBSim/FGPropagate.h deleted file mode 100644 index b778bb096..000000000 --- a/src/FDM/JSBSim/FGPropagate.h +++ /dev/null @@ -1,167 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGPropagate.h - Author: Jon S. Berndt - Date started: 1/5/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 --------------------------------------------------------------------------------- -01/05/99 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGPROPAGATE_H -#define FGPROPAGATE_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGModel.h" -#include "FGColumnVector3.h" -#include "FGInitialCondition.h" -#include "FGLocation.h" -#include "FGQuaternion.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_PROPAGATE "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models the EOM and integration/propagation of state - @author Jon S. Berndt, Mathias Froehlich - @version $Id$ - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -// state vector - -struct VehicleState { - FGLocation vLocation; - FGColumnVector3 vUVW; - FGColumnVector3 vPQR; - FGQuaternion vQtrn; -}; - -class FGPropagate : public FGModel { -public: - /** Constructor - @param Executive a pointer to the parent executive object */ - FGPropagate(FGFDMExec* Executive); - - /// Destructor - ~FGPropagate(); - - bool InitModel(void); - - /** Runs the Propagate model; called by the Executive - @return false if no error */ - bool Run(void); - - const FGColumnVector3& GetVel(void) const { return vVel; } - const FGColumnVector3& GetUVW(void) const { return VState.vUVW; } - const FGColumnVector3& GetUVWdot(void) const { return vUVWdot; } - const FGColumnVector3& GetPQR(void) const {return VState.vPQR;} - const FGColumnVector3& GetPQRdot(void) const {return vPQRdot;} - const FGColumnVector3& GetEuler(void) const { return VState.vQtrn.GetEuler(); } - - double GetUVW (int idx) const { return VState.vUVW(idx); } - double GetUVWdot(int idx) const { return vUVWdot(idx); } - double GetVel(int idx) const { return vVel(idx); } - double Geth(void) const { return VState.vLocation.GetRadius() - SeaLevelRadius; } - double GetPQR(int axis) const {return VState.vPQR(axis);} - double GetPQRdot(int idx) const {return vPQRdot(idx);} - double GetEuler(int axis) const { return VState.vQtrn.GetEuler(axis); } - double GetCosEuler(int idx) const { return VState.vQtrn.GetCosEuler(idx); } - double GetSinEuler(int idx) const { return VState.vQtrn.GetSinEuler(idx); } - double Gethdot(void) const { return -vVel(eDown); } - - /** Returns the "constant" RunwayRadius. - The RunwayRadius parameter is set by the calling application or set to - zero if JSBSim is running in standalone mode. - @return distance of the runway from the center of the earth. - @units feet */ - double GetRunwayRadius(void) const; - double GetSeaLevelRadius(void) const { return SeaLevelRadius; } - double GetDistanceAGL(void) const; - double GetRadius(void) const { return VState.vLocation.GetRadius(); } - double GetLongitude(void) const { return VState.vLocation.GetLongitude(); } - double GetLatitude(void) const { return VState.vLocation.GetLatitude(); } - const FGLocation& GetLocation(void) const { return VState.vLocation; } - - /** Retrieves the local-to-body transformation matrix. - @return a reference to the local-to-body transformation matrix. */ - const FGMatrix33& GetTl2b(void) const { return VState.vQtrn.GetT(); } - - /** Retrieves the body-to-local transformation matrix. - @return a reference to the body-to-local matrix. */ - const FGMatrix33& GetTb2l(void) const { return VState.vQtrn.GetTInv(); } - -// SET functions - - void SetLongitude(double lon) { VState.vLocation.SetLongitude(lon); } - void SetLatitude(double lat) { VState.vLocation.SetLatitude(lat); } - void SetRadius(double r) { VState.vLocation.SetRadius(r); } - void SetLocation(const FGLocation& l) { VState.vLocation = l; } - void Seth(double tt); - void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; } - void SetDistanceAGL(double tt); - void SetInitialState(const FGInitialCondition *); - - void RecomputeRunwayRadius(void); - - void bind(void); - void unbind(void); - -private: - -// state vector - - struct VehicleState VState; - - FGColumnVector3 vVel; - FGColumnVector3 vPQRdot; - FGColumnVector3 vUVWdot; - - double RunwayRadius, SeaLevelRadius; - - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif diff --git a/src/FDM/JSBSim/FGPropeller.cpp b/src/FDM/JSBSim/FGPropeller.cpp deleted file mode 100644 index 6ef0f53a1..000000000 --- a/src/FDM/JSBSim/FGPropeller.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGPropeller.cpp - Author: Jon S. Berndt - Date started: 08/24/00 - Purpose: Encapsulates the propeller object - - ------------- 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 --------------------------------------------------------------------------------- -08/24/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "FGPropeller.h" -#include "FGPropagate.h" -#include "FGAtmosphere.h" -#include "FGAuxiliary.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_PROPELLER; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -// This class currently makes certain assumptions when calculating torque and -// p-factor. That is, that the axis of rotation is the X axis of the aircraft - -// not just the X-axis of the engine/propeller. This may or may not work for a -// helicopter. - -FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg, int num) : FGThruster(exec) -{ - string token; - int rows, cols; - - MaxPitch = MinPitch = P_Factor = Sense = Pitch = Advance = 0.0; - GearRatio = 1.0; - - Name = Prop_cfg->GetValue("NAME"); - Prop_cfg->GetNextConfigLine(); - while (Prop_cfg->GetValue() != string("/FG_PROPELLER")) { - *Prop_cfg >> token; - if (token == "IXX") { - *Prop_cfg >> Ixx; - } else if (token == "DIAMETER") { - *Prop_cfg >> Diameter; - Diameter /= 12.0; - } else if (token == "NUMBLADES") { - *Prop_cfg >> numBlades; - } else if (token == "GEARRATIO") { - *Prop_cfg >> GearRatio; - } else if (token == "MINPITCH") { - *Prop_cfg >> MinPitch; - } else if (token == "MAXPITCH") { - *Prop_cfg >> MaxPitch; - } else if (token == "MINRPM") { - *Prop_cfg >> MinRPM; - } else if (token == "MAXRPM") { - *Prop_cfg >> MaxRPM; - } else if (token == "C_THRUST") { - *Prop_cfg >> rows >> cols; - if (cols == 1) cThrust = new FGTable(rows); - else cThrust = new FGTable(rows, cols); - *cThrust << *Prop_cfg; - } else if (token == "C_POWER") { - *Prop_cfg >> rows >> cols; - if (cols == 1) cPower = new FGTable(rows); - else cPower = new FGTable(rows, cols); - *cPower << *Prop_cfg; - } else if (token == "EOF") { - cerr << " End of file reached" << endl; - break; - } else { - cerr << "Unhandled token in Propeller config file: " << token << endl; - } - } - - Type = ttPropeller; - RPM = 0; - vTorque.InitMatrix(); - - char property_name[80]; - snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); - PropertyManager->Tie( property_name, &ThrustCoeff ); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGPropeller::~FGPropeller() -{ - if (cThrust) delete cThrust; - if (cPower) delete cPower; - - char property_name[80]; - snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); - PropertyManager->Untie( property_name ); - - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// -// We must be getting the aerodynamic velocity here, NOT the inertial velocity. -// We need the velocity with respect to the wind. -// -// Note that PowerAvailable is the excess power available after the drag of the -// propeller has been subtracted. At equilibrium, PowerAvailable will be zero - -// indicating that the propeller will not accelerate or decelerate. -// Remembering that Torque * omega = Power, we can derive the torque on the -// propeller and its acceleration to give a new RPM. The current RPM will be -// used to calculate thrust. -// -// Because RPM could be zero, we need to be creative about what RPM is stated as. - -double FGPropeller::Calculate(double PowerAvailable) -{ - double J, omega; - double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU); - double rho = fdmex->GetAtmosphere()->GetDensity(); - double RPS = RPM/60.0; - double alpha, beta; - - if (RPM > 0.10) { - J = Vel / (Diameter * RPS); - } else { - J = 0.0; - } - - if (MaxPitch == MinPitch) { // Fixed pitch prop - ThrustCoeff = cThrust->GetValue(J); - } else { // Variable pitch prop - ThrustCoeff = cThrust->GetValue(J, Pitch); - } - - if (P_Factor > 0.0001) { - alpha = fdmex->GetAuxiliary()->Getalpha(); - beta = fdmex->GetAuxiliary()->Getbeta(); - SetActingLocationY( GetLocationY() + P_Factor*alpha*Sense); - SetActingLocationZ( GetLocationZ() + P_Factor*beta*Sense); - } else if (P_Factor < 0.000) { - cerr << "P-Factor value in config file must be greater than zero" << endl; - } - - Thrust = ThrustCoeff*RPS*RPS*Diameter*Diameter*Diameter*Diameter*rho; - omega = RPS*2.0*M_PI; - - vFn(1) = Thrust; - - // The Ixx value and rotation speed given below are for rotation about the - // natural axis of the engine. The transform takes place in the base class - // FGForce::GetBodyForces() function. - - vH(eX) = Ixx*omega*Sense; - vH(eY) = 0.0; - vH(eZ) = 0.0; - - if (omega <= 5) omega = 1.0; - - ExcessTorque = PowerAvailable / omega * GearRatio; - RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0; - - // The friction from the engine should - // stop it somewhere; I chose an - // arbitrary point. - if (RPM < 5.0) - RPM = 0; - - vMn = fdmex->GetPropagate()->GetPQR()*vH + vTorque*Sense; - - return Thrust; // return thrust in pounds -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGPropeller::GetPowerRequired(void) -{ - if (RPM <= 0.10) return 0.0; // If the prop ain't turnin', the fuel ain't burnin'. - - double cPReq, RPS = RPM / 60.0; - - double J = fdmex->GetAuxiliary()->GetAeroUVW(eU) / (Diameter * RPS); - double rho = fdmex->GetAtmosphere()->GetDensity(); - - if (MaxPitch == MinPitch) { // Fixed pitch prop - Pitch = MinPitch; - cPReq = cPower->GetValue(J); - } else { // Variable pitch prop - - if (MaxRPM != MinRPM) { // fixed-speed prop - double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance; - double dRPM = rpmReq - RPM; - - Pitch -= dRPM / 10; - - if (Pitch < MinPitch) Pitch = MinPitch; - else if (Pitch > MaxPitch) Pitch = MaxPitch; - - } else { - Pitch = MinPitch + (MaxPitch - MinPitch) * Advance; - } - cPReq = cPower->GetValue(J, Pitch); - } - - PowerRequired = cPReq*RPS*RPS*RPS*Diameter*Diameter*Diameter*Diameter - *Diameter*rho; - vTorque(eX) = -Sense*PowerRequired / (RPS*2.0*M_PI); - - return PowerRequired; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGColumnVector3 FGPropeller::GetPFactor() -{ - double px=0.0, py, pz; - - py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0; - pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0; - - return FGColumnVector3(px, py, pz); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropeller::GetThrusterLabels(int id, string delimeter) -{ - std::ostringstream buf; - - buf << Name << "_Torque[" << id << "]" << delimeter - << Name << "_PFactor_Pitch[" << id << "]" << delimeter - << Name << "_PFactor_Yaw[" << id << "]" << delimeter - << Name << "_Thrust[" << id << "]" << delimeter; - if (IsVPitch()) - buf << Name << "_Pitch[" << id << "]" << delimeter; - buf << Name << "_RPM[" << id << "]"; - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropeller::GetThrusterValues(int id, string delimeter) -{ - std::ostringstream buf; - - FGColumnVector3 vPFactor = GetPFactor(); - buf << vTorque(eX) << delimeter - << vPFactor(ePitch) << delimeter - << vPFactor(eYaw) << delimeter - << Thrust << delimeter; - if (IsVPitch()) - buf << Pitch << delimeter; - buf << RPM; - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGPropeller::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << "\n Propeller Name: " << Name << endl; - cout << " IXX = " << Ixx << endl; - cout << " Diameter = " << Diameter << " ft." << endl; - cout << " Number of Blades = " << numBlades << endl; - cout << " Minimum Pitch = " << MinPitch << endl; - cout << " Maximum Pitch = " << MaxPitch << endl; - cout << " Thrust Coefficient: " << endl; - cThrust->Print(); - cout << " Power Coefficient: " << endl; - cPower->Print(); - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGPropeller" << endl; - if (from == 1) cout << "Destroyed: FGPropeller" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGPropeller.h b/src/FDM/JSBSim/FGPropeller.h deleted file mode 100644 index 0434e6943..000000000 --- a/src/FDM/JSBSim/FGPropeller.h +++ /dev/null @@ -1,184 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGPropeller.h - Author: Jon S. Berndt - Date started: 08/24/00 - - ------------- 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. - -HISTORY --------------------------------------------------------------------------------- -08/24/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGPROPELLER_H -#define FGPROPELLER_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGThruster.h" -#include "FGTable.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_PROPELLER "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Propeller modeling class. - FGPropeller models a propeller given the tabular data for Ct and Cp - indexed by advance ratio "J". The data for the propeller is - stored in a config file named "prop_name.xml". The propeller config file - is referenced from the main aircraft config file in the "Propulsion" section. - See the constructor for FGPropeller to see what is read in and what should - be stored in the config file.
- Several references were helpful, here:
    -
  • Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics", - Wiley & Sons, 1979 ISBN 0-471-03032-5
  • -
  • Edwin Hartman, David Biermann, "The Aerodynamic Characteristics of - Full Scale Propellers Having 2, 3, and 4 Blades of Clark Y and R.A.F. 6 - Airfoil Sections", NACA Report TN-640, 1938 (?)
  • -
  • Various NACA Technical Notes and Reports
  • -
- @author Jon S. Berndt - @version $Id$ - @see FGEngine - @see FGThruster - @see FGTable -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGPropeller : public FGThruster { - -public: - /** Constructor for FGPropeller. - @param exec a pointer to the main executive object - @param AC_cfg a pointer to the main aircraft config file object */ - FGPropeller(FGFDMExec* exec, FGConfigFile* AC_cfg, int num = 0); - - /// Destructor for FGPropeller - deletes the FGTable objects - ~FGPropeller(); - - /** Sets the Revolutions Per Minute for the propeller. Normally the propeller - instance will calculate its own rotational velocity, given the Torque - produced by the engine and integrating over time using the standard - equation for rotational acceleration "a": a = Q/I , where Q is Torque and - I is moment of inertia for the propeller. - @param rpm the rotational velocity of the propeller */ - void SetRPM(double rpm) {RPM = rpm;} - - /// Returns true of this propeller is variable pitch - bool IsVPitch(void) {return MaxPitch != MinPitch;} - - /** This commands the pitch of the blade to change to the value supplied. - This call is meant to be issued either from the cockpit or by the flight - control system (perhaps to maintain constant RPM for a constant-speed - propeller). This value will be limited to be within whatever is specified - in the config file for Max and Min pitch. It is also one of the lookup - indices to the power and thrust tables for variable-pitch propellers. - @param pitch the pitch of the blade in degrees. */ - void SetPitch(double pitch) {Pitch = pitch;} - - void SetAdvance(double advance) {Advance = advance;} - - /// Sets the P-Factor constant - void SetPFactor(double pf) {P_Factor = pf;} - - /** Sets the rotation sense of the propeller. - @param s this value should be +/- 1 ONLY. +1 indicates clockwise rotation as - viewed by someone standing behind the engine looking forward into - the direction of flight. */ - void SetSense(double s) { Sense = s;} - - double GetSense(void) {return Sense;} - double GetPFactorValue(void) {return P_Factor;} - - /// Retrieves the pitch of the propeller in degrees. - double GetPitch(void) { return Pitch; } - - /// Retrieves the RPMs of the propeller - double GetRPM(void) { return RPM; } - - /// Retrieves the propeller moment of inertia - double GetIxx(void) { return Ixx; } - - /// Retrieves the Torque in foot-pounds (Don't you love the English system?) - double GetTorque(void) { return vTorque(eX); } - - /** Retrieves the power required (or "absorbed") by the propeller - - i.e. the power required to keep spinning the propeller at the current - velocity, air density, and rotational rate. */ - double GetPowerRequired(void); - - /** Calculates and returns the thrust produced by this propeller. - Given the excess power available from the engine (in foot-pounds), the thrust is - calculated, as well as the current RPM. The RPM is calculated by integrating - the torque provided by the engine over what the propeller "absorbs" - (essentially the "drag" of the propeller). - @param PowerAvailable this is the excess power provided by the engine to - accelerate the prop. It could be negative, dictating that the propeller - would be slowed. - @return the thrust in pounds */ - double Calculate(double PowerAvailable); - FGColumnVector3 GetPFactor(void); - string GetThrusterLabels(int id, string delimeter); - string GetThrusterValues(int id, string delimeter); - -private: - int numBlades; - double RPM; - double Ixx; - double Diameter; - double MaxPitch; - double MinPitch; - double MinRPM; - double MaxRPM; - double P_Factor; - double Sense; - double Pitch; - double Advance; - double ExcessTorque; - FGColumnVector3 vTorque; - FGTable *cThrust; - FGTable *cPower; - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGPropertyManager.cpp b/src/FDM/JSBSim/FGPropertyManager.cpp deleted file mode 100644 index 42d632d4b..000000000 --- a/src/FDM/JSBSim/FGPropertyManager.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGPropertyManager.cpp - Author: Tony Peden - Based on work originally by David Megginson - Date: 2/2002 - - ------------- Copyright (C) 2002 ------------- - - 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. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGPropertyManager.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -using namespace std; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*/ - -namespace JSBSim { - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropertyManager::mkPropertyName(string name, bool lowercase) { - - /* do this two pass to avoid problems with characters getting skipped - because the index changed */ - unsigned i; - for(i=0;igetNode(path.c_str(), create); - //if(node == 0) - // cout << "FGPropertyManager::GetNode() No node found for " - // << path << endl; - return (FGPropertyManager*)node; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGPropertyManager* -FGPropertyManager::GetNode (const string &relpath, int index, bool create) -{ - return (FGPropertyManager*)getNode(relpath.c_str(),index,create); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -bool FGPropertyManager::HasNode (const string &path) -{ - return (GetNode(path, false) != 0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropertyManager::GetName( void ) { - return string( getName() ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropertyManager::GetFullyQualifiedName(void) { - vector stack; - stack.push_back( getDisplayName(true) ); - SGPropertyNode* tmpn=getParent(); - bool atroot=false; - while( !atroot ) { - stack.push_back( tmpn->getDisplayName(true) ); - if( !tmpn->getParent() ) - atroot=true; - else - tmpn=tmpn->getParent(); - } - - string fqname=""; - for(unsigned i=stack.size()-1;i>0;i--) { - fqname+= stack[i]; - fqname+= "/"; - } - fqname+= stack[0]; - return fqname; - -} - - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropertyManager::GetBool (const string &name, bool defaultValue) -{ - return getBoolValue(name.c_str(), defaultValue); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -int FGPropertyManager::GetInt (const string &name, int defaultValue ) -{ - return getIntValue(name.c_str(), defaultValue); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -int FGPropertyManager::GetLong (const string &name, long defaultValue ) -{ - return getLongValue(name.c_str(), defaultValue); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -float FGPropertyManager::GetFloat (const string &name, float defaultValue ) -{ - return getFloatValue(name.c_str(), defaultValue); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGPropertyManager::GetDouble (const string &name, double defaultValue ) -{ - return getDoubleValue(name.c_str(), defaultValue); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropertyManager::GetString (const string &name, string defaultValue ) -{ - return string(getStringValue(name.c_str(), defaultValue.c_str())); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropertyManager::SetBool (const string &name, bool val) -{ - return setBoolValue(name.c_str(), val); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropertyManager::SetInt (const string &name, int val) -{ - return setIntValue(name.c_str(), val); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropertyManager::SetLong (const string &name, long val) -{ - return setLongValue(name.c_str(), val); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropertyManager::SetFloat (const string &name, float val) -{ - return setFloatValue(name.c_str(), val); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropertyManager::SetDouble (const string &name, double val) -{ - return setDoubleValue(name.c_str(), val); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropertyManager::SetString (const string &name, const string &val) -{ - return setStringValue(name.c_str(), val.c_str()); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::SetArchivable (const string &name, bool state ) -{ - SGPropertyNode * node = getNode(name.c_str()); - if (node == 0) - cout << - "Attempt to set archive flag for non-existant property " - << name << endl; - else - node->setAttribute(SGPropertyNode::ARCHIVE, state); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::SetReadable (const string &name, bool state ) -{ - SGPropertyNode * node = getNode(name.c_str()); - if (node == 0) - cout << - "Attempt to set read flag for non-existant property " - << name << endl; - else - node->setAttribute(SGPropertyNode::READ, state); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::SetWritable (const string &name, bool state ) -{ - SGPropertyNode * node = getNode(name.c_str()); - if (node == 0) - cout << - "Attempt to set write flag for non-existant property " - << name << endl; - else - node->setAttribute(SGPropertyNode::WRITE, state); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::Untie (const string &name) -{ - if (!untie(name.c_str())) - cout << "Failed to untie property " << name << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault) -{ - if (!tie(name.c_str(), SGRawValuePointer(pointer), - useDefault)) - cout << - "Failed to tie property " << name << " to a pointer" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::Tie (const string &name, int *pointer, - bool useDefault ) -{ - if (!tie(name.c_str(), SGRawValuePointer(pointer), - useDefault)) - cout << - "Failed to tie property " << name << " to a pointer" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::Tie (const string &name, long *pointer, - bool useDefault ) -{ - if (!tie(name.c_str(), SGRawValuePointer(pointer), - useDefault)) - cout << - "Failed to tie property " << name << " to a pointer" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::Tie (const string &name, float *pointer, - bool useDefault ) -{ - if (!tie(name.c_str(), SGRawValuePointer(pointer), - useDefault)) - cout << - "Failed to tie property " << name << " to a pointer" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropertyManager::Tie (const string &name, double *pointer, - bool useDefault) -{ - if (!tie(name.c_str(), SGRawValuePointer(pointer), - useDefault)) - cout << - "Failed to tie property " << name << " to a pointer" << endl; -} - -} // namespace JSBSim diff --git a/src/FDM/JSBSim/FGPropertyManager.h b/src/FDM/JSBSim/FGPropertyManager.h deleted file mode 100644 index e257e9bc4..000000000 --- a/src/FDM/JSBSim/FGPropertyManager.h +++ /dev/null @@ -1,611 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGPropertyManager.h - Author: Tony Peden - Based on work originally by David Megginson - Date: 2/2002 - - ------------- Copyright (C) 2002 ------------- - - 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 FGPROPERTYMANAGER_H -#define FGPROPERTYMANAGER_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include -#ifdef FGFS -#include -#else -#include "simgear/props/props.hxx" -#endif - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_PROPERTYMANAGER "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -using namespace std; - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Class wrapper for property handling. - @author David Megginson, Tony Peden - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGPropertyManager : public SGPropertyNode { - public: - /// Constructor - FGPropertyManager(void) {} - /// Destructor - ~FGPropertyManager(void) {} - - /** Property-ify a name - * replaces spaces with '-' and, optionally, makes name all lower case - * @param name string to change - * @param lowercase true to change all upper case chars to lower - * NOTE: this function changes its argument and thus relies - * on pass by value - */ - string mkPropertyName(string name, bool lowercase); - - /** - * Get a property node. - * - * @param path The path of the node, relative to root. - * @param create true to create the node if it doesn't exist. - * @return The node, or 0 if none exists and none was created. - */ - FGPropertyManager* - GetNode (const string &path, bool create = false); - - FGPropertyManager* - GetNode (const string &relpath, int index, bool create = false); - - /** - * Test whether a given node exists. - * - * @param path The path of the node, relative to root. - * @return true if the node exists, false otherwise. - */ - bool HasNode (const string &path); - - /** - * Get the name of a node - */ - string GetName( void ); - - /** - * Get the fully qualified name of a node - * This function is very slow, so is probably useful for debugging only. - */ - string GetFullyQualifiedName(void); - - /** - * Get a bool value for a property. - * - * This method is convenient but inefficient. It should be used - * infrequently (i.e. for initializing, loading, saving, etc.), - * not in the main loop. If you need to get a value frequently, - * it is better to look up the node itself using GetNode and then - * use the node's getBoolValue() method, to avoid the lookup overhead. - * - * @param name The property name. - * @param defaultValue The default value to return if the property - * does not exist. - * @return The property's value as a bool, or the default value provided. - */ - bool GetBool (const string &name, bool defaultValue = false); - - - /** - * Get an int value for a property. - * - * This method is convenient but inefficient. It should be used - * infrequently (i.e. for initializing, loading, saving, etc.), - * not in the main loop. If you need to get a value frequently, - * it is better to look up the node itself using GetNode and then - * use the node's getIntValue() method, to avoid the lookup overhead. - * - * @param name The property name. - * @param defaultValue The default value to return if the property - * does not exist. - * @return The property's value as an int, or the default value provided. - */ - int GetInt (const string &name, int defaultValue = 0); - - - /** - * Get a long value for a property. - * - * This method is convenient but inefficient. It should be used - * infrequently (i.e. for initializing, loading, saving, etc.), - * not in the main loop. If you need to get a value frequently, - * it is better to look up the node itself using GetNode and then - * use the node's getLongValue() method, to avoid the lookup overhead. - * - * @param name The property name. - * @param defaultValue The default value to return if the property - * does not exist. - * @return The property's value as a long, or the default value provided. - */ - int GetLong (const string &name, long defaultValue = 0L); - - - /** - * Get a float value for a property. - * - * This method is convenient but inefficient. It should be used - * infrequently (i.e. for initializing, loading, saving, etc.), - * not in the main loop. If you need to get a value frequently, - * it is better to look up the node itself using GetNode and then - * use the node's getFloatValue() method, to avoid the lookup overhead. - * - * @param name The property name. - * @param defaultValue The default value to return if the property - * does not exist. - * @return The property's value as a float, or the default value provided. - */ - float GetFloat (const string &name, float defaultValue = 0.0); - - - /** - * Get a double value for a property. - * - * This method is convenient but inefficient. It should be used - * infrequently (i.e. for initializing, loading, saving, etc.), - * not in the main loop. If you need to get a value frequently, - * it is better to look up the node itself using GetNode and then - * use the node's getDoubleValue() method, to avoid the lookup overhead. - * - * @param name The property name. - * @param defaultValue The default value to return if the property - * does not exist. - * @return The property's value as a double, or the default value provided. - */ - double GetDouble (const string &name, double defaultValue = 0.0); - - - /** - * Get a string value for a property. - * - * This method is convenient but inefficient. It should be used - * infrequently (i.e. for initializing, loading, saving, etc.), - * not in the main loop. If you need to get a value frequently, - * it is better to look up the node itself using GetNode and then - * use the node's getStringValue() method, to avoid the lookup overhead. - * - * @param name The property name. - * @param defaultValue The default value to return if the property - * does not exist. - * @return The property's value as a string, or the default value provided. - */ - string GetString (const string &name, string defaultValue = ""); - - - /** - * Set a bool value for a property. - * - * Assign a bool value to a property. If the property does not - * yet exist, it will be created and its type will be set to - * BOOL; if it has a type of UNKNOWN, the type will also be set to - * BOOL; otherwise, the bool value will be converted to the property's - * type. - * - * @param name The property name. - * @param val The new value for the property. - * @return true if the assignment succeeded, false otherwise. - */ - bool SetBool (const string &name, bool val); - - - /** - * Set an int value for a property. - * - * Assign an int value to a property. If the property does not - * yet exist, it will be created and its type will be set to - * INT; if it has a type of UNKNOWN, the type will also be set to - * INT; otherwise, the bool value will be converted to the property's - * type. - * - * @param name The property name. - * @param val The new value for the property. - * @return true if the assignment succeeded, false otherwise. - */ - bool SetInt (const string &name, int val); - - - /** - * Set a long value for a property. - * - * Assign a long value to a property. If the property does not - * yet exist, it will be created and its type will be set to - * LONG; if it has a type of UNKNOWN, the type will also be set to - * LONG; otherwise, the bool value will be converted to the property's - * type. - * - * @param name The property name. - * @param val The new value for the property. - * @return true if the assignment succeeded, false otherwise. - */ - bool SetLong (const string &name, long val); - - - /** - * Set a float value for a property. - * - * Assign a float value to a property. If the property does not - * yet exist, it will be created and its type will be set to - * FLOAT; if it has a type of UNKNOWN, the type will also be set to - * FLOAT; otherwise, the bool value will be converted to the property's - * type. - * - * @param name The property name. - * @param val The new value for the property. - * @return true if the assignment succeeded, false otherwise. - */ - bool SetFloat (const string &name, float val); - - - /** - * Set a double value for a property. - * - * Assign a double value to a property. If the property does not - * yet exist, it will be created and its type will be set to - * DOUBLE; if it has a type of UNKNOWN, the type will also be set to - * DOUBLE; otherwise, the double value will be converted to the property's - * type. - * - * @param name The property name. - * @param val The new value for the property. - * @return true if the assignment succeeded, false otherwise. - */ - bool SetDouble (const string &name, double val); - - - /** - * Set a string value for a property. - * - * Assign a string value to a property. If the property does not - * yet exist, it will be created and its type will be set to - * STRING; if it has a type of UNKNOWN, the type will also be set to - * STRING; otherwise, the string value will be converted to the property's - * type. - * - * @param name The property name. - * @param val The new value for the property. - * @return true if the assignment succeeded, false otherwise. - */ - bool SetString (const string &name, const string &val); - - - //////////////////////////////////////////////////////////////////////// - // Convenience functions for setting property attributes. - //////////////////////////////////////////////////////////////////////// - - - /** - * Set the state of the archive attribute for a property. - * - * If the archive attribute is true, the property will be written - * when a flight is saved; if it is false, the property will be - * skipped. - * - * A warning message will be printed if the property does not exist. - * - * @param name The property name. - * @param state The state of the archive attribute (defaults to true). - */ - void SetArchivable (const string &name, bool state = true); - - - /** - * Set the state of the read attribute for a property. - * - * If the read attribute is true, the property value will be readable; - * if it is false, the property value will always be the default value - * for its type. - * - * A warning message will be printed if the property does not exist. - * - * @param name The property name. - * @param state The state of the read attribute (defaults to true). - */ - void SetReadable (const string &name, bool state = true); - - - /** - * Set the state of the write attribute for a property. - * - * If the write attribute is true, the property value may be modified - * (depending on how it is tied); if the write attribute is false, the - * property value may not be modified. - * - * A warning message will be printed if the property does not exist. - * - * @param name The property name. - * @param state The state of the write attribute (defaults to true). - */ - void SetWritable (const string &name, bool state = true); - - - //////////////////////////////////////////////////////////////////////// - // Convenience functions for tying properties, with logging. - //////////////////////////////////////////////////////////////////////// - - - /** - * Untie a property from an external data source. - * - * Classes should use this function to release control of any - * properties they are managing. - */ - void Untie (const string &name); - - - // Templates cause ambiguity here - - /** - * Tie a property to an external bool variable. - * - * The property's value will automatically mirror the variable's - * value, and vice-versa, until the property is untied. - * - * @param name The property name to tie (full path). - * @param pointer A pointer to the variable. - * @param useDefault true if any existing property value should be - * copied to the variable; false if the variable should not - * be modified; defaults to true. - */ - void - Tie (const string &name, bool *pointer, bool useDefault = true); - - - /** - * Tie a property to an external int variable. - * - * The property's value will automatically mirror the variable's - * value, and vice-versa, until the property is untied. - * - * @param name The property name to tie (full path). - * @param pointer A pointer to the variable. - * @param useDefault true if any existing property value should be - * copied to the variable; false if the variable should not - * be modified; defaults to true. - */ - void - Tie (const string &name, int *pointer, bool useDefault = true); - - - /** - * Tie a property to an external long variable. - * - * The property's value will automatically mirror the variable's - * value, and vice-versa, until the property is untied. - * - * @param name The property name to tie (full path). - * @param pointer A pointer to the variable. - * @param useDefault true if any existing property value should be - * copied to the variable; false if the variable should not - * be modified; defaults to true. - */ - void - Tie (const string &name, long *pointer, bool useDefault = true); - - - /** - * Tie a property to an external float variable. - * - * The property's value will automatically mirror the variable's - * value, and vice-versa, until the property is untied. - * - * @param name The property name to tie (full path). - * @param pointer A pointer to the variable. - * @param useDefault true if any existing property value should be - * copied to the variable; false if the variable should not - * be modified; defaults to true. - */ - void - Tie (const string &name, float *pointer, bool useDefault = true); - - /** - * Tie a property to an external double variable. - * - * The property's value will automatically mirror the variable's - * value, and vice-versa, until the property is untied. - * - * @param name The property name to tie (full path). - * @param pointer A pointer to the variable. - * @param useDefault true if any existing property value should be - * copied to the variable; false if the variable should not - * be modified; defaults to true. - */ - void - Tie (const string &name, double *pointer, bool useDefault = true); - -//============================================================================ -// -// All of the following functions *must* be inlined, otherwise linker -// errors will result -// -//============================================================================ - - /* template void - Tie (const string &name, V (*getter)(), void (*setter)(V) = 0, - bool useDefault = true); - - template void - Tie (const string &name, int index, V (*getter)(int), - void (*setter)(int, V) = 0, bool useDefault = true); - - template void - Tie (const string &name, T * obj, V (T::*getter)() const, - void (T::*setter)(V) = 0, bool useDefault = true); - - template void - Tie (const string &name, T * obj, int index, - V (T::*getter)(int) const, void (T::*setter)(int, V) = 0, - bool useDefault = true); */ - - /** - * Tie a property to a pair of simple functions. - * - * Every time the property value is queried, the getter (if any) will - * be invoked; every time the property value is modified, the setter - * (if any) will be invoked. The getter can be 0 to make the property - * unreadable, and the setter can be 0 to make the property - * unmodifiable. - * - * @param name The property name to tie (full path). - * @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 - * discarded; defaults to true. - */ - - template inline void - Tie (const string &name, V (*getter)(), void (*setter)(V) = 0, - bool useDefault = true) - { - if (!tie(name.c_str(), SGRawValueFunctions(getter, setter), - useDefault)) - { - cout << - "Failed to tie property " << name << " to functions" << endl; - } - } - - - /** - * Tie a property to a pair of indexed functions. - * - * Every time the property value is queried, the getter (if any) will - * be invoked with the index provided; every time the property value - * is modified, the setter (if any) will be invoked with the index - * provided. The getter can be 0 to make the property unreadable, and - * the setter can be 0 to make the property unmodifiable. - * - * @param name The property name to tie (full path). - * @param index The integer argument to pass to the getter and - * setter functions. - * @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 - * discarded; defaults to true. - */ - template 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(index, getter, setter), useDefault)) - { - cout << - "Failed to tie property " << name << " to indexed functions" << endl; - } - } - - - /** - * Tie a property to a pair of object methods. - * - * Every time the property value is queried, the getter (if any) will - * be invoked; every time the property value is modified, the setter - * (if any) will be invoked. The getter can be 0 to make the property - * unreadable, and the setter can be 0 to make the property - * unmodifiable. - * - * @param name The property name to tie (full path). - * @param obj The object whose methods should be invoked. - * @param getter The object's getter method, or 0 if the value is - * unreadable. - * @param setter The object's setter method, 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 - * discarded; defaults to true. - */ - template inline void - Tie (const string &name, T * obj, V (T::*getter)() const, - void (T::*setter)(V) = 0, bool useDefault = true) - { - if (!tie(name.c_str(), - SGRawValueMethods(*obj, getter, setter), useDefault)) - { - cout << - "Failed to tie property " << name << " to object methods" << endl; - } - } - - /** - * Tie a property to a pair of indexed object methods. - * - * Every time the property value is queried, the getter (if any) will - * be invoked with the index provided; every time the property value - * is modified, the setter (if any) will be invoked with the index - * provided. The getter can be 0 to make the property unreadable, and - * the setter can be 0 to make the property unmodifiable. - * - * @param name The property name to tie (full path). - * @param obj The object whose methods should be invoked. - * @param index The integer argument to pass to the getter and - * setter methods. - * @param getter The getter method, or 0 if the value is unreadable. - * @param setter The setter method, 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 - * discarded; defaults to true. - */ - template inline void - 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(*obj, index, getter, setter), useDefault)) - { - cout << - "Failed to tie property " << name << " to indexed object methods" << endl; - } - } -}; -} -#endif // FGPROPERTYMANAGER_H - diff --git a/src/FDM/JSBSim/FGPropulsion.cpp b/src/FDM/JSBSim/FGPropulsion.cpp deleted file mode 100644 index 19d7e9aca..000000000 --- a/src/FDM/JSBSim/FGPropulsion.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGPropulsion.cpp - Author: Jon S. Berndt - Date started: 08/20/00 - Purpose: Encapsulates the set of engines and tanks associated - with this aircraft - - ------------- 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 --------------------------------------------------------------------------------- -The Propulsion class is the container for the entire propulsion system, which is -comprised of engines and tanks. Once the Propulsion class gets the config file, -it reads in information which is specific to a type of engine. Then: - -1) The appropriate engine type instance is created -2) At least one tank object is created, and is linked to an engine. - -At Run time each engines Calculate() method is called. - -HISTORY --------------------------------------------------------------------------------- -08/20/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGPropulsion.h" -#include "FGRocket.h" -#include "FGTurbine.h" -#include "FGPiston.h" -#include "FGElectric.h" -#include "FGPropertyManager.h" -#include - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_PROPULSION; - -extern short debug_lvl; - - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec) -{ - Name = "FGPropulsion"; - - numSelectedFuelTanks = numSelectedOxiTanks = 0; - numTanks = numEngines = 0; - numOxiTanks = numFuelTanks = 0; - ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ... - tankJ.InitMatrix(); - refuel = false; - fuel_freeze = false; - - bind(); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGPropulsion::~FGPropulsion() -{ - for (unsigned int i=0; iGetdt(); - - vForces.InitMatrix(); - vMoments.InitMatrix(); - - for (i=0; iCalculate(); - vForces += Engines[i]->GetBodyForces(); // sum body frame forces - vMoments += Engines[i]->GetMoments(); // sum body frame moments - } - - for (i=0; iCalculate( dt * rate ); - } - - if (refuel) DoRefuel( dt * rate ); - - return false; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropulsion::GetSteadyState(void) -{ - double currentThrust = 0, lastThrust=-1; - int steady_count,j=0; - bool steady=false; - - vForces.InitMatrix(); - vMoments.InitMatrix(); - - if (!FGModel::Run()) { - for (unsigned int i=0; iSetTrimMode(true); - steady=false; - steady_count=0; - while (!steady && j < 6000) { - Engines[i]->Calculate(); - lastThrust = currentThrust; - currentThrust = Engines[i]->GetThrust(); - if (fabs(lastThrust-currentThrust) < 0.0001) { - steady_count++; - if (steady_count > 120) { steady=true; } - } else { - steady_count=0; - } - j++; - } - vForces += Engines[i]->GetBodyForces(); // sum body frame forces - vMoments += Engines[i]->GetMoments(); // sum body frame moments - Engines[i]->SetTrimMode(false); - } - - return false; - } else { - return true; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropulsion::ICEngineStart(void) -{ - int j; - - vForces.InitMatrix(); - vMoments.InitMatrix(); - - for (unsigned int i=0; iSetTrimMode(true); - j=0; - while (!Engines[i]->GetRunning() && j < 2000) { - Engines[i]->Calculate(); - j++; - } - vForces += Engines[i]->GetBodyForces(); // sum body frame forces - vMoments += Engines[i]->GetMoments(); // sum body frame moments - Engines[i]->SetTrimMode(false); - } - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGPropulsion::Load(FGConfigFile* AC_cfg) -{ - string token, fullpath, localpath; - string engineFileName, engType; - string parameter; - string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetAircraftPath(); - double xLoc, yLoc, zLoc, Pitch, Yaw; - int Feed; - bool ThrottleAdded = false; - FGConfigFile* Cfg_ptr = 0; - -# ifndef macintosh - fullpath = enginePath + "/"; - localpath = aircraftPath + "/Engines/"; -# else - fullpath = enginePath + ";"; - localpath = aircraftPath + ";Engines;"; -# endif - - AC_cfg->GetNextConfigLine(); - - 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++; - } - AC_cfg->GetNextConfigLine(); - } - - CalculateTankInertias(); - if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropulsion::GetPropulsionStrings(string delimeter) -{ - unsigned int i; - - string PropulsionStrings = ""; - bool firstime = true; - stringstream buf; - - for (i=0; iGetEngineLabels(delimeter); - } - for (i=0; iGetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i; - else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i; - } - - return PropulsionStrings; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGPropulsion::GetPropulsionValues(string delimeter) -{ - unsigned int i; - - string PropulsionValues = ""; - bool firstime = true; - stringstream buf; - - for (i=0; iGetEngineValues(delimeter); - } - for (i=0; iGetContents(); - } - - return PropulsionValues; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGColumnVector3& FGPropulsion::GetTanksMoment(void) -{ - iTank = Tanks.begin(); - vXYZtank_arm.InitMatrix(); - while (iTank < Tanks.end()) { - vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents(); - vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents(); - vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents(); - iTank++; - } - return vXYZtank_arm; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGPropulsion::GetTanksWeight(void) -{ - double Tw = 0.0; - - iTank = Tanks.begin(); - while (iTank < Tanks.end()) { - Tw += (*iTank)->GetContents(); - iTank++; - } - return Tw; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGMatrix33& FGPropulsion::CalculateTankInertias(void) -{ - unsigned int size; - - size = Tanks.size(); - if (size == 0) return tankJ; - - tankJ = FGMatrix33(); - - for (unsigned int i=0; iGetPointmassInertia( lbtoslug * Tanks[i]->GetContents(), - Tanks[i]->GetXYZ() ); - - return tankJ; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropulsion::SetMagnetos(int setting) -{ - if (ActiveEngine < 0) { - for (unsigned i=0; iSetMagnetos(setting); - } - } else { - ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropulsion::SetStarter(int setting) -{ - if (ActiveEngine < 0) { - for (unsigned i=0; iSetStarter(false); - else - Engines[i]->SetStarter(true); - } - } else { - if (setting == 0) - Engines[ActiveEngine]->SetStarter(false); - else - Engines[ActiveEngine]->SetStarter(true); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropulsion::SetCutoff(int setting) -{ - if (ActiveEngine < 0) { - for (unsigned i=0; iSetCutoff(false); - else - ((FGTurbine*)Engines[i])->SetCutoff(true); - } - } else { - if (setting == 0) - ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false); - else - ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropulsion::SetActiveEngine(int engine) -{ - if (engine >= Engines.size() || engine < 0) - ActiveEngine = -1; - else - ActiveEngine = engine; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGPropulsion::Transfer(int source, int target, double amount) -{ - double shortage, overage; - - if (source == -1) { - shortage = 0.0; - } else { - shortage = Tanks[source]->Drain(amount); - } - if (target == -1) { - overage = 0.0; - } else { - overage = Tanks[target]->Fill(amount - shortage); - } - return overage; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropulsion::DoRefuel(double time_slice) -{ - double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min - int TanksNotFull = 0; - - for (unsigned int i=0; iGetPctFull() < 99.99) ++TanksNotFull; - } - - if (TanksNotFull) { - for (unsigned int i=0; iGetPctFull() < 99.99) - Transfer(-1, i, fillrate/TanksNotFull); - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropulsion::SetFuelFreeze(bool f) -{ - fuel_freeze = f; - for (unsigned int i=0; iSetFuelFreeze(f); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -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); - - 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); - - PropertyManager->Tie("propulsion/active_engine", this, - (iPMF)&FGPropulsion::GetActiveEngine, &FGPropulsion::SetActiveEngine, true); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGPropulsion::unbind(void) -{ - PropertyManager->Untie("propulsion/magneto_cmd"); - PropertyManager->Untie("propulsion/starter_cmd"); - PropertyManager->Untie("propulsion/cutoff_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"); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGPropulsion::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: FGPropulsion" << endl; - if (from == 1) cout << "Destroyed: FGPropulsion" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGPropulsion.h b/src/FDM/JSBSim/FGPropulsion.h deleted file mode 100644 index 6d143f79b..000000000 --- a/src/FDM/JSBSim/FGPropulsion.h +++ /dev/null @@ -1,211 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGPropulsion.h - Author: Jon S. Berndt - Date started: 08/20/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 --------------------------------------------------------------------------------- -08/20/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGPROPULSION_H -#define FGPROPULSION_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef FGFS -# include -# ifdef SG_HAVE_STD_INCLUDES -# include -# include -# else -# include -# include -# endif -#else -# include -# include -#endif - -#include "FGModel.h" -#include "FGEngine.h" -#include "FGTank.h" -#include "FGMatrix33.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_PROPULSION "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Propulsion management class. - The Propulsion class is the container for the entire propulsion system, which is - comprised of engines, and tanks. Once the Propulsion class gets the config file, - it reads in information which is specific to a type of engine. Then: - - -# The appropriate engine type instance is created - -# At least one tank object is created, and is linked to an engine. - - At Run time each engines Calculate() method is called. - @author Jon S. Berndt - @version $Id$ - @see - FGEngine - FGTank -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGPropulsion : public FGModel -{ -public: - /// Constructor - FGPropulsion(FGFDMExec*); - /// Destructor - ~FGPropulsion(); - - /** Executes the propulsion model. - The initial plan for the FGPropulsion class calls for Run() to be executed, - calculating the power available from the engine. - - [Note: Should we be checking the Starved flag here?] */ - bool Run(void); - - /** 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. - @return true if successfully loaded, otherwise false */ - bool Load(FGConfigFile* AC_cfg); - - /// Retrieves the number of engines defined for the aircraft. - inline unsigned int GetNumEngines(void) const {return Engines.size();} - - /** Retrieves an engine object pointer from the list of engines. - @param index the engine index within the vector container - @return the address of the specific engine, or zero if no such engine is - available */ - inline FGEngine* GetEngine(unsigned int index) { - if (index <= Engines.size()-1) return Engines[index]; - else return 0L; } - - /// Retrieves the number of tanks defined for the aircraft. - inline unsigned int GetNumTanks(void) const {return Tanks.size();} - - /** Retrieves a tank object pointer from the list of tanks. - @param index the tank index within the vector container - @return the address of the specific tank, or zero if no such tank is - available */ - inline FGTank* GetTank(unsigned int index) { - if (index <= Tanks.size()-1) return Tanks[index]; - else return 0L; } - - /** Returns the number of fuel tanks currently actively supplying fuel */ - inline int GetnumSelectedFuelTanks(void) const {return numSelectedFuelTanks;} - - /** Returns the number of oxidizer tanks currently actively supplying oxidizer */ - inline int GetnumSelectedOxiTanks(void) const {return numSelectedOxiTanks;} - - /** Loops the engines until thrust output steady (used for trimming) */ - bool GetSteadyState(void); - - /** starts the engines in IC mode (dt=0). All engine-specific setup must - be done before calling this (i.e. magnetos, starter engage, etc.) */ - bool ICEngineStart(void); - - string GetPropulsionStrings(string delimeter); - string GetPropulsionValues(string delimeter); - - inline FGColumnVector3& GetForces(void) {return vForces; } - inline double GetForces(int n) const { return vForces(n);} - inline FGColumnVector3& GetMoments(void) {return vMoments;} - inline double GetMoments(int n) const {return vMoments(n);} - - inline bool GetRefuel(void) {return refuel;} - 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); - inline bool GetFuelFreeze(void) {return fuel_freeze;} - - void SetMagnetos(int setting); - void SetStarter(int setting); - void SetCutoff(int setting=0); - void SetActiveEngine(int engine); - void SetFuelFreeze(bool f); - FGMatrix33& CalculateTankInertias(void); - - void bind(); - void unbind(); - -private: - vector Engines; - vector Tanks; - vector ::iterator iTank; - unsigned int numSelectedFuelTanks; - unsigned int numSelectedOxiTanks; - unsigned int numFuelTanks; - unsigned int numOxiTanks; - unsigned int numEngines; - unsigned int numTanks; - int ActiveEngine; - FGColumnVector3 vForces; - FGColumnVector3 vMoments; - FGColumnVector3 vTankXYZ; - FGColumnVector3 vXYZtank_arm; - FGMatrix33 tankJ; - bool refuel; - bool fuel_freeze; - - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGQuaternion.cpp b/src/FDM/JSBSim/FGQuaternion.cpp deleted file mode 100644 index bc32c8137..000000000 --- a/src/FDM/JSBSim/FGQuaternion.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGQuaternion.cpp - Author: Jon Berndt, Mathias Froehlich - Date started: 12/02/98 - - ------- 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. - -HISTORY -------------------------------------------------------------------------------- -12/02/98 JSB Created -15/01/04 Mathias Froehlich implemented a quaternion class from many places - in JSBSim. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - INCLUDES - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef FGFS -# include -# include -# include STL_IOSTREAM - SG_USING_STD(cerr); - SG_USING_STD(cout); - SG_USING_STD(endl); -#else -# include -# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) -# include -# include -# else -# include -# if defined(sgi) && !defined(__GNUC__) -# include -# else -# include -# endif - using std::cerr; - using std::cout; - using std::endl; -# endif -#endif - -#include "FGMatrix33.h" -#include "FGColumnVector3.h" - -#include "FGQuaternion.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - DEFINITIONS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_QUATERNION; - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -// Initialize from q -FGQuaternion::FGQuaternion(const FGQuaternion& q) - : mCacheValid(q.mCacheValid) { - Entry(1) = q(1); - Entry(2) = q(2); - Entry(3) = q(3); - Entry(4) = q(4); - if (mCacheValid) { - mT = q.mT; - mTInv = q.mTInv; - mEulerAngles = q.mEulerAngles; - mEulerSines = q.mEulerSines; - mEulerCosines = q.mEulerCosines; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -// Initialize with the three euler angles -FGQuaternion::FGQuaternion(double phi, double tht, double psi) - : mCacheValid(false) { - double thtd2 = 0.5*tht; - double psid2 = 0.5*psi; - double phid2 = 0.5*phi; - - double Sthtd2 = sin(thtd2); - double Spsid2 = sin(psid2); - double Sphid2 = sin(phid2); - - double Cthtd2 = cos(thtd2); - double Cpsid2 = cos(psid2); - double Cphid2 = cos(phid2); - - double Cphid2Cthtd2 = Cphid2*Cthtd2; - double Cphid2Sthtd2 = Cphid2*Sthtd2; - double Sphid2Sthtd2 = Sphid2*Sthtd2; - double Sphid2Cthtd2 = Sphid2*Cthtd2; - - Entry(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2; - Entry(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2; - Entry(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2; - Entry(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -/** - Returns the derivative of the quaternion coresponding to the - angular velocities PQR. -*/ -FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR) const { - double norm = Magnitude(); - if (norm == 0.0) - return FGQuaternion::zero(); - double rnorm = 1.0/norm; - - FGQuaternion QDot; - QDot(1) = -0.5*(Entry(2)*PQR(eP) + Entry(3)*PQR(eQ) + Entry(4)*PQR(eR)); - QDot(2) = 0.5*(Entry(1)*PQR(eP) + Entry(3)*PQR(eR) - Entry(4)*PQR(eQ)); - QDot(3) = 0.5*(Entry(1)*PQR(eQ) + Entry(4)*PQR(eP) - Entry(2)*PQR(eR)); - QDot(4) = 0.5*(Entry(1)*PQR(eR) + Entry(2)*PQR(eQ) - Entry(3)*PQR(eP)); - return rnorm*QDot; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGQuaternion::Normalize() -{ - // Note: this does not touch the cache - // since it does not change the orientation ... - - double norm = Magnitude(); - if (norm == 0.0) - return; - - double rnorm = 1.0/norm; - Entry(1) *= rnorm; - Entry(2) *= rnorm; - Entry(3) *= rnorm; - Entry(4) *= rnorm; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -// Compute the derived values if required ... -void FGQuaternion::ComputeDerivedUnconditional(void) const -{ - mCacheValid = true; - - // First normalize the 4-vector - double norm = Magnitude(); - if (norm == 0.0) - return; - - double rnorm = 1.0/norm; - double q1 = rnorm*Entry(1); - double q2 = rnorm*Entry(2); - double q3 = rnorm*Entry(3); - double q4 = rnorm*Entry(4); - - // Now compute the transformation matrix. - double q1q1 = q1*q1; - double q2q2 = q2*q2; - double q3q3 = q3*q3; - double q4q4 = q4*q4; - double q1q2 = q1*q2; - double q1q3 = q1*q3; - double q1q4 = q1*q4; - double q2q3 = q2*q3; - double q2q4 = q2*q4; - double q3q4 = q3*q4; - - mT(1,1) = q1q1 + q2q2 - q3q3 - q4q4; - mT(1,2) = 2.0*(q2q3 + q1q4); - mT(1,3) = 2.0*(q2q4 - q1q3); - mT(2,1) = 2.0*(q2q3 - q1q4); - mT(2,2) = q1q1 - q2q2 + q3q3 - q4q4; - mT(2,3) = 2.0*(q3q4 + q1q2); - mT(3,1) = 2.0*(q2q4 + q1q3); - mT(3,2) = 2.0*(q3q4 - q1q2); - mT(3,3) = q1q1 - q2q2 - q3q3 + q4q4; - // Since this is an orthogonal matrix, the inverse is simply - // the transpose. - mTInv = mT; - mTInv.T(); - - // Compute the Euler-angles - if (mT(3,3) == 0.0) - mEulerAngles(ePhi) = 0.5*M_PI; - else - mEulerAngles(ePhi) = atan2(mT(2,3), mT(3,3)); - - if (mT(1,3) < -1.0) - mEulerAngles(eTht) = 0.5*M_PI; - else if (1.0 < mT(1,3)) - mEulerAngles(eTht) = -0.5*M_PI; - else - mEulerAngles(eTht) = asin(-mT(1,3)); - - if (mT(1,1) == 0.0) - mEulerAngles(ePsi) = 0.5*M_PI; - else { - double psi = atan2(mT(1,2), mT(1,1)); - if (psi < 0.0) - psi += 2*M_PI; - mEulerAngles(ePsi) = psi; - } - - // FIXME: may be one can compute those values easier ??? - mEulerSines(ePhi) = sin(mEulerAngles(ePhi)); - // mEulerSines(eTht) = sin(mEulerAngles(eTht)); - mEulerSines(eTht) = -mT(1,3); - mEulerSines(ePsi) = sin(mEulerAngles(ePsi)); - mEulerCosines(ePhi) = cos(mEulerAngles(ePhi)); - mEulerCosines(eTht) = cos(mEulerAngles(eTht)); - mEulerCosines(ePsi) = cos(mEulerAngles(ePsi)); -} - -} // namespace JSBSim diff --git a/src/FDM/JSBSim/FGQuaternion.h b/src/FDM/JSBSim/FGQuaternion.h deleted file mode 100644 index 2800a1549..000000000 --- a/src/FDM/JSBSim/FGQuaternion.h +++ /dev/null @@ -1,494 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGQuaternion.h - Author: Jon Berndt, Mathis Froehlich - Date started: 12/02/98 - - ------- 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. - -HISTORY -------------------------------------------------------------------------------- -12/02/98 JSB Created -15/01/04 MF Quaternion class from old FGColumnVector4 - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGQUATERNION_H -#define FGQUATERNION_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - INCLUDES - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGJSBBase.h" -#include "FGMatrix33.h" -#include "FGColumnVector3.h" -#include "FGPropertyManager.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - DEFINITIONS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_QUATERNION "$Id$" - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - CLASS DOCUMENTATION - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models the Quaternion representation of rotations. - FGQuaternion is a representation of an arbitrary rotation through a - quaternion. It has vector properties. This class also contains access - functions to the euler angle representation of rotations and access to - transformation matrices for 3D vectors. Transformations and euler angles are - therefore computed once they are requested for the first time. Then they are - cached for later usage as long as the class is not accessed trough - a nonconst member function. - - Note: The order of rotations used in this class corresponds to a 3-2-1 sequence, - or Y-P-R, or Z-Y-X, if you prefer. - - @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 - @author Mathias Froehlich, extended FGColumnVector4 originally by Tony Peden - and Jon Berndt -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - CLASS DECLARATION - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGQuaternion - : virtual FGJSBBase { -public: - /** Default initializer. - Default initializer, initializes the class with the identity rotation. */ - FGQuaternion() : mCacheValid(false) { - Entry(1) = 1.0; - Entry(2) = Entry(3) = Entry(4) = 0.0; - } - - /** Copy constructor. - Copy constructor, initializes the quaternion. - @param q a constant reference to another FGQuaternion instance */ - FGQuaternion(const FGQuaternion& q); - - /** Initializer by euler angles. - Initialize the quaternion with the euler angles. - @param phi The euler X axis (roll) angle in radians - @param tht The euler Y axis (attitude) angle in radians - @param psi The euler Z axis (heading) angle in radians */ - FGQuaternion(double phi, double tht, double psi); - - /** Initializer by one euler angle. - Initialize the quaternion with the single euler angle where its index - is given in the first argument. - @param idx Index of the euler angle to initialize - @param angle The euler angle in radians */ - FGQuaternion(int idx, double angle) - : mCacheValid(false) { - double angle2 = 0.5*angle; - - double Sangle2 = sin(angle2); - double Cangle2 = cos(angle2); - - if (idx == ePhi) { - Entry(1) = Cangle2; - Entry(2) = Sangle2; - Entry(3) = 0.0; - Entry(4) = 0.0; - - } else if (idx == eTht) { - Entry(1) = Cangle2; - Entry(2) = 0.0; - Entry(3) = Sangle2; - Entry(4) = 0.0; - - } else { - Entry(1) = Cangle2; - Entry(2) = 0.0; - Entry(3) = 0.0; - Entry(4) = Sangle2; - - } - } - - /// Destructor. - ~FGQuaternion() {} - - /** Quaternion 'velocity' for given angular rates. - Computes the quaternion derivative which results from the given - angular velocities - @param PQR a constant reference to the body rate vector - @return the quaternion derivative */ - FGQuaternion GetQDot(const FGColumnVector3& PQR) const; - - /** Transformation matrix. - @return a reference to the transformation/rotation matrix - corresponding to this quaternion rotation. */ - const FGMatrix33& GetT(void) const { ComputeDerived(); return mT; } - - /** Backward transformation matrix. - @return a reference to the inverse transformation/rotation matrix - corresponding to this quaternion rotation. */ - const FGMatrix33& GetTInv(void) const { ComputeDerived(); return mTInv; } - - /** Retrieves the Euler angles. - @return a reference to the triad of euler angles corresponding - to this quaternion rotation. - @units radians */ - const FGColumnVector3& GetEuler(void) const { - ComputeDerived(); - return mEulerAngles; - } - - /** Retrieves the Euler angles. - @param i the euler angle index. - @return a reference to the i-th euler angles corresponding - to this quaternion rotation. - @units radians */ - double GetEuler(int i) const { - ComputeDerived(); - return mEulerAngles(i); - } - - /** Retrieves the Euler angles. - @param i the euler angle index. - @return a reference to the i-th euler angles corresponding - to this quaternion rotation. - @units degrees */ - double GetEulerDeg(int i) const { - ComputeDerived(); - return radtodeg*mEulerAngles(i); - } - - /** Retrieves sine of the given euler angle. - @return the sine of the Euler angle theta (pitch attitude) corresponding - to this quaternion rotation. */ - double GetSinEuler(int i) const { - ComputeDerived(); - return mEulerSines(i); - } - - /** Retrieves cosine of the given euler angle. - @return the sine of the Euler angle theta (pitch attitude) corresponding - to this quaternion rotation. */ - double GetCosEuler(int i) const { - ComputeDerived(); - return mEulerCosines(i); - } - - /** 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 mData[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) { mCacheValid = false; return mData[idx-1]; } - - /** Assignment operator "=". - Assign the value of q to the current object. Cached values are - conserved. - @param q reference to an FGQuaternion instance - @return reference to a quaternion object */ - const FGQuaternion& operator=(const FGQuaternion& q) { - // Copy the master values ... - Entry(1) = q(1); - Entry(2) = q(2); - Entry(3) = q(3); - Entry(4) = q(4); - // .. and copy the derived values if they are valid - mCacheValid = q.mCacheValid; - if (mCacheValid) { - mT = q.mT; - mTInv = q.mTInv; - mEulerAngles = q.mEulerAngles; - mEulerSines = q.mEulerSines; - mEulerCosines = q.mEulerCosines; - } - return *this; - } - - /** Comparison operator "==". - @param q a quaternion reference - @return true if both quaternions represent the same rotation. */ - bool operator==(const FGQuaternion& q) const { - return Entry(1) == q(1) && Entry(2) == q(2) - && Entry(3) == q(3) && Entry(4) == q(4); - } - - /** Comparison operator "!=". - @param q a quaternion reference - @return true if both quaternions do not represent the same rotation. */ - bool operator!=(const FGQuaternion& q) const { return ! operator==(q); } - const FGQuaternion& operator+=(const FGQuaternion& q) { - // Copy the master values ... - Entry(1) += q(1); - Entry(2) += q(2); - Entry(3) += q(3); - Entry(4) += q(4); - mCacheValid = false; - return *this; - } - - /** Arithmetic operator "-=". - @param q a quaternion reference. - @return a quaternion reference representing Q, where Q = Q - q. */ - const FGQuaternion& operator-=(const FGQuaternion& q) { - // Copy the master values ... - Entry(1) -= q(1); - Entry(2) -= q(2); - Entry(3) -= q(3); - Entry(4) -= q(4); - mCacheValid = false; - return *this; - } - - /** Arithmetic operator "*=". - @param scalar a multiplicative value. - @return a quaternion reference representing Q, where Q = Q * scalar. */ - const FGQuaternion& operator*=(double scalar) { - Entry(1) *= scalar; - Entry(2) *= scalar; - Entry(3) *= scalar; - Entry(4) *= scalar; - mCacheValid = false; - return *this; - } - - /** Arithmetic operator "/=". - @param scalar a divisor value. - @return a quaternion reference representing Q, where Q = Q / scalar. */ - const FGQuaternion& operator/=(double scalar) { - return operator*=(1.0/scalar); - } - - /** Arithmetic operator "+". - @param q a quaternion to be summed. - @return a quaternion representing Q, where Q = Q + q. */ - FGQuaternion operator+(const FGQuaternion& q) const { - return FGQuaternion(Entry(1)+q(1), Entry(2)+q(2), - Entry(3)+q(3), Entry(4)+q(4)); - } - - /** Arithmetic operator "-". - @param q a quaternion to be subtracted. - @return a quaternion representing Q, where Q = Q - q. */ - FGQuaternion operator-(const FGQuaternion& q) const { - return FGQuaternion(Entry(1)-q(1), Entry(2)-q(2), - Entry(3)-q(3), Entry(4)-q(4)); - } - - /** Arithmetic operator "*". - Multiplication of two quaternions is like performing successive rotations. - @param q a quaternion to be multiplied. - @return a quaternion representing Q, where Q = Q * q. */ - FGQuaternion operator*(const FGQuaternion& q) const { - return FGQuaternion(Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4), - Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3), - Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2), - Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1)); - } - - /** Arithmetic operator "*=". - Multiplication of two quaternions is like performing successive rotations. - @param q a quaternion to be multiplied. - @return a quaternion reference representing Q, where Q = Q * q. */ - const FGQuaternion& operator*=(const FGQuaternion& q) { - double q0 = Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4); - double q1 = Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3); - double q2 = Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2); - double q3 = Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1); - Entry(1) = q0; - Entry(2) = q1; - Entry(3) = q2; - Entry(4) = q3; - mCacheValid = false; - return *this; - } - - /** Inverse of the quaternion. - - Compute and return the inverse of the quaternion so that the orientation - represented with *this multiplied with the returned value is equal to - the identity orientation. - */ - FGQuaternion Inverse(void) const { - double norm = Magnitude(); - if (norm == 0.0) - return *this; - double rNorm = 1.0/norm; - return FGQuaternion( Entry(1)*rNorm, -Entry(2)*rNorm, - -Entry(3)*rNorm, -Entry(4)*rNorm ); - } - - /** Conjugate of the quaternion. - - Compute and return the conjugate of the quaternion. This one is equal - to the inverse iff the quaternion is normalized. - */ - FGQuaternion Conjugate(void) const { - return FGQuaternion( Entry(1), -Entry(2), -Entry(3), -Entry(4) ); - } - - friend FGQuaternion operator*(double, const FGQuaternion&); - - /** Length of the vector. - - Compute and return the euclidean norm of this vector. - */ - double Magnitude(void) const { return sqrt(SqrMagnitude()); } - - /** Square of the length of the vector. - - Compute and return the square of the euclidean norm of this vector. - */ - double SqrMagnitude(void) const { - return Entry(1)*Entry(1)+Entry(2)*Entry(2) - +Entry(3)*Entry(3)+Entry(4)*Entry(4); - } - - /** Normialze. - - Normalize the vector to have the Magnitude() == 1.0. If the vector - is equal to zero it is left untouched. - */ - void Normalize(void); - - /** Zero quaternion vector. Does not represent any orientation. - Useful for initialization of increments */ - static FGQuaternion zero(void) { return FGQuaternion( 0.0, 0.0, 0.0, 0.0 ); } - -private: - /** Copying by assigning the vector valued components. */ - FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false) - { Entry(1) = q1; Entry(2) = q2; Entry(3) = q3; Entry(4) = q4; } - - /** Computation of derived values. - This function recomputes the derived values like euler angles and - transformation matrices. It does this unconditionally. */ - void ComputeDerivedUnconditional(void) const; - - /** Computation of derived values. - This function checks if the derived values like euler angles and - transformation matrices are already computed. If so, it - returns. If they need to be computed the real worker routine - \ref FGQuaternion::ComputeDerivedUnconditional(void) const - is called. - This function is inlined to avoid function calls in the fast path. */ - void ComputeDerived(void) const { - if (!mCacheValid) - ComputeDerivedUnconditional(); - } - - /** The quaternion values itself. This is the master copy. */ - double mData[4]; - - /** A data validity flag. - This class implements caching of the derived values like the - orthogonal rotation matrices or the Euler angles. For caching we - carry a flag which signals if the values are valid or not. - The C++ keyword "mutable" tells the compiler that the data member is - allowed to change during a const member function. */ - mutable bool mCacheValid; - - /** This stores the transformation matrices. */ - mutable FGMatrix33 mT; - mutable FGMatrix33 mTInv; - - /** The cached euler angles. */ - mutable FGColumnVector3 mEulerAngles; - - /** The cached sines and cosines of the euler angles. */ - mutable FGColumnVector3 mEulerSines; - mutable FGColumnVector3 mEulerCosines; -}; - -/** Scalar multiplication. - - @param scalar scalar value to multiply with. - @param p Vector to multiply. - - Multiply the Vector with a scalar value. -*/ -inline FGQuaternion operator*(double scalar, const FGQuaternion& q) { - return FGQuaternion(scalar*q(1), scalar*q(2), scalar*q(3), scalar*q(4)); -} - -} // namespace JSBSim - -#endif diff --git a/src/FDM/JSBSim/FGRocket.cpp b/src/FDM/JSBSim/FGRocket.cpp deleted file mode 100644 index e278cca93..000000000 --- a/src/FDM/JSBSim/FGRocket.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGRocket.cpp - Author: Jon S. Berndt - Date started: 09/12/2000 - Purpose: This module models a rocket engine - - ------------- 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 --------------------------------------------------------------------------------- - -This class descends from the FGEngine class and models a rocket engine based on -parameters given in the engine config file for this class - -HISTORY --------------------------------------------------------------------------------- -09/12/2000 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "FGRocket.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_ROCKET; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGRocket::FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number) - : FGEngine(exec, engine_number) -{ - string token; - - Name = Eng_cfg->GetValue("NAME"); - Eng_cfg->GetNextConfigLine(); - - while (Eng_cfg->GetValue() != string("/FG_ROCKET")) { - *Eng_cfg >> token; - if (token == "SHR") *Eng_cfg >> SHR; - else if (token == "MAX_PC") *Eng_cfg >> maxPC; - else if (token == "PROP_EFF") *Eng_cfg >> propEff; - else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle; - else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle; - else if (token == "SLFUELFLOWMAX") *Eng_cfg >> SLFuelFlowMax; - else if (token == "SLOXIFLOWMAX") *Eng_cfg >> SLOxiFlowMax; - else if (token == "VARIANCE") *Eng_cfg >> Variance; - else cerr << "Unhandled token in Engine config file: " << token << endl; - } - - Debug(0); - - Type = etRocket; - Flameout = false; - - PC = 0.0; - kFactor = (2.0*SHR*SHR/(SHR-1.0))*pow(2.0/(SHR+1), (SHR+1)/(SHR-1)); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGRocket::~FGRocket(void) -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGRocket::Calculate(void) -{ - double Cf=0; - - if (!Flameout && !Starved) ConsumeFuel(); - - Throttle = FCS->GetThrottlePos(EngineNumber); - - if (Throttle < MinThrottle || Starved) { - PctPower = Thrust = 0.0; // desired thrust - Flameout = true; - PC = 0.0; - } else { - PctPower = Throttle / MaxThrottle; - PC = maxPC*PctPower * (1.0 + Variance * ((double)rand()/(double)RAND_MAX - 0.5)); - // The Cf (below) is CF from Eqn. 3-30, "Rocket Propulsion Elements", Fifth Edition, - // George P. Sutton. Note that the thruster function GetPowerRequired() might - // be better called GetResistance() or something; this function returns the - // nozzle exit pressure. - Cf = sqrt(kFactor*(1 - pow(Thruster->GetPowerRequired()/(PC), (SHR-1)/SHR))); - Flameout = false; - } - - return Thrust = Thruster->Calculate(Cf*maxPC*PctPower*propEff); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGRocket::GetEngineLabels(string delimeter) -{ - std::ostringstream buf; - - buf << Name << "_ChamberPress[" << EngineNumber << "]" << delimeter - << Thruster->GetThrusterLabels(EngineNumber, delimeter); - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGRocket::GetEngineValues(string delimeter) -{ - std::ostringstream buf; - - buf << PC << delimeter << Thruster->GetThrusterValues(EngineNumber, delimeter); - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGRocket::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << " Engine Name: " << Name << endl; - cout << " Specific Heat Ratio = " << SHR << endl; - cout << " Maximum Chamber Pressure = " << maxPC << endl; - cout << " Propulsive Efficiency = " << propEff << endl; - cout << " MaxThrottle = " << MaxThrottle << endl; - cout << " MinThrottle = " << MinThrottle << endl; - cout << " FuelFlowMax = " << SLFuelFlowMax << endl; - cout << " OxiFlowMax = " << SLOxiFlowMax << endl; - cout << " Variance = " << Variance << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGRocket" << endl; - if (from == 1) cout << "Destroyed: FGRocket" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGRocket.h b/src/FDM/JSBSim/FGRocket.h deleted file mode 100644 index 00befb0d4..000000000 --- a/src/FDM/JSBSim/FGRocket.h +++ /dev/null @@ -1,143 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGRocket.h - Author: Jon S. Berndt - Date started: 09/12/2000 - - ------------- 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. - -HISTORY --------------------------------------------------------------------------------- -09/12/2000 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGROCKET_H -#define FGROCKET_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGEngine.h" -#include "FGConfigFile.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_ROCKET "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models a generic rocket engine. - The rocket engine is modeled given the following parameters: -
    -
  • Chamber pressure (in psf)
  • -
  • Specific heat ratio (usually about 1.2 for hydrocarbon fuel and LOX)
  • -
  • Propulsive efficiency (in percent, from 0 to 1.0)
  • -
  • Variance (in percent, from 0 to 1.0, nominally 0.05)
  • -
- Additionally, the following control inputs, operating characteristics, and - location are required, as with all other engine types: -
    -
  • Throttle setting (in percent, from 0 to 1.0)
  • -
  • Maximum allowable throttle setting
  • -
  • Minimum working throttle setting
  • -
  • Sea level fuel flow at maximum thrust
  • -
  • Sea level oxidizer flow at maximum thrust
  • -
  • X, Y, Z location in structural coordinate frame
  • -
  • Pitch and Yaw
  • -
- The nozzle exit pressure (p2) is returned via a - call to FGNozzle::GetPowerRequired(). This exit pressure is used, - along with chamber pressure and specific heat ratio, to get the - thrust coefficient for the throttle setting. This thrust - coefficient is multiplied by the chamber pressure and then passed - to the nozzle Calculate() routine, where the thrust force is - determined. - - @author Jon S. Berndt - $Id$ - @see FGNozzle, - FGThruster, - FGForce, - FGEngine, - FGPropulsion, - FGTank -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGRocket : public FGEngine -{ -public: - /** Constructor. - @param exec pointer to JSBSim parent object, the FDM Executive. - @param Eng_cfg pointer to the config file object. - @param engine_number engine number */ - FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number); - - /** Destructor */ - ~FGRocket(void); - - /** Determines the thrust coefficient. - @return thrust coefficient times chamber pressure */ - double Calculate(void); - - /** Gets the chamber pressure. - @return chamber pressure in psf. */ - double GetChamberPressure(void) {return PC;} - - /** Gets the flame-out status. - The engine will "flame out" if the throttle is set below the minimum - sustainable setting. - @return true if engine has flamed out. */ - bool GetFlameout(void) {return Flameout;} - string GetEngineLabels(string delimeter); - string GetEngineValues(string delimeter); - -private: - double SHR; - double maxPC; - double propEff; - double kFactor; - double Variance; - double PC; - bool Flameout; - - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGRotor.cpp b/src/FDM/JSBSim/FGRotor.cpp deleted file mode 100644 index 58fee4572..000000000 --- a/src/FDM/JSBSim/FGRotor.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGRotor.cpp - Author: Jon S. Berndt - Date started: 08/24/00 - Purpose: Encapsulates the rotor object - - ------------- 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 --------------------------------------------------------------------------------- -08/24/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGRotor.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_ROTOR; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGRotor::FGRotor(FGFDMExec *FDMExec) : FGThruster(FDMExec) -{ - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGRotor::~FGRotor() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGRotor::Calculate(double PowerAvailable) -{ - return 0.0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGRotor::GetThrusterLabels(int id, string delimeter) -{ - return ""; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGRotor::GetThrusterValues(int id, string delimeter) -{ - return ""; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGRotor::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: FGRotor" << endl; - if (from == 1) cout << "Destroyed: FGRotor" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGRotor.h b/src/FDM/JSBSim/FGRotor.h deleted file mode 100644 index 2e4b3b34d..000000000 --- a/src/FDM/JSBSim/FGRotor.h +++ /dev/null @@ -1,81 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGRotor.h - Author: Jon S. Berndt - Date started: 08/24/00 - - ------------- 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. - -HISTORY --------------------------------------------------------------------------------- -08/24/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGROTOR_H -#define FGROTOR_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGThruster.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_ROTOR "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models a rotor (such as for a helicopter); NOT YET IMPLEMENTED. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGRotor : public FGThruster { - -public: - FGRotor(FGFDMExec *FDMExec); - ~FGRotor(); - - double Calculate(double); - string GetThrusterLabels(int id, string delimeter); - string GetThrusterValues(int id, string delimeter); - -private: - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif diff --git a/src/FDM/JSBSim/FGScript.cpp b/src/FDM/JSBSim/FGScript.cpp deleted file mode 100644 index 4fe946df7..000000000 --- a/src/FDM/JSBSim/FGScript.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGScript.cpp - Author: Jon S. Berndt - Date started: 12/21/01 - Purpose: Loads and runs JSBSim scripts. - - ------------- 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 wraps up the simulation scripting routines. - -HISTORY --------------------------------------------------------------------------------- -12/21/01 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -COMMENTS, REFERENCES, and NOTES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef FGFS -# include -# include STL_IOSTREAM -# include STL_ITERATOR -#else -# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) -# include -# else -# include -# endif -# include -#endif - -#include "FGScript.h" -#include "FGConfigFile.h" -#include "FGTrim.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_FGSCRIPT; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -GLOBAL DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -// Constructor - -FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex) -{ - State = FDMExec->GetState(); - PropertyManager=FDMExec->GetPropertyManager(); - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGScript::~FGScript() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGScript::LoadScript( string script ) -{ - FGConfigFile Script(script); - string token=""; - string aircraft=""; - string initialize=""; - string prop_name; - bool result = false; - double dt = 0.0; - struct condition *newCondition; - - if (!Script.IsOpen()) return false; - - Script.GetNextConfigLine(); - if (Script.GetValue("runscript").length() <= 0) { - 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; - - 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 - } else { - cerr << "Unrecognized keyword in script file: \"" << token << "\" [runscript] " << endl; - } - } - - if (aircraft == "") { - cerr << "Aircraft file not loaded in script" << endl; - exit(-1); - } - - 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; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGScript::RunScript(void) -{ - vector ::iterator iC = Conditions.begin(); - bool truth = false; - bool WholeTruth = false; - unsigned i; - - double currentTime = State->Getsim_time(); - double newSetValue = 0; - - if (currentTime > EndTime) return false; - - while (iC < Conditions.end()) { - // determine whether the set of conditional tests for this condition equate - // to true - for (i=0; iTestValue.size(); i++) { - if (iC->Comparison[i] == "lt") - truth = iC->TestParam[i]->getDoubleValue() < iC->TestValue[i]; - else if (iC->Comparison[i] == "le") - truth = iC->TestParam[i]->getDoubleValue() <= iC->TestValue[i]; - else if (iC->Comparison[i] == "eq") - truth = iC->TestParam[i]->getDoubleValue() == iC->TestValue[i]; - else if (iC->Comparison[i] == "ge") - truth = iC->TestParam[i]->getDoubleValue() >= iC->TestValue[i]; - else if (iC->Comparison[i] == "gt") - truth = iC->TestParam[i]->getDoubleValue() > iC->TestValue[i]; - else if (iC->Comparison[i] == "ne") - truth = iC->TestParam[i]->getDoubleValue() != iC->TestValue[i]; - else - cerr << "Bad comparison" << endl; - - if (i == 0) WholeTruth = truth; - else WholeTruth = WholeTruth && truth; - - if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false; - } - - // if the conditions are true, do the setting of the desired parameters - - if (WholeTruth) { - for (i=0; iSetValue.size(); i++) { - if ( ! iC->Triggered[i]) { - iC->OriginalValue[i] = iC->SetParam[i]->getDoubleValue(); - switch (iC->Type[i]) { - case FG_VALUE: - iC->newValue[i] = iC->SetValue[i]; - break; - case FG_DELTA: - iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i]; - break; - case FG_BOOL: - iC->newValue[i] = iC->SetValue[i]; - break; - default: - cerr << "Invalid Type specified" << endl; - break; - } - iC->Triggered[i] = true; - iC->StartTime[i] = currentTime; - } - - 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]; - 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]; - break; - default: - cerr << "Invalid Action specified" << endl; - break; - } - iC->SetParam[i]->setDoubleValue(newSetValue); - } - } - iC++; - } - 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 FGScript::Debug(int from) -{ - unsigned int i; - - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - } else if (from == 3) { - } else if (from == 4) { // print out script data - vector ::iterator iterConditions = Conditions.begin(); - int count=0; - - cout << "\n Script goes from " << StartTime << " to " << EndTime - << " with dt = " << State->Getdt() << endl << endl; - - while (iterConditions < Conditions.end()) { - cout << " Condition: " << count++ << endl; - cout << " if ("; - - for (i=0; iTestValue.size(); i++) { - if (i>0) cout << " and" << endl << " "; - cout << "(" << iterConditions->TestParam[i]->GetName() - << " " << iterConditions->Comparison[i] << " " - << iterConditions->TestValue[i] << ")"; - } - cout << ") then {"; - - for (i=0; iSetValue.size(); i++) { - cout << endl << " set " << iterConditions->SetParam[i]->GetName() - << " to " << iterConditions->SetValue[i]; - - switch (iterConditions->Type[i]) { - case FG_VALUE: - cout << " (constant"; - break; - case FG_DELTA: - cout << " (delta"; - break; - case FG_BOOL: - cout << " (boolean"; - break; - default: - cout << " (unspecified type"; - } - - switch (iterConditions->Action[i]) { - case FG_RAMP: - cout << " via ramp"; - break; - case FG_STEP: - cout << " via step"; - break; - case FG_EXP: - cout << " via exponential approach"; - break; - default: - cout << " via unspecified action"; - } - - if (!iterConditions->Persistent[i]) cout << endl - << " once"; - else cout << endl - << " repeatedly"; - - if (iterConditions->Action[i] == FG_RAMP || - iterConditions->Action[i] == FG_EXP) cout << endl - << " with time constant " - << iterConditions->TC[i]; - } - cout << ")" << endl << " }" << endl << endl; - - iterConditions++; - } - - cout << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGScript" << endl; - if (from == 1) cout << "Destroyed: FGScript" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGScript.h b/src/FDM/JSBSim/FGScript.h deleted file mode 100644 index 7b4587a92..000000000 --- a/src/FDM/JSBSim/FGScript.h +++ /dev/null @@ -1,197 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - Header: FGScript.h - Author: Jon Berndt - Date started: 12/21/2001 - - ------------- Copyright (C) 2001 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/21/01 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGSCRIPT_HEADER_H -#define FGSCRIPT_HEADER_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGJSBBase.h" -#include "FGState.h" -#include "FGFDMExec.h" -#include - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_FGSCRIPT "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates the JSBSim scripting capability. -

Scripting support provided via FGScript.

- -

There is simple scripting support provided in the FGScript - class. Commands are specified using the Simple Scripting - Directives for JSBSim (SSDJ). The script file is in XML - format. A test condition (or conditions) can be set up in the - script and when the condition evaluates to true, the specified - action[s] is/are taken. A test condition can be persistent, - meaning that if a test condition evaluates to true, then passes - and evaluates to false, the condition is reset and may again be - triggered. When the set of tests evaluates to true for a given - condition, an item may be set to another value. This value might - be a boolean, a value, or a delta value, and the change from the - current value to the new value can be either via a step function, - a ramp, or an exponential approach. The speed of a ramp or - approach is specified via the time constant. Here is the format - of the script file:

- -
<?xml version="1.0"?>
-    <runscript name="C172-01A">
-
-    <!--
-    This run is for testing C172 runs
-    -->
-
-    <use aircraft="c172">
-    <use initialize="reset00">
-
-    <run start="0.0" end="4.5" dt="0.05">
-      <when>
-        <parameter name="FG_TIME" comparison="ge" value="0.25">
-        <parameter name="FG_TIME" comparison="le" value="0.50">
-        <set name="FG_AILERON_CMD" type="FG_VALUE" value="0.25"
-        action="FG_STEP" persistent="false" tc ="0.25">
-      </when>
-      <when>
-        <parameter name="FG_TIME" comparison="ge" value="0.5">
-        <parameter name="FG_TIME" comparison="le" value="1.5">
-        <set name="FG_AILERON_CMD" type="FG_DELTA" value="0.5"
-        action="FG_EXP" persistent="false" tc ="0.5">
-      </when>
-      <when>
-        <parameter name="FG_TIME" comparison="ge" value="1.5">
-        <parameter name="FG_TIME" comparison="le" value="2.5">
-        <set name="FG_RUDDER_CMD" type="FG_DELTA" value="0.5"
-        action="FG_RAMP" persistent="false" tc ="0.5">
-      </when>
-    </run>
-
-    </runscript>
- -

The first line must always be present. The second line - identifies this file as a script file, and gives a descriptive - name to the script file. Comments are next, delineated by the - <!-- and --> symbols. The aircraft and initialization files - to be used are specified in the "use" lines. Next, - comes the "run" section, where the conditions are - described in "when" clauses.

- @author Jon S. Berndt - @version "$Id$" - -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGScript : public FGJSBBase -{ -public: - /// Default constructor - FGScript(FGFDMExec* exec); - - /// Default destructor - ~FGScript(); - - /** Loads a script to drive JSBSim (usually in standalone mode). - The language is the Simple Script Directives for JSBSim (SSDJ). - @param script the filename (including path name, if any) for the script. - @return true if successful */ - bool LoadScript( string script ); - - /** This function is called each pass through the executive Run() method IF - scripting is enabled. - @return false if script should exit (i.e. if time limits are violated */ - bool RunScript(void); - -private: - enum eAction { - FG_RAMP = 1, - FG_STEP = 2, - FG_EXP = 3 - }; - - enum eType { - FG_VALUE = 1, - FG_DELTA = 2, - FG_BOOL = 3 - }; - - struct condition { - vector TestParam; - vector SetParam; - vector TestValue; - vector SetValue; - vector Comparison; - vector TC; - vector Persistent; - vector Action; - vector Type; - vector Triggered; - vector newValue; - vector OriginalValue; - vector StartTime; - vector EndTime; - - condition() { - } - }; - - bool Scripted; - - string ScriptName; - double StartTime; - double EndTime; - vector Conditions; - - FGFDMExec* FDMExec; - FGState* State; - FGPropertyManager* PropertyManager; - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGState.cpp b/src/FDM/JSBSim/FGState.cpp index 1f581b96a..cee30b905 100644 --- a/src/FDM/JSBSim/FGState.cpp +++ b/src/FDM/JSBSim/FGState.cpp @@ -36,10 +36,6 @@ HISTORY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#ifdef HAVE_CONFIG_H -# include -#endif - #ifdef FGFS # include # include @@ -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(); diff --git a/src/FDM/JSBSim/FGState.h b/src/FDM/JSBSim/FGState.h index 8709b00b3..f26b5465b 100644 --- a/src/FDM/JSBSim/FGState.h +++ b/src/FDM/JSBSim/FGState.h @@ -59,20 +59,19 @@ INCLUDES #include #include #include "FGJSBBase.h" -#include "FGInitialCondition.h" -#include "FGMatrix33.h" -#include "FGColumnVector3.h" -#include "FGQuaternion.h" +#include +#include +#include +#include #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 +#include +#include +#include +#include +#include +#include +#include /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 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; diff --git a/src/FDM/JSBSim/FGTable.cpp b/src/FDM/JSBSim/FGTable.cpp deleted file mode 100644 index b2b869d8f..000000000 --- a/src/FDM/JSBSim/FGTable.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGTable.cpp - Author: Jon S. Berndt - Date started: 1/9/2001 - Purpose: Models a lookup table - - ------------- Copyright (C) 2001 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 a lookup table - -HISTORY --------------------------------------------------------------------------------- -JSB 1/9/00 Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGTable.h" - -#if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740) -#include -#else -#include -#endif - -using namespace std; - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -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 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) -{ - Type = tt1D; - colCounter = 0; - rowCounter = 1; - - Data = Allocate(); - Debug(0); - lastRowIndex=lastColumnIndex=2; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTable::FGTable(const FGTable& t) -{ - Type = t.Type; - colCounter = t.colCounter; - rowCounter = t.rowCounter; - tableCounter = t.tableCounter; - - nRows = t.nRows; - nCols = t.nCols; - nTables = t.nTables; - - Tables = t.Tables; - Data = Allocate(); - for (int r=0; r<=nRows; r++) { - for (int c=0; c<=nCols; c++) { - Data[r][c] = t.Data[r][c]; - } - } - lastRowIndex = t.lastRowIndex; - lastColumnIndex = t.lastColumnIndex; - lastTableIndex = t.lastTableIndex; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double** FGTable::Allocate(void) -{ - Data = new double*[nRows+1]; - for (int r=0; r<=nRows; r++) { - Data[r] = new double[nCols+1]; - for (int c=0; c<=nCols; c++) { - Data[r][c] = 0.0; - } - } - return Data; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTable::~FGTable() -{ - if (nTables > 0) Tables.clear(); - for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r]; - if (Data) delete[] Data; - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTable::GetValue(double key) -{ - double Factor, Value, Span; - int r=lastRowIndex; - - //if the key is off the end of the table, just return the - //end-of-table value, do not extrapolate - if( key <= Data[1][0] ) { - lastRowIndex=2; - //cout << "Key underneath table: " << key << endl; - return Data[1][1]; - } else if ( key >= Data[nRows][0] ) { - lastRowIndex=nRows; - //cout << "Key over table: " << key << endl; - return Data[nRows][1]; - } - - // the key is somewhere in the middle, search for the right breakpoint - // assume the correct breakpoint has not changed since last frame or - // has only changed very little - - if ( r > 2 && Data[r-1][0] > key ) { - while( Data[r-1][0] > key && r > 2) { r--; } - } else if ( Data[r][0] < key ) { - while( Data[r][0] <= key && r <= nRows) { r++; } - } - - lastRowIndex=r; - // make sure denominator below does not go to zero. - - Span = Data[r][0] - Data[r-1][0]; - if (Span != 0.0) { - Factor = (key - Data[r-1][0]) / Span; - if (Factor > 1.0) Factor = 1.0; - } else { - Factor = 1.0; - } - - Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1]; - - return Value; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -double FGTable::GetValue(double rowKey, double colKey) -{ - double rFactor, cFactor, col1temp, col2temp, Value; - int r=lastRowIndex; - int c=lastColumnIndex; - - 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; - } - - if ( c > 2 && Data[0][c-1] > colKey ) { - while( Data[0][c-1] > colKey && c > 2) { c--; } - } else if ( Data[0][c] < colKey ) { - while( Data[0][c] <= colKey && c <= nCols) { c++; } - if ( c > nCols ) c = nCols; - } - - lastRowIndex=r; - lastColumnIndex=c; - - rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]); - cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]); - - if (rFactor > 1.0) rFactor = 1.0; - else if (rFactor < 0.0) rFactor = 0.0; - - if (cFactor > 1.0) cFactor = 1.0; - else if (cFactor < 0.0) cFactor = 0.0; - - col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1]; - col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c]; - - Value = col1temp + cFactor*(col2temp - col1temp); - - return Value; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTable::GetValue(double rowKey, double colKey, double tableKey) -{ - double Factor, Value, Span; - int r=lastRowIndex; - - //if the key is off the end (or before the beginning) of the table, - // just return the boundary-table value, do not extrapolate - - if( tableKey <= Data[1][1] ) { - lastRowIndex=2; - return Tables[0].GetValue(rowKey, colKey); - } else if ( tableKey >= Data[nRows][1] ) { - lastRowIndex=nRows; - return Tables[nRows-1].GetValue(rowKey, colKey); - } - - // the key is somewhere in the middle, search for the right breakpoint - // assume the correct breakpoint has not changed since last frame or - // has only changed very little - - if ( r > 2 && Data[r-1][1] > tableKey ) { - while( Data[r-1][1] > tableKey && r > 2) { r--; } - } else if ( Data[r][1] < tableKey ) { - while( Data[r][1] <= tableKey && r <= nRows) { r++; } - } - - lastRowIndex=r; - // make sure denominator below does not go to zero. - - Span = Data[r][1] - Data[r-1][1]; - if (Span != 0.0) { - Factor = (tableKey - Data[r-1][1]) / Span; - if (Factor > 1.0) Factor = 1.0; - } else { - Factor = 1.0; - } - - 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) -{ - int startRow=0; - int startCol=0; - int tableCtr=0; - - if (Type == tt1D || Type == tt3D) startRow = 1; - if (Type == tt3D) startCol = 1; - - 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++; - } - } - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTable& FGTable::operator<<(const double n) -{ - Data[rowCounter][colCounter] = n; - if (colCounter == nCols) { - colCounter = 0; - rowCounter++; - } else { - colCounter++; - } - return *this; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTable& FGTable::operator<<(const int n) -{ - *this << (double)n; - return *this; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTable::Print(int spaces) -{ - string tabspace; - int startRow=0; - int startCol=0; - - if (Type == tt1D || Type == tt3D) startRow = 1; - if (Type == tt3D) startCol = 1; - -#if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) - unsigned long flags = cout.setf(ios::fixed); -#else - ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream -#endif - - for (int i=0;i - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_TABLE "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -using std::vector; - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Lookup table class. - Models a one, two, or three dimensional lookup table for use in FGCoefficient, - FGPropeller, etc. A one-dimensional table is called a "VECTOR" in a coefficient - definition. For example: -
-    \
-      {name}
-      {number of rows}
-      {row lookup property}
-      {non-dimensionalizing properties}
-      {row_1_key} {col_1_data}
-      {row_2_key} {...       }
-      { ...     } {...       }
-      {row_n_key} {...       }
-    \
-
- A "real life" example is as shown here: -
-    \
-      Delta_lift_due_to_flap_deflection
-      4
-      fcs/flap-pos-deg
-      aero/qbar-psf | metrics/Sw-sqft
-      0   0
-      10  0.20
-      20  0.30
-      30  0.35
-    \
-
- The first column in the data table represents the lookup index (or "key"). In - this case, the lookup index is fcs/flap-pos-deg (flap extension in degrees). - If the flap position is 10 degrees, the value returned from the lookup table - would be 0.20. This value would be multiplied by qbar (aero/qbar-psf) and wing - area (metrics/Sw-sqft) to get the total lift force that is a result of flap - deflection (measured in pounds force). If the value of the flap-pos-deg property - was 15 (degrees), the value output by the table routine would be 0.25 - an - interpolation. If the flap position in degrees ever went below 0.0, or above - 30 (degrees), the output from the table routine would be 0 and 0.35, respectively. - That is, there is no _extrapolation_ to values outside the range of the lookup - index. This is why it is important to chose the data for the table wisely. - - The definition for a 2D table - referred to simply as a TABLE, is as follows: -
-    \
-      {name}
-      {number of rows}
-      {number of columns}
-      {row lookup property}
-      {column lookup property}
-      {non-dimensionalizing}
-                  {col_1_key   col_2_key   ...  col_n_key }
-      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
-      {row_2_key} {...         ...         ...  ...       }
-      { ...     } {...         ...         ...  ...       }
-      {row_n_key} {...         ...         ...  ...       }
-    \
-
- A "real life" example is as shown here: -
-    \
-      Side_force_due_to_beta
-      3
-      2
-      aero/beta-rad
-      fcs/flap-pos-deg
-      aero/qbar-psf | metrics/Sw-sqft
-               0     30
-      -0.349   0.137  0.106
-       0       0      0
-       0.349  -0.137 -0.106
-    \
-
- The definition for a 3D table in a coefficient would be (for example): -
-    \
-      {name}
-      {number of rows}
-      {number of columns}
-      {number of tables}
-      {row lookup property}
-      {column lookup property}
-      {table lookup property}
-      {non-dimensionalizing}
-      {first table key}
-                  {col_1_key   col_2_key   ...  col_n_key }
-      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
-      {row_2_key} {...         ...         ...  ...       }
-      { ...     } {...         ...         ...  ...       }
-      {row_n_key} {...         ...         ...  ...       }
-
-      {second table key}
-                  {col_1_key   col_2_key   ...  col_n_key }
-      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
-      {row_2_key} {...         ...         ...  ...       }
-      { ...     } {...         ...         ...  ...       }
-      {row_n_key} {...         ...         ...  ...       }
-
-      ...
-
-    \
-
- [At the present time, all rows and columns for each table must have the - same dimension.] - - In addition to using a Table for something like a coefficient, where all the - row and column elements are read in from a file, a Table could be created - and populated completely within program code: -
-    // First column is thi, second is neta (combustion efficiency)
-    Lookup_Combustion_Efficiency = new FGTable(12);
-    *Lookup_Combustion_Efficiency << 0.00 << 0.980;
-    *Lookup_Combustion_Efficiency << 0.90 << 0.980;
-    *Lookup_Combustion_Efficiency << 1.00 << 0.970;
-    *Lookup_Combustion_Efficiency << 1.05 << 0.950;
-    *Lookup_Combustion_Efficiency << 1.10 << 0.900;
-    *Lookup_Combustion_Efficiency << 1.15 << 0.850;
-    *Lookup_Combustion_Efficiency << 1.20 << 0.790;
-    *Lookup_Combustion_Efficiency << 1.30 << 0.700;
-    *Lookup_Combustion_Efficiency << 1.40 << 0.630;
-    *Lookup_Combustion_Efficiency << 1.50 << 0.570;
-    *Lookup_Combustion_Efficiency << 1.60 << 0.525;
-    *Lookup_Combustion_Efficiency << 2.00 << 0.345;
-
- The first column in the table, above, is thi (the lookup index, or key). The - second column is the output data - in this case, "neta" (the Greek letter - referring to combustion efficiency). Later on, the table is used like this: - - combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio); - - @author Jon S. Berndt - @version $Id$ - @see FGCoefficient - @see FGPropeller -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGTable : public FGJSBBase -{ -public: - /// Destructor - ~FGTable(); - - /** This is the very important copy constructor. - @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); - /** 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 - the first row. The implication of this layout is that there should - be no value in the upper left corner of the matrix e.g: -
-           0  10  20 30 ...
-      -5   1  2   3  4  ...
-       ...
-       
- - For multiple-table (i.e. 3D) data sets there is an additional number - key in the table definition. For example: - -
-       0.0
-           0  10  20 30 ...
-      -5   1  2   3  4  ...
-       ...
-       
- */ - - void operator<<(FGConfigFile&); - 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); - -private: - enum type {tt1D, tt2D, tt3D} Type; - double** Data; - vector Tables; - int nRows, nCols, nTables; - int colCounter, rowCounter, tableCounter; - int lastRowIndex, lastColumnIndex, lastTableIndex; - double** Allocate(void); - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -#endif - diff --git a/src/FDM/JSBSim/FGTank.cpp b/src/FDM/JSBSim/FGTank.cpp deleted file mode 100644 index f66fcbdfa..000000000 --- a/src/FDM/JSBSim/FGTank.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGTank.cpp - Author: Jon Berndt - Date started: 01/21/99 - 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 --------------------------------------------------------------------------------- -See header file. - -HISTORY --------------------------------------------------------------------------------- -01/21/99 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGTank.h" - -#if !defined ( sgi ) || defined( __GNUC__ ) && (_COMPILER_VERSION < 740) -using std::cerr; -using std::endl; -using std::cout; -#endif - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_TANK; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGTank::FGTank(FGConfigFile* AC_cfg, FGFDMExec* exec) -{ - string token; - double X, Y, Z; - Area = 1.0; - Temperature = -9999.0; - Auxiliary = exec->GetAuxiliary(); - - type = AC_cfg->GetValue("TYPE"); - - if (type == "FUEL") Type = ttFUEL; - else if (type == "OXIDIZER") Type = ttOXIDIZER; - else Type = ttUNKNOWN; - - AC_cfg->GetNextConfigLine(); - while ((token = AC_cfg->GetValue()) != string("/AC_TANK")) { - if (token == "XLOC") *AC_cfg >> X; - else if (token == "YLOC") *AC_cfg >> Y; - else if (token == "ZLOC") *AC_cfg >> Z; - else if (token == "RADIUS") *AC_cfg >> Radius; - else if (token == "CAPACITY") *AC_cfg >> Capacity; - else if (token == "CONTENTS") *AC_cfg >> Contents; - else if (token == "TEMPERATURE") *AC_cfg >> Temperature; - else cerr << "Unknown identifier: " << token << " in tank definition." << endl; - } - - vXYZ << X << Y << Z; - - Selected = true; - - if (Capacity != 0) { - PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0 - } else { - Contents = 0; - PctFull = 0; - } - - if (Temperature != -9999.0) Temperature = FahrenheitToCelsius(Temperature); - Area = 40.0 * pow(Capacity/1975, 0.666666667); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTank::~FGTank() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTank::Drain(double used) -{ - double shortage = Contents - used; - - if (shortage >= 0) { - Contents -= used; - PctFull = 100.0*Contents/Capacity; - } else { - Contents = 0.0; - PctFull = 0.0; - Selected = false; - } - return shortage; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTank::Fill(double amount) -{ - double overage = 0.0; - - Contents += amount; - - if (Contents > Capacity) { - overage = Contents - Capacity; - Contents = Capacity; - PctFull = 100.0; - } else { - PctFull = Contents/Capacity*100.0; - } - return overage; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTank::SetContents(double amount) -{ - Contents = amount; - if (Contents > Capacity) { - Contents = Capacity; - PctFull = 100.0; - } else { - PctFull = Contents/Capacity*100.0; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTank::Calculate(double dt) -{ - if (Temperature == -9999.0) return 0.0; - double HeatCapacity = 900.0; // Joules/lbm/C - double TempFlowFactor = 1.115; // Watts/sqft/C - double TAT = Auxiliary->GetTAT_C(); - double Tdiff = TAT - Temperature; - double dT = 0.0; // Temp change due to one surface - if (fabs(Tdiff) > 0.1) { - dT = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity); - } - return Temperature += (dT + dT); // For now, assume upper/lower the same -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGTank::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << " " << type << " tank holds " << Capacity << " lbs. " << type << endl; - cout << " currently at " << PctFull << "% of maximum capacity" << endl; - cout << " Tank location (X, Y, Z): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl; - cout << " Effective radius: " << Radius << " inches" << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGTank" << endl; - if (from == 1) cout << "Destroyed: FGTank" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGTank.h b/src/FDM/JSBSim/FGTank.h deleted file mode 100644 index ec8ecbb53..000000000 --- a/src/FDM/JSBSim/FGTank.h +++ /dev/null @@ -1,174 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGTank.h - Author: Jon S. Berndt - Date started: 01/21/99 - - ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) ------------- - - This program is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any later - version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 Temple - Place - Suite 330, Boston, MA 02111-1307, USA. - - Further information about the GNU General Public License can also be found on - the world wide web at http://www.gnu.org. - -FUNCTIONAL DESCRIPTION --------------------------------------------------------------------------------- - -Based on Flightgear code, which is based on LaRCSim. This class simulates -a generic Tank. - -HISTORY --------------------------------------------------------------------------------- -01/21/99 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGTank_H -#define FGTank_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGJSBBase.h" -#include "FGConfigFile.h" -#include "FGColumnVector3.h" -#include "FGAuxiliary.h" - -#ifdef FGFS -# include -# include STL_STRING - SG_USING_STD(string); - SG_USING_STD(cerr); - SG_USING_STD(endl); - SG_USING_STD(cout); -#else -# include - using std::string; -# if !defined(sgi) || defined(__GNUC__) || (_COMPILER_VERSION >= 740) - using std::cerr; - using std::endl; - using std::cout; -# endif -#endif - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_TANK "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models a fuel tank. - @author Jon Berndt - @see Akbar, Raza et al. "A Simple Analysis of Fuel Addition to the CWT of - 747", California Institute of Technology, 1998 -

- Fuel temperature is calculated using the following assumptions: -

- Fuel temperature will only be calculated for tanks which have an initial fuel - temperature specified in the configuration file. -

- The surface area of the tank is estimated from the capacity in pounds. It - is assumed that the tank is a wing tank with dimensions h by 4h by 10h. The - volume of the tank is then 40(h)(h)(h). The area of the upper or lower - surface is then 40(h)(h). The volume is also equal to the capacity divided - by 49.368 lbs/cu-ft, for jet fuel. The surface area of one side can then be - derived from the tank's capacity. -

- The heat capacity of jet fuel is assumed to be 900 Joules/lbm/K, and the - heat transfer factor of the tank is 1.115 Watts/sq-ft/K. -

-Configuration File Format -

-\
-  XLOC        \
-  YLOC        \
-  ZLOC        \
-  RADIUS      \
-  CAPACITY    \
-  CONTENTS    \
-  TEMPERATURE \
-\
-
-Definition of the tank configuration file parameters: -
-TYPE - One of FUEL or OXIDIZER.
-XLOC - Location of tank on aircraft's x-axis, inches.
-YLOC - Location of tank on aircraft's y-axis, inches.
-ZLOC - Location of tank on aircraft's z-axis, inches.
-RADIUS - Equivalent radius of tank, inches, for modeling slosh.
-CAPACITY - Capacity in pounds.
-CONTENTS - Initial contents in pounds.
-TEMPERATURE - Initial temperature in degrees Fahrenheit.
-
- */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGTank : public FGJSBBase -{ -public: - FGTank(FGConfigFile*, FGFDMExec*); - ~FGTank(); - - double Drain(double); - double Calculate(double dt); - int GetType(void) {return Type;} - bool GetSelected(void) {return Selected;} - double GetPctFull(void) {return PctFull;} - double GetContents(void) {return Contents;} - double GetTemperature_degC(void) {return Temperature;} - double GetTemperature(void) {return CelsiusToFahrenheit(Temperature);} - const FGColumnVector3& GetXYZ(void) {return vXYZ;} - double GetXYZ(int idx) {return vXYZ(idx);} - - double Fill(double amount); - void SetContents(double amount); - void SetTemperature(double temp) { Temperature = temp; } - - enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER}; - -private: - TankType Type; - string type; - FGColumnVector3 vXYZ; - double Capacity; - double Radius; - double PctFull; - double Contents; - double Area; - double Temperature; - bool Selected; - FGAuxiliary* Auxiliary; - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGThruster.cpp b/src/FDM/JSBSim/FGThruster.cpp deleted file mode 100644 index 24904aa20..000000000 --- a/src/FDM/JSBSim/FGThruster.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGThruster.cpp - Author: Jon S. Berndt - Date started: 08/23/00 - Purpose: Encapsulates the thruster object - - ------------- 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 --------------------------------------------------------------------------------- -08/23/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "FGThruster.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_THRUSTER; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGThruster::FGThruster(FGFDMExec *FDMExec) : FGForce(FDMExec) -{ - Type = ttDirect; - SetTransformType(FGForce::tCustom); - - EngineNum = 0; - PropertyManager = FDMExec->GetPropertyManager(); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGThruster::FGThruster(FGFDMExec *FDMExec, - FGConfigFile *Eng_cfg, int num ): FGForce(FDMExec) -{ - Type = ttDirect; - SetTransformType(FGForce::tCustom); - Name = Eng_cfg->GetValue(); - GearRatio = 1.0; - - EngineNum = num; - ThrustCoeff = 0.0; - ReverserAngle = 0.0; - PropertyManager = FDMExec->GetPropertyManager(); - - char property_name[80]; - snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); - PropertyManager->Tie( property_name, &ThrustCoeff ); - snprintf(property_name, 80, "propulsion/engine[%u]/reverser-angle", EngineNum); - PropertyManager->Tie( property_name, &ReverserAngle ); - - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGThruster::~FGThruster() -{ - char property_name[80]; - snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); - PropertyManager->Untie( property_name ); - snprintf(property_name, 80, "propulsion/engine[%u]/reverser-angle", EngineNum); - PropertyManager->Untie( property_name ); - - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGThruster::GetThrusterLabels(int id, string delimeter) -{ - std::ostringstream buf; - - buf << Name << "_Thrust[" << id << "]"; - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGThruster::GetThrusterValues(int id, string delimeter) -{ - std::ostringstream buf; - - buf << Thrust; - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGThruster::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: FGThruster" << endl; - if (from == 1) cout << "Destroyed: FGThruster" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGThruster.h b/src/FDM/JSBSim/FGThruster.h deleted file mode 100644 index ff523588d..000000000 --- a/src/FDM/JSBSim/FGThruster.h +++ /dev/null @@ -1,120 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGThruster.h - Author: Jon S. Berndt - Date started: 08/23/00 - - ------------- 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. - -HISTORY --------------------------------------------------------------------------------- -08/24/00 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGTHRUSTER_H -#define FGTHRUSTER_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGForce.h" -#include "FGConfigFile.h" -#include "FGPropertyManager.h" -#include - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_THRUSTER "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Base class for specific thrusting devices such as propellers, nozzles, etc. - @author Jon Berndt - @version $Id$ - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGThruster : public FGForce { - -public: - /// Constructor - FGThruster(FGFDMExec *FDMExec); - FGThruster(FGFDMExec *FDMExec, FGConfigFile *Eng_cfg, int num ); - /// Destructor - virtual ~FGThruster(); - - enum eType {ttNozzle, ttRotor, ttPropeller, ttDirect}; - - virtual double Calculate(double tt) { - Thrust = tt; - vFn(1) = Thrust * cos(ReverserAngle); - return vFn(1); - } - void SetName(string name) {Name = name;} - virtual void SetRPM(double rpm) {}; - virtual double GetPowerRequired(void) {return 0.0;} - virtual void SetdeltaT(double dt) {deltaT = dt;} - double GetThrust(void) {return Thrust;} - eType GetType(void) {return Type;} - string GetName(void) {return Name;} - virtual double GetRPM(void) { return 0.0; }; - double GetGearRatio(void) {return GearRatio; } - virtual string GetThrusterLabels(int id, string delimeter); - virtual string GetThrusterValues(int id, string delimeter); - void SetReverserAngle(double radians) { ReverserAngle = radians; } - double GetReverserAngle(void) {return ReverserAngle;} - - - inline void SetThrustCoefficient(double ct) { ThrustCoeff = ct; } - -protected: - eType Type; - string Name; - double Thrust; - double PowerRequired; - double deltaT; - double GearRatio; - double ThrustCoeff; - double ReverserAngle; - int EngineNum; - FGPropertyManager* PropertyManager; - virtual void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGTrim.cpp b/src/FDM/JSBSim/FGTrim.cpp deleted file mode 100644 index a4921e277..000000000 --- a/src/FDM/JSBSim/FGTrim.cpp +++ /dev/null @@ -1,684 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGTrim.cpp - Author: Tony Peden - Date started: 9/8/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 --------------------------------------------------------------------------------- -9/8/99 TP Created - - -FUNCTIONAL DESCRIPTION --------------------------------------------------------------------------------- - -This class takes the given set of IC's and finds the angle of attack, elevator, -and throttle setting required to fly steady level. This is currently for in-air -conditions only. It is implemented using an iterative, one-axis-at-a-time -scheme. */ - -// !!!!!!! BEWARE ALL YE WHO ENTER HERE !!!!!!! - - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include - -#include "FGFDMExec.h" -#include "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" - -#if _MSC_VER -#pragma warning (disable : 4786 4788) -#endif - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_TRIM; - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) { - - N=Nsub=0; - max_iterations=60; - max_sub_iterations=100; - Tolerance=1E-3; - A_Tolerance = Tolerance / 10; - - Debug=0;DebugLevel=0; - fdmex=FDMExec; - fgic=fdmex->GetIC(); - total_its=0; - trimudot=true; - gamma_fallback=true; - axis_count=0; - mode=tt; - xlo=xhi=alo=ahi=0.0; - targetNlf=1.0; - debug_axis=tAll; - SetMode(tt); - if (debug_lvl & 2) cout << "Instantiated: FGTrim" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTrim::~FGTrim(void) { - for(current_axis=0; current_axis 0) { - cout << " Sub-iterations:" << endl; - for(current_axis=0; current_axisGetRunCount(); - snprintf(out,80," %5s: %3.0f average: %5.2f successful: %3.0f stability: %5.2f\n", - TrimAxes[current_axis]->GetStateName().c_str(), - sub_iterations[current_axis], - sub_iterations[current_axis]/double(total_its), - successful[current_axis], - TrimAxes[current_axis]->GetAvgStability() ); - cout << out; - } - cout << " Run Count: " << run_sum << endl; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTrim::Report(void) { - cout << " Trim Results: " << endl; - for(current_axis=0; current_axisAxisReport(); - -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTrim::ClearStates(void) { - FGTrimAxis* ta; - - mode=tCustom; - vector::iterator iAxes; - iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) { - ta=*iAxes; - delete ta; - iAxes++; - } - TrimAxes.clear(); - //cout << "TrimAxes.size(): " << TrimAxes.size() << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGTrim::AddState( State state, Control control ) { - FGTrimAxis* ta; - bool result=true; - - mode = tCustom; - vector ::iterator iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) { - ta=*iAxes; - if( ta->GetStateType() == state ) - result=false; - iAxes++; - } - if(result) { - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,state,control)); - delete[] sub_iterations; - delete[] successful; - delete[] solution; - sub_iterations=new double[TrimAxes.size()]; - successful=new double[TrimAxes.size()]; - solution=new bool[TrimAxes.size()]; - } - return result; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGTrim::RemoveState( State state ) { - FGTrimAxis* ta; - bool result=false; - - mode = tCustom; - vector ::iterator iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) { - ta=*iAxes; - if( ta->GetStateType() == state ) { - delete ta; - TrimAxes.erase(iAxes); - result=true; - continue; - } - iAxes++; - } - if(result) { - delete[] sub_iterations; - delete[] successful; - delete[] solution; - sub_iterations=new double[TrimAxes.size()]; - successful=new double[TrimAxes.size()]; - solution=new bool[TrimAxes.size()]; - } - return result; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGTrim::EditState( State state, Control new_control ){ - FGTrimAxis* ta; - bool result=false; - - mode = tCustom; - vector ::iterator iAxes = TrimAxes.begin(); - while (iAxes != TrimAxes.end()) { - ta=*iAxes; - if( ta->GetStateType() == state ) { - TrimAxes.insert(iAxes,1,new FGTrimAxis(fdmex,fgic,state,new_control)); - delete ta; - TrimAxes.erase(iAxes+1); - result=true; - break; - } - iAxes++; - } - return result; -} - - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGTrim::DoTrim(void) { - - trim_failed=false; - int i; - - for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ - fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false); - } - - fdmex->GetOutput()->Disable(); - - fgic->SetPRadpsIC(0.0); - fgic->SetQRadpsIC(0.0); - fgic->SetRRadpsIC(0.0); - - //clear the sub iterations counts & zero out the controls - for(current_axis=0;current_axisGetStateName() - //<< " " << TrimAxes[current_axis]->GetControlName()<< endl; - if(TrimAxes[current_axis]->GetStateType() == tQdot) { - if(mode == tGround) { - TrimAxes[current_axis]->initTheta(); - } - } - xlo=TrimAxes[current_axis]->GetControlMin(); - xhi=TrimAxes[current_axis]->GetControlMax(); - TrimAxes[current_axis]->SetControl((xlo+xhi)/2); - TrimAxes[current_axis]->Run(); - //TrimAxes[current_axis]->AxisReport(); - sub_iterations[current_axis]=0; - successful[current_axis]=0; - solution[current_axis]=false; - } - - - if(mode == tPullup ) { - cout << "Setting pitch rate and nlf... " << endl; - setupPullup(); - cout << "pitch rate done ... " << endl; - TrimAxes[0]->SetStateTarget(targetNlf); - cout << "nlf done" << endl; - } else if (mode == tTurn) { - setupTurn(); - //TrimAxes[0]->SetStateTarget(targetNlf); - } - - do { - axis_count=0; - for(current_axis=0;current_axis 0) TrimAxes[current_axis]->AxisReport(); - if(TrimAxes[current_axis]->InTolerance()) { - axis_count++; - successful[current_axis]++; - } - } - - - if((axis_count == TrimAxes.size()-1) && (TrimAxes.size() > 1)) { - //cout << TrimAxes.size()-1 << " out of " << TrimAxes.size() << "!" << endl; - //At this point we can check the input limits of the failed axis - //and declare the trim failed if there is no sign change. If there - //is, keep going until success or max iteration count - - //Oh, well: two out of three ain't bad - for(current_axis=0;current_axisInTolerance()) { - if(!checkLimits()) { - // special case this for now -- if other cases arise proper - // support can be added to FGTrimAxis - if( (gamma_fallback) && - (TrimAxes[current_axis]->GetStateType() == tUdot) && - (TrimAxes[current_axis]->GetControlType() == tThrottle)) { - cout << " Can't trim udot with throttle, trying flight" - << " path angle. (" << N << ")" << endl; - if(TrimAxes[current_axis]->GetState() > 0) - TrimAxes[current_axis]->SetControlToMin(); - else - TrimAxes[current_axis]->SetControlToMax(); - TrimAxes[current_axis]->Run(); - delete TrimAxes[current_axis]; - TrimAxes[current_axis]=new FGTrimAxis(fdmex,fgic,tUdot, - tGamma ); - } else { - cout << " Sorry, " << TrimAxes[current_axis]->GetStateName() - << " doesn't appear to be trimmable" << endl; - //total_its=k; - trim_failed=true; //force the trim to fail - } //gamma_fallback - } - } //solution check - } //for loop - } //all-but-one check - N++; - if(N > max_iterations) - trim_failed=true; - } while((axis_count < TrimAxes.size()) && (!trim_failed)); - if((!trim_failed) && (axis_count >= TrimAxes.size())) { - total_its=N; - if (debug_lvl > 0) - cout << endl << " Trim successful" << endl; - } else { - total_its=N; - if (debug_lvl > 0) - cout << endl << " Trim failed" << endl; - } - for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ - fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); - } - fdmex->GetOutput()->Enable(); - return !trim_failed; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGTrim::solve(void) { - - double x1,x2,x3,f1,f2,f3,d,d0; - const double relax =0.9; - double eps=TrimAxes[current_axis]->GetSolverEps(); - - x1=x2=x3=0; - d=1; - bool success=false; - //initializations - if( solutionDomain != 0) { - /* if(ahi > alo) { */ - x1=xlo;f1=alo; - x3=xhi;f3=ahi; - /* } else { - x1=xhi;f1=ahi; - x3=xlo;f3=alo; - } */ - d0=fabs(x3-x1); - //iterations - //max_sub_iterations=TrimAxes[current_axis]->GetIterationLimit(); - while ( (TrimAxes[current_axis]->InTolerance() == false ) - && (fabs(d) > eps) && (Nsub < max_sub_iterations)) { - Nsub++; - d=(x3-x1)/d0; - x2=x1-d*d0*f1/(f3-f1); - TrimAxes[current_axis]->SetControl(x2); - TrimAxes[current_axis]->Run(); - f2=TrimAxes[current_axis]->GetState(); - if(Debug > 1) { - cout << "FGTrim::solve Nsub,x1,x2,x3: " << Nsub << ", " << x1 - << ", " << x2 << ", " << x3 << endl; - cout << " " << f1 << ", " << f2 << ", " << f3 << endl; - } - if(f1*f2 <= 0.0) { - x3=x2; - f3=f2; - f1=relax*f1; - //cout << "Solution is between x1 and x2" << endl; - } - else if(f2*f3 <= 0.0) { - x1=x2; - f1=f2; - f3=relax*f3; - //cout << "Solution is between x2 and x3" << endl; - - } - //cout << i << endl; - - - }//end while - if(Nsub < max_sub_iterations) success=true; - } - return success; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/* - produces an interval (xlo..xhi) on one side or the other of the current - control value in which a solution exists. This domain is, hopefully, - smaller than xmin..0 or 0..xmax and the solver will require fewer iterations - to find the solution. This is, hopefully, more efficient than having the - solver start from scratch every time. Maybe it isn't though... - This tries to take advantage of the idea that the changes from iteration to - iteration will be small after the first one or two top-level iterations. - - assumes that changing the control will a produce significant change in the - accel i.e. checkLimits() has already been called. - - if a solution is found above the current control, the function returns true - and xlo is set to the current control, xhi to the interval max it found, and - solutionDomain is set to 1. - if the solution lies below the current control, then the function returns - true and xlo is set to the interval min it found and xmax to the current - control. if no solution is found, then the function returns false. - - - in all cases, alo=accel(xlo) and ahi=accel(xhi) after the function exits. - no assumptions about the state of the sim after this function has run - can be made. -*/ -bool FGTrim::findInterval(void) { - bool found=false; - double step; - double current_control=TrimAxes[current_axis]->GetControl(); - double current_accel=TrimAxes[current_axis]->GetState();; - double xmin=TrimAxes[current_axis]->GetControlMin(); - double xmax=TrimAxes[current_axis]->GetControlMax(); - double lastxlo,lastxhi,lastalo,lastahi; - - step=0.025*fabs(xmax); - xlo=xhi=current_control; - alo=ahi=current_accel; - lastxlo=xlo;lastxhi=xhi; - lastalo=alo;lastahi=ahi; - do { - - Nsub++; - step*=2; - xlo-=step; - if(xlo < xmin) xlo=xmin; - xhi+=step; - if(xhi > xmax) xhi=xmax; - TrimAxes[current_axis]->SetControl(xlo); - TrimAxes[current_axis]->Run(); - alo=TrimAxes[current_axis]->GetState(); - TrimAxes[current_axis]->SetControl(xhi); - TrimAxes[current_axis]->Run(); - ahi=TrimAxes[current_axis]->GetState(); - if(fabs(ahi-alo) <= TrimAxes[current_axis]->GetTolerance()) continue; - if(alo*ahi <=0) { //found interval with root - found=true; - if(alo*current_accel <= 0) { //narrow interval down a bit - solutionDomain=-1; - xhi=lastxlo; - ahi=lastalo; - //xhi=current_control; - //ahi=current_accel; - } else { - solutionDomain=1; - xlo=lastxhi; - alo=lastahi; - //xlo=current_control; - //alo=current_accel; - } - } - lastxlo=xlo;lastxhi=xhi; - lastalo=alo;lastahi=ahi; - if( !found && xlo==xmin && xhi==xmax ) continue; - if(Debug > 1) - cout << "FGTrim::findInterval: Nsub=" << Nsub << " Lo= " << xlo - << " Hi= " << xhi << " alo*ahi: " << alo*ahi << endl; - } while(!found && (Nsub <= max_sub_iterations) ); - return found; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//checks to see which side of the current control value the solution is on -//and sets solutionDomain accordingly: -// 1 if solution is between the current and max -// -1 if solution is between the min and current -// 0 if there is no solution -// -//if changing the control produces no significant change in the accel then -//solutionDomain is set to zero and the function returns false -//if a solution is found, then xlo and xhi are set so that they bracket -//the solution, alo is set to accel(xlo), and ahi is set to accel(xhi) -//if there is no change or no solution then xlo=xmin, alo=accel(xmin) and -//xhi=xmax and ahi=accel(xmax) -//in all cases the sim is left such that the control=xmax and accel=ahi - -bool FGTrim::checkLimits(void) { - bool solutionExists; - double current_control=TrimAxes[current_axis]->GetControl(); - double current_accel=TrimAxes[current_axis]->GetState(); - xlo=TrimAxes[current_axis]->GetControlMin(); - xhi=TrimAxes[current_axis]->GetControlMax(); - - TrimAxes[current_axis]->SetControl(xlo); - TrimAxes[current_axis]->Run(); - alo=TrimAxes[current_axis]->GetState(); - TrimAxes[current_axis]->SetControl(xhi); - TrimAxes[current_axis]->Run(); - ahi=TrimAxes[current_axis]->GetState(); - if(Debug > 1) - cout << "checkLimits() xlo,xhi,alo,ahi: " << xlo << ", " << xhi << ", " - << alo << ", " << ahi << endl; - solutionDomain=0; - solutionExists=false; - if(fabs(ahi-alo) > TrimAxes[current_axis]->GetTolerance()) { - if(alo*current_accel <= 0) { - solutionExists=true; - solutionDomain=-1; - xhi=current_control; - ahi=current_accel; - } else if(current_accel*ahi < 0){ - solutionExists=true; - solutionDomain=1; - xlo=current_control; - alo=current_accel; - } - } - TrimAxes[current_axis]->SetControl(current_control); - TrimAxes[current_axis]->Run(); - return solutionExists; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTrim::setupPullup() { - double g,q,cgamma; - g=fdmex->GetInertial()->gravity(); - cgamma=cos(fgic->GetFlightPathAngleRadIC()); - cout << "setPitchRateInPullup(): " << g << ", " << cgamma << ", " - << fgic->GetVtrueFpsIC() << endl; - q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); - cout << targetNlf << ", " << q << endl; - fgic->SetQRadpsIC(q); - cout << "setPitchRateInPullup() complete" << endl; - -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTrim::setupTurn(void){ - double g,phi; - phi = fgic->GetRollAngleRadIC(); - if( fabs(phi) > 0.001 && fabs(phi) < 1.56 ) { - targetNlf = 1 / cos(phi); - g = fdmex->GetInertial()->gravity(); - psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); - cout << targetNlf << ", " << psidot << endl; - } - -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTrim::updateRates(void){ - if( mode == tTurn ) { - double phi = fgic->GetRollAngleRadIC(); - double g = fdmex->GetInertial()->gravity(); - double p,q,r,theta; - if(fabs(phi) > 0.001 && fabs(phi) < 1.56 ) { - theta=fgic->GetPitchAngleRadIC(); - phi=fgic->GetRollAngleRadIC(); - psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); - p=-psidot*sin(theta); - q=psidot*cos(theta)*sin(phi); - r=psidot*cos(theta)*cos(phi); - } else { - p=q=r=0; - } - fgic->SetPRadpsIC(p); - fgic->SetQRadpsIC(q); - fgic->SetRRadpsIC(r); - } else if( mode == tPullup && fabs(targetNlf-1) > 0.01) { - double g,q,cgamma; - g=fdmex->GetInertial()->gravity(); - cgamma=cos(fgic->GetFlightPathAngleRadIC()); - q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); - fgic->SetQRadpsIC(q); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTrim::setDebug(void) { - if(debug_axis == tAll || - TrimAxes[current_axis]->GetStateType() == debug_axis ) { - Debug=DebugLevel; - return; - } else { - Debug=0; - return; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTrim::SetMode(TrimMode tt) { - ClearStates(); - mode=tt; - switch(tt) { - case tFull: - if (debug_lvl > 0) - cout << " Full Trim" << endl; - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); - break; - case tLongitudinal: - if (debug_lvl > 0) - cout << " Longitudinal Trim" << endl; - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); - break; - case tGround: - if (debug_lvl > 0) - cout << " Ground Trim" << endl; - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta )); - //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi )); - break; - case tPullup: - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); - break; - case tTurn: - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); - TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); - break; - case tCustom: - case tNone: - break; - } - //cout << "TrimAxes.size(): " << TrimAxes.size() << endl; - sub_iterations=new double[TrimAxes.size()]; - successful=new double[TrimAxes.size()]; - solution=new bool[TrimAxes.size()]; - current_axis=0; -} -//YOU WERE WARNED, BUT YOU DID IT ANYWAY. -} diff --git a/src/FDM/JSBSim/FGTrim.h b/src/FDM/JSBSim/FGTrim.h deleted file mode 100644 index 19647cc04..000000000 --- a/src/FDM/JSBSim/FGTrim.h +++ /dev/null @@ -1,296 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGTrim.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 --------------------------------------------------------------------------------- -9/8/99 TP Created - - -FUNCTIONAL DESCRIPTION --------------------------------------------------------------------------------- - -This class takes the given set of IC's and finds the aircraft state required to -maintain a specified flight condition. This flight condition can be -steady-level with non-zero sideslip, a steady turn, a pull-up or pushover. -On-ground conditions can be trimmed as well, but this is currently limited to -adjusting altitude and pitch angle only. It is implemented using an iterative, -one-axis-at-a-time scheme. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGTRIM_H -#define FGTRIM_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGFDMExec.h" -#include "FGJSBBase.h" -#include "FGTrimAxis.h" - -#include - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_TRIM "$Id$" - -#if defined(_WIN32) && !defined(__CYGWIN__) - #define snprintf _snprintf -#endif - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -typedef enum { tLongitudinal, tFull, tGround, tPullup, - tCustom, tNone, tTurn - } TrimMode; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** FGTrim -- the trimming routine for JSBSim. - FGTrim finds the aircraft attitude and control settings needed to maintain - the steady state described by the FGInitialCondition object . It does this - iteratively by assigning a control to each state and adjusting that control - until the state is within a specified tolerance of zero. States include the - recti-linear accelerations udot, vdot, and wdot, the angular accelerations - qdot, pdot, and rdot, and the difference between heading and ground track. - Controls include the usual flight deck controls available to the pilot plus - angle of attack (alpha), sideslip angle(beta), flight path angle (gamma), - pitch attitude(theta), roll attitude(phi), and altitude above ground. The - last three are used for on-ground trimming. The state-control pairs used in - a given trim are completely user configurable and several pre-defined modes - are provided as well. They are: - - tLongitudinal: Trim wdot with alpha, udot with thrust, qdot with elevator - - tFull: tLongitudinal + vdot with phi, pdot with aileron, rdot with rudder - and heading minus ground track (hmgt) with beta - - tPullup: tLongitudinal but adjust alpha to achieve load factor input - with SetTargetNlf() - - tGround: wdot with altitude, qdot with theta, and pdot with phi - - The remaining modes include tCustom, which is completely user defined and - tNone. - - Note that trims can (and do) fail for reasons that are completely outside - the control of the trimming routine itself. The most common problem is the - initial conditions: is the model capable of steady state flight - at those conditions? Check the speed, altitude, configuration (flaps, - gear, etc.), weight, cg, and anything else that may be relevant. - - Example usage:
-    FGFDMExec* FDMExec = new FGFDMExec();
-
-    FGInitialCondition* fgic = new FGInitialCondition(FDMExec);
-    FGTrim fgt(FDMExec, fgic, tFull);
-    fgic->SetVcaibratedKtsIC(100);
-    fgic->SetAltitudeFtIC(1000);
-    fgic->SetClimbRate(500);
-    if( !fgt.DoTrim() ) {
-      cout << "Trim Failed" << endl;
-    }
-    fgt.Report(); 
- @author Tony Peden - @version "$Id$" -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGTrim : public FGJSBBase -{ -private: - - vector TrimAxes; - unsigned int current_axis; - int N, Nsub; - TrimMode mode; - int DebugLevel, Debug; - double Tolerance, A_Tolerance; - double wdot,udot,qdot; - double dth; - double *sub_iterations; - double *successful; - bool *solution; - int max_sub_iterations; - int max_iterations; - int total_its; - bool trimudot; - bool gamma_fallback; - bool trim_failed; - unsigned int axis_count; - int solutionDomain; - double xlo,xhi,alo,ahi; - double targetNlf; - int debug_axis; - - double psidot,thetadot; - - FGFDMExec* fdmex; - FGInitialCondition* fgic; - - bool solve(void); - - /** @return false if there is no change in the current axis accel - between accel(control_min) and accel(control_max). If there is a - change, sets solutionDomain to: - 0 for no sign change, - -1 if sign change between accel(control_min) and accel(0) - 1 if sign between accel(0) and accel(control_max) - */ - bool findInterval(void); - - bool checkLimits(void); - - void setupPullup(void); - void setupTurn(void); - - void updateRates(void); - - void setDebug(void); - -public: - /** Initializes the trimming class - @param FDMExec pointer to a JSBSim executive object. - @param tm trim mode - */ - FGTrim(FGFDMExec *FDMExec, TrimMode tm=tGround ); - - ~FGTrim(void); - - /** Execute the trim - */ - bool DoTrim(void); - - /** Print the results of the trim. For each axis trimmed, this - includes the final state value, control value, and tolerance - used. - @return true if trim succeeds - */ - void Report(void); - - /** Iteration statistics - */ - void TrimStats(); - - /** Clear all state-control pairs and set a predefined trim mode - @param tm the set of axes to trim. Can be: - tLongitudinal, tFull, tGround, tCustom, or tNone - */ - void SetMode(TrimMode tm); - - /** Clear all state-control pairs from the current configuration. - The trimming routine must have at least one state-control pair - configured to be useful - */ - void ClearStates(void); - - /** Add a state-control pair to the current configuration. See the enums - State and Control in FGTrimAxis.h for the available options. - Will fail if the given state is already configured. - @param state the accel or other condition to zero - @param control the control used to zero the state - @return true if add is successful - */ - bool AddState( State state, Control control ); - - /** Remove a specific state-control pair from the current configuration - @param state the state to remove - @return true if removal is successful - */ - bool RemoveState( State state ); - - /** Change the control used to zero a state previously configured - @param state the accel or other condition to zero - @param new_control the control used to zero the state - */ - bool EditState( State state, Control new_control ); - - /** automatically switch to trimming longitudinal acceleration with - flight path angle (gamma) once it becomes apparent that there - is not enough/too much thrust. - @param bb true to enable fallback - */ - inline void SetGammaFallback(bool bb) { gamma_fallback=bb; } - - /** query the fallback state - @return true if fallback is enabled. - */ - inline bool GetGammaFallback(void) { return gamma_fallback; } - - /** Set the iteration limit. DoTrim() will return false if limit - iterations are reached before trim is achieved. The default - is 60. This does not ordinarily need to be changed. - @param ii integer iteration limit - */ - inline void SetMaxCycles(int ii) { max_iterations = ii; } - - /** Set the per-axis iteration limit. Attempt to zero each state - by iterating limit times before moving on to the next. The - default limit is 100 and also does not ordinarily need to - be changed. - @param ii integer iteration limit - */ - inline void SetMaxCyclesPerAxis(int ii) { max_sub_iterations = ii; } - - /** Set the tolerance for declaring a state trimmed. Angular accels are - held to a tolerance of 1/10th of the given. The default is - 0.001 for the recti-linear accelerations and 0.0001 for the angular. - */ - inline void SetTolerance(double tt) { - Tolerance = tt; - A_Tolerance = tt / 10; - } - - /** - Debug level 1 shows results of each top-level iteration - Debug level 2 shows level 1 & results of each per-axis iteration - */ - inline void SetDebug(int level) { DebugLevel = level; } - inline void ClearDebug(void) { DebugLevel = 0; } - - /** - Output debug data for one of the axes - The State enum is defined in FGTrimAxis.h - */ - inline void DebugState(State state) { debug_axis=state; } - - inline void SetTargetNlf(double nlf) { targetNlf=nlf; } - inline double GetTargetNlf(void) { return targetNlf; } - -}; -} - -#endif diff --git a/src/FDM/JSBSim/FGTrimAxis.cpp b/src/FDM/JSBSim/FGTrimAxis.cpp deleted file mode 100644 index 7dd968228..000000000 --- a/src/FDM/JSBSim/FGTrimAxis.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGTrimAxis.cpp - Author: Tony Peden - Date started: 7/3/00 - - --------- 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/3/00 TP Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef _MSC_VER -# pragma warning (disable : 4786) -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include "FGFDMExec.h" -#include "FGAtmosphere.h" -#include "FGInitialCondition.h" -#include "FGTrimAxis.h" -#include "FGAircraft.h" -#include "FGPropulsion.h" -#include "FGAerodynamics.h" - - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_TRIMAXIS; - -/*****************************************************************************/ - -FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st, - Control ctrl) { - - fdmex=fdex; - fgic=ic; - state=st; - control=ctrl; - max_iterations=10; - control_value=0; - its_to_stable_value=0; - total_iterations=0; - total_stability_iterations=0; - state_convert=1.0; - control_convert=1.0; - state_value=0; - state_target=0; - switch(state) { - case tUdot: tolerance = DEFAULT_TOLERANCE; break; - case tVdot: tolerance = DEFAULT_TOLERANCE; break; - case tWdot: tolerance = DEFAULT_TOLERANCE; break; - case tQdot: tolerance = DEFAULT_TOLERANCE / 10; break; - case tPdot: tolerance = DEFAULT_TOLERANCE / 10; break; - case tRdot: tolerance = DEFAULT_TOLERANCE / 10; break; - case tHmgt: tolerance = 0.01; break; - case tNlf: state_target=1.0; tolerance = 1E-5; break; - case tAll: break; - } - - solver_eps=tolerance; - switch(control) { - case tThrottle: - control_min=0; - control_max=1; - control_value=0.5; - break; - case tBeta: - control_min=-30*degtorad; - control_max=30*degtorad; - control_convert=radtodeg; - break; - case tAlpha: - control_min=fdmex->GetAerodynamics()->GetAlphaCLMin(); - control_max=fdmex->GetAerodynamics()->GetAlphaCLMax(); - if(control_max <= control_min) { - control_max=20*degtorad; - control_min=-5*degtorad; - } - control_value= (control_min+control_max)/2; - control_convert=radtodeg; - solver_eps=tolerance/100; - break; - case tPitchTrim: - case tElevator: - case tRollTrim: - case tAileron: - case tYawTrim: - case tRudder: - control_min=-1; - control_max=1; - state_convert=radtodeg; - solver_eps=tolerance/100; - break; - case tAltAGL: - control_min=0; - control_max=30; - control_value=fdmex->GetPropagate()->GetDistanceAGL(); - solver_eps=tolerance/100; - break; - case tTheta: - control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad; - state_convert=radtodeg; - break; - case tPhi: - control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad; - state_convert=radtodeg; - control_convert=radtodeg; - break; - case tGamma: - solver_eps=tolerance/100; - control_min=-80*degtorad; - control_max=80*degtorad; - control_convert=radtodeg; - break; - case tHeading: - control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad; - control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad; - state_convert=radtodeg; - break; - } - - - Debug(0); -} - -/*****************************************************************************/ - -FGTrimAxis::~FGTrimAxis(void) -{ - Debug(1); -} - -/*****************************************************************************/ - -void FGTrimAxis::getState(void) { - switch(state) { - case tUdot: state_value=fdmex->GetPropagate()->GetUVWdot(1)-state_target; break; - case tVdot: state_value=fdmex->GetPropagate()->GetUVWdot(2)-state_target; break; - case tWdot: state_value=fdmex->GetPropagate()->GetUVWdot(3)-state_target; break; - case tQdot: state_value=fdmex->GetPropagate()->GetPQRdot(2)-state_target;break; - case tPdot: state_value=fdmex->GetPropagate()->GetPQRdot(1)-state_target; break; - case tRdot: state_value=fdmex->GetPropagate()->GetPQRdot(3)-state_target; break; - case tHmgt: state_value=computeHmgt()-state_target; break; - case tNlf: state_value=fdmex->GetAircraft()->GetNlf()-state_target; break; - case tAll: break; - } -} - -/*****************************************************************************/ - -//States are not settable - -void FGTrimAxis::getControl(void) { - switch(control) { - case tThrottle: control_value=fdmex->GetFCS()->GetThrottleCmd(0); break; - case tBeta: control_value=fdmex->GetAuxiliary()->Getalpha(); break; - case tAlpha: control_value=fdmex->GetAuxiliary()->Getbeta(); break; - case tPitchTrim: control_value=fdmex->GetFCS() -> GetPitchTrimCmd(); break; - case tElevator: control_value=fdmex->GetFCS() -> GetDeCmd(); break; - case tRollTrim: - case tAileron: control_value=fdmex->GetFCS() -> GetDaCmd(); break; - case tYawTrim: - case tRudder: control_value=fdmex->GetFCS() -> GetDrCmd(); break; - case tAltAGL: control_value=fdmex->GetPropagate()->GetDistanceAGL();break; - case tTheta: control_value=fdmex->GetPropagate()->GetEuler(eTht); break; - case tPhi: control_value=fdmex->GetPropagate()->GetEuler(ePhi); break; - case tGamma: control_value=fdmex->GetAuxiliary()->GetGamma();break; - case tHeading: control_value=fdmex->GetPropagate()->GetEuler(ePsi); break; - } -} - -/*****************************************************************************/ - -double FGTrimAxis::computeHmgt(void) { - double diff; - - diff = fdmex->GetPropagate()->GetEuler(ePsi) - - fdmex->GetAuxiliary()->GetGroundTrack(); - - if( diff < -M_PI ) { - return (diff + 2*M_PI); - } else if( diff > M_PI ) { - return (diff - 2*M_PI); - } else { - return diff; - } - -} - -/*****************************************************************************/ - - -void FGTrimAxis::setControl(void) { - switch(control) { - case tThrottle: setThrottlesPct(); break; - case tBeta: fgic->SetBetaRadIC(control_value); break; - case tAlpha: fgic->SetAlphaRadIC(control_value); break; - case tPitchTrim: fdmex->GetFCS()->SetPitchTrimCmd(control_value); break; - case tElevator: fdmex->GetFCS()->SetDeCmd(control_value); break; - case tRollTrim: - case tAileron: fdmex->GetFCS()->SetDaCmd(control_value); break; - case tYawTrim: - case tRudder: fdmex->GetFCS()->SetDrCmd(control_value); break; - case tAltAGL: fgic->SetAltitudeAGLFtIC(control_value); break; - case tTheta: fgic->SetPitchAngleRadIC(control_value); break; - case tPhi: fgic->SetRollAngleRadIC(control_value); break; - case tGamma: fgic->SetFlightPathAngleRadIC(control_value); break; - case tHeading: fgic->SetTrueHeadingRadIC(control_value); break; - } -} - - - - - -/*****************************************************************************/ - -// the aircraft center of rotation is no longer the cg once the gear -// contact the ground so the altitude needs to be changed when pitch -// and roll angle are adjusted. Instead of attempting to calculate the -// new center of rotation, pick a gear unit as a reference and use its -// location vector to calculate the new height change. i.e. new altitude = -// earth z component of that vector (which is in body axes ) -void FGTrimAxis::SetThetaOnGround(double ff) { - int center,i,ref; - - // favor an off-center unit so that the same one can be used for both - // pitch and roll. An on-center unit is used (for pitch)if that's all - // that's in contact with the ground. - i=0; ref=-1; center=-1; - while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { - if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) { - if(fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01) - ref=i; - else - center=i; - } - i++; - } - if((ref < 0) && (center >= 0)) { - ref=center; - } - cout << "SetThetaOnGround ref gear: " << ref << endl; - if(ref >= 0) { - double sp = fdmex->GetPropagate()->GetSinEuler(ePhi); - double cp = fdmex->GetPropagate()->GetCosEuler(ePhi); - double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); - double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); - double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); - double hagl = -1*lx*sin(ff) + - ly*sp*cos(ff) + - lz*cp*cos(ff); - - fgic->SetAltitudeAGLFtIC(hagl); - cout << "SetThetaOnGround new alt: " << hagl << endl; - } - fgic->SetPitchAngleRadIC(ff); - cout << "SetThetaOnGround new theta: " << ff << endl; -} - -/*****************************************************************************/ - -bool FGTrimAxis::initTheta(void) { - int i,N; - int iForward = 0; - int iAft = 1; - double zAft,zForward,zDiff,theta; - double xAft,xForward,xDiff; - bool level; - double saveAlt; - - saveAlt=fgic->GetAltitudeAGLFtIC(); - fgic->SetAltitudeAGLFtIC(100); - - - N=fdmex->GetGroundReactions()->GetNumGearUnits(); - - //find the first wheel unit forward of the cg - //the list is short so a simple linear search is fine - for( i=0; iGetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) { - iForward=i; - break; - } - } - //now find the first wheel unit aft of the cg - for( i=0; iGetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) { - iAft=i; - break; - } - } - - // now adjust theta till the wheels are the same distance from the ground - xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetBodyLocation(1); - xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetBodyLocation(1); - xDiff = xForward - xAft; - zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); - zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); - zDiff = zForward - zAft; - level=false; - theta=fgic->GetPitchAngleDegIC(); - while(!level && (i < 100)) { - theta+=radtodeg*atan(zDiff/xDiff); - fgic->SetPitchAngleDegIC(theta); - fdmex->RunIC(); - zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); - zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); - zDiff = zForward - zAft; - //cout << endl << theta << " " << zDiff << endl; - //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl; - //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl; - if(fabs(zDiff ) < 0.1) - level=true; - i++; - } - //cout << i << endl; - if (debug_lvl > 0) { - cout << " Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*radtodeg << endl; - cout << " Used gear unit " << iAft << " as aft and " << iForward << " as forward" << endl; - } - control_min=(theta+5)*degtorad; - control_max=(theta-5)*degtorad; - fgic->SetAltitudeAGLFtIC(saveAlt); - if(i < 100) - return true; - else - return false; -} - -/*****************************************************************************/ - -void FGTrimAxis::SetPhiOnGround(double ff) { - int i,ref; - - i=0; ref=-1; - //must have an off-center unit here - while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { - if ( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) && - (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)) - ref=i; - i++; - } - if (ref >= 0) { - double st = fdmex->GetPropagate()->GetSinEuler(eTht); - double ct = fdmex->GetPropagate()->GetCosEuler(eTht); - double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); - double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); - double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); - double hagl = -1*lx*st + - ly*sin(ff)*ct + - lz*cos(ff)*ct; - - fgic->SetAltitudeAGLFtIC(hagl); - } - fgic->SetRollAngleRadIC(ff); - -} - -/*****************************************************************************/ - -void FGTrimAxis::Run(void) { - - double last_state_value; - int i; - setControl(); - //cout << "FGTrimAxis::Run: " << control_value << endl; - i=0; - bool stable=false; - while(!stable) { - i++; - last_state_value=state_value; - fdmex->RunIC(); - getState(); - if(i > 1) { - if((fabs(last_state_value - state_value) < tolerance) || (i >= 100) ) - stable=true; - } - } - - its_to_stable_value=i; - total_stability_iterations+=its_to_stable_value; - total_iterations++; -} - -/*****************************************************************************/ - -void FGTrimAxis::setThrottlesPct(void) { - double tMin,tMax; - for(unsigned i=0;iGetPropulsion()->GetNumEngines();i++) { - tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin(); - tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax(); - //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value; - fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin)); - //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl; - fdmex->RunIC(); //apply throttle change - fdmex->GetPropulsion()->GetSteadyState(); - } -} - -/*****************************************************************************/ - -void FGTrimAxis::AxisReport(void) { - - char out[80]; - - sprintf(out," %20s: %6.2f %5s: %9.2e Tolerance: %3.0e", - GetControlName().c_str(), GetControl()*control_convert, - GetStateName().c_str(), GetState()+state_target, GetTolerance()); - cout << out; - - if( fabs(GetState()+state_target) < fabs(GetTolerance()) ) - cout << " Passed" << endl; - else - cout << " Failed" << endl; -} - -/*****************************************************************************/ - -double FGTrimAxis::GetAvgStability( void ) { - if(total_iterations > 0) { - return double(total_stability_iterations)/double(total_iterations); - } - return 0; -} - -/*****************************************************************************/ -// 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 FGTrimAxis::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: FGTrimAxis" << endl; - if (from == 1) cout << "Destroyed: FGTrimAxis" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGTrimAxis.h b/src/FDM/JSBSim/FGTrimAxis.h deleted file mode 100644 index e0754a03c..000000000 --- a/src/FDM/JSBSim/FGTrimAxis.h +++ /dev/null @@ -1,186 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGTrimAxis.h - Author: Tony Peden - Date started: 7/3/00 - - ------------- 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/3/00 TP Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGTRIMAXIS_H -#define FGTRIMAXIS_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include - -#include "FGFDMExec.h" -#include "FGJSBBase.h" -#include "FGInitialCondition.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_TRIMAXIS "$Id$" - -#define DEFAULT_TOLERANCE 0.001 - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -const string StateNames[10]= { "all","udot","vdot","wdot","qdot","pdot","rdot", - "hmgt","nlf" - }; -const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack", - "Elevator","Ailerons","Rudder", - "Altitude AGL", "Pitch Angle", - "Roll Angle", "Flight Path Angle", - "Pitch Trim", "Roll Trim", "Yaw Trim", - "Heading" - }; - -class FGInitialCondition; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models an aircraft axis for purposes of trimming. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -enum State { tAll,tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt,tNlf }; -enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL, - tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading }; - -class FGTrimAxis : public FGJSBBase -{ -public: - FGTrimAxis(FGFDMExec* fdmex, - FGInitialCondition *ic, - State st, - Control ctrl ); - ~FGTrimAxis(); - - void Run(void); - - double GetState(void) { getState(); return state_value; } - //Accels are not settable - inline void SetControl(double value ) { control_value=value; } - inline double GetControl(void) { return control_value; } - - inline State GetStateType(void) { return state; } - inline Control GetControlType(void) { return control; } - - inline string GetStateName(void) { return StateNames[state]; } - inline string GetControlName(void) { return ControlNames[control]; } - - inline double GetControlMin(void) { return control_min; } - inline double GetControlMax(void) { return control_max; } - - inline void SetControlToMin(void) { control_value=control_min; } - inline void SetControlToMax(void) { control_value=control_max; } - - inline void SetControlLimits(double min, double max) { - control_min=min; - control_max=max; - } - - inline void SetTolerance(double ff) { tolerance=ff;} - inline double GetTolerance(void) { return tolerance; } - - inline double GetSolverEps(void) { return solver_eps; } - inline void SetSolverEps(double ff) { solver_eps=ff; } - - inline int GetIterationLimit(void) { return max_iterations; } - inline void SetIterationLimit(int ii) { max_iterations=ii; } - - inline int GetStability(void) { return its_to_stable_value; } - inline int GetRunCount(void) { return total_stability_iterations; } - double GetAvgStability( void ); - - void SetThetaOnGround(double ff); - void SetPhiOnGround(double ff); - - inline void SetStateTarget(double target) { state_target=target; } - inline double GetStateTarget(void) { return state_target; } - - bool initTheta(void); - - void AxisReport(void); - - bool InTolerance(void) { getState(); return (fabs(state_value) <= tolerance); } - -private: - FGFDMExec *fdmex; - FGInitialCondition *fgic; - - State state; - Control control; - - double state_target; - - double state_value; - double control_value; - - double control_min; - double control_max; - - double tolerance; - - double solver_eps; - - double state_convert; - double control_convert; - - int max_iterations; - - int its_to_stable_value; - int total_stability_iterations; - int total_iterations; - - void setThrottlesPct(void); - - void getState(void); - void getControl(void); - void setControl(void); - - double computeHmgt(void); - - void Debug(int from); -}; -} -#endif diff --git a/src/FDM/JSBSim/FGTurbine.cpp b/src/FDM/JSBSim/FGTurbine.cpp deleted file mode 100644 index 03c6a3587..000000000 --- a/src/FDM/JSBSim/FGTurbine.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGTurbine.cpp - Author: David Culp - Date started: 03/11/2003 - Purpose: This module models a turbine engine. - - ------------- Copyright (C) 2003 David 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. - -FUNCTIONAL DESCRIPTION --------------------------------------------------------------------------------- - -This class descends from the FGEngine class and models a turbine engine based -on parameters given in the engine config file for this class - -HISTORY --------------------------------------------------------------------------------- -03/11/2003 DPC Created -09/08/2003 DPC Changed Calculate() and added engine phases - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include "FGTurbine.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_TURBINE; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGTurbine::FGTurbine(FGFDMExec* exec, FGConfigFile* cfg, int engine_number) - : FGEngine(exec, engine_number) -{ - SetDefaults(); - - Load(cfg); - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGTurbine::~FGTurbine() -{ - unbind(); - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// The main purpose of Calculate() is to determine what phase the engine should -// be in, then call the corresponding function. - -double FGTurbine::Calculate(void) -{ - TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; - dt = State->Getdt() * Propulsion->GetRate(); - ThrottlePos = FCS->GetThrottlePos(EngineNumber); - if (ThrottlePos > 1.0) { - AugmentCmd = ThrottlePos - 1.0; - ThrottlePos -= AugmentCmd; - } else { - AugmentCmd = 0.0; - } - - // When trimming is finished check if user wants engine OFF or RUNNING - if ((phase == tpTrim) && (dt > 0)) { - if (Running && !Starved) { - phase = tpRun; - N2 = IdleN2 + ThrottlePos * N2_factor; - N1 = IdleN1 + ThrottlePos * N1_factor; - OilTemp_degK = 366.0; - Cutoff = false; - } - else { - phase = tpOff; - Cutoff = true; - EGT_degC = TAT; - } - } - - if (!Running && Cutoff && Starter) { - if (phase == tpOff) phase = tpSpinUp; - } - if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart; - if (Cutoff && (phase != tpSpinUp)) phase = tpOff; - if (dt == 0) phase = tpTrim; - if (Starved) phase = tpOff; - if (Stalled) phase = tpStall; - if (Seized) phase = tpSeize; - - switch (phase) { - case tpOff: Thrust = Off(); break; - case tpRun: Thrust = Run(); break; - case tpSpinUp: Thrust = SpinUp(); break; - case tpStart: Thrust = Start(); break; - case tpStall: Thrust = Stall(); break; - case tpSeize: Thrust = Seize(); break; - case tpTrim: Thrust = Trim(); break; - default: Thrust = Off(); - } - - // The thruster can modify the thrust, eg. thrust reverser - return Thrust = Thruster->Calculate(Thrust); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::Off(void) -{ - double qbar = Auxiliary->Getqbar(); - Running = false; - FuelFlow_pph = Seek(&FuelFlow_pph, 0, 1000.0, 10000.0); - N1 = Seek(&N1, qbar/10.0, N1/2.0, N1/2.0); - N2 = Seek(&N2, qbar/15.0, N2/2.0, N2/2.0); - EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); - OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); - OilPressure_psi = N2 * 0.62; - NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); - EPR = Seek(&EPR, 1.0, 0.2, 0.2); - Augmentation = false; - return 0.0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::Run(void) -{ - double idlethrust, milthrust, thrust; - double N2norm; // 0.0 = idle N2, 1.0 = maximum N2 - idlethrust = MilThrust * ThrustTables[0]->TotalValue(); - milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue(); - - Running = true; - Starter = false; - - N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, delay, delay * 3.0); - N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, delay, delay * 2.4); - N2norm = (N2 - IdleN2) / N2_factor; - thrust = idlethrust + (milthrust * N2norm * N2norm); - EGT_degC = TAT + 363.1 + ThrottlePos * 357.1; - OilPressure_psi = N2 * 0.62; - OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1); - - if (!Augmentation) { - double correctedTSFC = TSFC * (0.84 + (1-N2norm)*(1-N2norm)); - FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 100000); - if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF; - NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8); - thrust = thrust * (1.0 - BleedDemand); - EPR = 1.0 + thrust/MilThrust; - } - - if (AugMethod == 1) { - if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;} - else {Augmentation = false;} - } - - if ((Augmented == 1) && Augmentation && (AugMethod < 2)) { - thrust = MaxThrust * ThrustTables[2]->TotalValue(); - FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); - NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); - } - - if (AugMethod == 2) { - if (AugmentCmd > 0.0) { - Augmentation = true; - double tdiff = (MaxThrust * ThrustTables[2]->TotalValue()) - thrust; - thrust += (tdiff * AugmentCmd); - FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); - NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); - } else { - Augmentation = false; - } - } - - if ((Injected == 1) && Injection) { - thrust = thrust * ThrustTables[3]->TotalValue(); - } - - ConsumeFuel(); - if (Cutoff) phase = tpOff; - if (Starved) phase = tpOff; - - return thrust; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::SpinUp(void) -{ - Running = false; - FuelFlow_pph = 0.0; - N2 = Seek(&N2, 25.18, 3.0, N2/2.0); - N1 = Seek(&N1, 5.21, 1.0, N1/2.0); - EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); - OilPressure_psi = N2 * 0.62; - OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); - EPR = 1.0; - NozzlePosition = 1.0; - return 0.0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::Start(void) -{ - if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start - Cranking = true; // provided for sound effects signal - if (N2 < IdleN2) { - N2 = Seek(&N2, IdleN2, 2.0, N2/2.0); - N1 = Seek(&N1, IdleN1, 1.4, N1/2.0); - EGT_degC = Seek(&EGT_degC, TAT + 363.1, 21.3, 7.3); - FuelFlow_pph = Seek(&FuelFlow_pph, IdleFF, 103.7, 103.7); - OilPressure_psi = N2 * 0.62; - ConsumeFuel(); - } - else { - phase = tpRun; - Running = true; - Starter = false; - Cranking = false; - } - } - else { // no start if N2 < 15% - phase = tpOff; - Starter = false; - } - - return 0.0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::Stall(void) -{ - double qbar = Auxiliary->Getqbar(); - EGT_degC = TAT + 903.14; - FuelFlow_pph = IdleFF; - N1 = Seek(&N1, qbar/10.0, 0, N1/10.0); - N2 = Seek(&N2, qbar/15.0, 0, N2/10.0); - ConsumeFuel(); - if (ThrottlePos < 0.01) phase = tpRun; // clear the stall with throttle - - return 0.0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::Seize(void) -{ - double qbar = Auxiliary->Getqbar(); - N2 = 0.0; - N1 = Seek(&N1, qbar/20.0, 0, N1/15.0); - FuelFlow_pph = IdleFF; - ConsumeFuel(); - OilPressure_psi = 0.0; - OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0, 0.2); - Running = false; - return 0.0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::Trim(void) -{ - double idlethrust, milthrust, thrust, tdiff; - idlethrust = MilThrust * ThrustTables[0]->TotalValue();; - milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue(); - thrust = (idlethrust + (milthrust * ThrottlePos * ThrottlePos)) - * (1.0 - BleedDemand); - if (AugmentCmd > 0.0) { - tdiff = (MaxThrust * ThrustTables[2]->TotalValue()) - thrust; - thrust += (tdiff * AugmentCmd); - } - - return thrust; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::CalcFuelNeed(void) -{ - return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::GetPowerAvailable(void) { - if( ThrottlePos <= 0.77 ) - return 64.94*ThrottlePos; - else - return 217.38*ThrottlePos - 117.38; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -double FGTurbine::Seek(double *var, double target, double accel, double decel) { - double v = *var; - if (v > target) { - v -= dt * decel; - if (v < target) v = target; - } else if (v < target) { - v += dt * accel; - if (v > target) v = target; - } - return v; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTurbine::SetDefaults(void) -{ - Name = "Not defined"; - N1 = N2 = 0.0; - Type = etTurbine; - MilThrust = 10000.0; - MaxThrust = 10000.0; - BypassRatio = 0.0; - TSFC = 0.8; - ATSFC = 1.7; - IdleN1 = 30.0; - IdleN2 = 60.0; - MaxN1 = 100.0; - MaxN2 = 100.0; - Augmented = 0; - AugMethod = 0; - Injected = 0; - BleedDemand = 0.0; - ThrottlePos = 0.0; - AugmentCmd = 0.0; - InletPosition = 1.0; - NozzlePosition = 1.0; - Augmentation = false; - Injection = false; - Reversed = false; - Cutoff = true; - phase = tpOff; - Stalled = false; - Seized = false; - Overtemp = false; - Fire = false; - EGT_degC = 0.0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGTurbine::Load(FGConfigFile *Eng_cfg) -{ - string token; - - Name = Eng_cfg->GetValue("NAME"); - Eng_cfg->GetNextConfigLine(); - int counter=0; - - while ( ((token = Eng_cfg->GetValue()) != string("/FG_TURBINE")) && - (token != string("/FG_SIMTURBINE")) ) { - *Eng_cfg >> token; - - if (token[0] == '<') token.erase(0,1); // Tables are read "> MilThrust; - else if (token == "MAXTHRUST") *Eng_cfg >> MaxThrust; - else if (token == "BYPASSRATIO") *Eng_cfg >> BypassRatio; - else if (token == "BLEED") *Eng_cfg >> BleedDemand; - else if (token == "TSFC") *Eng_cfg >> TSFC; - else if (token == "ATSFC") *Eng_cfg >> ATSFC; - else if (token == "IDLEN1") *Eng_cfg >> IdleN1; - else if (token == "IDLEN2") *Eng_cfg >> IdleN2; - else if (token == "MAXN1") *Eng_cfg >> MaxN1; - else if (token == "MAXN2") *Eng_cfg >> MaxN2; - else if (token == "AUGMENTED") *Eng_cfg >> Augmented; - else if (token == "AUGMETHOD") *Eng_cfg >> AugMethod; - else if (token == "INJECTED") *Eng_cfg >> Injected; - else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle; - else if (token == "TABLE") { - if (counter++ == 0) Debug(2); // print engine specs prior to table read - ThrustTables.push_back( new FGCoefficient(FDMExec) ); - ThrustTables.back()->Load(Eng_cfg); - } - else cerr << "Unhandled token in Engine config file: " << token << endl; - if (token == "EOF") return false; - } - - // Pre-calculations and initializations - - delay = 60.0 / (BypassRatio + 3.0); - N1_factor = MaxN1 - IdleN1; - N2_factor = MaxN2 - IdleN2; - OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; - IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate - - bindmodel(); - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGTurbine::GetEngineLabels(string delimeter) -{ - std::ostringstream buf; - - buf << Name << "_N1[" << EngineNumber << "]" << delimeter - << Name << "_N2[" << EngineNumber << "]" << delimeter - << Thruster->GetThrusterLabels(EngineNumber, delimeter); - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -string FGTurbine::GetEngineValues(string delimeter) -{ - std::ostringstream buf; - - buf << N1 << delimeter - << N2 << delimeter - << Thruster->GetThrusterValues(EngineNumber, delimeter); - - return buf.str(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTurbine::bindmodel() -{ - char property_name[80]; - - snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber); - PropertyManager->Tie( property_name, &N1); - snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber); - PropertyManager->Tie( property_name, &N2); - snprintf(property_name, 80, "propulsion/engine[%u]/fuel-flow", EngineNumber); - PropertyManager->Tie( property_name, &FuelFlow_pph); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGTurbine::unbind() -{ - char property_name[80]; - - snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber); - PropertyManager->Untie(property_name); - snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber); - PropertyManager->Untie(property_name); - snprintf(property_name, 80, "propulsion/engine[%u]/fuel-flow", EngineNumber); - PropertyManager->Untie( property_name); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGTurbine::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - - } - if (from == 2) { // called from Load() - cout << "\n Engine Name: " << Name << endl; - cout << " MilThrust: " << MilThrust << endl; - cout << " MaxThrust: " << MaxThrust << endl; - cout << " BypassRatio: " << BypassRatio << endl; - cout << " TSFC: " << TSFC << endl; - cout << " ATSFC: " << ATSFC << endl; - cout << " IdleN1: " << IdleN1 << endl; - cout << " IdleN2: " << IdleN2 << endl; - cout << " MaxN1: " << MaxN1 << endl; - cout << " MaxN2: " << MaxN2 << endl; - cout << " Augmented: " << Augmented << endl; - cout << " AugMethod: " << AugMethod << endl; - cout << " Injected: " << Injected << endl; - cout << " MinThrottle: " << MinThrottle << endl; - - cout << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGTurbine" << endl; - if (from == 1) cout << "Destroyed: FGTurbine" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGTurbine.h b/src/FDM/JSBSim/FGTurbine.h deleted file mode 100644 index 5f685e611..000000000 --- a/src/FDM/JSBSim/FGTurbine.h +++ /dev/null @@ -1,253 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGTurbine.h - Author: David Culp - Date started: 03/11/2003 - - ------------- Copyright (C) 2003 David 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 --------------------------------------------------------------------------------- -03/11/2003 DPC Created, based on FGTurbine -09/22/2003 DPC Added starting, stopping, new framework -04/29/2004 DPC Renamed from FGSimTurbine to FGTurbine - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGTURBINE_H -#define FGTURBINE_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include -#include "FGEngine.h" -#include "FGConfigFile.h" -#include "FGCoefficient.h" - -#define ID_TURBINE "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** This class models a turbine engine. Based on Jon Berndt's FGTurbine module. - Here the term "phase" signifies the engine's mode of operation. At any given - time the engine is in only one phase. At simulator startup the engine will be - placed in the Trim phase in order to provide a simplified thrust value without - throttle lag. When trimming is complete the engine will go to the Off phase, - unless the value FGEngine::Running has been previously set to true, in which - case the engine will go to the Run phase. Once an engine is in the Off phase - the full starting procedure (or airstart) must be used to get it running. -

- - STARTING (on ground): - -# Set the control FGEngine::Starter to true. The engine will spin up to - a maximum of about %25 N2 (%5.2 N1). This simulates the action of a - pneumatic starter. - -# After reaching %15 N2 set the control FGEngine::Cutoff to false. If fuel - is available the engine will now accelerate to idle. The starter will - automatically be set to false after the start cycle. -

- - STARTING (in air): - -# Increase speed to obtain a minimum of %15 N2. If this is not possible, - the starter may be used to assist. - -# Place the control FGEngine::Cutoff to false. -

- Ignition is assumed to be on anytime the Cutoff control is set to false, - therefore a seperate ignition system is not modeled. - -Configuration File Format -

-\
-  MILTHRUST   \
-  MAXTHRUST   \
-  BYPASSRATIO \
-  TSFC        \
-  ATSFC       \
-  IDLEN1      \
-  IDLEN2      \
-  MAXN1       \
-  MAXN2       \
-  AUGMENTED   \<0|1>
-  AUGMETHOD   \<0|1>
-  INJECTED    \<0|1>
-  ...
-\
-
-Definition of the turbine engine configuration file parameters: -
-MILTHRUST - Maximum thrust, static, at sea level, lbf.
-MAXTHRUST - Afterburning thrust, static, at sea level, lbf
-[this value will be ignored when AUGMENTED is zero (false)].
-BYPASSRATIO - Ratio of bypass air flow to core air flow.
-TSFC - Thrust-specific fuel consumption, lbm/hr/lbf
-[i.e. fuel flow divided by thrust].
-ATSFC - Afterburning TSFC, lbm/hr/lbf
-[this value will be ignored when AUGMENTED is zero (false)]
-IDLEN1 - Fan rotor rpm (% of max) at idle
-IDLEN2 - Core rotor rpm (% of max) at idle
-MAXN1 - Fan rotor rpm (% of max) at full throttle [not always 100!]
-MAXN2 - Core rotor rpm (% of max) at full throttle [not always 100!]
-AUGMENTED
-  0 == afterburner not installed
-  1 == afterburner installed
-AUGMETHOD
-  0 == afterburner activated by property /engines/engine[n]/augmentation
-  1 == afterburner activated by pushing throttle above 99% position
-  2 == throttle range is expanded in the FCS, and values above 1.0 are afterburner range
-  [this item will be ignored when AUGMENTED == 0]
-INJECTED
-  0 == Water injection not installed
-  1 == Water injection installed
-
- @author David P. Culp - @version "$Id$" -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGTurbine : public FGEngine -{ -public: - /** Constructor - @param Executive pointer to executive structure - @param Eng_cfg pointer to engine config file instance - @param engine_number engine number*/ - FGTurbine(FGFDMExec* Executive, FGConfigFile* Eng_cfg, int engine_number); - /// Destructor - ~FGTurbine(); - - enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; - - double Calculate(void); - double CalcFuelNeed(void); - double GetPowerAvailable(void); - double Seek(double* var, double target, double accel, double decel); - - phaseType GetPhase(void) { return phase; } - - bool GetOvertemp(void) {return Overtemp; } - bool GetInjection(void) {return Injection;} - bool GetFire(void) { return Fire; } - bool GetAugmentation(void) {return Augmentation;} - bool GetReversed(void) { return Reversed; } - bool GetCutoff(void) { return Cutoff; } - int GetIgnition(void) {return Ignition;} - - double GetInlet(void) { return InletPosition; } - double GetNozzle(void) { return NozzlePosition; } - double GetBleedDemand(void) {return BleedDemand;} - double GetN1(void) {return N1;} - double GetN2(void) {return N2;} - double GetEPR(void) {return EPR;} - double GetEGT(void) {return EGT_degC;} - - double getOilPressure_psi () const {return OilPressure_psi;} - double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} - - void SetInjection(bool injection) {Injection = injection;} - void SetIgnition(int ignition) {Ignition = ignition;} - void SetAugmentation(bool augmentation) {Augmentation = augmentation;} - void SetPhase( phaseType p ) { phase = p; } - void SetEPR(double epr) {EPR = epr;} - void SetBleedDemand(double bleedDemand) {BleedDemand = bleedDemand;} - void SetReverse(bool reversed) { Reversed = reversed; } - void SetCutoff(bool cutoff) { Cutoff = cutoff; } - - string GetEngineLabels(string delimeter); - string GetEngineValues(string delimeter); - -private: - - typedef vector CoeffArray; - CoeffArray ThrustTables; - - phaseType phase; ///< Operating mode, or "phase" - double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) - double MaxThrust; ///< Maximum Augmented Thrust, static @ S.L. (lbf) - double BypassRatio; ///< Bypass Ratio - double TSFC; ///< Thrust Specific Fuel Consumption (lbm/hr/lbf) - double ATSFC; ///< Augmented TSFC (lbm/hr/lbf) - double IdleN1; ///< Idle N1 - double IdleN2; ///< Idle N2 - double N1; ///< N1 - double N2; ///< N2 - double MaxN1; ///< N1 at 100% throttle - double MaxN2; ///< N2 at 100% throttle - double IdleFF; ///< Idle Fuel Flow (lbm/hr) - double delay; ///< Inverse spool-up time from idle to 100% (seconds) - double dt; ///< Simulator time slice - double N1_factor; ///< factor to tie N1 and throttle - double N2_factor; ///< factor to tie N2 and throttle - double ThrottlePos; ///< FCS-supplied throttle position - double AugmentCmd; ///< modulated afterburner command (0.0 to 1.0) - double TAT; ///< total air temperature (deg C) - bool Stalled; ///< true if engine is compressor-stalled - bool Seized; ///< true if inner spool is seized - bool Overtemp; ///< true if EGT exceeds limits - bool Fire; ///< true if engine fire detected - bool Injection; - bool Augmentation; - bool Reversed; - bool Cutoff; - int Injected; ///< = 1 if water injection installed - int Ignition; - int Augmented; ///< = 1 if augmentation installed - int AugMethod; ///< = 0 if using property /engine[n]/augmentation - ///< = 1 if using last 1% of throttle movement - ///< = 2 if using FCS-defined throttle - double EGT_degC; - double EPR; - double OilPressure_psi; - double OilTemp_degK; - double BleedDemand; - double InletPosition; - double NozzlePosition; - - double Off(void); - double Run(); - double SpinUp(void); - double Start(void); - double Stall(void); - double Seize(void); - double Trim(); - - void SetDefaults(void); - bool Load(FGConfigFile *ENG_cfg); - void bindmodel(void); - void unbind(void); - void Debug(int from); - -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#endif - diff --git a/src/FDM/JSBSim/FGfdmSocket.cpp b/src/FDM/JSBSim/FGfdmSocket.cpp deleted file mode 100644 index c6672a749..000000000 --- a/src/FDM/JSBSim/FGfdmSocket.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGfdmSocket.cpp - Author: Jon S. Berndt - Date started: 11/08/99 - Purpose: Encapsulates a socket - Called by: FGOutput, et. al. - - ------------- 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 excapsulates a socket for simple data writing - -HISTORY --------------------------------------------------------------------------------- -11/08/99 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGfdmSocket.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_FDMSOCKET; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGfdmSocket::FGfdmSocket(string address, int port) -{ - size = 0; - connected = false; - - #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 cout << "Winsock DLL not initialized ..." << endl; - #endif - - if (address.find_first_not_of("0123456789.",0) != address.npos) { - if ((host = gethostbyname(address.c_str())) == NULL) { - cout << "Could not get host net address by name..." << endl; - } - } else { - if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) { - cout << "Could not get host net address by number..." << endl; - } - } - - if (host != NULL) { - cout << "Got host net address..." << endl; - 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 (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful - cout << "Successfully connected to socket ..." << endl; - connected = true; - } else { // unsuccessful - cout << "Could not connect to socket ..." << endl; - } - } else { // unsuccessful - cout << "Could not create socket for FDM, error = " << errno << endl; - } - } - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGfdmSocket::~FGfdmSocket() -{ - #ifndef macintosh - if (sckt) shutdown(sckt,2); - #endif - - #ifdef __BORLANDC__ - WSACleanup(); - #endif - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGfdmSocket::Clear(void) -{ - buffer = ""; - size = 0; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGfdmSocket::Append(const char* item) -{ - if (size == 0) buffer += string(item); - else buffer += string(",") + string(item); - size++; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGfdmSocket::Append(double item) -{ - char s[25]; - - sprintf(s,"%12.7f",item); - - if (size == 0) buffer += string(s); - else buffer += string(",") + string(s); - size++; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGfdmSocket::Append(long item) -{ - char s[25]; - - sprintf(s,"%12ld",item); - - if (size == 0) buffer += string(s); - else buffer += string(",") + string(s); - size++; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGfdmSocket::Send(void) -{ - buffer += string("\n"); - if ((send(sckt,buffer.c_str(),buffer.size(),0)) <= 0) { - perror("send"); - } else { - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGfdmSocket::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: FGfdmSocket" << endl; - if (from == 1) cout << "Destroyed: FGfdmSocket" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/FGfdmSocket.h b/src/FDM/JSBSim/FGfdmSocket.h deleted file mode 100644 index 0c64541b2..000000000 --- a/src/FDM/JSBSim/FGfdmSocket.h +++ /dev/null @@ -1,122 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGfdmSocket.h - Author: Jon S. Berndt - Date started: 11/08/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/08/99 JSB Created - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SENTRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifndef FGfdmSocket_H -#define FGfdmSocket_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include - -#ifdef FGFS -# include -# include STL_STRING -# include STL_IOSTREAM -# include STL_FSTREAM - SG_USING_STD(cout); - SG_USING_STD(endl); -#else -# include -# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) -# include -# include -# else -# include -# include - using std::cout; - using std::endl; -# endif -#endif - -#include -#include "FGJSBBase.h" - -#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) - #include -#else - #include - #include - #include - #include -#endif - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_FDMSOCKET "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates a socket object. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -using std::string; - -class FGfdmSocket : public FGJSBBase -{ -public: - FGfdmSocket(string, int); - ~FGfdmSocket(); - void Send(void); - void Append(const char*); - void Append(double); - void Append(long); - void Clear(void); - bool GetConnectStatus(void) {return connected;} - -private: - int sckt; - int size; - struct sockaddr_in scktName; - struct hostent *host; - string buffer; - bool connected; - void Debug(int from); -}; -} -#endif diff --git a/src/FDM/JSBSim/JSBSim.cxx b/src/FDM/JSBSim/JSBSim.cxx index d7ffc2ad5..a60060e8a 100644 --- a/src/FDM/JSBSim/JSBSim.cxx +++ b/src/FDM/JSBSim/JSBSim.cxx @@ -47,30 +47,35 @@ #include
#include
+#include "JSBSim.hxx" #include -#include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "JSBSim.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); - } -} diff --git a/src/FDM/JSBSim/JSBSim.hxx b/src/FDM/JSBSim/JSBSim.hxx index 64f1dfcb1..5bd13816b 100644 --- a/src/FDM/JSBSim/JSBSim.hxx +++ b/src/FDM/JSBSim/JSBSim.hxx @@ -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; - }; diff --git a/src/FDM/JSBSim/Makefile.am b/src/FDM/JSBSim/Makefile.am index fd3001eb7..c2d2b93c7 100644 --- a/src/FDM/JSBSim/Makefile.am +++ b/src/FDM/JSBSim/Makefile.am @@ -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 - - -# noinst_PROGRAMS = testJSBsim +libJSBSim_a_SOURCES = FGFDMExec.cpp FGJSBBase.cpp FGState.cpp JSBSim.cxx -AM_CXXFLAGS = -DFGFS +noinst_HEADERS = FGFDMExec.h FGJSBBase.h FGState.h JSBSim.hxx -INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src +INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/FDM/JSBSim diff --git a/src/FDM/JSBSim/Makefile.solo b/src/FDM/JSBSim/Makefile.solo deleted file mode 100644 index b1a10450b..000000000 --- a/src/FDM/JSBSim/Makefile.solo +++ /dev/null @@ -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 diff --git a/src/FDM/JSBSim/README b/src/FDM/JSBSim/README deleted file mode 100644 index 2ad5ae7f6..000000000 --- a/src/FDM/JSBSim/README +++ /dev/null @@ -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. - diff --git a/src/FDM/JSBSim/filtersjb/FGCondition.cpp b/src/FDM/JSBSim/filtersjb/FGCondition.cpp deleted file mode 100644 index e3c527171..000000000 --- a/src/FDM/JSBSim/filtersjb/FGCondition.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGCondition.cpp - Author: Jon S. Berndt - Date started: 1/2/2003 - - -------------- Copyright (C) 2003 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 --------------------------------------------------------------------------------- - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -COMMENTS, REFERENCES, and NOTES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGCondition.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_CONDITION; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -string FGCondition::indent = " "; - - -FGCondition::FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManager) : - PropertyManager(PropertyManager) -{ - 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; - - TestParam1 = TestParam2 = 0L; - TestValue = 0.0; - Comparison = ecUndef; - 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(); - } - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGCondition::~FGCondition(void) -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGCondition::Evaluate(void ) -{ - vector ::iterator iConditions; - bool pass = false; - double compareValue; - - if (Logic == eAND) { - - iConditions = conditions.begin(); - pass = true; - while (iConditions < conditions.end()) { - if (!iConditions->Evaluate()) pass = false; - *iConditions++; - } - - } else if (Logic == eOR) { - - pass = false; - while (iConditions < conditions.end()) { - if (iConditions->Evaluate()) pass = true; - *iConditions++; - } - - } else { - - if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue(); - else compareValue = TestValue; - - switch (Comparison) { - case ecUndef: - cerr << "Undefined comparison operator." << endl; - break; - case eEQ: - pass = TestParam1->getDoubleValue() == compareValue; - break; - case eNE: - pass = TestParam1->getDoubleValue() != compareValue; - break; - case eGT: - pass = TestParam1->getDoubleValue() > compareValue; - break; - case eGE: - pass = TestParam1->getDoubleValue() >= compareValue; - break; - case eLT: - pass = TestParam1->getDoubleValue() < compareValue; - break; - case eLE: - pass = TestParam1->getDoubleValue() <= compareValue; - break; - default: - cerr << "Unknown comparison operator." << endl; - } - } - - return pass; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGCondition::PrintCondition(void ) -{ - vector ::iterator iConditions; - string scratch; - - if (isGroup) { - switch(Logic) { - case (elUndef): - scratch = " UNSET"; - cerr << "unset logic for test condition" << endl; - break; - case (eAND): - scratch = " if all of the following are true"; - break; - case (eOR): - scratch = " if any of the following are true:"; - break; - default: - scratch = " UNKNOWN"; - cerr << "Unknown logic for test condition" << endl; - } - - iConditions = conditions.begin(); - cout << scratch << endl; - while (iConditions < conditions.end()) { - iConditions->PrintCondition(); - *iConditions++; - } - } else { - if (TestParam2 != 0L) - cout << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName(); - else - cout << TestParam1->GetName() << " " << conditional << " " << TestValue; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGCondition::convert(void) -{ - if (conditions.empty()) - cout << " " << property1 << " " << conditional << " " << property2 << endl; - else - for (int i; i -#include "../FGPropertyManager.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_CONDITION "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates a condition, which is used in parts of JSBSim including switches -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGCondition : public FGJSBBase -{ -public: - FGCondition(FGConfigFile* AC_cfg, 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 mComparison; - eLogic Logic; - - FGPropertyManager *TestParam1, *TestParam2, *PropertyManager; - double TestValue; - eComparison Comparison; - bool isGroup; - string conditional; - string property1, property2; - - static string indent; - - vector conditions; - - void Debug(int from); -}; -} -#endif - diff --git a/src/FDM/JSBSim/filtersjb/FGDeadBand.cpp b/src/FDM/JSBSim/filtersjb/FGDeadBand.cpp deleted file mode 100644 index 0158ecd3f..000000000 --- a/src/FDM/JSBSim/filtersjb/FGDeadBand.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - 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 - 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGDeadBand.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_DEADBAND; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGDeadBand::FGDeadBand(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs), - AC_cfg(AC_cfg) -{ - 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); - } - } - FGFCSComponent::bind(); - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGDeadBand::~FGDeadBand() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGDeadBand::Run(void ) -{ - FGFCSComponent::Run(); // call the base class for initialization of Input - - Input = InputNodes[0]->getDoubleValue(); - - if (Input < -width/2.0) { - Output = (Input + width/2.0)*gain; - } else if (Input > width/2.0) { - Output = (Input - width/2.0)*gain; - } else { - Output = 0.0; - } - - if (clip) { - if (Output > clipmax) Output = clipmax; - else if (Output < clipmin) Output = clipmin; - } - - if (IsOutput) SetOutput(); - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGDeadBand::convert(void) -{ - cout << endl; - cout << " " << endl; - - cout << " " << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "" << endl; - - if (gain != 1.0) - cout << " " << gain << "" << endl; - - cout << " " << width << "" << endl; - - if (clip) { - cout << " " << endl; - cout << " " << clipmin << "" << endl; - cout << " " << clipmax << "" << endl; - cout << " " << endl; - } - - if (IsOutput) - cout << " " << (OutputNode->GetFullyQualifiedName()).substr(12) << "" << endl; - - cout << " " << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGDeadBand::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << " INPUT: " << InputNodes[0]->getName() << endl; - cout << " DEADBAND WIDTH: " << width << endl; - cout << " GAIN: " << gain << 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: FGDeadBand" << endl; - if (from == 1) cout << "Destroyed: FGDeadBand" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/filtersjb/FGDeadBand.h b/src/FDM/JSBSim/filtersjb/FGDeadBand.h deleted file mode 100644 index c89a6c9f7..000000000 --- a/src/FDM/JSBSim/filtersjb/FGDeadBand.h +++ /dev/null @@ -1,105 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGDeadBand.h - Author: - Date started: - - ------------- Copyright (C) ------------- - - 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 FGDEADBAND_H -#define FGDEADBAND_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGFCSComponent.h" -#include "../FGConfigFile.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_DEADBAND "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -class FGFCS; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models a deadband object. - Here is the format of the deadband control specification: -
-    \
-       INPUT {input}
-       WIDTH {deadband width}
-       MIN {minimum value}
-       MAX {maximum value}
-       [GAIN {optional deadband gain}]
-       [OUTPUT {optional output parameter to set}]
-    \
-    
- The WIDTH value is the total deadband region within which an input will - produce no output. For example, say that the WIDTH value is 2.0. If the - input is between -1.0 and +1.0, the output will be zero. - @author Jon S. Berndt - @version $Id$ -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGDeadBand : public FGFCSComponent -{ -public: - FGDeadBand(FGFCS* fcs, FGConfigFile* AC_cfg); - ~FGDeadBand(); - - bool Run(void); - void convert(void); - -private: - FGConfigFile* AC_cfg; - double width; - double clipmax, clipmin; - bool clip; - double gain; - - void Debug(int from); -}; -} -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -#endif diff --git a/src/FDM/JSBSim/filtersjb/FGFCSComponent.cpp b/src/FDM/JSBSim/filtersjb/FGFCSComponent.cpp deleted file mode 100644 index 4833a645c..000000000 --- a/src/FDM/JSBSim/filtersjb/FGFCSComponent.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGFCSComponent.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_FCSCOMPONENT; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGFCSComponent::FGFCSComponent(FGFCS* _fcs) : fcs(_fcs) -{ - Type = ""; - Input = 0.0; - Output = 0.0; - OutputNode = 0; - IsOutput = false; - PropertyManager=fcs->GetPropertyManager(); - treenode = 0; - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGFCSComponent::~FGFCSComponent() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGFCSComponent::SetOutput(void) -{ - OutputNode->setDoubleValue(Output); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -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;iGetNode( "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 -// 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 (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; - } - } -} -} diff --git a/src/FDM/JSBSim/filtersjb/FGFCSComponent.h b/src/FDM/JSBSim/filtersjb/FGFCSComponent.h deleted file mode 100644 index f624b20a5..000000000 --- a/src/FDM/JSBSim/filtersjb/FGFCSComponent.h +++ /dev/null @@ -1,131 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGFCSComponent.h - Author: Jon S. Berndt - Date started: 05/01/2000 - - ------------- Copyright (C) ------------- - - 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 FGFCSCOMPONENT_H -#define FGFCSCOMPONENT_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef FGFS -# include -#endif - -#include -#include -#include "../FGJSBBase.h" -#include "../FGPropertyManager.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_FCSCOMPONENT "$Id$" - -using std::string; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -class FGFCS; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Base class for JSBSim Flight Control System Components. - The Flight Control System (FCS) for JSBSim consists of the FCS container - class (see \URL[FGFCS]{FGFCS.html}), the FGFCSComponent base class, and the - component classes from which can be constructed a string, or channel. See: - - - FGSwitch - - FGGain - - FGKinemat - - FGFilter - - FGDeadBand - - FGSummer - - FGGradient - - @author Jon S. Berndt - @version $Id$ - @see Documentation for the FGFCS class, and for the configuration file class - FGConfigFile. -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGFCSComponent : public FGJSBBase -{ -public: - /// Constructor - FGFCSComponent(FGFCS*); - /// Destructor - virtual ~FGFCSComponent(); - - virtual bool Run(void); - virtual void SetOutput(void); - inline double GetOutput (void) const {return Output;} - inline FGPropertyManager* GetOutputNode(void) { return OutputNode; } - 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; - vector InputNodes; - vector InputSigns; - double Input; - FGPropertyManager* OutputNode; - double Output; - bool IsOutput; - virtual void Debug(int from); -}; - -} //namespace JSBSim - -#include "../FGFCS.h" - -#endif - diff --git a/src/FDM/JSBSim/filtersjb/FGFilter.cpp b/src/FDM/JSBSim/filtersjb/FGFilter.cpp deleted file mode 100644 index e1a143bd0..000000000 --- a/src/FDM/JSBSim/filtersjb/FGFilter.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGFilter.cpp - Author: Jon S. Berndt - Date started: 11/2000 - - ------------- 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGFilter.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_FILTER; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs), - AC_cfg(AC_cfg) -{ - 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; - - C1 = C2 = C3 = C4 = C5 = C6 = 0.0; - - if (Type == "LAG_FILTER") FilterType = eLag ; - else if (Type == "LEAD_LAG_FILTER") FilterType = eLeadLag ; - else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2 ; - else if (Type == "WASHOUT_FILTER") FilterType = eWashout ; - 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; - } - - Initialize = true; - - switch (FilterType) { - case eLag: - denom = 2.00 + dt*C1; - ca = dt*C1 / denom; - cb = (2.00 - dt*C1) / denom; - break; - case eLeadLag: - denom = 2.00*C3 + dt*C4; - ca = (2.00*C1 + dt*C2) / denom; - cb = (dt*C2 - 2.00*C1) / denom; - cc = (2.00*C3 - dt*C4) / denom; - break; - case eOrder2: - denom = 4.0*C4 + 2.0*C5*dt + C6*dt*dt; - ca = (4.0*C1 + 2.0*C2*dt + C3*dt*dt) / denom; - cb = (2.0*C3*dt*dt - 8.0*C1) / denom; - cc = (4.0*C1 - 2.0*C2*dt + C3*dt*dt) / denom; - cd = (2.0*C6*dt*dt - 8.0*C4) / denom; - ce = (4.0*C4 - 2.0*C5*dt + C6*dt*dt) / denom; - break; - case eWashout: - denom = 2.00 + dt*C1; - ca = 2.00 / denom; - cb = (2.00 - dt*C1) / denom; - break; - case eIntegrator: - ca = dt*C1 / 2.00; - break; - case eUnknown: - cerr << "Unknown filter type" << endl; - break; - } - FGFCSComponent::bind(); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGFilter::~FGFilter() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGFilter::Run(void) -{ - int test = 0; - - FGFCSComponent::Run(); // call the base class for initialization of Input - - 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(); - switch (FilterType) { - case eLag: - Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb; - break; - case eLeadLag: - Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc; - break; - case eOrder2: - Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc - - PreviousOutput1 * cd - PreviousOutput2 * ce; - break; - case eWashout: - Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb; - break; - case eIntegrator: - Output = Input * ca + PreviousInput1 * ca + PreviousOutput1; - break; - case eUnknown: - break; - } - - } - - PreviousOutput2 = PreviousOutput1; - PreviousOutput1 = Output; - PreviousInput2 = PreviousInput1; - PreviousInput1 = Input; - - if (IsOutput) SetOutput(); - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGFilter::convert(void) -{ - cout << endl; - cout << " " << endl; - - cout << " " << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "" << endl; - - if (C1 != 0) cout << " " << C1 << "" << endl; - if (C2 != 0) cout << " " << C2 << "" << endl; - if (C3 != 0) cout << " " << C3 << "" << endl; - if (C4 != 0) cout << " " << C4 << "" << endl; - if (C5 != 0) cout << " " << C5 << "" << endl; - if (C6 != 0) cout << " " << C6 << "" << endl; - - if (Trigger != 0) cout << " " << Trigger << "" << endl; - - if (IsOutput) - cout << " " << (OutputNode->GetFullyQualifiedName()).substr(12) << "" << endl; - - cout << " " << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGFilter::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << " INPUT: " << InputNodes[0]->getName() << endl; - cout << " C1: " << C1 << endl; - cout << " C2: " << C2 << endl; - cout << " C3: " << C3 << endl; - cout << " C4: " << C4 << endl; - cout << " C5: " << C5 << endl; - cout << " C6: " << C6 << endl; - if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGFilter" << endl; - if (from == 1) cout << "Destroyed: FGFilter" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/filtersjb/FGFilter.h b/src/FDM/JSBSim/filtersjb/FGFilter.h deleted file mode 100644 index e919bf1d4..000000000 --- a/src/FDM/JSBSim/filtersjb/FGFilter.h +++ /dev/null @@ -1,225 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGFilter.h - Author: Jon S. Berndt - Date started: 4/2000 - - ------------- Copyright (C) ------------- - - 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 FGFILTER_H -#define FGFILTER_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGFCSComponent.h" -#include "../FGConfigFile.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_FILTER "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates a filter for the flight control system. -The filter component can simulate any filter up to second order. The -Tustin substitution is used to take filter definitions from LaPlace space to the -time domain. The general format for a filter specification is: - -
-\
-  INPUT \
-  C1  \
-  [C2 \]
-  [C3 \]
-  [C4 \]
-  [C5 \]
-  [C6 \]
-  [OUTPUT \]
-\
-
- -For a lag filter of the form, -
-  C1
-------
-s + C1 
-
-the corresponding filter definition is: -
-\
-  INPUT \
-  C1 \
-  [OUTPUT \]
-\
-
-As an example, for the specific filter: -
-  600
-------
-s + 600 
-
-the corresponding filter definition could be: -
-\
-  INPUT aileron_cmd
-  C1 600
-\
-
-For a lead-lag filter of the form: -
-C1*s + C2
----------
-C3*s + C4 
-
-The corresponding filter definition is: -
-\
-  INPUT \
-  C1 \
-  C2 \
-  C3 \
-  C4 \
-  [OUTPUT \]
-\
-
-For a washout filter of the form: -
-  s
-------
-s + C1 
-
-The corresponding filter definition is: -
-\
-  INPUT \
-  C1 \
-  [OUTPUT \]
-\
-
-For a second order filter of the form: -
-C1*s^2 + C2*s + C3
-------------------
-C4*s^2 + C5*s + C6
-
-The corresponding filter definition is: -
-\
-  INPUT \
-  C1 \
-  C2 \
-  C3 \
-  C4 \
-  C5 \
-  C6 \
-  [OUTPUT \]
-\
-
-For an integrator of the form: -
- C1
- ---
-  s
-
-The corresponding filter definition is: -
-\
-  INPUT \
-  C1 \
-  [OUTPUT \]
-  [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 - -In all the filter specifications above, an [OUTPUT] keyword 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 -{ -public: - FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg); - ~FGFilter(); - - bool Run (void); - - /** 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; - -private: - double dt; - double ca; - double cb; - double cc; - double cd; - double ce; - double C1; - double C2; - double C3; - double C4; - double C5; - double C6; - double PreviousInput1; - double PreviousInput2; - double PreviousOutput1; - double PreviousOutput2; - FGConfigFile* AC_cfg; - FGPropertyManager* Trigger; - void Debug(int from); -}; -} -#endif - diff --git a/src/FDM/JSBSim/filtersjb/FGGain.cpp b/src/FDM/JSBSim/filtersjb/FGGain.cpp deleted file mode 100644 index 79b8611a5..000000000 --- a/src/FDM/JSBSim/filtersjb/FGGain.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGGain.cpp - Author: Jon S. Berndt - Date started: 4/2000 - - ------------- 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGGain.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_GAIN; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs), - AC_cfg(AC_cfg) -{ - string token; - string strScheduledBy; - string sOutputIdx; - - State = fcs->GetState(); - - Gain = 1.000; - Rows = 0; - Min = Max = 0.0; - OutputPct = 0; - invert = false; - ScheduledBy = 0; - clip = false; - clipmin = clipmax = 0.0; - - Type = AC_cfg->GetValue("TYPE"); - Name = AC_cfg->GetValue("NAME"); - AC_cfg->GetNextConfigLine(); - - 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 ); - } else { - AC_cfg->ResetLineIndexToZero(); - *Table << *AC_cfg; - } - } - - FGFCSComponent::bind(); - if (Type == "AEROSURFACE_SCALE") - treenode->Tie( "output-norm", this, &FGGain::GetOutputPct ); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGGain::~FGGain() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -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(); - - if (invert) Input = -Input; - - if (Type == "PURE_GAIN") { // PURE_GAIN - - Output = Gain * Input; - - } else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN - - LookupVal = ScheduledBy->getDoubleValue(); - SchedGain = Table->GetValue(LookupVal); - Output = Gain * SchedGain * Input; - - } else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE - - OutputPct = Input; - if (Input >= 0.0) Output = Input * Max; - else Output = Input * -Min; - Output *= Gain; - - } - - if (clip) { - if (Output > clipmax) Output = clipmax; - else if (Output < clipmin) Output = clipmin; - } - - if (IsOutput) SetOutput(); - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGGain::convert(void) -{ - cout << endl; - cout << " " << endl; - - if (invert) - cout << " -" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "" << endl; - else - cout << " " << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "" << endl; - - if (Gain != 1.0) - cout << " " << Gain << "" << endl; - - if (Type == "PURE_GAIN") { // PURE_GAIN - } else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN - cout << " " << endl; - cout << " " << ScheduledBy->GetFullyQualifiedName().substr(12) << "" << endl; - cout << " " << endl; - Table->Print(20); - cout << " " << endl; - cout << "
" << endl; - } else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE - cout << " " << endl; - cout << " " << Min << "" << endl; - cout << " " << Max << "" << endl; - cout << " " << endl; - } - - if (clip) { - cout << " " << endl; - cout << " " << clipmin << "" << endl; - cout << " " << clipmax << "" << endl; - cout << " " << endl; - } - - if (IsOutput) - cout << " " << (OutputNode->GetFullyQualifiedName()).substr(12) << "" << endl; - - cout << "
" << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGGain::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - if (invert) - 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; - Table->Print(); - } - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGGain" << endl; - if (from == 1) cout << "Destroyed: FGGain" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/filtersjb/FGGain.h b/src/FDM/JSBSim/filtersjb/FGGain.h deleted file mode 100644 index 0dec3ee57..000000000 --- a/src/FDM/JSBSim/filtersjb/FGGain.h +++ /dev/null @@ -1,194 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGGain.h - Author: - Date started: - - ------------- Copyright (C) ------------- - - 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 FGGAIN_H -#define FGGAIN_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef FGFS -# include -# include STL_STRING - SG_USING_STD(string); -#else -# include -#endif - -#include "FGFCSComponent.h" -#include "../FGConfigFile.h" -#include "../FGTable.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_GAIN "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -class FGFCS; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates a gain component for the flight control system. - The gain component merely multiplies the input by a gain. The form of the - gain component specification is: -
-    \
-      INPUT \
-      GAIN  \
-      [OUTPUT \]
-    \
-    
- 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. - - The scheduled gain component multiplies the input by a variable gain that is - dependent on another property (such as qbar, altitude, etc.). The lookup - mapping is in the form of a table. This kind of component might be used, for - example, in a case where aerosurface deflection must only be commanded to - acceptable settings - i.e at higher qbar the commanded elevator setting might - be attenuated. The form of the scheduled gain component specification is: -
-    \
-      INPUT \
-      [GAIN  \]
-      SCHEDULED_BY \
-      ROWS \
-      \
-      ?
-      [CLIPTO \ \ 1]
-      [OUTPUT \]
-    \
-    
- An overall GAIN may be supplied that is multiplicative with the scheduled gain. - - 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. - - Here is an example of a scheduled gain component specification: -
-    \
-      INPUT        fcs/pitch-gain-1
-      GAIN         0.017
-      SCHEDULED_BY fcs/elevator-pos-rad
-      ROWS         22
-      -0.68  -26.548
-      -0.595 -20.513
-      -0.51  -15.328
-      -0.425 -10.993
-      -0.34   -7.508
-      -0.255  -4.873
-      -0.17   -3.088
-      -0.085  -2.153
-       0      -2.068
-       0.085  -2.833
-       0.102  -3.088
-       0.119  -3.377
-       0.136  -3.7
-       0.153  -4.057
-       0.17   -4.448
-       0.187  -4.873
-       0.272  -7.508
-       0.357 -10.993
-       0.442 -15.328
-       0.527 -20.513
-       0.612 -26.548
-       0.697 -33.433
-    \
-    
- In the example above, we see the utility of the overall GAIN value in - effecting a degrees-to-radians conversion. - - The aerosurface scale component is a modified version of the simple gain - component. The normal purpose - for this component is to take control inputs that range from -1 to +1 or - from 0 to +1 and scale them to match the expected inputs to a flight control - system. For instance, the normal and expected ability of a pilot to push or - pull on a control stick is about 50 pounds. The input to the pitch channelb - lock diagram of a flight control system is in units of pounds. Yet, the - joystick control input is usually in a range from -1 to +1. The form of the - aerosurface scaling component specification is: -
-    \
-      INPUT \
-      MIN \
-      MAX \
-      [GAIN  \]
-      [OUTPUT \]
-    \
-
- 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. - - @author Jon S. Berndt - @version $Id$ -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGGain : public FGFCSComponent -{ -public: - FGGain(FGFCS* fcs, FGConfigFile* AC_cfg); - ~FGGain(); - - double GetOutputPct() const { return OutputPct; } - void convert(void); - bool Run (void); - -private: - FGConfigFile* AC_cfg; - FGTable* Table; - FGState* State; - double Gain; - double Min, Max; - double clipmin, clipmax; - double OutputPct; - bool invert, clip; - int Rows; - FGPropertyManager* ScheduledBy; - - void Debug(int from); -}; -} -#endif diff --git a/src/FDM/JSBSim/filtersjb/FGGradient.cpp b/src/FDM/JSBSim/filtersjb/FGGradient.cpp deleted file mode 100644 index 359a9edb8..000000000 --- a/src/FDM/JSBSim/filtersjb/FGGradient.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGGradient.cpp - Author: - Date started: - - ------------- 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGGradient.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_GRADIENT; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGGradient::FGGradient(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs), - AC_cfg(AC_cfg) -{ - Type = AC_cfg->GetValue("TYPE"); - Name = AC_cfg->GetValue("NAME"); - - FGFCSComponent::bind(); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGGradient::~FGGradient() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGGradient::Run(void ) -{ - FGFCSComponent::Run(); // call the base class for initialization of Input - - 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 FGGradient::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: FGGradient" << endl; - if (from == 1) cout << "Destroyed: FGGradient" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/filtersjb/FGGradient.h b/src/FDM/JSBSim/filtersjb/FGGradient.h deleted file mode 100644 index 66ac96369..000000000 --- a/src/FDM/JSBSim/filtersjb/FGGradient.h +++ /dev/null @@ -1,81 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGGradient.h - Author: - Date started: - - ------------- Copyright (C) ------------- - - 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 FGGRADIENT_H -#define FGGRADIENT_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGFCSComponent.h" -#include "../FGConfigFile.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_GRADIENT "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -class FGFCS; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates a gradient component for the flight control system. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGGradient : public FGFCSComponent -{ -public: - FGGradient(FGFCS* fcs, FGConfigFile* AC_cfg); - ~FGGradient(); - - bool Run (void); - -private: - FGConfigFile* AC_cfg; - void Debug(int from); -}; -} -#endif diff --git a/src/FDM/JSBSim/filtersjb/FGKinemat.cpp b/src/FDM/JSBSim/filtersjb/FGKinemat.cpp deleted file mode 100644 index c9b9f460e..000000000 --- a/src/FDM/JSBSim/filtersjb/FGKinemat.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGKinemat.cpp - Author: Tony Peden, for flight control system authored by Jon S. Berndt - Date started: 12/02/01 - - ------------- Copyright (C) 2000 Anthony K. Peden ------------- - - 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include "FGKinemat.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_FLAPS; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -FGKinemat::FGKinemat(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs), - AC_cfg(AC_cfg) -{ - string token,sOutputIdx; - double tmpDetent; - double tmpTime; - - Detents.clear(); - TransitionTimes.clear(); - - OutputPct=0; - DoScale = true; - - Type = AC_cfg->GetValue("TYPE"); - Name = AC_cfg->GetValue("NAME"); - AC_cfg->GetNextConfigLine(); - - 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> 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; - } - } - FGFCSComponent::bind(); - treenode->Tie("output-norm", this, &FGKinemat::GetOutputPct ); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGKinemat::~FGKinemat() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGKinemat::Run(void ) -{ - double dt = fcs->GetState()->Getdt(); - - Input = InputNodes[0]->getDoubleValue(); - - if (DoScale) Input *= Detents[NumDetents-1]; - - Output = OutputNode->getDoubleValue(); - - if (Input < Detents[0]) - Input = Detents[0]; - else if (Detents[NumDetents-1] < Input) - Input = Detents[NumDetents-1]; - - // Process all detent intervals the movement traverses until either the - // final value is reached or the time interval has finished. - while ( 0.0 < dt && !EqualToRoundoff(Input, Output) ) { - - // Find the area where Output is in - int ind; - for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind) - if (NumDetents <= ind) - break; - - // A transition time of 0.0 means an infinite rate. - // The output is reached in one step - if (TransitionTimes[ind] <= 0.0) { - Output = Input; - break; - } else { - // Compute the rate in this area - double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind]; - // Compute the maximum input value inside this area - double ThisInput = Input; - if (ThisInput < Detents[ind-1]) ThisInput = Detents[ind-1]; - if (Detents[ind] < ThisInput) ThisInput = Detents[ind]; - // Compute the time to reach the value in ThisInput - double ThisDt = fabs((ThisInput-Output)/Rate); - - // and clip to the timestep size - if (dt < ThisDt) { - ThisDt = dt; - if (Output < Input) - Output += ThisDt*Rate; - else - Output -= ThisDt*Rate; - } else - // Handle this case separate to make shure the termination condition - // is met even in inexact arithmetics ... - Output = ThisInput; - - dt -= ThisDt; - } - } - - OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]); - - if (IsOutput) SetOutput(); - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGKinemat::convert(void) -{ - cout << endl; - cout << " " << endl; - - cout << " " << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "" << endl; - - cout << " " << endl; - for (int i=0; i" << endl; - cout << " " << Detents[i] << "" << endl; - cout << " " << endl; - cout << " " << endl; - } - cout << " " << endl; - - if (IsOutput) - cout << " " << (OutputNode->GetFullyQualifiedName()).substr(12) << "" << endl; - - cout << " " << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGKinemat::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << " INPUT: " << InputNodes[0]->getName() << endl; - cout << " DETENTS: " << NumDetents << endl; - for (int i=0;igetName() << endl; - if (!DoScale) cout << " NOSCALE" << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGKinemat" << endl; - if (from == 1) cout << "Destroyed: FGKinemat" << 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; - } - } -} -} diff --git a/src/FDM/JSBSim/filtersjb/FGKinemat.h b/src/FDM/JSBSim/filtersjb/FGKinemat.h deleted file mode 100644 index a438b5544..000000000 --- a/src/FDM/JSBSim/filtersjb/FGKinemat.h +++ /dev/null @@ -1,117 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGKinemat.h - Author: Tony Peden, for flight control system authored by Jon S. Berndt - Date started: 12/02/01 - - ------------- Copyright (C) Anthony K. Peden ------------- - - 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 FGKinemat_H -#define FGKinemat_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef FGFS -# include -# ifdef SG_HAVE_STD_INCLUDES -# include -# else -# include -# endif -#else -# include -#endif - -#include -#include "FGFCSComponent.h" -#include "../FGConfigFile.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_FLAPS "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates a kinematic component for the flight control system. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGKinemat : public FGFCSComponent { -public: - /** Initializer. - @param fcs A reference to the ccurrent flightcontrolsystem. - @param AC_cfg reference to the current aircraft configuration file. - Initializes the FGKinemat object from the given configuration - file. The Configuration file is expected to be at the stream - position where the KINEMAT object starts. Also it is expected to - be past the end of the current KINEMAT configuration on exit. - */ - FGKinemat(FGFCS* fcs, FGConfigFile* AC_cfg); - - /** Destructor. - */ - ~FGKinemat(); - - /** Kinemat output value. - @return the current output of the kinemat object on the range of [0,1]. - */ - double GetOutputPct() const { return OutputPct; } - - /** Run method, overwrites FGModel::Run(). - @return false on success, true on failure. - The routine doing the work. - */ - bool Run (void); - void convert(void); - -private: - FGConfigFile* AC_cfg; - vector Detents; - vector TransitionTimes; - int NumDetents; - double OutputPct; - bool DoScale; - - void Debug(int from); -}; -} -#endif diff --git a/src/FDM/JSBSim/filtersjb/FGSummer.cpp b/src/FDM/JSBSim/filtersjb/FGSummer.cpp deleted file mode 100644 index 68b8fa66a..000000000 --- a/src/FDM/JSBSim/filtersjb/FGSummer.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGSummer.cpp - Author: Jon S. Berndt - Date started: 4/2000 - - ------------- 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGSummer.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_SUMMER; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGSummer::FGSummer(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs), - AC_cfg(AC_cfg) -{ - string token,sOutputIdx; - - clip = false; - clipmin = clipmax = 0.0; - Bias = 0.0; - - Type = AC_cfg->GetValue("TYPE"); - Name = AC_cfg->GetValue("NAME"); - AC_cfg->GetNextConfigLine(); - - while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) { - *AC_cfg >> token; - - if (token == "INPUT") { - token = AC_cfg->GetValue("INPUT"); - *AC_cfg >> token; - - if (token[0] == '-') { - InputSigns.push_back(-1.0); - token.erase(0,1); - } else { - InputSigns.push_back( 1.0); - } - - InputNodes.push_back( resolveSymbol(token) ); - } else if (token == "BIAS") { - *AC_cfg >> Bias; - } else if (token == "CLIPTO") { - *AC_cfg >> clipmin >> clipmax; - if (clipmax > clipmin) { - clip = true; - } - } else if (token == "OUTPUT") { - IsOutput = true; - *AC_cfg >> sOutputIdx; - OutputNode = PropertyManager->GetNode(sOutputIdx, true); - } - } - - FGFCSComponent::bind(); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGSummer::~FGSummer() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGSummer::Run(void ) -{ - unsigned int idx; - - // The Summer takes several inputs, so do not call the base class Run() - // FGFCSComponent::Run(); - - Output = 0.0; - - for (idx=0; idxgetDoubleValue()*InputSigns[idx]; - } - - Output += Bias; - - if (clip) { - if (Output > clipmax) Output = clipmax; - else if (Output < clipmin) Output = clipmin; - } - - if (IsOutput) SetOutput(); - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGSummer::convert(void) -{ - string sSign; - - cout << endl; - cout << " " << endl; - - for (int i=0; i" << sSign << (InputNodes[i]->GetFullyQualifiedName()).substr(12) << "" << endl; - } - - if (Bias != 0.0) - cout << " " << Bias << "" << endl; - - if (clip) { - cout << " " << endl; - cout << " " << clipmin << "" << endl; - cout << " " << clipmax << "" << endl; - cout << " " << endl; - } - - if (IsOutput) - cout << " " << (OutputNode->GetFullyQualifiedName()).substr(12) << "" << endl; - - cout << " " << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGSummer::Debug(int from) -{ - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - cout << " INPUTS: " << endl; - for (unsigned i=0;igetName() << endl; - else - cout << " " << InputNodes[i]->getName() << endl; - } - if (Bias != 0.0) cout << " Bias: " << Bias << endl; - if (clip) cout << " CLIPTO: " << clipmin - << ", " << clipmax << endl; - if (IsOutput) cout << " OUTPUT: " <getName() << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGSummer" << endl; - if (from == 1) cout << "Destroyed: FGSummer" << 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 - diff --git a/src/FDM/JSBSim/filtersjb/FGSummer.h b/src/FDM/JSBSim/filtersjb/FGSummer.h deleted file mode 100644 index 7ee68c626..000000000 --- a/src/FDM/JSBSim/filtersjb/FGSummer.h +++ /dev/null @@ -1,128 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGSummer.h - Author: - Date started: - - ------------- Copyright (C) ------------- - - 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 FGSUMMER_H -#define FGSUMMER_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef FGFS -# include -# ifdef SG_HAVE_STD_INCLUDES -# include -# else -# include -# endif -#else -# include -#endif - -#include -#include "FGFCSComponent.h" -#include "../FGConfigFile.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_SUMMER "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Models a flight control system summing component. - The Summer component sums two or more inputs. These can be pilot control - inputs or state variables, and a bias can also be added in using the BIAS - keyword. The form of the summer component specification is: -
-    \
-      INPUT \
-      INPUT \
-      [BIAS \]
-      [?]
-      [CLIPTO \ \ 1]
-      [OUTPUT \]
-    \
-
- Note that in the case of an input property the property name may be - immediately preceded by a minus sign. Here's an example of a summer - component specification: -
-    \
-      INPUT  velocities/p-rad_sec
-      INPUT -fcs/roll-ap-wing-leveler
-      INPUT  fcs/roll-ap-error-integrator
-      CLIPTO -1 1
-    \
-
- Note that there can be only one BIAS statement per component. - - @author Jon S. Berndt - @version $Id$ -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGSummer : public FGFCSComponent -{ -public: - /** Constructor. - @param fcs a pointer to the parent FGFCS object. - @param AC_cfg a pointer to the configuration file object. */ - FGSummer(FGFCS* fcs, FGConfigFile* AC_cfg); - /// Destructor - ~FGSummer(); - - /// The execution method for this FCS component. - bool Run(void); - void convert(void); - -private: - FGConfigFile* AC_cfg; - bool clip; - double clipmin,clipmax; - double Bias; - void Debug(int from); -}; -} -#endif diff --git a/src/FDM/JSBSim/filtersjb/FGSwitch.cpp b/src/FDM/JSBSim/filtersjb/FGSwitch.cpp deleted file mode 100644 index ca5058de5..000000000 --- a/src/FDM/JSBSim/filtersjb/FGSwitch.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Module: FGSwitch.cpp - Author: Jon S. Berndt - Date started: 4/2000 - - ------------- 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 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The SWITCH component is defined as follows (see the API documentation for more -information): - - - - {property} {conditional} {property|value} - - {property} {conditional} {property|value} - ... - - ... - - - {property} {conditional} {property|value} - ... - - ... - - -Also, see the header file (FGSwitch.h) for further details. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "FGSwitch.h" - -namespace JSBSim { - -static const char *IdSrc = "$Id$"; -static const char *IdHdr = ID_SWITCH; - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS IMPLEMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - - -FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs), - AC_cfg(AC_cfg) -{ - string token, value; - struct test *current_test; - string sOutputIdx; - - Type = AC_cfg->GetValue("TYPE"); - Name = AC_cfg->GetValue("NAME"); - - AC_cfg->GetNextConfigLine(); - while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) { - - // See the above documentation, or the API docs, for information on what - // the SWITCH component is supposed to look like in the configuration file. - // Below, the switch component is read in. - - if (token == "TEST") { - tests.push_back(test()); - current_test = &tests.back(); - - if (AC_cfg->GetValue("LOGIC") == "OR") { - current_test->Logic = eOR; - } else if (AC_cfg->GetValue("LOGIC") == "AND") { - current_test->Logic = eAND; - } else if (AC_cfg->GetValue("LOGIC") == "DEFAULT") { - current_test->Logic = eDefault; - } else { // error - cerr << "Unrecognized LOGIC token in switch component: " << Name << endl; - } - - value = AC_cfg->GetValue("VALUE"); - if (value.empty()) { - cerr << "No VALUE supplied for switch component: " << Name << endl; - } else { - if (value.find_first_not_of("-.0123456789eE") == string::npos) { - // if true (and execution falls into this block), "value" is a number. - current_test->OutputVal = atof(value.c_str()); - } else { - // "value" must be a property if execution passes to here. - if (value[0] == '-') { - current_test->sign = -1.0; - value.erase(0,1); - } else { - current_test->sign = 1.0; - } - current_test->OutputProp = PropertyManager->GetNode(value); - } - } - - AC_cfg->GetNextConfigLine(); - while (AC_cfg->GetValue() != string("/TEST")) { - current_test->conditions.push_back(FGCondition(AC_cfg, PropertyManager)); - } - AC_cfg->GetNextConfigLine(); - } else if (token == "OUTPUT") { - IsOutput = true; - *AC_cfg >> sOutputIdx; - *AC_cfg >> sOutputIdx; - OutputNode = PropertyManager->GetNode( sOutputIdx, true ); - } - } - - FGFCSComponent::bind(); - - Debug(0); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -FGSwitch::~FGSwitch() -{ - Debug(1); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -bool FGSwitch::Run(void ) -{ - vector ::iterator iTests = tests.begin(); - vector ::iterator iConditions; - bool pass = false; - - FGFCSComponent::Run(); // call the base class for initialization of Input - - while (iTests < tests.end()) { - iConditions = iTests->conditions.begin(); - - if (iTests->Logic == eDefault) { - Output = iTests->GetValue(); - } else if (iTests->Logic == eAND) { - pass = true; - while (iConditions < iTests->conditions.end()) { - if (!iConditions->Evaluate()) pass = false; - *iConditions++; - } - } else if (iTests->Logic == eOR) { - pass = false; - while (iConditions < iTests->conditions.end()) { - if (iConditions->Evaluate()) pass = true; - *iConditions++; - } - } else { - cerr << "Invalid logic test" << endl; - } - - if (pass) { - Output = iTests->GetValue(); - break; - } - *iTests++; - } - - if (IsOutput) SetOutput(); - - return true; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGSwitch::convert(void) -{ - cout << endl; - cout << " " << endl; - -// cout << " " << InputNodes[0]->GetName() << "" << endl; - - for (int i=0; i" << endl; - else - cout << " GetFullyQualifiedName()).substr(12) << "\"/>" << endl; - } else if (tests[i].Logic == eAND) { - if (tests[i].OutputProp == 0L) - cout << " " << endl; - else - cout << " GetFullyQualifiedName()).substr(12) << "\">" << endl; - } else if (tests[i].Logic == eOR) { - if (tests[i].OutputProp == 0L) - cout << " " << endl; - else - cout << " GetFullyQualifiedName()).substr(12) << "\">" << endl; - } - for (int j=0; j" << endl; - } - - if (IsOutput) - cout << " " << (OutputNode->GetFullyQualifiedName()).substr(12) << "" << endl; - - cout << " " << endl; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// 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 FGSwitch::Debug(int from) -{ - vector ::iterator iTests = tests.begin(); - vector ::iterator iConditions; - string comp, scratch; - string indent = " "; - bool first = false; - - if (debug_lvl <= 0) return; - - if (debug_lvl & 1) { // Standard console startup message output - if (from == 0) { // Constructor - while (iTests < tests.end()) { - - scratch = " if "; - - switch(iTests->Logic) { - case (elUndef): - comp = " UNSET "; - cerr << "Unset logic for test condition" << endl; - break; - case (eAND): - comp = " AND "; - break; - case (eOR): - comp=" OR "; - break; - case (eDefault): - scratch = " by default."; - break; - default: - comp = " UNKNOWN "; - cerr << "Unknown logic for test condition" << endl; - } - - if (iTests->OutputProp != 0L) - if (iTests->sign < 0) - cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl; - else - cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl; - else - cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl; - - iConditions = iTests->conditions.begin(); - first = true; - while (iConditions < iTests->conditions.end()) { - if (!first) cout << indent << comp << " "; - else cout << indent << " "; - first = false; - iConditions->PrintCondition(); - cout << endl; - *iConditions++; - } - cout << endl; - *iTests++; - } - if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; - } - } - if (debug_lvl & 2 ) { // Instantiation/Destruction notification - if (from == 0) cout << "Instantiated: FGSwitch" << endl; - if (from == 1) cout << "Destroyed: FGSwitch" << 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 - diff --git a/src/FDM/JSBSim/filtersjb/FGSwitch.h b/src/FDM/JSBSim/filtersjb/FGSwitch.h deleted file mode 100644 index a942a8da5..000000000 --- a/src/FDM/JSBSim/filtersjb/FGSwitch.h +++ /dev/null @@ -1,171 +0,0 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Header: FGSwitch.h - Author: Jon S. Berndt - Date started: 12/23/2002 - - ------------- Copyright (C) ------------- - - 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 FGSWITCH_H -#define FGSWITCH_H - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -INCLUDES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#include "FGFCSComponent.h" -#include "../FGConfigFile.h" -#include "FGCondition.h" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DEFINITIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -#define ID_SWITCH "$Id$" - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FORWARD DECLARATIONS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -namespace JSBSim { - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Encapsulates a switch for the flight control system. - -The SWITCH component models a switch - either on/off or a multi-choice rotary -switch. The switch can represent a physical cockpit switch, or can represent a -logical switch, where several conditions might need to be satisfied before a -particular state is reached. The VALUE of the switch - the output value for the -component - is chosen depending on the state of the switch. Each switch is -comprised of two or more TESTs. Each TEST has a VALUE associated with it. The -first TEST that evaluates to TRUE will set the output value of the switch -according to the VALUE parameter belonging to that TEST. Each TEST contains one -or more CONDITIONS, which each must be logically related (if there are more than -one) given the value of the LOGIC parameter, and which takes the form: - - property conditional property|value - -e.g. - - qbar GE 21.0 - -or, - - roll_rate < pitch_rate - -Within a TEST, a CONDITION_GROUP can be specified. A CONDITION_GROUP allows for -complex groupings of logical comparisons. Each CONDITION_GROUP contains -additional conditions, as well as possibly additional CONDITION_GROUPs. - -
-\
-  \
-    {property} {conditional} {property|value}
-    \
-      {property} {conditional} {property|value}
-      ...
-    \
-    ...
-  \
-  \
-    {property} {conditional} {property|value}
-    ...
-  \
-  ...
-  [OUTPUT \]
-\
-
- -Here's an example: -
-\
-  \
-  \
-  \
-    ap/attitude_hold == 1
-  \
-\
-
-The above example specifies that the default value of the component (i.e. the -output property of the component, addressed by the property, ap/roll-ap-autoswitch) -is 0.0. If or when the attitude hold switch is selected (property -ap/attitude_hold takes the value 1), the value of the switch component will be -whatever value fcs/roll-ap-error-summer is. -@author Jon S. Berndt -@version $Id$ -*/ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DECLARATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class FGSwitch : public FGFCSComponent -{ -public: - FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg); - ~FGSwitch(); - - bool Run(void); - void convert(void); - - enum eLogic {elUndef=0, eAND, eOR, eDefault}; - enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE}; - -private: - FGFCS* fcs; - FGConfigFile* AC_cfg; - - struct test { - vector conditions; - eLogic Logic; - double OutputVal; - FGPropertyManager *OutputProp; - float sign; - - double GetValue(void) { - if (OutputProp == 0L) return OutputVal; - else return OutputProp->getDoubleValue()*sign; - } - - test(void) { // constructor for the test structure - Logic = elUndef; - OutputVal = 0.0; - OutputProp = 0L; - sign = 1.0; - } - - }; - - vector tests; - - void Debug(int from); -}; -} -#endif diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp new file mode 100644 index 000000000..00538380a --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp @@ -0,0 +1,1077 @@ +/******************************************************************************* + + Header: FGInitialCondition.cpp + 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. + +******************************************************************************** +INCLUDES +*******************************************************************************/ + +#ifdef FGFS +# include +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# else +# include +# endif +#endif + +#include "FGInitialCondition.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_INITIALCONDITION; + +//****************************************************************************** + +FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec) +{ + vt=vc=ve=vg=0; + mach=0; + alpha=beta=gamma=0; + theta=phi=psi=0; + altitude=hdot=0; + latitude=longitude=0; + u=v=w=0; + p=q=r=0; + uw=vw=ww=0; + vnorth=veast=vdown=0; + wnorth=weast=wdown=0; + whead=wcross=0; + wdir=wmag=0; + lastSpeedSet=setvt; + lastWindSet=setwned; + sea_level_radius = FDMExec->GetInertial()->RefRadius(); + radius_to_vehicle = FDMExec->GetInertial()->RefRadius(); + terrain_altitude = 0; + + salpha=sbeta=stheta=sphi=spsi=sgamma=0; + calpha=cbeta=ctheta=cphi=cpsi=cgamma=1; + + if(FDMExec != NULL ) { + fdmex=FDMExec; + fdmex->GetPropagate()->Seth(altitude); + fdmex->GetAtmosphere()->Run(); + PropertyManager=fdmex->GetPropertyManager(); + bind(); + } else { + cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl; + } + + Debug(0); +} + +//****************************************************************************** + +FGInitialCondition::~FGInitialCondition() +{ + unbind(); + Debug(1); +} + +//****************************************************************************** + +void FGInitialCondition::SetVcalibratedKtsIC(double tt) { + + if(getMachFromVcas(&mach,tt*ktstofps)) { + //cout << "Mach: " << mach << endl; + lastSpeedSet=setvc; + vc=tt*ktstofps; + vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed(); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl; + } + else { + cout << "Failed to get Mach number for given Vc and altitude, Vc unchanged." << endl; + cout << "Please mail the set of initial conditions used to apeden@earthlink.net" << endl; + } +} + +//****************************************************************************** + +void FGInitialCondition::SetVequivalentKtsIC(double tt) { + ve=tt*ktstofps; + lastSpeedSet=setve; + vt=ve*1/sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); +} + +//****************************************************************************** + +void FGInitialCondition::SetVgroundFpsIC(double tt) { + double ua,va,wa; + double vxz; + + vg=tt; + lastSpeedSet=setvg; + vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0; + calcUVWfromNED(); + ua = u + uw; va = v + vw; wa = w + ww; + vt = sqrt( ua*ua + va*va + wa*wa ); + alpha = beta = 0; + vxz = sqrt( u*u + w*w ); + if( w != 0 ) alpha = atan2( w, u ); + if( vxz != 0 ) beta = atan2( v, vxz ); + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); +} + +//****************************************************************************** + +void FGInitialCondition::SetVtrueFpsIC(double tt) { + vt=tt; + lastSpeedSet=setvt; + mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); +} + +//****************************************************************************** + +void FGInitialCondition::SetMachIC(double tt) { + mach=tt; + lastSpeedSet=setmach; + vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed(); + vc=calcVcas(mach); + ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio()); + //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl; +} + +//****************************************************************************** + +void FGInitialCondition::SetClimbRateFpmIC(double tt) { + SetClimbRateFpsIC(tt/60.0); +} + +//****************************************************************************** + +void FGInitialCondition::SetClimbRateFpsIC(double tt) { + + if(vt > 0.1) { + hdot=tt; + gamma=asin(hdot/vt); + sgamma=sin(gamma); cgamma=cos(gamma); + } +} + +//****************************************************************************** + +void FGInitialCondition::SetFlightPathAngleRadIC(double tt) { + gamma=tt; + sgamma=sin(gamma); cgamma=cos(gamma); + getTheta(); + hdot=vt*sgamma; +} + +//****************************************************************************** + +void FGInitialCondition::SetAlphaRadIC(double tt) { + alpha=tt; + salpha=sin(alpha); calpha=cos(alpha); + getTheta(); +} + +//****************************************************************************** + +void FGInitialCondition::SetPitchAngleRadIC(double tt) { + theta=tt; + stheta=sin(theta); ctheta=cos(theta); + getAlpha(); +} + +//****************************************************************************** + +void FGInitialCondition::SetBetaRadIC(double tt) { + beta=tt; + sbeta=sin(beta); cbeta=cos(beta); + getTheta(); + +} + +//****************************************************************************** + +void FGInitialCondition::SetRollAngleRadIC(double tt) { + phi=tt; + sphi=sin(phi); cphi=cos(phi); + getTheta(); +} + +//****************************************************************************** + +void FGInitialCondition::SetTrueHeadingRadIC(double tt) { + psi=tt; + spsi=sin(psi); cpsi=cos(psi); + calcWindUVW(); +} + +//****************************************************************************** + +void FGInitialCondition::SetUBodyFpsIC(double tt) { + u=tt; + vt=sqrt(u*u + v*v + w*w); + lastSpeedSet=setuvw; +} + +//****************************************************************************** + +void FGInitialCondition::SetVBodyFpsIC(double tt) { + v=tt; + vt=sqrt(u*u + v*v + w*w); + lastSpeedSet=setuvw; +} + +//****************************************************************************** + +void FGInitialCondition::SetWBodyFpsIC(double tt) { + w=tt; + vt=sqrt( u*u + v*v + w*w ); + lastSpeedSet=setuvw; +} + +//****************************************************************************** + +double FGInitialCondition::GetUBodyFpsIC(void) const { + if(lastSpeedSet == setvg ) + return u; + else + return vt*calpha*cbeta - uw; +} + +//****************************************************************************** + +double FGInitialCondition::GetVBodyFpsIC(void) const { + if( lastSpeedSet == setvg ) + return v; + else { + return vt*sbeta - vw; + } +} + +//****************************************************************************** + +double FGInitialCondition::GetWBodyFpsIC(void) const { + if( lastSpeedSet == setvg ) + return w; + else + return vt*salpha*cbeta -ww; +} + +//****************************************************************************** + +void FGInitialCondition::SetWindNEDFpsIC(double wN, double wE, double wD ) { + wnorth = wN; weast = wE; wdown = wD; + lastWindSet = setwned; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); +} + +//****************************************************************************** + +void FGInitialCondition::SetCrossWindKtsIC(double cross){ + wcross=cross*ktstofps; + lastWindSet=setwhc; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); + +} + +//****************************************************************************** + +// positive from left +void FGInitialCondition::SetHeadWindKtsIC(double head){ + whead=head*ktstofps; + lastWindSet=setwhc; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); + +} + +//****************************************************************************** + +void FGInitialCondition::SetWindDownKtsIC(double wD) { + wdown=wD; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); +} + +//****************************************************************************** + +void FGInitialCondition::SetWindMagKtsIC(double mag) { + wmag=mag*ktstofps; + lastWindSet=setwmd; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); +} + +//****************************************************************************** + +void FGInitialCondition::SetWindDirDegIC(double dir) { + wdir=dir*degtorad; + lastWindSet=setwmd; + calcWindUVW(); + if(lastSpeedSet == setvg) + SetVgroundFpsIC(vg); +} + + +//****************************************************************************** + +void FGInitialCondition::calcWindUVW(void) { + + switch(lastWindSet) { + case setwmd: + wnorth=wmag*cos(wdir); + weast=wmag*sin(wdir); + break; + case setwhc: + wnorth=whead*cos(psi) + wcross*cos(psi+M_PI/2); + weast=whead*sin(psi) + wcross*sin(psi+M_PI/2); + break; + case setwned: + break; + } + uw=wnorth*ctheta*cpsi + + weast*ctheta*spsi - + wdown*stheta; + vw=wnorth*( sphi*stheta*cpsi - cphi*spsi ) + + weast*( sphi*stheta*spsi + cphi*cpsi ) + + wdown*sphi*ctheta; + ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) + + weast*(cphi*stheta*spsi - sphi*cpsi) + + wdown*cphi*ctheta; + + + /* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown " + << wnorth << ", " << weast << ", " << wdown << endl; + cout << "FGInitialCondition::calcWindUVW: theta, phi, psi " + << theta << ", " << phi << ", " << psi << endl; + cout << "FGInitialCondition::calcWindUVW: uw, vw, ww " + << uw << ", " << vw << ", " << ww << endl; */ + +} + +//****************************************************************************** + +void FGInitialCondition::SetAltitudeFtIC(double tt) { + altitude=tt; + fdmex->GetPropagate()->Seth(altitude); + fdmex->GetAtmosphere()->Run(); + //lets try to make sure the user gets what they intended + + switch(lastSpeedSet) { + case setned: + case setuvw: + case setvt: + SetVtrueKtsIC(vt*fpstokts); + break; + case setvc: + SetVcalibratedKtsIC(vc*fpstokts); + break; + case setve: + SetVequivalentKtsIC(ve*fpstokts); + break; + case setmach: + SetMachIC(mach); + break; + case setvg: + SetVgroundFpsIC(vg); + break; + } +} + +//****************************************************************************** + +void FGInitialCondition::SetAltitudeAGLFtIC(double tt) { + SetAltitudeFtIC(terrain_altitude + tt); +} + +//****************************************************************************** + +void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) { + sea_level_radius = tt; +} + +//****************************************************************************** + +void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) { + terrain_altitude=tt; +} + +//****************************************************************************** + +void FGInitialCondition::calcUVWfromNED(void) { + u=vnorth*ctheta*cpsi + + veast*ctheta*spsi - + vdown*stheta; + v=vnorth*( sphi*stheta*cpsi - cphi*spsi ) + + veast*( sphi*stheta*spsi + cphi*cpsi ) + + vdown*sphi*ctheta; + w=vnorth*( cphi*stheta*cpsi + sphi*spsi ) + + veast*( cphi*stheta*spsi - sphi*cpsi ) + + vdown*cphi*ctheta; +} + +//****************************************************************************** + +void FGInitialCondition::SetVnorthFpsIC(double tt) { + vnorth=tt; + calcUVWfromNED(); + vt=sqrt(u*u + v*v + w*w); + lastSpeedSet=setned; +} + +//****************************************************************************** + +void FGInitialCondition::SetVeastFpsIC(double tt) { + veast=tt; + calcUVWfromNED(); + vt=sqrt(u*u + v*v + w*w); + lastSpeedSet=setned; +} + +//****************************************************************************** + +void FGInitialCondition::SetVdownFpsIC(double tt) { + vdown=tt; + calcUVWfromNED(); + vt=sqrt(u*u + v*v + w*w); + SetClimbRateFpsIC(-1*vdown); + lastSpeedSet=setned; +} + +//****************************************************************************** + +bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) { + + bool result=false; + double guess=1.5; + xlo=xhi=0; + xmin=0;xmax=50; + sfunc=&FGInitialCondition::calcVcas; + if(findInterval(vcas,guess)) { + if(solve(&mach,vcas)) + result=true; + } + return result; +} + +//****************************************************************************** + +bool FGInitialCondition::getAlpha(void) { + bool result=false; + double guess=theta-gamma; + + if(vt < 0.01) return 0; + + xlo=xhi=0; + xmin=fdmex->GetAerodynamics()->GetAlphaCLMin(); + xmax=fdmex->GetAerodynamics()->GetAlphaCLMax(); + sfunc=&FGInitialCondition::GammaEqOfAlpha; + if(findInterval(0,guess)){ + if(solve(&alpha,0)){ + result=true; + salpha=sin(alpha); + calpha=cos(alpha); + } + } + calcWindUVW(); + return result; +} + +//****************************************************************************** + +bool FGInitialCondition::getTheta(void) { + bool result=false; + double guess=alpha+gamma; + + if(vt < 0.01) return 0; + + xlo=xhi=0; + xmin=-89;xmax=89; + sfunc=&FGInitialCondition::GammaEqOfTheta; + if(findInterval(0,guess)){ + if(solve(&theta,0)){ + result=true; + stheta=sin(theta); + ctheta=cos(theta); + } + } + calcWindUVW(); + return result; +} + +//****************************************************************************** + +double FGInitialCondition::GammaEqOfTheta(double Theta) { + double a,b,c; + double sTheta,cTheta; + + //theta=Theta; stheta=sin(theta); ctheta=cos(theta); + sTheta=sin(Theta); cTheta=cos(Theta); + calcWindUVW(); + a=wdown + vt*calpha*cbeta + uw; + b=vt*sphi*sbeta + vw*sphi; + c=vt*cphi*salpha*cbeta + ww*cphi; + return vt*sgamma - ( a*sTheta - (b+c)*cTheta); +} + +//****************************************************************************** + +double FGInitialCondition::GammaEqOfAlpha(double Alpha) { + double a,b,c; + double sAlpha,cAlpha; + sAlpha=sin(Alpha); cAlpha=cos(Alpha); + a=wdown + vt*cAlpha*cbeta + uw; + b=vt*sphi*sbeta + vw*sphi; + c=vt*cphi*sAlpha*cbeta + ww*cphi; + + return vt*sgamma - ( a*stheta - (b+c)*ctheta ); +} + +//****************************************************************************** + +double FGInitialCondition::calcVcas(double Mach) { + + double p=fdmex->GetAtmosphere()->GetPressure(); + double psl=fdmex->GetAtmosphere()->GetPressureSL(); + double rhosl=fdmex->GetAtmosphere()->GetDensitySL(); + double pt,A,B,D,vcas; + if(Mach < 0) Mach=0; + if(Mach < 1) //calculate total pressure assuming isentropic flow + pt=p*pow((1 + 0.2*Mach*Mach),3.5); + else { + // shock in front of pitot tube, we'll assume its normal and use + // the Rayleigh Pitot Tube Formula, i.e. the ratio of total + // pressure behind the shock to the static pressure in front + + + //the normal shock assumption should not be a bad one -- most supersonic + //aircraft place the pitot probe out front so that it is the forward + //most point on the aircraft. The real shock would, of course, take + //on something like the shape of a rounded-off cone but, here again, + //the assumption should be good since the opening of the pitot probe + //is very small and, therefore, the effects of the shock curvature + //should be small as well. AFAIK, this approach is fairly well accepted + //within the aerospace community + + B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8); + + // The denominator above is zero for Mach ~ 0.38, for which + // we'll never be here, so we're safe + + D = (2.8*Mach*Mach-0.4)*0.4167; + pt = p*pow(B,3.5)*D; + } + + A = pow(((pt-p)/psl+1),0.28571); + vcas = sqrt(7*psl/rhosl*(A-1)); + //cout << "calcVcas: vcas= " << vcas*fpstokts << " mach= " << Mach << " pressure: " << pt << endl; + return vcas; +} + +//****************************************************************************** + +bool FGInitialCondition::findInterval(double x,double guess) { + //void find_interval(inter_params &ip,eqfunc f,double y,double constant, int &flag){ + + int i=0; + bool found=false; + double flo,fhi,fguess; + double lo,hi,step; + step=0.1; + fguess=(this->*sfunc)(guess)-x; + lo=hi=guess; + do { + step=2*step; + lo-=step; + hi+=step; + if(lo < xmin) lo=xmin; + if(hi > xmax) hi=xmax; + i++; + flo=(this->*sfunc)(lo)-x; + fhi=(this->*sfunc)(hi)-x; + if(flo*fhi <=0) { //found interval with root + found=true; + if(flo*fguess <= 0) { //narrow interval down a bit + hi=lo+step; //to pass solver interval that is as + //small as possible + } + else if(fhi*fguess <= 0) { + lo=hi-step; + } + } + //cout << "findInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl; + } + while((found == 0) && (i <= 100)); + xlo=lo; + xhi=hi; + return found; +} + +//****************************************************************************** + +bool FGInitialCondition::solve(double *y,double x) +{ + double x1,x2,x3,f1,f2,f3,d,d0; + double eps=1E-5; + double const relax =0.9; + int i; + bool success=false; + + //initializations + d=1; + x2 = 0; + x1=xlo;x3=xhi; + f1=(this->*sfunc)(x1)-x; + f3=(this->*sfunc)(x3)-x; + d0=fabs(x3-x1); + + //iterations + i=0; + while ((fabs(d) > eps) && (i < 100)) { + d=(x3-x1)/d0; + x2 = x1-d*d0*f1/(f3-f1); + + f2=(this->*sfunc)(x2)-x; + //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl; + //cout << " " << f1 << "," << f2 << "," << f3 << endl; + + if(fabs(f2) <= 0.001) { + x1=x3=x2; + } else if(f1*f2 <= 0.0) { + x3=x2; + f3=f2; + f1=relax*f1; + } else if(f2*f3 <= 0) { + x1=x2; + f1=f2; + f3=relax*f3; + } + //cout << i << endl; + i++; + }//end while + if(i < 100) { + success=true; + *y=x2; + } + + //cout << "Success= " << success << " Vcas: " << vcas*fpstokts << " Mach: " << x2 << endl; + return success; +} + +//****************************************************************************** + +double FGInitialCondition::GetWindDirDegIC(void) { + if(weast != 0.0) + return atan2(weast,wnorth)*radtodeg; + else if(wnorth > 0) + return 0.0; + else + return 180.0; +} + +//****************************************************************************** + +bool FGInitialCondition::Load(string rstfile, bool useStoredPath) +{ + string resetDef, acpath; + ifstream initialization_file; + FGXMLParse initialization_file_parser; + Element *document, *el; + int n; + + string sep = "/"; +# ifdef macintosh + string sep = ";"; +# endif + + if( useStoredPath ) { + acpath = fdmex->GetAircraftPath() + sep + fdmex->GetModelName(); + resetDef = acpath + sep + rstfile + ".xml"; + } else { + resetDef = rstfile; + } + + initialization_file.open(resetDef.c_str()); + if ( !initialization_file.is_open()) { + cerr << "Could not open initialization file: " << resetDef << endl; + return false; + } + + readXML(initialization_file, initialization_file_parser); + document = initialization_file_parser.GetDocument(); // document holds the + // initialization description + if (document->GetName() != string("initialize")) { + cerr << "File: " << resetDef << " is not a reset file" << endl; + exit(-1); + } + + if (document->FindElement("ubody")) + SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC")); + if (document->FindElement("vbody")) + SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC")); + if (document->FindElement("wbody")) + SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC")); + if (document->FindElement("latitude")) + SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG")); + if (document->FindElement("longitude")) + SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG")); + if (document->FindElement("phi")) + SetRollAngleDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG")); + if (document->FindElement("theta")) + SetPitchAngleDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG")); + if (document->FindElement("psi")) + SetTrueHeadingDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG")); + if (document->FindElement("alpha")) + SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG")); + if (document->FindElement("beta")) + SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG")); + if (document->FindElement("gamma")) + SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG")); + if (document->FindElement("roc")) + SetClimbRateFpmIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC")); + if (document->FindElement("altitude")) + SetAltitudeFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT")); + if (document->FindElement("winddir")) + SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG")); + if (document->FindElement("vwind")) + SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "FT/SEC")); + if (document->FindElement("hwind")) + SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS")); + if (document->FindElement("xwind")) + SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS")); + if (document->FindElement("vc")) + SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "FT/SEC")); + if (document->FindElement("mach")) + SetMachIC(document->FindElementValueAsNumber("mach")); + if (document->FindElement("vground")) + SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "FT/SEC")); + if (document->FindElement("running")) { + n = document->FindElementValueAsNumber("running"); + if (n != 0) { + FGPropulsion* propulsion = fdmex->GetPropulsion(); + for(int i=0; iGetNumEngines(); i++) { + propulsion->GetEngine(i)->SetRunning(true); + } + } + } + + fdmex->RunIC(); + + return true; +} + +//****************************************************************************** + +void FGInitialCondition::bind(void){ + PropertyManager->Tie("ic/vc-kts", this, + &FGInitialCondition::GetVcalibratedKtsIC, + &FGInitialCondition::SetVcalibratedKtsIC, + true); + PropertyManager->Tie("ic/ve-kts", this, + &FGInitialCondition::GetVequivalentKtsIC, + &FGInitialCondition::SetVequivalentKtsIC, + true); + PropertyManager->Tie("ic/vg-kts", this, + &FGInitialCondition::GetVgroundKtsIC, + &FGInitialCondition::SetVgroundKtsIC, + true); + PropertyManager->Tie("ic/vt-kts", this, + &FGInitialCondition::GetVtrueKtsIC, + &FGInitialCondition::SetVtrueKtsIC, + true); + PropertyManager->Tie("ic/mach-norm", this, + &FGInitialCondition::GetMachIC, + &FGInitialCondition::SetMachIC, + true); + PropertyManager->Tie("ic/roc-fpm", this, + &FGInitialCondition::GetClimbRateFpmIC, + &FGInitialCondition::SetClimbRateFpmIC, + true); + PropertyManager->Tie("ic/gamma-deg", this, + &FGInitialCondition::GetFlightPathAngleDegIC, + &FGInitialCondition::SetFlightPathAngleDegIC, + true); + PropertyManager->Tie("ic/alpha-deg", this, + &FGInitialCondition::GetAlphaDegIC, + &FGInitialCondition::SetAlphaDegIC, + true); + PropertyManager->Tie("ic/beta-deg", this, + &FGInitialCondition::GetBetaDegIC, + &FGInitialCondition::SetBetaDegIC, + true); + PropertyManager->Tie("ic/theta-deg", this, + &FGInitialCondition::GetPitchAngleDegIC, + &FGInitialCondition::SetPitchAngleDegIC, + true); + PropertyManager->Tie("ic/phi-deg", this, + &FGInitialCondition::GetRollAngleDegIC, + &FGInitialCondition::SetRollAngleDegIC, + true); + PropertyManager->Tie("ic/psi-true-deg", this, + &FGInitialCondition::GetHeadingDegIC ); + PropertyManager->Tie("ic/lat-gc-deg", this, + &FGInitialCondition::GetLatitudeDegIC, + &FGInitialCondition::SetLatitudeDegIC, + true); + PropertyManager->Tie("ic/long-gc-deg", this, + &FGInitialCondition::GetLongitudeDegIC, + &FGInitialCondition::SetLongitudeDegIC, + true); + PropertyManager->Tie("ic/h-sl-ft", this, + &FGInitialCondition::GetAltitudeFtIC, + &FGInitialCondition::SetAltitudeFtIC, + true); + PropertyManager->Tie("ic/h-agl-ft", this, + &FGInitialCondition::GetAltitudeAGLFtIC, + &FGInitialCondition::SetAltitudeAGLFtIC, + true); + PropertyManager->Tie("ic/sea-level-radius-ft", this, + &FGInitialCondition::GetSeaLevelRadiusFtIC, + &FGInitialCondition::SetSeaLevelRadiusFtIC, + true); + PropertyManager->Tie("ic/terrain-altitude-ft", this, + &FGInitialCondition::GetTerrainAltitudeFtIC, + &FGInitialCondition::SetTerrainAltitudeFtIC, + true); + PropertyManager->Tie("ic/vg-fps", this, + &FGInitialCondition::GetVgroundFpsIC, + &FGInitialCondition::SetVgroundFpsIC, + true); + PropertyManager->Tie("ic/vt-fps", this, + &FGInitialCondition::GetVtrueFpsIC, + &FGInitialCondition::SetVtrueFpsIC, + true); + PropertyManager->Tie("ic/vw-bx-fps", this, + &FGInitialCondition::GetWindUFpsIC); + PropertyManager->Tie("ic/vw-by-fps", this, + &FGInitialCondition::GetWindVFpsIC); + PropertyManager->Tie("ic/vw-bz-fps", this, + &FGInitialCondition::GetWindWFpsIC); + PropertyManager->Tie("ic/vw-north-fps", this, + &FGInitialCondition::GetWindNFpsIC); + PropertyManager->Tie("ic/vw-east-fps", this, + &FGInitialCondition::GetWindEFpsIC); + PropertyManager->Tie("ic/vw-down-fps", this, + &FGInitialCondition::GetWindDFpsIC); + PropertyManager->Tie("ic/vw-mag-fps", this, + &FGInitialCondition::GetWindFpsIC); + /* PropertyManager->Tie("ic/vw-dir-deg", this, + &FGInitialCondition::GetWindDirDegIC, + &FGInitialCondition::SetWindDirDegIC, + true); */ + + PropertyManager->Tie("ic/roc-fps", this, + &FGInitialCondition::GetClimbRateFpsIC, + &FGInitialCondition::SetClimbRateFpsIC, + true); + /* PropertyManager->Tie("ic/u-fps", this, + &FGInitialCondition::GetUBodyFpsIC, + &FGInitialCondition::SetUBodyFpsIC, + true); + PropertyManager->Tie("ic/v-fps", this, + &FGInitialCondition::GetVBodyFpsIC, + &FGInitialCondition::SetVBodyFpsIC, + true); + PropertyManager->Tie("ic/w-fps", this, + &FGInitialCondition::GetWBodyFpsIC, + &FGInitialCondition::SetWBodyFpsIC, + true); */ + + PropertyManager->Tie("ic/gamma-rad", this, + &FGInitialCondition::GetFlightPathAngleRadIC, + &FGInitialCondition::SetFlightPathAngleRadIC, + true); + PropertyManager->Tie("ic/alpha-rad", this, + &FGInitialCondition::GetAlphaRadIC, + &FGInitialCondition::SetAlphaRadIC, + true); + PropertyManager->Tie("ic/theta-rad", this, + &FGInitialCondition::GetPitchAngleRadIC, + &FGInitialCondition::SetPitchAngleRadIC, + true); + PropertyManager->Tie("ic/beta-rad", this, + &FGInitialCondition::GetBetaRadIC, + &FGInitialCondition::SetBetaRadIC, + true); + PropertyManager->Tie("ic/phi-rad", this, + &FGInitialCondition::GetRollAngleRadIC, + &FGInitialCondition::SetRollAngleRadIC, + true); + PropertyManager->Tie("ic/psi-true-rad", this, + &FGInitialCondition::GetHeadingRadIC); + PropertyManager->Tie("ic/lat-gc-rad", this, + &FGInitialCondition::GetLatitudeRadIC, + &FGInitialCondition::SetLatitudeRadIC, + true); + PropertyManager->Tie("ic/long-gc-rad", this, + &FGInitialCondition::GetLongitudeRadIC, + &FGInitialCondition::SetLongitudeRadIC, + true); + PropertyManager->Tie("ic/p-rad_sec", this, + &FGInitialCondition::GetPRadpsIC, + &FGInitialCondition::SetPRadpsIC, + true); + PropertyManager->Tie("ic/q-rad_sec", this, + &FGInitialCondition::GetQRadpsIC, + &FGInitialCondition::SetQRadpsIC, + true); + PropertyManager->Tie("ic/r-rad_sec", this, + &FGInitialCondition::GetRRadpsIC, + &FGInitialCondition::SetRRadpsIC, + true); + +} + +//****************************************************************************** + +void FGInitialCondition::unbind(void){ + PropertyManager->Untie("ic/vc-kts"); + PropertyManager->Untie("ic/ve-kts"); + PropertyManager->Untie("ic/vg-kts"); + PropertyManager->Untie("ic/vt-kts"); + PropertyManager->Untie("ic/mach-norm"); + PropertyManager->Untie("ic/roc-fpm"); + PropertyManager->Untie("ic/gamma-deg"); + PropertyManager->Untie("ic/alpha-deg"); + PropertyManager->Untie("ic/beta-deg"); + PropertyManager->Untie("ic/theta-deg"); + PropertyManager->Untie("ic/phi-deg"); + PropertyManager->Untie("ic/psi-true-deg"); + PropertyManager->Untie("ic/lat-gc-deg"); + PropertyManager->Untie("ic/long-gc-deg"); + PropertyManager->Untie("ic/h-sl-ft"); + PropertyManager->Untie("ic/h-agl-ft"); + PropertyManager->Untie("ic/sea-level-radius-ft"); + PropertyManager->Untie("ic/terrain-altitude-ft"); + PropertyManager->Untie("ic/vg-fps"); + PropertyManager->Untie("ic/vt-fps"); + PropertyManager->Untie("ic/vw-bx-fps"); + PropertyManager->Untie("ic/vw-by-fps"); + PropertyManager->Untie("ic/vw-bz-fps"); + PropertyManager->Untie("ic/vw-north-fps"); + PropertyManager->Untie("ic/vw-east-fps"); + PropertyManager->Untie("ic/vw-down-fps"); + PropertyManager->Untie("ic/vw-mag-fps"); + /* PropertyManager->Untie("ic/vw-dir-deg"); */ + + PropertyManager->Untie("ic/roc-fps"); + + /* PropertyManager->Untie("ic/u-fps"); + PropertyManager->Untie("ic/v-fps"); + PropertyManager->Untie("ic/w-fps"); */ + + PropertyManager->Untie("ic/gamma-rad"); + PropertyManager->Untie("ic/alpha-rad"); + PropertyManager->Untie("ic/theta-rad"); + PropertyManager->Untie("ic/beta-rad"); + PropertyManager->Untie("ic/phi-rad"); + PropertyManager->Untie("ic/psi-true-rad"); + PropertyManager->Untie("ic/lat-gc-rad"); + PropertyManager->Untie("ic/long-gc-rad"); + PropertyManager->Untie("ic/p-rad_sec"); + PropertyManager->Untie("ic/q-rad_sec"); + PropertyManager->Untie("ic/r-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 FGInitialCondition::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: FGInitialCondition" << endl; + if (from == 1) cout << "Destroyed: FGInitialCondition" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.h b/src/FDM/JSBSim/initialization/FGInitialCondition.h new file mode 100644 index 000000000..b11c9cee2 --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.h @@ -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 +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 + VBODY + WBODY + LATITUDE + LONGITUDE + PHI + THETA + PSI + ALPHA + BETA + GAMMA + ROC + ALTITUDE + WINDDIR + VWIND + HWIND + XWIND + VC + MACH + VGROUND + 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 + diff --git a/src/FDM/JSBSim/initialization/FGTrim.cpp b/src/FDM/JSBSim/initialization/FGTrim.cpp new file mode 100644 index 000000000..26edd99aa --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGTrim.cpp @@ -0,0 +1,683 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTrim.cpp + Author: Tony Peden + Date started: 9/8/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 +-------------------------------------------------------------------------------- +9/8/99 TP Created + + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +This class takes the given set of IC's and finds the angle of attack, elevator, +and throttle setting required to fly steady level. This is currently for in-air +conditions only. It is implemented using an iterative, one-axis-at-a-time +scheme. */ + +// !!!!!!! BEWARE ALL YE WHO ENTER HERE !!!!!!! + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include +#include +#include "FGInitialCondition.h" +#include "FGTrim.h" +#include +#include +#include +#include +#include +#include + +#if _MSC_VER +#pragma warning (disable : 4786 4788) +#endif + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_TRIM; + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) { + + N=Nsub=0; + max_iterations=60; + max_sub_iterations=100; + Tolerance=1E-3; + A_Tolerance = Tolerance / 10; + + Debug=0;DebugLevel=0; + fdmex=FDMExec; + fgic=fdmex->GetIC(); + total_its=0; + trimudot=true; + gamma_fallback=true; + axis_count=0; + mode=tt; + xlo=xhi=alo=ahi=0.0; + targetNlf=1.0; + debug_axis=tAll; + SetMode(tt); + if (debug_lvl & 2) cout << "Instantiated: FGTrim" << endl; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTrim::~FGTrim(void) { + for(current_axis=0; current_axis 0) { + cout << " Sub-iterations:" << endl; + for(current_axis=0; current_axisGetRunCount(); + snprintf(out,80," %5s: %3.0f average: %5.2f successful: %3.0f stability: %5.2f\n", + TrimAxes[current_axis]->GetStateName().c_str(), + sub_iterations[current_axis], + sub_iterations[current_axis]/double(total_its), + successful[current_axis], + TrimAxes[current_axis]->GetAvgStability() ); + cout << out; + } + cout << " Run Count: " << run_sum << endl; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTrim::Report(void) { + cout << " Trim Results: " << endl; + for(current_axis=0; current_axisAxisReport(); + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTrim::ClearStates(void) { + FGTrimAxis* ta; + + mode=tCustom; + vector::iterator iAxes; + iAxes = TrimAxes.begin(); + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + delete ta; + iAxes++; + } + TrimAxes.clear(); + //cout << "TrimAxes.size(): " << TrimAxes.size() << endl; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGTrim::AddState( State state, Control control ) { + FGTrimAxis* ta; + bool result=true; + + mode = tCustom; + vector ::iterator iAxes = TrimAxes.begin(); + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + if( ta->GetStateType() == state ) + result=false; + iAxes++; + } + if(result) { + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,state,control)); + delete[] sub_iterations; + delete[] successful; + delete[] solution; + sub_iterations=new double[TrimAxes.size()]; + successful=new double[TrimAxes.size()]; + solution=new bool[TrimAxes.size()]; + } + return result; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGTrim::RemoveState( State state ) { + FGTrimAxis* ta; + bool result=false; + + mode = tCustom; + vector ::iterator iAxes = TrimAxes.begin(); + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + if( ta->GetStateType() == state ) { + delete ta; + TrimAxes.erase(iAxes); + result=true; + continue; + } + iAxes++; + } + if(result) { + delete[] sub_iterations; + delete[] successful; + delete[] solution; + sub_iterations=new double[TrimAxes.size()]; + successful=new double[TrimAxes.size()]; + solution=new bool[TrimAxes.size()]; + } + return result; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGTrim::EditState( State state, Control new_control ){ + FGTrimAxis* ta; + bool result=false; + + mode = tCustom; + vector ::iterator iAxes = TrimAxes.begin(); + while (iAxes != TrimAxes.end()) { + ta=*iAxes; + if( ta->GetStateType() == state ) { + TrimAxes.insert(iAxes,1,new FGTrimAxis(fdmex,fgic,state,new_control)); + delete ta; + TrimAxes.erase(iAxes+1); + result=true; + break; + } + iAxes++; + } + return result; +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGTrim::DoTrim(void) { + + trim_failed=false; + int i; + + for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ + fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false); + } + + fdmex->DisableOutput(); + + fgic->SetPRadpsIC(0.0); + fgic->SetQRadpsIC(0.0); + fgic->SetRRadpsIC(0.0); + + //clear the sub iterations counts & zero out the controls + for(current_axis=0;current_axisGetStateName() + //<< " " << TrimAxes[current_axis]->GetControlName()<< endl; + if(TrimAxes[current_axis]->GetStateType() == tQdot) { + if(mode == tGround) { + TrimAxes[current_axis]->initTheta(); + } + } + xlo=TrimAxes[current_axis]->GetControlMin(); + xhi=TrimAxes[current_axis]->GetControlMax(); + TrimAxes[current_axis]->SetControl((xlo+xhi)/2); + TrimAxes[current_axis]->Run(); + //TrimAxes[current_axis]->AxisReport(); + sub_iterations[current_axis]=0; + successful[current_axis]=0; + solution[current_axis]=false; + } + + + if(mode == tPullup ) { + cout << "Setting pitch rate and nlf... " << endl; + setupPullup(); + cout << "pitch rate done ... " << endl; + TrimAxes[0]->SetStateTarget(targetNlf); + cout << "nlf done" << endl; + } else if (mode == tTurn) { + setupTurn(); + //TrimAxes[0]->SetStateTarget(targetNlf); + } + + do { + axis_count=0; + for(current_axis=0;current_axis 0) TrimAxes[current_axis]->AxisReport(); + if(TrimAxes[current_axis]->InTolerance()) { + axis_count++; + successful[current_axis]++; + } + } + + + if((axis_count == TrimAxes.size()-1) && (TrimAxes.size() > 1)) { + //cout << TrimAxes.size()-1 << " out of " << TrimAxes.size() << "!" << endl; + //At this point we can check the input limits of the failed axis + //and declare the trim failed if there is no sign change. If there + //is, keep going until success or max iteration count + + //Oh, well: two out of three ain't bad + for(current_axis=0;current_axisInTolerance()) { + if(!checkLimits()) { + // special case this for now -- if other cases arise proper + // support can be added to FGTrimAxis + if( (gamma_fallback) && + (TrimAxes[current_axis]->GetStateType() == tUdot) && + (TrimAxes[current_axis]->GetControlType() == tThrottle)) { + cout << " Can't trim udot with throttle, trying flight" + << " path angle. (" << N << ")" << endl; + if(TrimAxes[current_axis]->GetState() > 0) + TrimAxes[current_axis]->SetControlToMin(); + else + TrimAxes[current_axis]->SetControlToMax(); + TrimAxes[current_axis]->Run(); + delete TrimAxes[current_axis]; + TrimAxes[current_axis]=new FGTrimAxis(fdmex,fgic,tUdot, + tGamma ); + } else { + cout << " Sorry, " << TrimAxes[current_axis]->GetStateName() + << " doesn't appear to be trimmable" << endl; + //total_its=k; + trim_failed=true; //force the trim to fail + } //gamma_fallback + } + } //solution check + } //for loop + } //all-but-one check + N++; + if(N > max_iterations) + trim_failed=true; + } while((axis_count < TrimAxes.size()) && (!trim_failed)); + if((!trim_failed) && (axis_count >= TrimAxes.size())) { + total_its=N; + if (debug_lvl > 0) + cout << endl << " Trim successful" << endl; + } else { + total_its=N; + if (debug_lvl > 0) + cout << endl << " Trim failed" << endl; + } + for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ + fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); + } + fdmex->EnableOutput(); + return !trim_failed; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGTrim::solve(void) { + + double x1,x2,x3,f1,f2,f3,d,d0; + const double relax =0.9; + double eps=TrimAxes[current_axis]->GetSolverEps(); + + x1=x2=x3=0; + d=1; + bool success=false; + //initializations + if( solutionDomain != 0) { + /* if(ahi > alo) { */ + x1=xlo;f1=alo; + x3=xhi;f3=ahi; + /* } else { + x1=xhi;f1=ahi; + x3=xlo;f3=alo; + } */ + d0=fabs(x3-x1); + //iterations + //max_sub_iterations=TrimAxes[current_axis]->GetIterationLimit(); + while ( (TrimAxes[current_axis]->InTolerance() == false ) + && (fabs(d) > eps) && (Nsub < max_sub_iterations)) { + Nsub++; + d=(x3-x1)/d0; + x2=x1-d*d0*f1/(f3-f1); + TrimAxes[current_axis]->SetControl(x2); + TrimAxes[current_axis]->Run(); + f2=TrimAxes[current_axis]->GetState(); + if(Debug > 1) { + cout << "FGTrim::solve Nsub,x1,x2,x3: " << Nsub << ", " << x1 + << ", " << x2 << ", " << x3 << endl; + cout << " " << f1 << ", " << f2 << ", " << f3 << endl; + } + if(f1*f2 <= 0.0) { + x3=x2; + f3=f2; + f1=relax*f1; + //cout << "Solution is between x1 and x2" << endl; + } + else if(f2*f3 <= 0.0) { + x1=x2; + f1=f2; + f3=relax*f3; + //cout << "Solution is between x2 and x3" << endl; + + } + //cout << i << endl; + + + }//end while + if(Nsub < max_sub_iterations) success=true; + } + return success; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/* + produces an interval (xlo..xhi) on one side or the other of the current + control value in which a solution exists. This domain is, hopefully, + smaller than xmin..0 or 0..xmax and the solver will require fewer iterations + to find the solution. This is, hopefully, more efficient than having the + solver start from scratch every time. Maybe it isn't though... + This tries to take advantage of the idea that the changes from iteration to + iteration will be small after the first one or two top-level iterations. + + assumes that changing the control will a produce significant change in the + accel i.e. checkLimits() has already been called. + + if a solution is found above the current control, the function returns true + and xlo is set to the current control, xhi to the interval max it found, and + solutionDomain is set to 1. + if the solution lies below the current control, then the function returns + true and xlo is set to the interval min it found and xmax to the current + control. if no solution is found, then the function returns false. + + + in all cases, alo=accel(xlo) and ahi=accel(xhi) after the function exits. + no assumptions about the state of the sim after this function has run + can be made. +*/ +bool FGTrim::findInterval(void) { + bool found=false; + double step; + double current_control=TrimAxes[current_axis]->GetControl(); + double current_accel=TrimAxes[current_axis]->GetState();; + double xmin=TrimAxes[current_axis]->GetControlMin(); + double xmax=TrimAxes[current_axis]->GetControlMax(); + double lastxlo,lastxhi,lastalo,lastahi; + + step=0.025*fabs(xmax); + xlo=xhi=current_control; + alo=ahi=current_accel; + lastxlo=xlo;lastxhi=xhi; + lastalo=alo;lastahi=ahi; + do { + + Nsub++; + step*=2; + xlo-=step; + if(xlo < xmin) xlo=xmin; + xhi+=step; + if(xhi > xmax) xhi=xmax; + TrimAxes[current_axis]->SetControl(xlo); + TrimAxes[current_axis]->Run(); + alo=TrimAxes[current_axis]->GetState(); + TrimAxes[current_axis]->SetControl(xhi); + TrimAxes[current_axis]->Run(); + ahi=TrimAxes[current_axis]->GetState(); + if(fabs(ahi-alo) <= TrimAxes[current_axis]->GetTolerance()) continue; + if(alo*ahi <=0) { //found interval with root + found=true; + if(alo*current_accel <= 0) { //narrow interval down a bit + solutionDomain=-1; + xhi=lastxlo; + ahi=lastalo; + //xhi=current_control; + //ahi=current_accel; + } else { + solutionDomain=1; + xlo=lastxhi; + alo=lastahi; + //xlo=current_control; + //alo=current_accel; + } + } + lastxlo=xlo;lastxhi=xhi; + lastalo=alo;lastahi=ahi; + if( !found && xlo==xmin && xhi==xmax ) continue; + if(Debug > 1) + cout << "FGTrim::findInterval: Nsub=" << Nsub << " Lo= " << xlo + << " Hi= " << xhi << " alo*ahi: " << alo*ahi << endl; + } while(!found && (Nsub <= max_sub_iterations) ); + return found; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//checks to see which side of the current control value the solution is on +//and sets solutionDomain accordingly: +// 1 if solution is between the current and max +// -1 if solution is between the min and current +// 0 if there is no solution +// +//if changing the control produces no significant change in the accel then +//solutionDomain is set to zero and the function returns false +//if a solution is found, then xlo and xhi are set so that they bracket +//the solution, alo is set to accel(xlo), and ahi is set to accel(xhi) +//if there is no change or no solution then xlo=xmin, alo=accel(xmin) and +//xhi=xmax and ahi=accel(xmax) +//in all cases the sim is left such that the control=xmax and accel=ahi + +bool FGTrim::checkLimits(void) { + bool solutionExists; + double current_control=TrimAxes[current_axis]->GetControl(); + double current_accel=TrimAxes[current_axis]->GetState(); + xlo=TrimAxes[current_axis]->GetControlMin(); + xhi=TrimAxes[current_axis]->GetControlMax(); + + TrimAxes[current_axis]->SetControl(xlo); + TrimAxes[current_axis]->Run(); + alo=TrimAxes[current_axis]->GetState(); + TrimAxes[current_axis]->SetControl(xhi); + TrimAxes[current_axis]->Run(); + ahi=TrimAxes[current_axis]->GetState(); + if(Debug > 1) + cout << "checkLimits() xlo,xhi,alo,ahi: " << xlo << ", " << xhi << ", " + << alo << ", " << ahi << endl; + solutionDomain=0; + solutionExists=false; + if(fabs(ahi-alo) > TrimAxes[current_axis]->GetTolerance()) { + if(alo*current_accel <= 0) { + solutionExists=true; + solutionDomain=-1; + xhi=current_control; + ahi=current_accel; + } else if(current_accel*ahi < 0){ + solutionExists=true; + solutionDomain=1; + xlo=current_control; + alo=current_accel; + } + } + TrimAxes[current_axis]->SetControl(current_control); + TrimAxes[current_axis]->Run(); + return solutionExists; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTrim::setupPullup() { + double g,q,cgamma; + g=fdmex->GetInertial()->gravity(); + cgamma=cos(fgic->GetFlightPathAngleRadIC()); + cout << "setPitchRateInPullup(): " << g << ", " << cgamma << ", " + << fgic->GetVtrueFpsIC() << endl; + q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); + cout << targetNlf << ", " << q << endl; + fgic->SetQRadpsIC(q); + cout << "setPitchRateInPullup() complete" << endl; + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTrim::setupTurn(void){ + double g,phi; + phi = fgic->GetRollAngleRadIC(); + if( fabs(phi) > 0.001 && fabs(phi) < 1.56 ) { + targetNlf = 1 / cos(phi); + g = fdmex->GetInertial()->gravity(); + psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); + cout << targetNlf << ", " << psidot << endl; + } + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTrim::updateRates(void){ + if( mode == tTurn ) { + double phi = fgic->GetRollAngleRadIC(); + double g = fdmex->GetInertial()->gravity(); + double p,q,r,theta; + if(fabs(phi) > 0.001 && fabs(phi) < 1.56 ) { + theta=fgic->GetPitchAngleRadIC(); + phi=fgic->GetRollAngleRadIC(); + psidot = g*tan(phi) / fgic->GetUBodyFpsIC(); + p=-psidot*sin(theta); + q=psidot*cos(theta)*sin(phi); + r=psidot*cos(theta)*cos(phi); + } else { + p=q=r=0; + } + fgic->SetPRadpsIC(p); + fgic->SetQRadpsIC(q); + fgic->SetRRadpsIC(r); + } else if( mode == tPullup && fabs(targetNlf-1) > 0.01) { + double g,q,cgamma; + g=fdmex->GetInertial()->gravity(); + cgamma=cos(fgic->GetFlightPathAngleRadIC()); + q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC(); + fgic->SetQRadpsIC(q); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTrim::setDebug(void) { + if(debug_axis == tAll || + TrimAxes[current_axis]->GetStateType() == debug_axis ) { + Debug=DebugLevel; + return; + } else { + Debug=0; + return; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTrim::SetMode(TrimMode tt) { + ClearStates(); + mode=tt; + switch(tt) { + case tFull: + if (debug_lvl > 0) + cout << " Full Trim" << endl; + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); + break; + case tLongitudinal: + if (debug_lvl > 0) + cout << " Longitudinal Trim" << endl; + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); + break; + case tGround: + if (debug_lvl > 0) + cout << " Ground Trim" << endl; + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta )); + //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi )); + break; + case tPullup: + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); + break; + case tTurn: + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron )); + TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder )); + break; + case tCustom: + case tNone: + break; + } + //cout << "TrimAxes.size(): " << TrimAxes.size() << endl; + sub_iterations=new double[TrimAxes.size()]; + successful=new double[TrimAxes.size()]; + solution=new bool[TrimAxes.size()]; + current_axis=0; +} +//YOU WERE WARNED, BUT YOU DID IT ANYWAY. +} diff --git a/src/FDM/JSBSim/initialization/FGTrim.h b/src/FDM/JSBSim/initialization/FGTrim.h new file mode 100644 index 000000000..1f6bbce76 --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGTrim.h @@ -0,0 +1,295 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTrim.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 +-------------------------------------------------------------------------------- +9/8/99 TP Created + + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +This class takes the given set of IC's and finds the aircraft state required to +maintain a specified flight condition. This flight condition can be +steady-level with non-zero sideslip, a steady turn, a pull-up or pushover. +On-ground conditions can be trimmed as well, but this is currently limited to +adjusting altitude and pitch angle only. It is implemented using an iterative, +one-axis-at-a-time scheme. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGTRIM_H +#define FGTRIM_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGFDMExec.h" +#include "FGJSBBase.h" +#include "FGTrimAxis.h" + +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_TRIM "$Id$" + +#if defined(_WIN32) && !defined(__CYGWIN__) + #define snprintf _snprintf +#endif + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +typedef enum { tLongitudinal=0, tFull, tGround, tPullup, + tCustom, tTurn, tNone } TrimMode; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** FGTrim -- the trimming routine for JSBSim. + FGTrim finds the aircraft attitude and control settings needed to maintain + the steady state described by the FGInitialCondition object . It does this + iteratively by assigning a control to each state and adjusting that control + until the state is within a specified tolerance of zero. States include the + recti-linear accelerations udot, vdot, and wdot, the angular accelerations + qdot, pdot, and rdot, and the difference between heading and ground track. + Controls include the usual flight deck controls available to the pilot plus + angle of attack (alpha), sideslip angle(beta), flight path angle (gamma), + pitch attitude(theta), roll attitude(phi), and altitude above ground. The + last three are used for on-ground trimming. The state-control pairs used in + a given trim are completely user configurable and several pre-defined modes + are provided as well. They are: + - tLongitudinal: Trim wdot with alpha, udot with thrust, qdot with elevator + - tFull: tLongitudinal + vdot with phi, pdot with aileron, rdot with rudder + and heading minus ground track (hmgt) with beta + - tPullup: tLongitudinal but adjust alpha to achieve load factor input + with SetTargetNlf() + - tGround: wdot with altitude, qdot with theta, and pdot with phi + + The remaining modes include tCustom, which is completely user defined and + tNone. + + Note that trims can (and do) fail for reasons that are completely outside + the control of the trimming routine itself. The most common problem is the + initial conditions: is the model capable of steady state flight + at those conditions? Check the speed, altitude, configuration (flaps, + gear, etc.), weight, cg, and anything else that may be relevant. + + Example usage:
+    FGFDMExec* FDMExec = new FGFDMExec();
+
+    FGInitialCondition* fgic = new FGInitialCondition(FDMExec);
+    FGTrim fgt(FDMExec, fgic, tFull);
+    fgic->SetVcaibratedKtsIC(100);
+    fgic->SetAltitudeFtIC(1000);
+    fgic->SetClimbRate(500);
+    if( !fgt.DoTrim() ) {
+      cout << "Trim Failed" << endl;
+    }
+    fgt.Report(); 
+ @author Tony Peden + @version "$Id$" +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGTrim : public FGJSBBase +{ +private: + + vector TrimAxes; + unsigned int current_axis; + int N, Nsub; + TrimMode mode; + int DebugLevel, Debug; + double Tolerance, A_Tolerance; + double wdot,udot,qdot; + double dth; + double *sub_iterations; + double *successful; + bool *solution; + int max_sub_iterations; + int max_iterations; + int total_its; + bool trimudot; + bool gamma_fallback; + bool trim_failed; + unsigned int axis_count; + int solutionDomain; + double xlo,xhi,alo,ahi; + double targetNlf; + int debug_axis; + + double psidot,thetadot; + + FGFDMExec* fdmex; + FGInitialCondition* fgic; + + bool solve(void); + + /** @return false if there is no change in the current axis accel + between accel(control_min) and accel(control_max). If there is a + change, sets solutionDomain to: + 0 for no sign change, + -1 if sign change between accel(control_min) and accel(0) + 1 if sign between accel(0) and accel(control_max) + */ + bool findInterval(void); + + bool checkLimits(void); + + void setupPullup(void); + void setupTurn(void); + + void updateRates(void); + + void setDebug(void); + +public: + /** Initializes the trimming class + @param FDMExec pointer to a JSBSim executive object. + @param tm trim mode + */ + FGTrim(FGFDMExec *FDMExec, TrimMode tm=tGround ); + + ~FGTrim(void); + + /** Execute the trim + */ + bool DoTrim(void); + + /** Print the results of the trim. For each axis trimmed, this + includes the final state value, control value, and tolerance + used. + @return true if trim succeeds + */ + void Report(void); + + /** Iteration statistics + */ + void TrimStats(); + + /** Clear all state-control pairs and set a predefined trim mode + @param tm the set of axes to trim. Can be: + tLongitudinal, tFull, tGround, tCustom, or tNone + */ + void SetMode(TrimMode tm); + + /** Clear all state-control pairs from the current configuration. + The trimming routine must have at least one state-control pair + configured to be useful + */ + void ClearStates(void); + + /** Add a state-control pair to the current configuration. See the enums + State and Control in FGTrimAxis.h for the available options. + Will fail if the given state is already configured. + @param state the accel or other condition to zero + @param control the control used to zero the state + @return true if add is successful + */ + bool AddState( State state, Control control ); + + /** Remove a specific state-control pair from the current configuration + @param state the state to remove + @return true if removal is successful + */ + bool RemoveState( State state ); + + /** Change the control used to zero a state previously configured + @param state the accel or other condition to zero + @param new_control the control used to zero the state + */ + bool EditState( State state, Control new_control ); + + /** automatically switch to trimming longitudinal acceleration with + flight path angle (gamma) once it becomes apparent that there + is not enough/too much thrust. + @param bb true to enable fallback + */ + inline void SetGammaFallback(bool bb) { gamma_fallback=bb; } + + /** query the fallback state + @return true if fallback is enabled. + */ + inline bool GetGammaFallback(void) { return gamma_fallback; } + + /** Set the iteration limit. DoTrim() will return false if limit + iterations are reached before trim is achieved. The default + is 60. This does not ordinarily need to be changed. + @param ii integer iteration limit + */ + inline void SetMaxCycles(int ii) { max_iterations = ii; } + + /** Set the per-axis iteration limit. Attempt to zero each state + by iterating limit times before moving on to the next. The + default limit is 100 and also does not ordinarily need to + be changed. + @param ii integer iteration limit + */ + inline void SetMaxCyclesPerAxis(int ii) { max_sub_iterations = ii; } + + /** Set the tolerance for declaring a state trimmed. Angular accels are + held to a tolerance of 1/10th of the given. The default is + 0.001 for the recti-linear accelerations and 0.0001 for the angular. + */ + inline void SetTolerance(double tt) { + Tolerance = tt; + A_Tolerance = tt / 10; + } + + /** + Debug level 1 shows results of each top-level iteration + Debug level 2 shows level 1 & results of each per-axis iteration + */ + inline void SetDebug(int level) { DebugLevel = level; } + inline void ClearDebug(void) { DebugLevel = 0; } + + /** + Output debug data for one of the axes + The State enum is defined in FGTrimAxis.h + */ + inline void DebugState(State state) { debug_axis=state; } + + inline void SetTargetNlf(double nlf) { targetNlf=nlf; } + inline double GetTargetNlf(void) { return targetNlf; } + +}; +} + +#endif diff --git a/src/FDM/JSBSim/initialization/FGTrimAxis.cpp b/src/FDM/JSBSim/initialization/FGTrimAxis.cpp new file mode 100644 index 000000000..3cea972aa --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGTrimAxis.cpp @@ -0,0 +1,500 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTrimAxis.cpp + Author: Tony Peden + Date started: 7/3/00 + + --------- 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/3/00 TP Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef _MSC_VER +# pragma warning (disable : 4786) +#endif + +#include +#include + +#include +#include +#include "FGInitialCondition.h" +#include "FGTrimAxis.h" +#include +#include +#include + + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_TRIMAXIS; + +/*****************************************************************************/ + +FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st, + Control ctrl) { + + fdmex=fdex; + fgic=ic; + state=st; + control=ctrl; + max_iterations=10; + control_value=0; + its_to_stable_value=0; + total_iterations=0; + total_stability_iterations=0; + state_convert=1.0; + control_convert=1.0; + state_value=0; + state_target=0; + switch(state) { + case tUdot: tolerance = DEFAULT_TOLERANCE; break; + case tVdot: tolerance = DEFAULT_TOLERANCE; break; + case tWdot: tolerance = DEFAULT_TOLERANCE; break; + case tQdot: tolerance = DEFAULT_TOLERANCE / 10; break; + case tPdot: tolerance = DEFAULT_TOLERANCE / 10; break; + case tRdot: tolerance = DEFAULT_TOLERANCE / 10; break; + case tHmgt: tolerance = 0.01; break; + case tNlf: state_target=1.0; tolerance = 1E-5; break; + case tAll: break; + } + + solver_eps=tolerance; + switch(control) { + case tThrottle: + control_min=0; + control_max=1; + control_value=0.5; + break; + case tBeta: + control_min=-30*degtorad; + control_max=30*degtorad; + control_convert=radtodeg; + break; + case tAlpha: + control_min=fdmex->GetAerodynamics()->GetAlphaCLMin(); + control_max=fdmex->GetAerodynamics()->GetAlphaCLMax(); + if(control_max <= control_min) { + control_max=20*degtorad; + control_min=-5*degtorad; + } + control_value= (control_min+control_max)/2; + control_convert=radtodeg; + solver_eps=tolerance/100; + break; + case tPitchTrim: + case tElevator: + case tRollTrim: + case tAileron: + case tYawTrim: + case tRudder: + control_min=-1; + control_max=1; + state_convert=radtodeg; + solver_eps=tolerance/100; + break; + case tAltAGL: + control_min=0; + control_max=30; + control_value=fdmex->GetPropagate()->GetDistanceAGL(); + solver_eps=tolerance/100; + break; + case tTheta: + control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad; + state_convert=radtodeg; + break; + case tPhi: + control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad; + state_convert=radtodeg; + control_convert=radtodeg; + break; + case tGamma: + solver_eps=tolerance/100; + control_min=-80*degtorad; + control_max=80*degtorad; + control_convert=radtodeg; + break; + case tHeading: + control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad; + control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad; + state_convert=radtodeg; + break; + } + + + Debug(0); +} + +/*****************************************************************************/ + +FGTrimAxis::~FGTrimAxis(void) +{ + Debug(1); +} + +/*****************************************************************************/ + +void FGTrimAxis::getState(void) { + switch(state) { + case tUdot: state_value=fdmex->GetPropagate()->GetUVWdot(1)-state_target; break; + case tVdot: state_value=fdmex->GetPropagate()->GetUVWdot(2)-state_target; break; + case tWdot: state_value=fdmex->GetPropagate()->GetUVWdot(3)-state_target; break; + case tQdot: state_value=fdmex->GetPropagate()->GetPQRdot(2)-state_target;break; + case tPdot: state_value=fdmex->GetPropagate()->GetPQRdot(1)-state_target; break; + case tRdot: state_value=fdmex->GetPropagate()->GetPQRdot(3)-state_target; break; + case tHmgt: state_value=computeHmgt()-state_target; break; + case tNlf: state_value=fdmex->GetAircraft()->GetNlf()-state_target; break; + case tAll: break; + } +} + +/*****************************************************************************/ + +//States are not settable + +void FGTrimAxis::getControl(void) { + switch(control) { + case tThrottle: control_value=fdmex->GetFCS()->GetThrottleCmd(0); break; + case tBeta: control_value=fdmex->GetAuxiliary()->Getalpha(); break; + case tAlpha: control_value=fdmex->GetAuxiliary()->Getbeta(); break; + case tPitchTrim: control_value=fdmex->GetFCS() -> GetPitchTrimCmd(); break; + case tElevator: control_value=fdmex->GetFCS() -> GetDeCmd(); break; + case tRollTrim: + case tAileron: control_value=fdmex->GetFCS() -> GetDaCmd(); break; + case tYawTrim: + case tRudder: control_value=fdmex->GetFCS() -> GetDrCmd(); break; + case tAltAGL: control_value=fdmex->GetPropagate()->GetDistanceAGL();break; + case tTheta: control_value=fdmex->GetPropagate()->GetEuler(eTht); break; + case tPhi: control_value=fdmex->GetPropagate()->GetEuler(ePhi); break; + case tGamma: control_value=fdmex->GetAuxiliary()->GetGamma();break; + case tHeading: control_value=fdmex->GetPropagate()->GetEuler(ePsi); break; + } +} + +/*****************************************************************************/ + +double FGTrimAxis::computeHmgt(void) { + double diff; + + diff = fdmex->GetPropagate()->GetEuler(ePsi) - + fdmex->GetAuxiliary()->GetGroundTrack(); + + if( diff < -M_PI ) { + return (diff + 2*M_PI); + } else if( diff > M_PI ) { + return (diff - 2*M_PI); + } else { + return diff; + } + +} + +/*****************************************************************************/ + + +void FGTrimAxis::setControl(void) { + switch(control) { + case tThrottle: setThrottlesPct(); break; + case tBeta: fgic->SetBetaRadIC(control_value); break; + case tAlpha: fgic->SetAlphaRadIC(control_value); break; + case tPitchTrim: fdmex->GetFCS()->SetPitchTrimCmd(control_value); break; + case tElevator: fdmex->GetFCS()->SetDeCmd(control_value); break; + case tRollTrim: + case tAileron: fdmex->GetFCS()->SetDaCmd(control_value); break; + case tYawTrim: + case tRudder: fdmex->GetFCS()->SetDrCmd(control_value); break; + case tAltAGL: fgic->SetAltitudeAGLFtIC(control_value); break; + case tTheta: fgic->SetPitchAngleRadIC(control_value); break; + case tPhi: fgic->SetRollAngleRadIC(control_value); break; + case tGamma: fgic->SetFlightPathAngleRadIC(control_value); break; + case tHeading: fgic->SetTrueHeadingRadIC(control_value); break; + } +} + + + + + +/*****************************************************************************/ + +// the aircraft center of rotation is no longer the cg once the gear +// contact the ground so the altitude needs to be changed when pitch +// and roll angle are adjusted. Instead of attempting to calculate the +// new center of rotation, pick a gear unit as a reference and use its +// location vector to calculate the new height change. i.e. new altitude = +// earth z component of that vector (which is in body axes ) +void FGTrimAxis::SetThetaOnGround(double ff) { + int center,i,ref; + + // favor an off-center unit so that the same one can be used for both + // pitch and roll. An on-center unit is used (for pitch)if that's all + // that's in contact with the ground. + i=0; ref=-1; center=-1; + while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { + if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) { + if(fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01) + ref=i; + else + center=i; + } + i++; + } + if((ref < 0) && (center >= 0)) { + ref=center; + } + cout << "SetThetaOnGround ref gear: " << ref << endl; + if(ref >= 0) { + double sp = fdmex->GetPropagate()->GetSinEuler(ePhi); + double cp = fdmex->GetPropagate()->GetCosEuler(ePhi); + double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); + double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); + double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); + double hagl = -1*lx*sin(ff) + + ly*sp*cos(ff) + + lz*cp*cos(ff); + + fgic->SetAltitudeAGLFtIC(hagl); + cout << "SetThetaOnGround new alt: " << hagl << endl; + } + fgic->SetPitchAngleRadIC(ff); + cout << "SetThetaOnGround new theta: " << ff << endl; +} + +/*****************************************************************************/ + +bool FGTrimAxis::initTheta(void) { + int i,N; + int iForward = 0; + int iAft = 1; + double zAft,zForward,zDiff,theta; + double xAft,xForward,xDiff; + bool level; + double saveAlt; + + saveAlt=fgic->GetAltitudeAGLFtIC(); + fgic->SetAltitudeAGLFtIC(100); + + + N=fdmex->GetGroundReactions()->GetNumGearUnits(); + + //find the first wheel unit forward of the cg + //the list is short so a simple linear search is fine + for( i=0; iGetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) { + iForward=i; + break; + } + } + //now find the first wheel unit aft of the cg + for( i=0; iGetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) { + iAft=i; + break; + } + } + + // now adjust theta till the wheels are the same distance from the ground + xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetBodyLocation(1); + xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetBodyLocation(1); + xDiff = xForward - xAft; + zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); + zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); + zDiff = zForward - zAft; + level=false; + theta=fgic->GetPitchAngleDegIC(); + while(!level && (i < 100)) { + theta+=radtodeg*atan(zDiff/xDiff); + fgic->SetPitchAngleDegIC(theta); + fdmex->RunIC(); + zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3); + zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3); + zDiff = zForward - zAft; + //cout << endl << theta << " " << zDiff << endl; + //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl; + //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl; + if(fabs(zDiff ) < 0.1) + level=true; + i++; + } + //cout << i << endl; + if (debug_lvl > 0) { + cout << " Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*radtodeg << endl; + cout << " Used gear unit " << iAft << " as aft and " << iForward << " as forward" << endl; + } + control_min=(theta+5)*degtorad; + control_max=(theta-5)*degtorad; + fgic->SetAltitudeAGLFtIC(saveAlt); + if(i < 100) + return true; + else + return false; +} + +/*****************************************************************************/ + +void FGTrimAxis::SetPhiOnGround(double ff) { + int i,ref; + + i=0; ref=-1; + //must have an off-center unit here + while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) { + if ( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) && + (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)) + ref=i; + i++; + } + if (ref >= 0) { + double st = fdmex->GetPropagate()->GetSinEuler(eTht); + double ct = fdmex->GetPropagate()->GetCosEuler(eTht); + double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1); + double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2); + double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3); + double hagl = -1*lx*st + + ly*sin(ff)*ct + + lz*cos(ff)*ct; + + fgic->SetAltitudeAGLFtIC(hagl); + } + fgic->SetRollAngleRadIC(ff); + +} + +/*****************************************************************************/ + +void FGTrimAxis::Run(void) { + + double last_state_value; + int i; + setControl(); + //cout << "FGTrimAxis::Run: " << control_value << endl; + i=0; + bool stable=false; + while(!stable) { + i++; + last_state_value=state_value; + fdmex->RunIC(); + getState(); + if(i > 1) { + if((fabs(last_state_value - state_value) < tolerance) || (i >= 100) ) + stable=true; + } + } + + its_to_stable_value=i; + total_stability_iterations+=its_to_stable_value; + total_iterations++; +} + +/*****************************************************************************/ + +void FGTrimAxis::setThrottlesPct(void) { + double tMin,tMax; + for(unsigned i=0;iGetPropulsion()->GetNumEngines();i++) { + tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin(); + tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax(); + //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value; + fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin)); + //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl; + fdmex->RunIC(); //apply throttle change + fdmex->GetPropulsion()->GetSteadyState(); + } +} + +/*****************************************************************************/ + +void FGTrimAxis::AxisReport(void) { + + char out[80]; + + sprintf(out," %20s: %6.2f %5s: %9.2e Tolerance: %3.0e", + GetControlName().c_str(), GetControl()*control_convert, + GetStateName().c_str(), GetState()+state_target, GetTolerance()); + cout << out; + + if( fabs(GetState()+state_target) < fabs(GetTolerance()) ) + cout << " Passed" << endl; + else + cout << " Failed" << endl; +} + +/*****************************************************************************/ + +double FGTrimAxis::GetAvgStability( void ) { + if(total_iterations > 0) { + return double(total_stability_iterations)/double(total_iterations); + } + return 0; +} + +/*****************************************************************************/ +// 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 FGTrimAxis::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: FGTrimAxis" << endl; + if (from == 1) cout << "Destroyed: FGTrimAxis" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/initialization/FGTrimAxis.h b/src/FDM/JSBSim/initialization/FGTrimAxis.h new file mode 100644 index 000000000..e0754a03c --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGTrimAxis.h @@ -0,0 +1,186 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTrimAxis.h + Author: Tony Peden + Date started: 7/3/00 + + ------------- 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/3/00 TP Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGTRIMAXIS_H +#define FGTRIMAXIS_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include "FGFDMExec.h" +#include "FGJSBBase.h" +#include "FGInitialCondition.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_TRIMAXIS "$Id$" + +#define DEFAULT_TOLERANCE 0.001 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +const string StateNames[10]= { "all","udot","vdot","wdot","qdot","pdot","rdot", + "hmgt","nlf" + }; +const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack", + "Elevator","Ailerons","Rudder", + "Altitude AGL", "Pitch Angle", + "Roll Angle", "Flight Path Angle", + "Pitch Trim", "Roll Trim", "Yaw Trim", + "Heading" + }; + +class FGInitialCondition; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models an aircraft axis for purposes of trimming. + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +enum State { tAll,tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt,tNlf }; +enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL, + tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading }; + +class FGTrimAxis : public FGJSBBase +{ +public: + FGTrimAxis(FGFDMExec* fdmex, + FGInitialCondition *ic, + State st, + Control ctrl ); + ~FGTrimAxis(); + + void Run(void); + + double GetState(void) { getState(); return state_value; } + //Accels are not settable + inline void SetControl(double value ) { control_value=value; } + inline double GetControl(void) { return control_value; } + + inline State GetStateType(void) { return state; } + inline Control GetControlType(void) { return control; } + + inline string GetStateName(void) { return StateNames[state]; } + inline string GetControlName(void) { return ControlNames[control]; } + + inline double GetControlMin(void) { return control_min; } + inline double GetControlMax(void) { return control_max; } + + inline void SetControlToMin(void) { control_value=control_min; } + inline void SetControlToMax(void) { control_value=control_max; } + + inline void SetControlLimits(double min, double max) { + control_min=min; + control_max=max; + } + + inline void SetTolerance(double ff) { tolerance=ff;} + inline double GetTolerance(void) { return tolerance; } + + inline double GetSolverEps(void) { return solver_eps; } + inline void SetSolverEps(double ff) { solver_eps=ff; } + + inline int GetIterationLimit(void) { return max_iterations; } + inline void SetIterationLimit(int ii) { max_iterations=ii; } + + inline int GetStability(void) { return its_to_stable_value; } + inline int GetRunCount(void) { return total_stability_iterations; } + double GetAvgStability( void ); + + void SetThetaOnGround(double ff); + void SetPhiOnGround(double ff); + + inline void SetStateTarget(double target) { state_target=target; } + inline double GetStateTarget(void) { return state_target; } + + bool initTheta(void); + + void AxisReport(void); + + bool InTolerance(void) { getState(); return (fabs(state_value) <= tolerance); } + +private: + FGFDMExec *fdmex; + FGInitialCondition *fgic; + + State state; + Control control; + + double state_target; + + double state_value; + double control_value; + + double control_min; + double control_max; + + double tolerance; + + double solver_eps; + + double state_convert; + double control_convert; + + int max_iterations; + + int its_to_stable_value; + int total_stability_iterations; + int total_iterations; + + void setThrottlesPct(void); + + void getState(void); + void getControl(void); + void setControl(void); + + double computeHmgt(void); + + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/initialization/Makefile.am b/src/FDM/JSBSim/initialization/Makefile.am new file mode 100644 index 000000000..b88485a3e --- /dev/null +++ b/src/FDM/JSBSim/initialization/Makefile.am @@ -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 diff --git a/src/FDM/JSBSim/input_output/FGGroundCallback.cpp b/src/FDM/JSBSim/input_output/FGGroundCallback.cpp new file mode 100644 index 000000000..8b9a5674b --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGGroundCallback.cpp @@ -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 +#include +#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; +} + +} diff --git a/src/FDM/JSBSim/input_output/FGGroundCallback.h b/src/FDM/JSBSim/input_output/FGGroundCallback.h new file mode 100644 index 000000000..8abffcff3 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGGroundCallback.h @@ -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 +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp new file mode 100755 index 000000000..63bc58951 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp @@ -0,0 +1,321 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGPropertyManager.cpp + Author: Tony Peden + Based on work originally by David Megginson + Date: 2/2002 + + ------------- Copyright (C) 2002 ------------- + + 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. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGPropertyManager.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +using namespace std; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +*/ + +namespace JSBSim { + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPropertyManager::mkPropertyName(string name, bool lowercase) { + + /* do this two pass to avoid problems with characters getting skipped + because the index changed */ + unsigned i; + for(i=0;igetNode(path.c_str(), create); + if (node == 0 && !suppress_warning) + cout << "FGPropertyManager::GetNode() No node found for " + << path << endl; + return (FGPropertyManager*)node; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGPropertyManager* +FGPropertyManager::GetNode (const string &relpath, int index, bool create) +{ + return (FGPropertyManager*)getNode(relpath.c_str(),index,create); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +bool FGPropertyManager::HasNode (const string &path) +{ + // 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; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPropertyManager::GetName( void ) { + return string( getName() ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPropertyManager::GetFullyQualifiedName(void) { + vector stack; + stack.push_back( getDisplayName(true) ); + SGPropertyNode* tmpn=getParent(); + bool atroot=false; + while( !atroot ) { + stack.push_back( tmpn->getDisplayName(true) ); + if( !tmpn->getParent() ) + atroot=true; + else + tmpn=tmpn->getParent(); + } + + string fqname=""; + for(unsigned i=stack.size()-1;i>0;i--) { + fqname+= stack[i]; + fqname+= "/"; + } + fqname+= stack[0]; + return fqname; + +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropertyManager::GetBool (const string &name, bool defaultValue) +{ + return getBoolValue(name.c_str(), defaultValue); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +int FGPropertyManager::GetInt (const string &name, int defaultValue ) +{ + return getIntValue(name.c_str(), defaultValue); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +int FGPropertyManager::GetLong (const string &name, long defaultValue ) +{ + return getLongValue(name.c_str(), defaultValue); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +float FGPropertyManager::GetFloat (const string &name, float defaultValue ) +{ + return getFloatValue(name.c_str(), defaultValue); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGPropertyManager::GetDouble (const string &name, double defaultValue ) +{ + return getDoubleValue(name.c_str(), defaultValue); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPropertyManager::GetString (const string &name, string defaultValue ) +{ + return string(getStringValue(name.c_str(), defaultValue.c_str())); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropertyManager::SetBool (const string &name, bool val) +{ + return setBoolValue(name.c_str(), val); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropertyManager::SetInt (const string &name, int val) +{ + return setIntValue(name.c_str(), val); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropertyManager::SetLong (const string &name, long val) +{ + return setLongValue(name.c_str(), val); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropertyManager::SetFloat (const string &name, float val) +{ + return setFloatValue(name.c_str(), val); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropertyManager::SetDouble (const string &name, double val) +{ + return setDoubleValue(name.c_str(), val); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropertyManager::SetString (const string &name, const string &val) +{ + return setStringValue(name.c_str(), val.c_str()); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropertyManager::SetArchivable (const string &name, bool state ) +{ + SGPropertyNode * node = getNode(name.c_str()); + if (node == 0) + cout << + "Attempt to set archive flag for non-existant property " + << name << endl; + else + node->setAttribute(SGPropertyNode::ARCHIVE, state); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropertyManager::SetReadable (const string &name, bool state ) +{ + SGPropertyNode * node = getNode(name.c_str()); + if (node == 0) + cout << + "Attempt to set read flag for non-existant property " + << name << endl; + else + node->setAttribute(SGPropertyNode::READ, state); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropertyManager::SetWritable (const string &name, bool state ) +{ + SGPropertyNode * node = getNode(name.c_str()); + if (node == 0) + cout << + "Attempt to set write flag for non-existant property " + << name << endl; + else + node->setAttribute(SGPropertyNode::WRITE, state); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropertyManager::Untie (const string &name) +{ + if (!untie(name.c_str())) + cout << "Failed to untie property " << name << endl; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault) +{ + if (!tie(name.c_str(), SGRawValuePointer(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, int *pointer, + bool useDefault ) +{ + if (!tie(name.c_str(), SGRawValuePointer(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, long *pointer, + bool useDefault ) +{ + if (!tie(name.c_str(), SGRawValuePointer(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, float *pointer, + bool useDefault ) +{ + if (!tie(name.c_str(), SGRawValuePointer(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) +{ + if (!tie(name.c_str(), SGRawValuePointer(pointer), useDefault)) + cout << "Failed to tie property " << name << " to a pointer" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; +} + +} // namespace JSBSim diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.h b/src/FDM/JSBSim/input_output/FGPropertyManager.h new file mode 100644 index 000000000..284c74761 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGPropertyManager.h @@ -0,0 +1,605 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGPropertyManager.h + Author: Tony Peden + Based on work originally by David Megginson + Date: 2/2002 + + ------------- Copyright (C) 2002 ------------- + + 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 FGPROPERTYMANAGER_H +#define FGPROPERTYMANAGER_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#ifdef FGFS +# include +#else +# include "simgear/props/props.hxx" +#endif + +#include "FGJSBBase.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_PROPERTYMANAGER "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +using namespace std; + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Class wrapper for property handling. + @author David Megginson, Tony Peden + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGPropertyManager : public SGPropertyNode, public FGJSBBase +{ + private: + bool suppress_warning; + public: + /// Constructor + FGPropertyManager(void) {suppress_warning = false;} + /// Destructor + ~FGPropertyManager(void) {} + + /** Property-ify a name + * replaces spaces with '-' and, optionally, makes name all lower case + * @param name string to change + * @param lowercase true to change all upper case chars to lower + * NOTE: this function changes its argument and thus relies + * on pass by value + */ + string mkPropertyName(string name, bool lowercase); + + /** + * Get a property node. + * + * @param path The path of the node, relative to root. + * @param create true to create the node if it doesn't exist. + * @return The node, or 0 if none exists and none was created. + */ + FGPropertyManager* + GetNode (const string &path, bool create = false); + + FGPropertyManager* + GetNode (const string &relpath, int index, bool create = false); + + /** + * Test whether a given node exists. + * + * @param path The path of the node, relative to root. + * @return true if the node exists, false otherwise. + */ + bool HasNode (const string &path); + + /** + * Get the name of a node + */ + string GetName( void ); + + /** + * Get the fully qualified name of a node + * This function is very slow, so is probably useful for debugging only. + */ + string GetFullyQualifiedName(void); + + /** + * Get a bool value for a property. + * + * This method is convenient but inefficient. It should be used + * infrequently (i.e. for initializing, loading, saving, etc.), + * not in the main loop. If you need to get a value frequently, + * it is better to look up the node itself using GetNode and then + * use the node's getBoolValue() method, to avoid the lookup overhead. + * + * @param name The property name. + * @param defaultValue The default value to return if the property + * does not exist. + * @return The property's value as a bool, or the default value provided. + */ + bool GetBool (const string &name, bool defaultValue = false); + + + /** + * Get an int value for a property. + * + * This method is convenient but inefficient. It should be used + * infrequently (i.e. for initializing, loading, saving, etc.), + * not in the main loop. If you need to get a value frequently, + * it is better to look up the node itself using GetNode and then + * use the node's getIntValue() method, to avoid the lookup overhead. + * + * @param name The property name. + * @param defaultValue The default value to return if the property + * does not exist. + * @return The property's value as an int, or the default value provided. + */ + int GetInt (const string &name, int defaultValue = 0); + + + /** + * Get a long value for a property. + * + * This method is convenient but inefficient. It should be used + * infrequently (i.e. for initializing, loading, saving, etc.), + * not in the main loop. If you need to get a value frequently, + * it is better to look up the node itself using GetNode and then + * use the node's getLongValue() method, to avoid the lookup overhead. + * + * @param name The property name. + * @param defaultValue The default value to return if the property + * does not exist. + * @return The property's value as a long, or the default value provided. + */ + int GetLong (const string &name, long defaultValue = 0L); + + + /** + * Get a float value for a property. + * + * This method is convenient but inefficient. It should be used + * infrequently (i.e. for initializing, loading, saving, etc.), + * not in the main loop. If you need to get a value frequently, + * it is better to look up the node itself using GetNode and then + * use the node's getFloatValue() method, to avoid the lookup overhead. + * + * @param name The property name. + * @param defaultValue The default value to return if the property + * does not exist. + * @return The property's value as a float, or the default value provided. + */ + float GetFloat (const string &name, float defaultValue = 0.0); + + + /** + * Get a double value for a property. + * + * This method is convenient but inefficient. It should be used + * infrequently (i.e. for initializing, loading, saving, etc.), + * not in the main loop. If you need to get a value frequently, + * it is better to look up the node itself using GetNode and then + * use the node's getDoubleValue() method, to avoid the lookup overhead. + * + * @param name The property name. + * @param defaultValue The default value to return if the property + * does not exist. + * @return The property's value as a double, or the default value provided. + */ + double GetDouble (const string &name, double defaultValue = 0.0); + + + /** + * Get a string value for a property. + * + * This method is convenient but inefficient. It should be used + * infrequently (i.e. for initializing, loading, saving, etc.), + * not in the main loop. If you need to get a value frequently, + * it is better to look up the node itself using GetNode and then + * use the node's getStringValue() method, to avoid the lookup overhead. + * + * @param name The property name. + * @param defaultValue The default value to return if the property + * does not exist. + * @return The property's value as a string, or the default value provided. + */ + string GetString (const string &name, string defaultValue = ""); + + + /** + * Set a bool value for a property. + * + * Assign a bool value to a property. If the property does not + * yet exist, it will be created and its type will be set to + * BOOL; if it has a type of UNKNOWN, the type will also be set to + * BOOL; otherwise, the bool value will be converted to the property's + * type. + * + * @param name The property name. + * @param val The new value for the property. + * @return true if the assignment succeeded, false otherwise. + */ + bool SetBool (const string &name, bool val); + + + /** + * Set an int value for a property. + * + * Assign an int value to a property. If the property does not + * yet exist, it will be created and its type will be set to + * INT; if it has a type of UNKNOWN, the type will also be set to + * INT; otherwise, the bool value will be converted to the property's + * type. + * + * @param name The property name. + * @param val The new value for the property. + * @return true if the assignment succeeded, false otherwise. + */ + bool SetInt (const string &name, int val); + + + /** + * Set a long value for a property. + * + * Assign a long value to a property. If the property does not + * yet exist, it will be created and its type will be set to + * LONG; if it has a type of UNKNOWN, the type will also be set to + * LONG; otherwise, the bool value will be converted to the property's + * type. + * + * @param name The property name. + * @param val The new value for the property. + * @return true if the assignment succeeded, false otherwise. + */ + bool SetLong (const string &name, long val); + + + /** + * Set a float value for a property. + * + * Assign a float value to a property. If the property does not + * yet exist, it will be created and its type will be set to + * FLOAT; if it has a type of UNKNOWN, the type will also be set to + * FLOAT; otherwise, the bool value will be converted to the property's + * type. + * + * @param name The property name. + * @param val The new value for the property. + * @return true if the assignment succeeded, false otherwise. + */ + bool SetFloat (const string &name, float val); + + + /** + * Set a double value for a property. + * + * Assign a double value to a property. If the property does not + * yet exist, it will be created and its type will be set to + * DOUBLE; if it has a type of UNKNOWN, the type will also be set to + * DOUBLE; otherwise, the double value will be converted to the property's + * type. + * + * @param name The property name. + * @param val The new value for the property. + * @return true if the assignment succeeded, false otherwise. + */ + bool SetDouble (const string &name, double val); + + + /** + * Set a string value for a property. + * + * Assign a string value to a property. If the property does not + * yet exist, it will be created and its type will be set to + * STRING; if it has a type of UNKNOWN, the type will also be set to + * STRING; otherwise, the string value will be converted to the property's + * type. + * + * @param name The property name. + * @param val The new value for the property. + * @return true if the assignment succeeded, false otherwise. + */ + bool SetString (const string &name, const string &val); + + + //////////////////////////////////////////////////////////////////////// + // Convenience functions for setting property attributes. + //////////////////////////////////////////////////////////////////////// + + + /** + * Set the state of the archive attribute for a property. + * + * If the archive attribute is true, the property will be written + * when a flight is saved; if it is false, the property will be + * skipped. + * + * A warning message will be printed if the property does not exist. + * + * @param name The property name. + * @param state The state of the archive attribute (defaults to true). + */ + void SetArchivable (const string &name, bool state = true); + + + /** + * Set the state of the read attribute for a property. + * + * If the read attribute is true, the property value will be readable; + * if it is false, the property value will always be the default value + * for its type. + * + * A warning message will be printed if the property does not exist. + * + * @param name The property name. + * @param state The state of the read attribute (defaults to true). + */ + void SetReadable (const string &name, bool state = true); + + + /** + * Set the state of the write attribute for a property. + * + * If the write attribute is true, the property value may be modified + * (depending on how it is tied); if the write attribute is false, the + * property value may not be modified. + * + * A warning message will be printed if the property does not exist. + * + * @param name The property name. + * @param state The state of the write attribute (defaults to true). + */ + void SetWritable (const string &name, bool state = true); + + + //////////////////////////////////////////////////////////////////////// + // Convenience functions for tying properties, with logging. + //////////////////////////////////////////////////////////////////////// + + + /** + * Untie a property from an external data source. + * + * Classes should use this function to release control of any + * properties they are managing. + */ + void Untie (const string &name); + + + // Templates cause ambiguity here + + /** + * Tie a property to an external bool variable. + * + * The property's value will automatically mirror the variable's + * value, and vice-versa, until the property is untied. + * + * @param name The property name to tie (full path). + * @param pointer A pointer to the variable. + * @param useDefault true if any existing property value should be + * copied to the variable; false if the variable should not + * be modified; defaults to true. + */ + void + Tie (const string &name, bool *pointer, bool useDefault = true); + + + /** + * Tie a property to an external int variable. + * + * The property's value will automatically mirror the variable's + * value, and vice-versa, until the property is untied. + * + * @param name The property name to tie (full path). + * @param pointer A pointer to the variable. + * @param useDefault true if any existing property value should be + * copied to the variable; false if the variable should not + * be modified; defaults to true. + */ + void + Tie (const string &name, int *pointer, bool useDefault = true); + + + /** + * Tie a property to an external long variable. + * + * The property's value will automatically mirror the variable's + * value, and vice-versa, until the property is untied. + * + * @param name The property name to tie (full path). + * @param pointer A pointer to the variable. + * @param useDefault true if any existing property value should be + * copied to the variable; false if the variable should not + * be modified; defaults to true. + */ + void + Tie (const string &name, long *pointer, bool useDefault = true); + + + /** + * Tie a property to an external float variable. + * + * The property's value will automatically mirror the variable's + * value, and vice-versa, until the property is untied. + * + * @param name The property name to tie (full path). + * @param pointer A pointer to the variable. + * @param useDefault true if any existing property value should be + * copied to the variable; false if the variable should not + * be modified; defaults to true. + */ + void + Tie (const string &name, float *pointer, bool useDefault = true); + + /** + * Tie a property to an external double variable. + * + * The property's value will automatically mirror the variable's + * value, and vice-versa, until the property is untied. + * + * @param name The property name to tie (full path). + * @param pointer A pointer to the variable. + * @param useDefault true if any existing property value should be + * copied to the variable; false if the variable should not + * be modified; defaults to true. + */ + void + Tie (const string &name, double *pointer, bool useDefault = true); + +//============================================================================ +// +// All of the following functions *must* be inlined, otherwise linker +// errors will result +// +//============================================================================ + + /* template void + Tie (const string &name, V (*getter)(), void (*setter)(V) = 0, + bool useDefault = true); + + template void + Tie (const string &name, int index, V (*getter)(int), + void (*setter)(int, V) = 0, bool useDefault = true); + + template void + Tie (const string &name, T * obj, V (T::*getter)() const, + void (T::*setter)(V) = 0, bool useDefault = true); + + template void + Tie (const string &name, T * obj, int index, + V (T::*getter)(int) const, void (T::*setter)(int, V) = 0, + bool useDefault = true); */ + + /** + * Tie a property to a pair of simple functions. + * + * Every time the property value is queried, the getter (if any) will + * be invoked; every time the property value is modified, the setter + * (if any) will be invoked. The getter can be 0 to make the property + * unreadable, and the setter can be 0 to make the property + * unmodifiable. + * + * @param name The property name to tie (full path). + * @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 + * discarded; defaults to true. + */ + + template inline void + Tie (const string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true) + { + if (!tie(name.c_str(), SGRawValueFunctions(getter, setter), useDefault)) + cout << "Failed to tie property " << name << " to functions" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; + } + + + /** + * Tie a property to a pair of indexed functions. + * + * Every time the property value is queried, the getter (if any) will + * be invoked with the index provided; every time the property value + * is modified, the setter (if any) will be invoked with the index + * provided. The getter can be 0 to make the property unreadable, and + * the setter can be 0 to make the property unmodifiable. + * + * @param name The property name to tie (full path). + * @param index The integer argument to pass to the getter and + * setter functions. + * @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 there be one; false if the old value should be + * discarded; defaults to true. + */ + template 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(index, getter, setter), useDefault)) + cout << "Failed to tie property " << name << " to indexed functions" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; + } + + + /** + * Tie a property to a pair of object methods. + * + * Every time the property value is queried, the getter (if any) will + * be invoked; every time the property value is modified, the setter + * (if any) will be invoked. The getter can be 0 to make the property + * unreadable, and the setter can be 0 to make the property + * unmodifiable. + * + * @param name The property name to tie (full path). + * @param obj The object whose methods should be invoked. + * @param getter The object's getter method, or 0 if the value is + * unreadable. + * @param setter The object's setter method, 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 + * discarded; defaults to true. + */ + template inline void + Tie (const string &name, T * obj, V (T::*getter)() const, + void (T::*setter)(V) = 0, bool useDefault = true) + { + if (!tie(name.c_str(), SGRawValueMethods(*obj, getter, setter), useDefault)) + cout << "Failed to tie property " << name << " to object methods" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; + } + + /** + * Tie a property to a pair of indexed object methods. + * + * Every time the property value is queried, the getter (if any) will + * be invoked with the index provided; every time the property value + * is modified, the setter (if any) will be invoked with the index + * provided. The getter can be 0 to make the property unreadable, and + * the setter can be 0 to make the property unmodifiable. + * + * @param name The property name to tie (full path). + * @param obj The object whose methods should be invoked. + * @param index The integer argument to pass to the getter and + * setter methods. + * @param getter The getter method, or 0 if the value is unreadable. + * @param setter The setter method, 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 + * discarded; defaults to true. + */ + template inline void + 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(*obj, index, getter, setter), useDefault)) + cout << "Failed to tie property " << name << " to indexed object methods" << endl; + else if (debug_lvl & 0x20) + cout << name << endl; + } +}; +} +#endif // FGPROPERTYMANAGER_H + diff --git a/src/FDM/JSBSim/input_output/FGScript.cpp b/src/FDM/JSBSim/input_output/FGScript.cpp new file mode 100755 index 000000000..83e87f752 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGScript.cpp @@ -0,0 +1,422 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGScript.cpp + Author: Jon S. Berndt + Date started: 12/21/01 + Purpose: Loads and runs JSBSim scripts. + + ------------- 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 wraps up the simulation scripting routines. + +HISTORY +-------------------------------------------------------------------------------- +12/21/01 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +COMMENTS, REFERENCES, and NOTES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# include STL_IOSTREAM +# include STL_ITERATOR +#else +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# else +# include +# endif +# include +#endif + +#include "FGScript.h" +#include "FGXMLParse.h" +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_FGSCRIPT; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +GLOBAL DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +// Constructor + +FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex) +{ + State = FDMExec->GetState(); + PropertyManager=FDMExec->GetPropertyManager(); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGScript::~FGScript() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGScript::LoadScript( string script ) +{ + 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, value = 0.0; + FGXMLParse script_file_parser; + struct condition *newCondition; + ifstream script_file(script.c_str()); + + if ( !script_file ) return false; + + 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; + return false; + } + + // read aircraft and initialization files + + element = document->FindElement("use"); + if (element) { + aircraft = element->GetAttributeValue("aircraft"); + if (!aircraft.empty()) { + result = FDMExec->LoadModel(aircraft); + if (!result) return false; + } else { + 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; + } + + 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); + } + + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGScript::RunScript(void) +{ + vector ::iterator iC = Conditions.begin(); + bool truth = false; + bool WholeTruth = false; + unsigned i; + + double currentTime = State->Getsim_time(); + double newSetValue = 0; + + if (currentTime > EndTime) return false; + + while (iC < Conditions.end()) { + // determine whether the set of conditional tests for this condition equate + // to true + for (i=0; iTestValue.size(); i++) { + if (iC->Comparison[i] == "lt") + truth = iC->TestParam[i]->getDoubleValue() < iC->TestValue[i]; + else if (iC->Comparison[i] == "le") + truth = iC->TestParam[i]->getDoubleValue() <= iC->TestValue[i]; + else if (iC->Comparison[i] == "eq") + truth = iC->TestParam[i]->getDoubleValue() == iC->TestValue[i]; + else if (iC->Comparison[i] == "ge") + truth = iC->TestParam[i]->getDoubleValue() >= iC->TestValue[i]; + else if (iC->Comparison[i] == "gt") + truth = iC->TestParam[i]->getDoubleValue() > iC->TestValue[i]; + else if (iC->Comparison[i] == "ne") + truth = iC->TestParam[i]->getDoubleValue() != iC->TestValue[i]; + else + cerr << "Bad comparison" << endl; + + if (i == 0) WholeTruth = truth; + else WholeTruth = WholeTruth && truth; + + if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false; + } + + // if the conditions are true, do the setting of the desired parameters + + if (WholeTruth) { + for (i=0; iSetValue.size(); i++) { + if ( ! iC->Triggered[i]) { + iC->OriginalValue[i] = iC->SetParam[i]->getDoubleValue(); + switch (iC->Type[i]) { + case FG_VALUE: + iC->newValue[i] = iC->SetValue[i]; + break; + case FG_DELTA: + iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i]; + break; + case FG_BOOL: + iC->newValue[i] = iC->SetValue[i]; + break; + default: + cerr << "Invalid Type specified" << endl; + break; + } + iC->Triggered[i] = true; + 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: + 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( -time_span/iC->TC[i] )) * value_span + iC->OriginalValue[i]; + break; + default: + cerr << "Invalid Action specified" << endl; + break; + } + iC->SetParam[i]->setDoubleValue(newSetValue); + } + } + iC++; + } + 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 FGScript::Debug(int from) +{ + unsigned int i; + + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + } else if (from == 3) { + } else if (from == 4) { // print out script data + vector ::iterator iterConditions = Conditions.begin(); + int count=0; + + cout << "\n Script goes from " << StartTime << " to " << EndTime + << " with dt = " << State->Getdt() << endl << endl; + + while (iterConditions < Conditions.end()) { + cout << " Condition: " << count++ << endl; + cout << " if ("; + + for (i=0; iTestValue.size(); i++) { + if (i>0) cout << " and" << endl << " "; + cout << "(" << iterConditions->TestParam[i]->GetName() + << " " << iterConditions->Comparison[i] << " " + << iterConditions->TestValue[i] << ")"; + } + cout << ") then {"; + + for (i=0; iSetValue.size(); i++) { + cout << endl << " set " << iterConditions->SetParam[i]->GetName() + << " to " << iterConditions->SetValue[i]; + + switch (iterConditions->Type[i]) { + case FG_VALUE: + cout << " (constant"; + break; + case FG_DELTA: + cout << " (delta"; + break; + case FG_BOOL: + cout << " (boolean"; + break; + default: + cout << " (unspecified type"; + } + + switch (iterConditions->Action[i]) { + case FG_RAMP: + cout << " via ramp"; + break; + case FG_STEP: + cout << " via step"; + break; + case FG_EXP: + cout << " via exponential approach"; + break; + default: + cout << " via unspecified action"; + } + + if (!iterConditions->Persistent[i]) cout << endl + << " once"; + else cout << endl + << " repeatedly"; + + if (iterConditions->Action[i] == FG_RAMP || + iterConditions->Action[i] == FG_EXP) cout << endl + << " with time constant " + << iterConditions->TC[i]; + } + cout << ")" << endl << " }" << endl << endl; + + iterConditions++; + } + + cout << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGScript" << endl; + if (from == 1) cout << "Destroyed: FGScript" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/input_output/FGScript.h b/src/FDM/JSBSim/input_output/FGScript.h new file mode 100644 index 000000000..7b4587a92 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGScript.h @@ -0,0 +1,197 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + Header: FGScript.h + Author: Jon Berndt + Date started: 12/21/2001 + + ------------- Copyright (C) 2001 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/21/01 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGSCRIPT_HEADER_H +#define FGSCRIPT_HEADER_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGJSBBase.h" +#include "FGState.h" +#include "FGFDMExec.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_FGSCRIPT "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates the JSBSim scripting capability. +

Scripting support provided via FGScript.

+ +

There is simple scripting support provided in the FGScript + class. Commands are specified using the Simple Scripting + Directives for JSBSim (SSDJ). The script file is in XML + format. A test condition (or conditions) can be set up in the + script and when the condition evaluates to true, the specified + action[s] is/are taken. A test condition can be persistent, + meaning that if a test condition evaluates to true, then passes + and evaluates to false, the condition is reset and may again be + triggered. When the set of tests evaluates to true for a given + condition, an item may be set to another value. This value might + be a boolean, a value, or a delta value, and the change from the + current value to the new value can be either via a step function, + a ramp, or an exponential approach. The speed of a ramp or + approach is specified via the time constant. Here is the format + of the script file:

+ +
<?xml version="1.0"?>
+    <runscript name="C172-01A">
+
+    <!--
+    This run is for testing C172 runs
+    -->
+
+    <use aircraft="c172">
+    <use initialize="reset00">
+
+    <run start="0.0" end="4.5" dt="0.05">
+      <when>
+        <parameter name="FG_TIME" comparison="ge" value="0.25">
+        <parameter name="FG_TIME" comparison="le" value="0.50">
+        <set name="FG_AILERON_CMD" type="FG_VALUE" value="0.25"
+        action="FG_STEP" persistent="false" tc ="0.25">
+      </when>
+      <when>
+        <parameter name="FG_TIME" comparison="ge" value="0.5">
+        <parameter name="FG_TIME" comparison="le" value="1.5">
+        <set name="FG_AILERON_CMD" type="FG_DELTA" value="0.5"
+        action="FG_EXP" persistent="false" tc ="0.5">
+      </when>
+      <when>
+        <parameter name="FG_TIME" comparison="ge" value="1.5">
+        <parameter name="FG_TIME" comparison="le" value="2.5">
+        <set name="FG_RUDDER_CMD" type="FG_DELTA" value="0.5"
+        action="FG_RAMP" persistent="false" tc ="0.5">
+      </when>
+    </run>
+
+    </runscript>
+ +

The first line must always be present. The second line + identifies this file as a script file, and gives a descriptive + name to the script file. Comments are next, delineated by the + <!-- and --> symbols. The aircraft and initialization files + to be used are specified in the "use" lines. Next, + comes the "run" section, where the conditions are + described in "when" clauses.

+ @author Jon S. Berndt + @version "$Id$" + +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGScript : public FGJSBBase +{ +public: + /// Default constructor + FGScript(FGFDMExec* exec); + + /// Default destructor + ~FGScript(); + + /** Loads a script to drive JSBSim (usually in standalone mode). + The language is the Simple Script Directives for JSBSim (SSDJ). + @param script the filename (including path name, if any) for the script. + @return true if successful */ + bool LoadScript( string script ); + + /** This function is called each pass through the executive Run() method IF + scripting is enabled. + @return false if script should exit (i.e. if time limits are violated */ + bool RunScript(void); + +private: + enum eAction { + FG_RAMP = 1, + FG_STEP = 2, + FG_EXP = 3 + }; + + enum eType { + FG_VALUE = 1, + FG_DELTA = 2, + FG_BOOL = 3 + }; + + struct condition { + vector TestParam; + vector SetParam; + vector TestValue; + vector SetValue; + vector Comparison; + vector TC; + vector Persistent; + vector Action; + vector Type; + vector Triggered; + vector newValue; + vector OriginalValue; + vector StartTime; + vector EndTime; + + condition() { + } + }; + + bool Scripted; + + string ScriptName; + double StartTime; + double EndTime; + vector Conditions; + + FGFDMExec* FDMExec; + FGState* State; + FGPropertyManager* PropertyManager; + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.cpp b/src/FDM/JSBSim/input_output/FGXMLElement.cpp new file mode 100755 index 000000000..8b21b0131 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGXMLElement.cpp @@ -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 +# endif +# ifdef SG_HAVE_STD_INCLUDES +# include +# include +# else +# include +# include +# endif +#else +# if defined (sgi) && !defined(__GNUC__) +# include +# include +# else +# include +# include +# endif +#endif + +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 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; iGetName()) { + 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; iGetName()) { + 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; iPrint(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 diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.h b/src/FDM/JSBSim/input_output/FGXMLElement.h new file mode 100755 index 000000000..8248fb8f5 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGXMLElement.h @@ -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 +# ifdef SG_HAVE_STD_INCLUDES +# include +# include +# include +# include +# else +# include +# include +# include +# include +# endif +#else +# include +# include +# include +# include + 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 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 attributes; + vector data_lines; + vector children; + vector attribute_key; + Element *parent; + int element_index; + typedef map > tMapConvert; + tMapConvert convert; +}; + +} // namespace JSBSim + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#endif diff --git a/src/FDM/JSBSim/input_output/FGXMLParse.cpp b/src/FDM/JSBSim/input_output/FGXMLParse.cpp new file mode 100755 index 000000000..6be5bf967 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGXMLParse.cpp @@ -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 + +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; iAddAttribute(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 diff --git a/src/FDM/JSBSim/input_output/FGXMLParse.h b/src/FDM/JSBSim/input_output/FGXMLParse.h new file mode 100755 index 000000000..a86cd6e86 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGXMLParse.h @@ -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 +# include STL_STRING +#else +# include +# include + 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 diff --git a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp new file mode 100644 index 000000000..c9db20f94 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp @@ -0,0 +1,340 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGfdmSocket.cpp + Author: Jon S. Berndt + Date started: 11/08/99 + Purpose: Encapsulates a socket + Called by: FGOutput, et. al. + + ------------- 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 excapsulates a socket for simple data writing + +HISTORY +-------------------------------------------------------------------------------- +11/08/99 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGfdmSocket.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_FDMSOCKET; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGfdmSocket::FGfdmSocket(string address, int port) +{ + sckt = sckt_in = size = 0; + connected = false; + + #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 cout << "Winsock DLL not initialized ..." << endl; + #endif + + if (address.find_first_not_of("0123456789.",0) != address.npos) { + if ((host = gethostbyname(address.c_str())) == NULL) { + cout << "Could not get host net address by name..." << endl; + } + } else { + if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) { + cout << "Could not get host net address by number..." << endl; + } + } + + if (host != NULL) { + cout << "Got host net address..." << endl; + 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 (connect(sckt, (struct sockaddr*)&scktName, len) == 0) { // successful + cout << "Successfully connected to socket ..." << endl; + connected = true; + } else { // unsuccessful + cout << "Could not connect to socket ..." << endl; + } + } else { // unsuccessful + cout << "Could not create socket for FDM, error = " << errno << endl; + } + } + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +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 + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +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 = ""; + size = 0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGfdmSocket::Clear(string s) +{ + buffer = s + " "; + size = buffer.size(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGfdmSocket::Append(const char* item) +{ + if (size == 0) buffer += string(item); + else buffer += string(",") + string(item); + size++; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGfdmSocket::Append(double item) +{ + char s[25]; + + sprintf(s,"%12.7f",item); + + if (size == 0) buffer += string(s); + else buffer += string(",") + string(s); + size++; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGfdmSocket::Append(long item) +{ + char s[25]; + + sprintf(s,"%12ld",item); + + if (size == 0) buffer += string(s); + else buffer += string(",") + string(s); + size++; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGfdmSocket::Send(void) +{ + buffer += string("\n"); + if ((send(sckt,buffer.c_str(),buffer.size(),0)) <= 0) { + perror("send"); + } else { + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGfdmSocket::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: FGfdmSocket" << endl; + if (from == 1) cout << "Destroyed: FGfdmSocket" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/input_output/FGfdmSocket.h b/src/FDM/JSBSim/input_output/FGfdmSocket.h new file mode 100644 index 000000000..7eed2fe36 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGfdmSocket.h @@ -0,0 +1,133 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGfdmSocket.h + Author: Jon S. Berndt + Date started: 11/08/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/08/99 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGfdmSocket_H +#define FGfdmSocket_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#ifdef FGFS +# include +# include STL_STRING +# include STL_IOSTREAM +# include STL_FSTREAM + SG_USING_STD(cout); + SG_USING_STD(endl); +#else +# include +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# include +# else +# include +# include + using std::cout; + using std::endl; +# endif +#endif + +#include +#include "FGJSBBase.h" + +#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) + #include + #include +#else + #include + #include + #include + #include + #include + #include +#endif + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_FDMSOCKET "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a socket object. + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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; + string buffer; + bool connected; + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/input_output/Makefile.am b/src/FDM/JSBSim/input_output/Makefile.am new file mode 100644 index 000000000..6fff1d27a --- /dev/null +++ b/src/FDM/JSBSim/input_output/Makefile.am @@ -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 diff --git a/src/FDM/JSBSim/math/FGColumnVector3.cpp b/src/FDM/JSBSim/math/FGColumnVector3.cpp new file mode 100644 index 000000000..0b0fa0351 --- /dev/null +++ b/src/FDM/JSBSim/math/FGColumnVector3.cpp @@ -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 + +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 diff --git a/src/FDM/JSBSim/math/FGColumnVector3.h b/src/FDM/JSBSim/math/FGColumnVector3.h new file mode 100644 index 000000000..e0d01bf7a --- /dev/null +++ b/src/FDM/JSBSim/math/FGColumnVector3.h @@ -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 +#ifdef FGFS +# include +# include +# 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 +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# include +# include +# else +# include +# include +# if defined(sgi) && !defined(__GNUC__) +# include +# else +# include +# 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 diff --git a/src/FDM/JSBSim/math/FGFunction.cpp b/src/FDM/JSBSim/math/FGFunction.cpp new file mode 100755 index 000000000..6a60e625e --- /dev/null +++ b/src/FDM/JSBSim/math/FGFunction.cpp @@ -0,0 +1,257 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Module: FGFunction.cpp +Author: Jon Berndt +Date started: 8/25/2004 +Purpose: Stores various parameter types for functions + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#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;iGetValue(); + break; + case eDifference: + for (i=1;iGetValue(); + break; + case eSum: + for (i=1;iGetValue(); + 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; + } + } +} + +} diff --git a/src/FDM/JSBSim/math/FGFunction.h b/src/FDM/JSBSim/math/FGFunction.h new file mode 100755 index 000000000..3c4fddf73 --- /dev/null +++ b/src/FDM/JSBSim/math/FGFunction.h @@ -0,0 +1,75 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Header: FGFunction.h +Author: Jon Berndt +Date started: August 25 2004 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGFUNCTION_H +#define FGFUNCTION_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include "FGParameter.h" +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 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 diff --git a/src/FDM/JSBSim/math/FGLocation.cpp b/src/FDM/JSBSim/math/FGLocation.cpp new file mode 100644 index 000000000..995c89e40 --- /dev/null +++ b/src/FDM/JSBSim/math/FGLocation.cpp @@ -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 +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# if defined(sgi) && !defined(__GNUC__) +# include +# else +# include +# endif +#endif + +#include "FGLocation.h" +#include + +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 diff --git a/src/FDM/JSBSim/math/FGLocation.h b/src/FDM/JSBSim/math/FGLocation.h new file mode 100644 index 000000000..44aa96969 --- /dev/null +++ b/src/FDM/JSBSim/math/FGLocation.h @@ -0,0 +1,444 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGLocation.h + Author: Jon S. Berndt, Mathias Froehlich + Date started: 04/04/2004 + + ------- 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. + +HISTORY +------------------------------------------------------------------------------- +04/04/2004 MF Created from code previously in the old positions class. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGLOCATION_H +#define FGLOCATION_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include "FGColumnVector3.h" +#include "FGMatrix33.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_LOCATION "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Holds an arbitrary location in the earth centered reference frame. + This coordinate frame has its center in the middle of the earth. + Its x-axis points from the center of the earth towards a location + with zero latitude and longitude on the earths surface. The y-axis + points from the center of the earth towards a location with zero + latitude and 90deg longitude on the earths surface. The z-axis + points from the earths center to the geographic north pole. + + This class provides access functions to set and get the location as + either the simple x, y and z values in ft or longitude/latitude and + the radial distance of the location from the earth center. + + It is common to associate a parent frame with a location. This + frame is usually called the local horizontal frame or simply the local + frame. This frame has its x/y plane parallel to the surface of the earth + (with the assumption of a spherical earth). The x-axis points + towards north, the y-axis points towards east and the z-axis + points to the center of the earth. + + Since this frame is determined by the location, this class also + provides the rotation matrices required to transform from the + earth centered frame to the local horizontal frame and back. There + are also conversion functions for conversion of position vectors + given in the one frame to positions in the other frame. + + The earth centered reference frame is *NOT* an inertial frame + since it rotates with the earth. + + The coordinates in the earth centered frame are the master values. + All other values are computed from these master values and are + cached as long as the location is changed by access through a + non-const member function. Values are cached to improve performance. + It is best practice to work with a natural set of master values. + Other parameters that are derived from these master values are calculated + only when needed, and IF they are needed and calculated, then they are + cached (stored and remembered) so they do not need to be re-calculated + until the master values they are derived from are themselves changed + (and become stale). + + Accuracy and round off: + + Given that we model a vehicle near the earth, the earths surface + radius is about 2*10^7, ft and that we use double values for the + representation of the location, we have an accuracy of about + 1e-16*2e7ft/1=2e-9ft left. This should be sufficient for our needs. + Note that this is the same relative accuracy we would have when we + compute directly with lon/lat/radius. For the radius value this + is clear. For the lon/lat pair this is easy to see. Take for + example KSFO located at about 37.61deg north 122.35deg west, which + corresponds to 0.65642rad north and 2.13541rad west. Both values + are of magnitude of about 1. But 1ft corresponds to about + 1/(2e7*2*pi)=7.9577e-09rad. So the left accuracy with this + representation is also about 1*1e-16/7.9577e-09=1.2566e-08 which + is of the same magnitude as the representation chosen here. + + The advantage of this representation is that it is a linear space + without singularities. The singularities are the north and south + pole and most notably the non-steady jump at -pi to pi. It is + harder to track this jump correctly especially when we need to + work with error norms and derivatives of the equations of motion + within the time-stepping code. Also, the rate of change is of the + same magnitude for all components in this representation which is + an advantage for numerical stability in implicit time-stepping too. + + Note: The latitude is a GEOCENTRIC value. FlightGear + converts latitude to a geodetic value and uses that. In order to get best + matching relative to a map, geocentric latitude must be converted to geodetic. + + @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 + + @author Mathias Froehlich + @version $Id$ + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGLocation : virtual FGJSBBase +{ +public: + /** Default constructor. */ + FGLocation() { mCacheValid = false; } + + /** Constructor to set the longitude, latitude and the distance + from the center of the earth. + @param lon longitude + @param lat GEOCENTRIC latitude + @param distance from center of earth to vehicle in feet*/ + FGLocation(double lon, double lat, double radius); + + /** Copy constructor. */ + FGLocation(const FGColumnVector3& lv) + : mECLoc(lv), mCacheValid(false) {} + + /** Copy constructor. */ + FGLocation(const FGLocation& l) + : mECLoc(l.mECLoc), mCacheValid(l.mCacheValid) { + if (!mCacheValid) + return; + + mLon = l.mLon; + mLat = l.mLat; + mRadius = l.mRadius; + + mTl2ec = l.mTl2ec; + mTec2l = l.mTec2l; + } + + /** Get the longitude. + @return the longitude in rad of the location represented with this + class instance. The returned values are in the range between + -pi <= lon <= pi. Longitude is positive east and negative west. */ + double GetLongitude() const { ComputeDerived(); return mLon; } + + /** Get the longitude. + @return the longitude in deg of the location represented with this + class instance. The returned values are in the range between + -180 <= lon <= 180. Longitude is positive east and negative west. */ + double GetLongitudeDeg() const { ComputeDerived(); return radtodeg*mLon; } + + /** Set the longitude. + @param longitude Longitude in rad to set. + Sets the longitude of the location represented with this class + instance to the value of the given argument. The value is meant + to be in rad. The latitude and the radius value are preserved + with this call with the exception of radius being equal to + zero. If the radius is previously set to zero it is changed to be + equal to 1.0 past this call. Longitude is positive east and negative west. */ + void SetLongitude(double longitude); + + /** Get the sine of Longitude. */ + double GetSinLongitude() const { ComputeDerived(); return -mTec2l(2,1); } + + /** Get the cosine of Longitude. */ + double GetCosLongitude() const { ComputeDerived(); return mTec2l(2,2); } + + /** Get the latitude. + @return the latitude in rad of the location represented with this + class instance. The returned values are in the range between + -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ + double GetLatitude() const { ComputeDerived(); return mLat; } + + /** Get the latitude. + @return the latitude in deg of the location represented with this + class instance. The returned values are in the range between + -90 <= lon <= 90. Latitude is positive north and negative south. */ + double GetLatitudeDeg() const { ComputeDerived(); return radtodeg*mLat; } + + /** Set the latitude. + @param latitude Latitude in rad to set. + Sets the latitude of the location represented with this class + instance to the value of the given argument. The value is meant + to be in rad. The longitude and the radius value are preserved + with this call with the exception of radius being equal to + zero. If the radius is previously set to zero it is changed to be + equal to 1.0 past this call. + Latitude is positive north and negative south. + The arguments should be within the bounds of -pi/2 <= lat <= pi/2. + The behavior of this function with arguments outside this range is + left as an exercise to the gentle reader ... */ + void SetLatitude(double latitude); + + /** Get the sine of Latitude. */ + double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); } + + /** Get the cosine of Latitude. */ + double GetCosLatitude() const { ComputeDerived(); return mTec2l(1,3); } + + /** Get the cosine of Latitude. */ + double GetTanLatitude() const { + ComputeDerived(); + double cLat = mTec2l(1,3); + if (cLat == 0.0) + return 0.0; + else + return -mTec2l(3,3)/cLat; + } + + /** Get the distance from the center of the earth. + @return the distance of the location represented with this class + instance to the center of the earth in ft. The radius value is + always positive. */ + double GetRadius() const { ComputeDerived(); return mRadius; } + + /** Set the distance from the center of the earth. + @param radius Radius in ft to set. + Sets the radius of the location represented with this class + instance to the value of the given argument. The value is meant + to be in ft. The latitude and longitude values are preserved + with this call with the exception of radius being equal to + zero. If the radius is previously set to zero, latitude and + longitude is set equal to zero past this call. + The argument should be positive. + The behavior of this function called with a negative argument is + left as an exercise to the gentle reader ... */ + void SetRadius(double radius); + + /** Transform matrix from local horizontal to earth centered frame. + Returns a const reference to the rotation matrix of the transform from + the local horizontal frame to the earth centered frame. */ + const FGMatrix33& GetTl2ec(void) const { ComputeDerived(); return mTl2ec; } + + /** Transform matrix from the earth centered to local horizontal frame. + Returns a const reference to the rotation matrix of the transform from + the earth centered frame to the local horizontal frame. */ + const FGMatrix33& GetTec2l(void) const { ComputeDerived(); return mTec2l; } + + /** Conversion from Local frame coordinates to a location in the + earth centered and fixed frame. + @parm lvec Vector in the local horizontal coordinate frame + @return The location in the earth centered and fixed frame */ + FGLocation LocalToLocation(const FGColumnVector3& lvec) const { + ComputeDerived(); return mTl2ec*lvec + mECLoc; + } + + /** Conversion from a location in the earth centered and fixed frame + to local horizontal frame coordinates. + @parm ecvec Vector in the earth centered and fixed frame + @return The vector in the local horizontal coordinate frame */ + FGColumnVector3 LocationToLocal(const FGColumnVector3& ecvec) const { + ComputeDerived(); return mTec2l*(ecvec - mECLoc); + } + + // For time-stepping, locations have vector properties... + + /** 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 mECLoc.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. + This function is just a shortcut for the 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) { + mCacheValid = false; return mECLoc.Entry(idx); + } + + const FGLocation& operator=(const FGLocation& l) { + mECLoc = l.mECLoc; + mCacheValid = l.mCacheValid; + if (!mCacheValid) + return *this; + + mLon = l.mLon; + mLat = l.mLat; + mRadius = l.mRadius; + + mTl2ec = l.mTl2ec; + mTec2l = l.mTec2l; + + return *this; + } + bool operator==(const FGLocation& l) const { + return mECLoc == l.mECLoc; + } + bool operator!=(const FGLocation& l) const { return ! operator==(l); } + const FGLocation& operator+=(const FGLocation &l) { + mCacheValid = false; + mECLoc += l.mECLoc; + return *this; + } + const FGLocation& operator-=(const FGLocation &l) { + mCacheValid = false; + mECLoc -= l.mECLoc; + return *this; + } + const FGLocation& operator*=(double scalar) { + mCacheValid = false; + mECLoc *= scalar; + return *this; + } + const FGLocation& operator/=(double scalar) { + return operator*=(1.0/scalar); + } + FGLocation operator+(const FGLocation& l) const { + return FGLocation(mECLoc + l.mECLoc); + } + FGLocation operator-(const FGLocation& l) const { + return FGLocation(mECLoc - l.mECLoc); + } + + FGLocation operator*(double scalar) const { + return FGLocation(scalar*mECLoc); + } + + /** Cast to a simple 3d vector */ + operator const FGColumnVector3&() const { + return mECLoc; + } + + /** Ties into the property tree. + Ties the variables represented by this class into the property tree. */ + void bind(FGPropertyManager*, const string&) const; + + /** Remove from property tree. + Unties the variables represented by this class into the property tree. */ + void unbind(FGPropertyManager*, const string&) const; + +private: + /** Computation of derived values. + This function re-computes the derived values like lat/lon and + transformation matrices. It does this unconditionally. */ + void ComputeDerivedUnconditional(void) const; + + /** Computation of derived values. + This function checks if the derived values like lat/lon and + transformation matrices are already computed. If so, it + returns. If they need to be computed this is done here. */ + void ComputeDerived(void) const { + if (!mCacheValid) + ComputeDerivedUnconditional(); + } + + /** The coordinates in the earth centered frame. This is the master copy. + The coordinate frame has its center in the middle of the earth. + Its x-axis points from the center of the earth towards a + location with zero latitude and longitude on the earths + surface. The y-axis points from the center of the earth towards a + location with zero latitude and 90deg longitude on the earths + surface. The z-axis points from the earths center to the + geographic north pole. + @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 */ + FGColumnVector3 mECLoc; + + /** The cached lon/lat/radius values. */ + mutable double mLon; + mutable double mLat; + mutable double mRadius; + + /** The cached rotation matrices from and to the associated frames. */ + mutable FGMatrix33 mTl2ec; + mutable FGMatrix33 mTec2l; + + /** A data validity flag. + This class implements caching of the derived values like the + orthogonal rotation matrices or the lon/lat/radius values. For caching we + carry a flag which signals if the values are valid or not. + The C++ keyword "mutable" tells the compiler that the data member is + allowed to change during a const member function. */ + mutable bool mCacheValid; +}; + +/** Scalar multiplication. + + @param scalar scalar value to multiply with. + @param l Vector to multiply. + + Multiply the Vector with a scalar value. */ +inline FGLocation operator*(double scalar, const FGLocation& l) +{ + return l.operator*(scalar); +} + +} // namespace JSBSim + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/math/FGMatrix33.cpp b/src/FDM/JSBSim/math/FGMatrix33.cpp new file mode 100644 index 000000000..0d42129f1 --- /dev/null +++ b/src/FDM/JSBSim/math/FGMatrix33.cpp @@ -0,0 +1,391 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Module: FGMatrix33.cpp +Author: Tony Peden, Jon Berndt, Mathias Frolich +Date started: 1998 +Purpose: FGMatrix33 class +Called by: Various + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +HISTORY +-------------------------------------------------------------------------------- +??/??/?? TP Created +03/16/2000 JSB Added exception throwing + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGMatrix33.h" +#include "FGColumnVector3.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_MATRIX33; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33::FGMatrix33(void) +{ + data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = + data[6] = data[7] = data[8] = 0.0; + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ostream& operator<<(ostream& os, const FGMatrix33& M) +{ + for (unsigned int i=1; i<=M.Rows(); i++) { + for (unsigned int j=1; j<=M.Cols(); j++) { + if (i == M.Rows() && j == M.Cols()) + os << M(i,j); + else + os << M(i,j) << ", "; + } + } + return os; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +istream& operator>>(istream& is, FGMatrix33& M) +{ + for (unsigned int i=1; i<=M.Rows(); i++) { + for (unsigned int j=1; j<=M.Cols(); j++) { + is >> M(i,j); + } + } + return is; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGMatrix33::Determinant(void) const { + return Entry(1,1)*Entry(2,2)*Entry(3,3) + Entry(1,2)*Entry(2,3)*Entry(3,1) + + Entry(1,3)*Entry(2,1)*Entry(3,2) - Entry(1,3)*Entry(2,2)*Entry(3,1) + - Entry(1,2)*Entry(2,1)*Entry(3,3) - Entry(2,3)*Entry(3,2)*Entry(1,1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33 FGMatrix33::Inverse(void) const { + // Compute the inverse of a general matrix using Cramers rule. + // I guess googling for cramers rule gives tons of references + // for this. :) + double rdet = 1.0/Determinant(); + + double i11 = rdet*(Entry(2,2)*Entry(3,3)-Entry(2,3)*Entry(3,2)); + double i21 = rdet*(Entry(2,3)*Entry(3,1)-Entry(2,1)*Entry(3,3)); + double i31 = rdet*(Entry(2,1)*Entry(3,2)-Entry(2,2)*Entry(3,1)); + double i12 = rdet*(Entry(1,3)*Entry(3,2)-Entry(1,2)*Entry(3,3)); + double i22 = rdet*(Entry(1,1)*Entry(3,3)-Entry(1,3)*Entry(3,1)); + double i32 = rdet*(Entry(1,2)*Entry(3,1)-Entry(1,1)*Entry(3,2)); + double i13 = rdet*(Entry(1,2)*Entry(2,3)-Entry(1,3)*Entry(2,2)); + double i23 = rdet*(Entry(1,3)*Entry(2,1)-Entry(1,1)*Entry(2,3)); + double i33 = rdet*(Entry(1,1)*Entry(2,2)-Entry(1,2)*Entry(2,1)); + + return FGMatrix33( i11, i12, i13, + i21, i22, i23, + i31, i32, i33 ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGMatrix33::InitMatrix(void) +{ + data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = + data[6] = data[7] = data[8] = 0.0; +} + +// ***************************************************************************** +// binary operators ************************************************************ +// ***************************************************************************** + +FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const +{ + return FGMatrix33( Entry(1,1) - M(1,1), + Entry(1,2) - M(1,2), + Entry(1,3) - M(1,3), + Entry(2,1) - M(2,1), + Entry(2,2) - M(2,2), + Entry(2,3) - M(2,3), + Entry(3,1) - M(3,1), + Entry(3,2) - M(3,2), + Entry(3,3) - M(3,3) ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M) +{ + data[0] -= M.data[0]; + data[1] -= M.data[1]; + data[2] -= M.data[2]; + data[3] -= M.data[3]; + data[4] -= M.data[4]; + data[5] -= M.data[5]; + data[6] -= M.data[6]; + data[7] -= M.data[7]; + data[8] -= M.data[8]; + + return *this; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const +{ + return FGMatrix33( Entry(1,1) + M(1,1), + Entry(1,2) + M(1,2), + Entry(1,3) + M(1,3), + Entry(2,1) + M(2,1), + Entry(2,2) + M(2,2), + Entry(2,3) + M(2,3), + Entry(3,1) + M(3,1), + Entry(3,2) + M(3,2), + Entry(3,3) + M(3,3) ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M) +{ + Entry(1,1) += M(1,1); + Entry(1,2) += M(1,2); + Entry(1,3) += M(1,3); + Entry(2,1) += M(2,1); + Entry(2,2) += M(2,2); + Entry(2,3) += M(2,3); + Entry(3,1) += M(3,1); + Entry(3,2) += M(3,2); + Entry(3,3) += M(3,3); + + return *this; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33 FGMatrix33::operator*(const double scalar) const +{ + return FGMatrix33( scalar * Entry(1,1), + scalar * Entry(1,2), + scalar * Entry(1,3), + scalar * Entry(2,1), + scalar * Entry(2,2), + scalar * Entry(2,3), + scalar * Entry(3,1), + scalar * Entry(3,2), + scalar * Entry(3,3) ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33 operator*(double scalar, FGMatrix33 &M) +{ + return FGMatrix33( scalar * M(1,1), + scalar * M(1,2), + scalar * M(1,3), + scalar * M(2,1), + scalar * M(2,2), + scalar * M(2,3), + scalar * M(3,1), + scalar * M(3,2), + scalar * M(3,3) ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33& FGMatrix33::operator*=(const double scalar) +{ + Entry(1,1) *= scalar; + Entry(1,2) *= scalar; + Entry(1,3) *= scalar; + Entry(2,1) *= scalar; + Entry(2,2) *= scalar; + Entry(2,3) *= scalar; + Entry(3,1) *= scalar; + Entry(3,2) *= scalar; + Entry(3,3) *= scalar; + + return *this; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const +{ + // FIXME: Make compiler friendlier + FGMatrix33 Product; + + Product(1,1) = Entry(1,1)*M(1,1) + Entry(1,2)*M(2,1) + Entry(1,3)*M(3,1); + Product(1,2) = Entry(1,1)*M(1,2) + Entry(1,2)*M(2,2) + Entry(1,3)*M(3,2); + Product(1,3) = Entry(1,1)*M(1,3) + Entry(1,2)*M(2,3) + Entry(1,3)*M(3,3); + Product(2,1) = Entry(2,1)*M(1,1) + Entry(2,2)*M(2,1) + Entry(2,3)*M(3,1); + Product(2,2) = Entry(2,1)*M(1,2) + Entry(2,2)*M(2,2) + Entry(2,3)*M(3,2); + Product(2,3) = Entry(2,1)*M(1,3) + Entry(2,2)*M(2,3) + Entry(2,3)*M(3,3); + Product(3,1) = Entry(3,1)*M(1,1) + Entry(3,2)*M(2,1) + Entry(3,3)*M(3,1); + Product(3,2) = Entry(3,1)*M(1,2) + Entry(3,2)*M(2,2) + Entry(3,3)*M(3,2); + Product(3,3) = Entry(3,1)*M(1,3) + Entry(3,2)*M(2,3) + Entry(3,3)*M(3,3); + + return Product; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M) +{ + // FIXME: Make compiler friendlier + double a,b,c; + + a = Entry(1,1); b=Entry(1,2); c=Entry(1,3); + Entry(1,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); + Entry(1,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); + Entry(1,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); + + a = Entry(2,1); b=Entry(2,2); c=Entry(2,3); + Entry(2,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); + Entry(2,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); + Entry(2,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); + + a = Entry(3,1); b=Entry(3,2); c=Entry(3,3); + Entry(3,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); + Entry(3,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); + Entry(3,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); + + return *this; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33 FGMatrix33::operator/(const double scalar) const +{ + FGMatrix33 Quot; + + if ( scalar != 0 ) { + double tmp = 1.0/scalar; + Quot(1,1) = Entry(1,1) * tmp; + Quot(1,2) = Entry(1,2) * tmp; + Quot(1,3) = Entry(1,3) * tmp; + Quot(2,1) = Entry(2,1) * tmp; + Quot(2,2) = Entry(2,2) * tmp; + Quot(2,3) = Entry(2,3) * tmp; + Quot(3,1) = Entry(3,1) * tmp; + Quot(3,2) = Entry(3,2) * tmp; + Quot(3,3) = Entry(3,3) * tmp; + } else { + MatrixException mE; + mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"; + throw mE; + } + return Quot; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33& FGMatrix33::operator/=(const double scalar) +{ + if ( scalar != 0 ) { + double tmp = 1.0/scalar; + Entry(1,1) *= tmp; + Entry(1,2) *= tmp; + Entry(1,3) *= tmp; + Entry(2,1) *= tmp; + Entry(2,2) *= tmp; + Entry(2,3) *= tmp; + Entry(3,1) *= tmp; + Entry(3,2) *= tmp; + Entry(3,3) *= tmp; + } else { + MatrixException mE; + mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"; + throw mE; + } + return *this; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGMatrix33::T(void) +{ + for (unsigned int i=1; i<=3; i++) { + for (unsigned int j=i+1; j<=3; j++) { + double tmp = Entry(i,j); + Entry(i,j) = Entry(j,i); + Entry(j,i) = tmp; + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const { + double tmp1 = v(1)*Entry(1,1); + double tmp2 = v(1)*Entry(2,1); + double tmp3 = v(1)*Entry(3,1); + + tmp1 += v(2)*Entry(1,2); + tmp2 += v(2)*Entry(2,2); + tmp3 += v(2)*Entry(3,2); + + tmp1 += v(3)*Entry(1,3); + tmp2 += v(3)*Entry(2,3); + tmp3 += v(3)*Entry(3,3); + + return FGColumnVector3( tmp1, tmp2, tmp3 ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGMatrix33::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: FGMatrix33" << endl; + if (from == 1) cout << "Destroyed: FGMatrix33" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/math/FGMatrix33.h b/src/FDM/JSBSim/math/FGMatrix33.h new file mode 100644 index 000000000..dc68b7358 --- /dev/null +++ b/src/FDM/JSBSim/math/FGMatrix33.h @@ -0,0 +1,470 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Header: FGMatrix33.h +Author: Tony Peden, Jon Berndt, Mathias Frolich +Date started: Unknown + +HISTORY +-------------------------------------------------------------------------------- +??/??/?? TP Created +03/16/2000 JSB Added exception throwing +03/06/2004 MF Rework of the code to make it a bit compiler friendlier + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGMATRIX33_H +#define FGMATRIX33_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#ifdef FGFS +# include +# include +# 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 +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) + include + include +# include +# else +# include +# include +# if defined(sgi) && !defined(__GNUC__) +# include +# else +# include +# endif + using std::ostream; + using std::istream; + using std::cerr; + using std::cout; + using std::endl; +# endif + using std::string; +#endif + +#include "FGColumnVector3.h" +#include "FGJSBBase.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_MATRIX33 "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGColumnVector3; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Exception convenience class. + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DECLARATION: MatrixException +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class MatrixException : public FGJSBBase +{ +public: + string Message; +}; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + /** Handles matrix math operations. + @author Tony Peden, Jon Berndt, Mathias Froelich + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DECLARATION: FGMatrix33 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGMatrix33 : public FGJSBBase +{ +public: + + enum { + eRows = 3, + eColumns = 3 + }; + + /** Default initializer. + + 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. + */ + FGMatrix33(const FGMatrix33& M) { + Entry(1,1) = M.Entry(1,1); + Entry(2,1) = M.Entry(2,1); + Entry(3,1) = M.Entry(3,1); + Entry(1,2) = M.Entry(1,2); + Entry(2,2) = M.Entry(2,2); + Entry(3,2) = M.Entry(3,2); + Entry(1,3) = M.Entry(1,3); + Entry(2,3) = M.Entry(2,3); + Entry(3,3) = M.Entry(3,3); + + Debug(0); + } + + /** 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. + @param m21 value of the 2,1 Matrix element. + @param m22 value of the 2,2 Matrix element. + @param m23 value of the 2,3 Matrix element. + @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. + */ + FGMatrix33(double m11, double m12, double m13, + double m21, double m22, double m23, + double m31, double m32, double m33) { + Entry(1,1) = m11; + Entry(2,1) = m21; + Entry(3,1) = m31; + Entry(1,2) = m12; + Entry(2,2) = m22; + Entry(3,2) = m32; + Entry(1,3) = m13; + Entry(2,3) = m23; + Entry(3,3) = m33; + + Debug(0); + } + + /** 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. + */ + 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. + */ + double& operator()(unsigned int row, unsigned int col) { + return Entry(row, col); + } + + /** Read access the entries of the matrix. + 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. + */ + double Entry(unsigned int row, unsigned int col) const { + return data[(col-1)*eRows+row-1]; + } + + /** Write access the entries of the matrix. + 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. + */ + 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. + */ + unsigned int Rows(void) const { return eRows; } + + /** Number of cloumns 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. + */ + FGMatrix33 Transposed(void) const { + return FGMatrix33( Entry(1,1), Entry(2,1), Entry(3,1), + Entry(1,2), Entry(2,2), Entry(3,2), + Entry(1,3), Entry(2,3), Entry(3,3) ); + } + + /** Transposes this matrix. + This function only transposes this matrix. Nothing is returned. + */ + void T(void); + +/** Initialize the matrix. + This function initializes a matrix to all 0.0. + */ + void InitMatrix(void); + +/** Initialize the matrix. + 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) { + Entry(1,1) = m11; + Entry(2,1) = m21; + Entry(3,1) = m31; + Entry(1,2) = m12; + Entry(2,2) = m22; + Entry(3,2) = m32; + Entry(1,3) = m13; + Entry(2,3) = m23; + Entry(3,3) = m33; + } + + /** Determinant of the matrix. + @return the determinant of the matrix. + */ + double Determinant(void) const; + + /** Return if the matrix is invertible. + Checks and returns if the matrix is nonsingular and thus + 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. + */ + 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. + */ + FGMatrix33 Inverse(void) const; + + /** Assignment operator. + + @param A source matrix. + + 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]; + data[2] = A.data[2]; + data[3] = A.data[3]; + data[4] = A.data[4]; + data[5] = A.data[5]; + data[6] = A.data[6]; + data[7] = A.data[7]; + data[8] = A.data[8]; + return *this; + } + + /** 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + FGMatrix33& operator/=(const double scalar); + +private: + double data[eRows*eColumns]; + + void Debug(int from); +}; + +/** Scalar multiplication. + + @param scalar scalar value to multiply with. + @param A Matrix to multiply. + + 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. +*/ +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. +*/ +istream& operator>>(istream& is, FGMatrix33& M); + +} // namespace JSBSim + +#endif diff --git a/src/FDM/JSBSim/math/FGParameter.h b/src/FDM/JSBSim/math/FGParameter.h new file mode 100755 index 000000000..c970f7ef4 --- /dev/null +++ b/src/FDM/JSBSim/math/FGParameter.h @@ -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 diff --git a/src/FDM/JSBSim/math/FGPropertyValue.cpp b/src/FDM/JSBSim/math/FGPropertyValue.cpp new file mode 100755 index 000000000..b0ae33eed --- /dev/null +++ b/src/FDM/JSBSim/math/FGPropertyValue.cpp @@ -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(); +} + +} diff --git a/src/FDM/JSBSim/math/FGPropertyValue.h b/src/FDM/JSBSim/math/FGPropertyValue.h new file mode 100755 index 000000000..afce3911f --- /dev/null +++ b/src/FDM/JSBSim/math/FGPropertyValue.h @@ -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 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 diff --git a/src/FDM/JSBSim/math/FGQuaternion.cpp b/src/FDM/JSBSim/math/FGQuaternion.cpp new file mode 100644 index 000000000..55edcf88e --- /dev/null +++ b/src/FDM/JSBSim/math/FGQuaternion.cpp @@ -0,0 +1,240 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGQuaternion.cpp + Author: Jon Berndt, Mathias Froehlich + Date started: 12/02/98 + + ------- 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. + +HISTORY +------------------------------------------------------------------------------- +12/02/98 JSB Created +15/01/04 Mathias Froehlich implemented a quaternion class from many places + in JSBSim. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + INCLUDES + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# include +# include STL_IOSTREAM + SG_USING_STD(cerr); + SG_USING_STD(cout); + SG_USING_STD(endl); +#else +# include +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# include +# else +# include +# if defined(sgi) && !defined(__GNUC__) +# include +# else +# include +# endif + using std::cerr; + using std::cout; + using std::endl; +# endif +#endif + +#include "FGMatrix33.h" +#include "FGColumnVector3.h" + +#include "FGQuaternion.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + DEFINITIONS + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_QUATERNION; + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +// Initialize from q +FGQuaternion::FGQuaternion(const FGQuaternion& q) + : mCacheValid(q.mCacheValid) { + Entry(1) = q(1); + Entry(2) = q(2); + Entry(3) = q(3); + Entry(4) = q(4); + if (mCacheValid) { + mT = q.mT; + mTInv = q.mTInv; + mEulerAngles = q.mEulerAngles; + mEulerSines = q.mEulerSines; + mEulerCosines = q.mEulerCosines; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +// Initialize with the three euler angles +FGQuaternion::FGQuaternion(double phi, double tht, double psi) + : mCacheValid(false) { + double thtd2 = 0.5*tht; + double psid2 = 0.5*psi; + double phid2 = 0.5*phi; + + double Sthtd2 = sin(thtd2); + double Spsid2 = sin(psid2); + double Sphid2 = sin(phid2); + + double Cthtd2 = cos(thtd2); + double Cpsid2 = cos(psid2); + double Cphid2 = cos(phid2); + + double Cphid2Cthtd2 = Cphid2*Cthtd2; + double Cphid2Sthtd2 = Cphid2*Sthtd2; + double Sphid2Sthtd2 = Sphid2*Sthtd2; + double Sphid2Cthtd2 = Sphid2*Cthtd2; + + Entry(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2; + Entry(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2; + Entry(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2; + Entry(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/** + Returns the derivative of the quaternion coresponding to the + angular velocities PQR. +*/ +FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR) const { + double norm = Magnitude(); + if (norm == 0.0) + return FGQuaternion::zero(); + double rnorm = 1.0/norm; + + FGQuaternion QDot; + QDot(1) = -0.5*(Entry(2)*PQR(eP) + Entry(3)*PQR(eQ) + Entry(4)*PQR(eR)); + QDot(2) = 0.5*(Entry(1)*PQR(eP) + Entry(3)*PQR(eR) - Entry(4)*PQR(eQ)); + QDot(3) = 0.5*(Entry(1)*PQR(eQ) + Entry(4)*PQR(eP) - Entry(2)*PQR(eR)); + QDot(4) = 0.5*(Entry(1)*PQR(eR) + Entry(2)*PQR(eQ) - Entry(3)*PQR(eP)); + return rnorm*QDot; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGQuaternion::Normalize() +{ + // Note: this does not touch the cache + // since it does not change the orientation ... + + double norm = Magnitude(); + if (norm == 0.0) + return; + + double rnorm = 1.0/norm; + Entry(1) *= rnorm; + Entry(2) *= rnorm; + Entry(3) *= rnorm; + Entry(4) *= rnorm; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +// Compute the derived values if required ... +void FGQuaternion::ComputeDerivedUnconditional(void) const +{ + mCacheValid = true; + + // First normalize the 4-vector + double norm = Magnitude(); + if (norm == 0.0) + return; + + double rnorm = 1.0/norm; + double q1 = rnorm*Entry(1); + double q2 = rnorm*Entry(2); + double q3 = rnorm*Entry(3); + double q4 = rnorm*Entry(4); + + // Now compute the transformation matrix. + double q1q1 = q1*q1; + double q2q2 = q2*q2; + double q3q3 = q3*q3; + double q4q4 = q4*q4; + double q1q2 = q1*q2; + double q1q3 = q1*q3; + double q1q4 = q1*q4; + double q2q3 = q2*q3; + double q2q4 = q2*q4; + double q3q4 = q3*q4; + + mT(1,1) = q1q1 + q2q2 - q3q3 - q4q4; + mT(1,2) = 2.0*(q2q3 + q1q4); + mT(1,3) = 2.0*(q2q4 - q1q3); + mT(2,1) = 2.0*(q2q3 - q1q4); + mT(2,2) = q1q1 - q2q2 + q3q3 - q4q4; + mT(2,3) = 2.0*(q3q4 + q1q2); + mT(3,1) = 2.0*(q2q4 + q1q3); + mT(3,2) = 2.0*(q3q4 - q1q2); + mT(3,3) = q1q1 - q2q2 - q3q3 + q4q4; + // Since this is an orthogonal matrix, the inverse is simply + // the transpose. + mTInv = mT; + mTInv.T(); + + // Compute the Euler-angles + if (mT(3,3) == 0.0) + mEulerAngles(ePhi) = 0.5*M_PI; + else + mEulerAngles(ePhi) = atan2(mT(2,3), mT(3,3)); + + if (mT(1,3) < -1.0) + mEulerAngles(eTht) = 0.5*M_PI; + else if (1.0 < mT(1,3)) + mEulerAngles(eTht) = -0.5*M_PI; + else + mEulerAngles(eTht) = asin(-mT(1,3)); + + if (mT(1,1) == 0.0) + mEulerAngles(ePsi) = 0.5*M_PI; + else { + double psi = atan2(mT(1,2), mT(1,1)); + if (psi < 0.0) + psi += 2*M_PI; + mEulerAngles(ePsi) = psi; + } + + // FIXME: may be one can compute those values easier ??? + mEulerSines(ePhi) = sin(mEulerAngles(ePhi)); + // mEulerSines(eTht) = sin(mEulerAngles(eTht)); + mEulerSines(eTht) = -mT(1,3); + mEulerSines(ePsi) = sin(mEulerAngles(ePsi)); + mEulerCosines(ePhi) = cos(mEulerAngles(ePhi)); + mEulerCosines(eTht) = cos(mEulerAngles(eTht)); + mEulerCosines(ePsi) = cos(mEulerAngles(ePsi)); +} + +} // namespace JSBSim diff --git a/src/FDM/JSBSim/math/FGQuaternion.h b/src/FDM/JSBSim/math/FGQuaternion.h new file mode 100644 index 000000000..a23ced79a --- /dev/null +++ b/src/FDM/JSBSim/math/FGQuaternion.h @@ -0,0 +1,494 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGQuaternion.h + Author: Jon Berndt, Mathis Froehlich + Date started: 12/02/98 + + ------- 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. + +HISTORY +------------------------------------------------------------------------------- +12/02/98 JSB Created +15/01/04 MF Quaternion class from old FGColumnVector4 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGQUATERNION_H +#define FGQUATERNION_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + INCLUDES + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include "FGMatrix33.h" +#include "FGColumnVector3.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + DEFINITIONS + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_QUATERNION "$Id$" + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + CLASS DOCUMENTATION + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models the Quaternion representation of rotations. + FGQuaternion is a representation of an arbitrary rotation through a + quaternion. It has vector properties. This class also contains access + functions to the euler angle representation of rotations and access to + transformation matrices for 3D vectors. Transformations and euler angles are + therefore computed once they are requested for the first time. Then they are + cached for later usage as long as the class is not accessed trough + a nonconst member function. + + Note: The order of rotations used in this class corresponds to a 3-2-1 sequence, + or Y-P-R, or Z-Y-X, if you prefer. + + @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 + @author Mathias Froehlich, extended FGColumnVector4 originally by Tony Peden + and Jon Berndt +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + CLASS DECLARATION + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGQuaternion + : virtual FGJSBBase { +public: + /** Default initializer. + Default initializer, initializes the class with the identity rotation. */ + FGQuaternion() : mCacheValid(false) { + Entry(1) = 1.0; + Entry(2) = Entry(3) = Entry(4) = 0.0; + } + + /** Copy constructor. + Copy constructor, initializes the quaternion. + @param q a constant reference to another FGQuaternion instance */ + FGQuaternion(const FGQuaternion& q); + + /** Initializer by euler angles. + Initialize the quaternion with the euler angles. + @param phi The euler X axis (roll) angle in radians + @param tht The euler Y axis (attitude) angle in radians + @param psi The euler Z axis (heading) angle in radians */ + FGQuaternion(double phi, double tht, double psi); + + /** Initializer by one euler angle. + Initialize the quaternion with the single euler angle where its index + is given in the first argument. + @param idx Index of the euler angle to initialize + @param angle The euler angle in radians */ + FGQuaternion(int idx, double angle) + : mCacheValid(false) { + double angle2 = 0.5*angle; + + double Sangle2 = sin(angle2); + double Cangle2 = cos(angle2); + + if (idx == ePhi) { + Entry(1) = Cangle2; + Entry(2) = Sangle2; + Entry(3) = 0.0; + Entry(4) = 0.0; + + } else if (idx == eTht) { + Entry(1) = Cangle2; + Entry(2) = 0.0; + Entry(3) = Sangle2; + Entry(4) = 0.0; + + } else { + Entry(1) = Cangle2; + Entry(2) = 0.0; + Entry(3) = 0.0; + Entry(4) = Sangle2; + + } + } + + /// Destructor. + ~FGQuaternion() {} + + /** Quaternion 'velocity' for given angular rates. + Computes the quaternion derivative which results from the given + angular velocities + @param PQR a constant reference to the body rate vector + @return the quaternion derivative */ + FGQuaternion GetQDot(const FGColumnVector3& PQR) const; + + /** Transformation matrix. + @return a reference to the transformation/rotation matrix + corresponding to this quaternion rotation. */ + const FGMatrix33& GetT(void) const { ComputeDerived(); return mT; } + + /** Backward transformation matrix. + @return a reference to the inverse transformation/rotation matrix + corresponding to this quaternion rotation. */ + const FGMatrix33& GetTInv(void) const { ComputeDerived(); return mTInv; } + + /** Retrieves the Euler angles. + @return a reference to the triad of euler angles corresponding + to this quaternion rotation. + @units radians */ + const FGColumnVector3& GetEuler(void) const { + ComputeDerived(); + return mEulerAngles; + } + + /** Retrieves the Euler angles. + @param i the euler angle index. + @return a reference to the i-th euler angles corresponding + to this quaternion rotation. + @units radians */ + double GetEuler(int i) const { + ComputeDerived(); + return mEulerAngles(i); + } + + /** Retrieves the Euler angles. + @param i the euler angle index. + @return a reference to the i-th euler angles corresponding + to this quaternion rotation. + @units degrees */ + double GetEulerDeg(int i) const { + ComputeDerived(); + return radtodeg*mEulerAngles(i); + } + + /** Retrieves sine of the given euler angle. + @return the sine of the Euler angle theta (pitch attitude) corresponding + to this quaternion rotation. */ + double GetSinEuler(int i) const { + ComputeDerived(); + return mEulerSines(i); + } + + /** Retrieves cosine of the given euler angle. + @return the sine of the Euler angle theta (pitch attitude) corresponding + to this quaternion rotation. */ + double GetCosEuler(int i) const { + ComputeDerived(); + return mEulerCosines(i); + } + + /** 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 mData[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) { mCacheValid = false; return mData[idx-1]; } + + /** Assignment operator "=". + Assign the value of q to the current object. Cached values are + conserved. + @param q reference to an FGQuaternion instance + @return reference to a quaternion object */ + const FGQuaternion& operator=(const FGQuaternion& q) { + // Copy the master values ... + Entry(1) = q(1); + Entry(2) = q(2); + Entry(3) = q(3); + Entry(4) = q(4); + // .. and copy the derived values if they are valid + mCacheValid = q.mCacheValid; + if (mCacheValid) { + mT = q.mT; + mTInv = q.mTInv; + mEulerAngles = q.mEulerAngles; + mEulerSines = q.mEulerSines; + mEulerCosines = q.mEulerCosines; + } + return *this; + } + + /** Comparison operator "==". + @param q a quaternion reference + @return true if both quaternions represent the same rotation. */ + bool operator==(const FGQuaternion& q) const { + return Entry(1) == q(1) && Entry(2) == q(2) + && Entry(3) == q(3) && Entry(4) == q(4); + } + + /** Comparison operator "!=". + @param q a quaternion reference + @return true if both quaternions do not represent the same rotation. */ + bool operator!=(const FGQuaternion& q) const { return ! operator==(q); } + const FGQuaternion& operator+=(const FGQuaternion& q) { + // Copy the master values ... + Entry(1) += q(1); + Entry(2) += q(2); + Entry(3) += q(3); + Entry(4) += q(4); + mCacheValid = false; + return *this; + } + + /** Arithmetic operator "-=". + @param q a quaternion reference. + @return a quaternion reference representing Q, where Q = Q - q. */ + const FGQuaternion& operator-=(const FGQuaternion& q) { + // Copy the master values ... + Entry(1) -= q(1); + Entry(2) -= q(2); + Entry(3) -= q(3); + Entry(4) -= q(4); + mCacheValid = false; + return *this; + } + + /** Arithmetic operator "*=". + @param scalar a multiplicative value. + @return a quaternion reference representing Q, where Q = Q * scalar. */ + const FGQuaternion& operator*=(double scalar) { + Entry(1) *= scalar; + Entry(2) *= scalar; + Entry(3) *= scalar; + Entry(4) *= scalar; + mCacheValid = false; + return *this; + } + + /** Arithmetic operator "/=". + @param scalar a divisor value. + @return a quaternion reference representing Q, where Q = Q / scalar. */ + const FGQuaternion& operator/=(double scalar) { + return operator*=(1.0/scalar); + } + + /** Arithmetic operator "+". + @param q a quaternion to be summed. + @return a quaternion representing Q, where Q = Q + q. */ + FGQuaternion operator+(const FGQuaternion& q) const { + return FGQuaternion(Entry(1)+q(1), Entry(2)+q(2), + Entry(3)+q(3), Entry(4)+q(4)); + } + + /** Arithmetic operator "-". + @param q a quaternion to be subtracted. + @return a quaternion representing Q, where Q = Q - q. */ + FGQuaternion operator-(const FGQuaternion& q) const { + return FGQuaternion(Entry(1)-q(1), Entry(2)-q(2), + Entry(3)-q(3), Entry(4)-q(4)); + } + + /** Arithmetic operator "*". + Multiplication of two quaternions is like performing successive rotations. + @param q a quaternion to be multiplied. + @return a quaternion representing Q, where Q = Q * q. */ + FGQuaternion operator*(const FGQuaternion& q) const { + return FGQuaternion(Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4), + Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3), + Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2), + Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1)); + } + + /** Arithmetic operator "*=". + Multiplication of two quaternions is like performing successive rotations. + @param q a quaternion to be multiplied. + @return a quaternion reference representing Q, where Q = Q * q. */ + const FGQuaternion& operator*=(const FGQuaternion& q) { + double q0 = Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4); + double q1 = Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3); + double q2 = Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2); + double q3 = Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1); + Entry(1) = q0; + Entry(2) = q1; + Entry(3) = q2; + Entry(4) = q3; + mCacheValid = false; + return *this; + } + + /** Inverse of the quaternion. + + Compute and return the inverse of the quaternion so that the orientation + represented with *this multiplied with the returned value is equal to + the identity orientation. + */ + FGQuaternion Inverse(void) const { + double norm = Magnitude(); + if (norm == 0.0) + return *this; + double rNorm = 1.0/norm; + return FGQuaternion( Entry(1)*rNorm, -Entry(2)*rNorm, + -Entry(3)*rNorm, -Entry(4)*rNorm ); + } + + /** Conjugate of the quaternion. + + Compute and return the conjugate of the quaternion. This one is equal + to the inverse iff the quaternion is normalized. + */ + FGQuaternion Conjugate(void) const { + return FGQuaternion( Entry(1), -Entry(2), -Entry(3), -Entry(4) ); + } + + friend FGQuaternion operator*(double, const FGQuaternion&); + + /** Length of the vector. + + Compute and return the euclidean norm of this vector. + */ + double Magnitude(void) const { return sqrt(SqrMagnitude()); } + + /** Square of the length of the vector. + + Compute and return the square of the euclidean norm of this vector. + */ + double SqrMagnitude(void) const { + return Entry(1)*Entry(1)+Entry(2)*Entry(2) + +Entry(3)*Entry(3)+Entry(4)*Entry(4); + } + + /** Normialze. + + Normalize the vector to have the Magnitude() == 1.0. If the vector + is equal to zero it is left untouched. + */ + void Normalize(void); + + /** Zero quaternion vector. Does not represent any orientation. + Useful for initialization of increments */ + static FGQuaternion zero(void) { return FGQuaternion( 0.0, 0.0, 0.0, 0.0 ); } + +private: + /** Copying by assigning the vector valued components. */ + FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false) + { Entry(1) = q1; Entry(2) = q2; Entry(3) = q3; Entry(4) = q4; } + + /** Computation of derived values. + This function recomputes the derived values like euler angles and + transformation matrices. It does this unconditionally. */ + void ComputeDerivedUnconditional(void) const; + + /** Computation of derived values. + This function checks if the derived values like euler angles and + transformation matrices are already computed. If so, it + returns. If they need to be computed the real worker routine + \ref FGQuaternion::ComputeDerivedUnconditional(void) const + is called. + This function is inlined to avoid function calls in the fast path. */ + void ComputeDerived(void) const { + if (!mCacheValid) + ComputeDerivedUnconditional(); + } + + /** The quaternion values itself. This is the master copy. */ + double mData[4]; + + /** A data validity flag. + This class implements caching of the derived values like the + orthogonal rotation matrices or the Euler angles. For caching we + carry a flag which signals if the values are valid or not. + The C++ keyword "mutable" tells the compiler that the data member is + allowed to change during a const member function. */ + mutable bool mCacheValid; + + /** This stores the transformation matrices. */ + mutable FGMatrix33 mT; + mutable FGMatrix33 mTInv; + + /** The cached euler angles. */ + mutable FGColumnVector3 mEulerAngles; + + /** The cached sines and cosines of the euler angles. */ + mutable FGColumnVector3 mEulerSines; + mutable FGColumnVector3 mEulerCosines; +}; + +/** Scalar multiplication. + + @param scalar scalar value to multiply with. + @param p Vector to multiply. + + Multiply the Vector with a scalar value. +*/ +inline FGQuaternion operator*(double scalar, const FGQuaternion& q) { + return FGQuaternion(scalar*q(1), scalar*q(2), scalar*q(3), scalar*q(4)); +} + +} // namespace JSBSim + +#endif diff --git a/src/FDM/JSBSim/math/FGRealValue.cpp b/src/FDM/JSBSim/math/FGRealValue.cpp new file mode 100755 index 000000000..d1f97cd72 --- /dev/null +++ b/src/FDM/JSBSim/math/FGRealValue.cpp @@ -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; +} + +} diff --git a/src/FDM/JSBSim/math/FGRealValue.h b/src/FDM/JSBSim/math/FGRealValue.h new file mode 100755 index 000000000..334bf8433 --- /dev/null +++ b/src/FDM/JSBSim/math/FGRealValue.h @@ -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 diff --git a/src/FDM/JSBSim/math/FGTable.cpp b/src/FDM/JSBSim/math/FGTable.cpp new file mode 100644 index 000000000..b5d6019fe --- /dev/null +++ b/src/FDM/JSBSim/math/FGTable.cpp @@ -0,0 +1,591 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGTable.cpp + Author: Jon S. Berndt + Date started: 1/9/2001 + Purpose: Models a lookup table + + ------------- Copyright (C) 2001 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 a lookup table + +HISTORY +-------------------------------------------------------------------------------- +JSB 1/9/00 Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGTable.h" + +#if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740) +# include +#else +# include +#endif + +using namespace std; + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_TABLE; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGTable::FGTable(int NRows) : nRows(NRows), nCols(1), PropertyManager(0) +{ + Type = tt1D; + colCounter = 0; + rowCounter = 1; + nTables = 0; + + Data = Allocate(); + Debug(0); + lastRowIndex=lastColumnIndex=2; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +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(); + for (int r=0; r<=nRows; r++) { + for (int c=0; c<=nCols; c++) { + Data[r][c] = t.Data[r][c]; + } + } + lastRowIndex = t.lastRowIndex; + lastColumnIndex = t.lastColumnIndex; + lastTableIndex = t.lastTableIndex; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +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; iGetNumDataLines(); 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; iGetAttributeValueAsNumber("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]; + for (int r=0; r<=nRows; r++) { + Data[r] = new double[nCols+1]; + for (int c=0; c<=nCols; c++) { + Data[r][c] = 0.0; + } + } + return Data; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTable::~FGTable() +{ + if (nTables > 0) { +cout << "nTables = " << nTables << endl; + for (int i=0; igetDoubleValue(); + 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; + + //if the key is off the end of the table, just return the + //end-of-table value, do not extrapolate + if( key <= Data[1][0] ) { + lastRowIndex=2; + //cout << "Key underneath table: " << key << endl; + return Data[1][1]; + } else if ( key >= Data[nRows][0] ) { + lastRowIndex=nRows; + //cout << "Key over table: " << key << endl; + return Data[nRows][1]; + } + + // the key is somewhere in the middle, search for the right breakpoint + // assume the correct breakpoint has not changed since last frame or + // has only changed very little + + if ( r > 2 && Data[r-1][0] > key ) { + while( Data[r-1][0] > key && r > 2) { r--; } + } else if ( Data[r][0] < key ) { + while( Data[r][0] <= key && r <= nRows) { r++; } + } + + lastRowIndex=r; + // make sure denominator below does not go to zero. + + Span = Data[r][0] - Data[r-1][0]; + if (Span != 0.0) { + Factor = (key - Data[r-1][0]) / Span; + if (Factor > 1.0) Factor = 1.0; + } else { + Factor = 1.0; + } + + Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1]; + + return Value; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTable::GetValue(double rowKey, double colKey) const +{ + double rFactor, cFactor, col1temp, col2temp, Value; + int r=lastRowIndex; + int c=lastColumnIndex; + + if ( r > 2 && Data[r-1][0] > rowKey ) { + while ( Data[r-1][0] > rowKey && r > 2) { r--; } + } else if ( Data[r][0] < rowKey ) { + while ( r <= nRows && Data[r][0] <= rowKey ) { r++; } + if ( r > nRows ) r = nRows; + } + + if ( c > 2 && Data[0][c-1] > colKey ) { + while( Data[0][c-1] > colKey && c > 2) { c--; } + } else if ( Data[0][c] < colKey ) { + while( Data[0][c] <= colKey && c <= nCols) { c++; } + if ( c > nCols ) c = nCols; + } + + lastRowIndex=r; + lastColumnIndex=c; + + rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]); + cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]); + + if (rFactor > 1.0) rFactor = 1.0; + else if (rFactor < 0.0) rFactor = 0.0; + + if (cFactor > 1.0) cFactor = 1.0; + else if (cFactor < 0.0) cFactor = 0.0; + + col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1]; + col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c]; + + Value = col1temp + cFactor*(col2temp - col1temp); + + return Value; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTable::GetValue(double rowKey, double colKey, double tableKey) const +{ + double Factor, Value, Span; + int r=lastRowIndex; + + //if the key is off the end (or before the beginning) of the table, + // just return the boundary-table value, do not extrapolate + + if( tableKey <= Data[1][1] ) { + lastRowIndex=2; + return Tables[0]->GetValue(rowKey, colKey); + } else if ( tableKey >= Data[nRows][1] ) { + lastRowIndex=nRows; + return Tables[nRows-1]->GetValue(rowKey, colKey); + } + + // the key is somewhere in the middle, search for the right breakpoint + // assume the correct breakpoint has not changed since last frame or + // has only changed very little + + if ( r > 2 && Data[r-1][1] > tableKey ) { + while( Data[r-1][1] > tableKey && r > 2) { r--; } + } else if ( Data[r][1] < tableKey ) { + while( Data[r][1] <= tableKey && r <= nRows) { r++; } + } + + lastRowIndex=r; + // make sure denominator below does not go to zero. + + Span = Data[r][1] - Data[r-1][1]; + if (Span != 0.0) { + Factor = (tableKey - Data[r-1][1]) / Span; + if (Factor > 1.0) Factor = 1.0; + } else { + Factor = 1.0; + } + + 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<<(stringstream& in_stream) +{ + int startRow=0; + int startCol=0; + + if (Type == tt1D || Type == tt3D) startRow = 1; + if (Type == tt3D) startCol = 1; + + for (int r=startRow; r<=nRows; r++) { + for (int c=startCol; c<=nCols; c++) { + if (r != 0 || c != 0) { + in_stream >> Data[r][c]; + } + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTable& FGTable::operator<<(const double n) +{ + Data[rowCounter][colCounter] = n; + if (colCounter == nCols) { + colCounter = 0; + rowCounter++; + } else { + colCounter++; + } + return *this; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTable& FGTable::operator<<(const int n) +{ + *this << (double)n; + return *this; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTable::Print(void) +{ + int startRow=0; + int startCol=0; + + if (Type == tt1D || Type == tt3D) startRow = 1; + if (Type == tt3D) startCol = 1; + +#if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) + unsigned long flags = cout.setf(ios::fixed); +#else + ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream +#endif + + 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 << " "; + for (int c=startCol; c<=nCols; c++) { + if (r == 0 && c == 0) { + cout << " "; + } else { + cout << Data[r][c] << " "; + if (Type == tt3D) { + cout << endl; + Tables[r-1]->Print(); + } + } + } + cout << endl; + } + cout.setf(flags); // reset +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGTable::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: FGTable" << endl; + if (from == 1) cout << "Destroyed: FGTable" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/math/FGTable.h b/src/FDM/JSBSim/math/FGTable.h new file mode 100644 index 000000000..be6e3b8d9 --- /dev/null +++ b/src/FDM/JSBSim/math/FGTable.h @@ -0,0 +1,276 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTable.h + Author: Jon S. Berndt + Date started: 1/9/2001 + + ------------- Copyright (C) 2001 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 +-------------------------------------------------------------------------------- +JSB 1/9/00 Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGTABLE_H +#define FGTABLE_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include "FGParameter.h" +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_TABLE "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +using std::vector; +using std::stringstream; + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Lookup table class. + Models a one, two, or three dimensional lookup table for use in FGCoefficient, + FGPropeller, etc. A one-dimensional table is called a "VECTOR" in a coefficient + definition. For example: +
+    \
+      {name}
+      {number of rows}
+      {row lookup property}
+      {non-dimensionalizing properties}
+      {row_1_key} {col_1_data}
+      {row_2_key} {...       }
+      { ...     } {...       }
+      {row_n_key} {...       }
+    \
+
+ A "real life" example is as shown here: +
+    \
+      Delta_lift_due_to_flap_deflection
+      4
+      fcs/flap-pos-deg
+      aero/qbar-psf | metrics/Sw-sqft
+      0   0
+      10  0.20
+      20  0.30
+      30  0.35
+    \
+
+ The first column in the data table represents the lookup index (or "key"). In + this case, the lookup index is fcs/flap-pos-deg (flap extension in degrees). + If the flap position is 10 degrees, the value returned from the lookup table + would be 0.20. This value would be multiplied by qbar (aero/qbar-psf) and wing + area (metrics/Sw-sqft) to get the total lift force that is a result of flap + deflection (measured in pounds force). If the value of the flap-pos-deg property + was 15 (degrees), the value output by the table routine would be 0.25 - an + interpolation. If the flap position in degrees ever went below 0.0, or above + 30 (degrees), the output from the table routine would be 0 and 0.35, respectively. + That is, there is no _extrapolation_ to values outside the range of the lookup + index. This is why it is important to chose the data for the table wisely. + + The definition for a 2D table - referred to simply as a TABLE, is as follows: +
+    \
+      {name}
+      {number of rows}
+      {number of columns}
+      {row lookup property}
+      {column lookup property}
+      {non-dimensionalizing}
+                  {col_1_key   col_2_key   ...  col_n_key }
+      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
+      {row_2_key} {...         ...         ...  ...       }
+      { ...     } {...         ...         ...  ...       }
+      {row_n_key} {...         ...         ...  ...       }
+    \
+
+ A "real life" example is as shown here: +
+    \
+      Side_force_due_to_beta
+      3
+      2
+      aero/beta-rad
+      fcs/flap-pos-deg
+      aero/qbar-psf | metrics/Sw-sqft
+               0     30
+      -0.349   0.137  0.106
+       0       0      0
+       0.349  -0.137 -0.106
+    \
+
+ The definition for a 3D table in a coefficient would be (for example): +
+    \
+      {name}
+      {number of rows}
+      {number of columns}
+      {number of tables}
+      {row lookup property}
+      {column lookup property}
+      {table lookup property}
+      {non-dimensionalizing}
+      {first table key}
+                  {col_1_key   col_2_key   ...  col_n_key }
+      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
+      {row_2_key} {...         ...         ...  ...       }
+      { ...     } {...         ...         ...  ...       }
+      {row_n_key} {...         ...         ...  ...       }
+
+      {second table key}
+                  {col_1_key   col_2_key   ...  col_n_key }
+      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
+      {row_2_key} {...         ...         ...  ...       }
+      { ...     } {...         ...         ...  ...       }
+      {row_n_key} {...         ...         ...  ...       }
+
+      ...
+
+    \
+
+ [At the present time, all rows and columns for each table must have the + same dimension.] + + In addition to using a Table for something like a coefficient, where all the + row and column elements are read in from a file, a Table could be created + and populated completely within program code: +
+    // First column is thi, second is neta (combustion efficiency)
+    Lookup_Combustion_Efficiency = new FGTable(12);
+    *Lookup_Combustion_Efficiency << 0.00 << 0.980;
+    *Lookup_Combustion_Efficiency << 0.90 << 0.980;
+    *Lookup_Combustion_Efficiency << 1.00 << 0.970;
+    *Lookup_Combustion_Efficiency << 1.05 << 0.950;
+    *Lookup_Combustion_Efficiency << 1.10 << 0.900;
+    *Lookup_Combustion_Efficiency << 1.15 << 0.850;
+    *Lookup_Combustion_Efficiency << 1.20 << 0.790;
+    *Lookup_Combustion_Efficiency << 1.30 << 0.700;
+    *Lookup_Combustion_Efficiency << 1.40 << 0.630;
+    *Lookup_Combustion_Efficiency << 1.50 << 0.570;
+    *Lookup_Combustion_Efficiency << 1.60 << 0.525;
+    *Lookup_Combustion_Efficiency << 2.00 << 0.345;
+
+ The first column in the table, above, is thi (the lookup index, or key). The + second column is the output data - in this case, "neta" (the Greek letter + referring to combustion efficiency). Later on, the table is used like this: + + combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio); + + @author Jon S. Berndt + @version $Id$ + @see FGCoefficient + @see FGPropeller +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGTable : public FGParameter +{ +public: + /// Destructor + ~FGTable(); + + /** This is the very important copy constructor. + @param table a const reference to a table.*/ + FGTable(const FGTable& table); + + /// 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 + the first row. The implication of this layout is that there should + be no value in the upper left corner of the matrix e.g: +
+           0  10  20 30 ...
+      -5   1  2   3  4  ...
+       ...
+       
+ + For multiple-table (i.e. 3D) data sets there is an additional number + key in the table definition. For example: + +
+       0.0
+           0  10  20 30 ...
+      -5   1  2   3  4  ...
+       ...
+       
+ */ + + 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 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 Tables; + int FindNumColumns(string); + int nRows, nCols, nTables, dimension; + int colCounter, rowCounter, tableCounter; + mutable int lastRowIndex, lastColumnIndex, lastTableIndex; + double** Allocate(void); + FGPropertyManager* const PropertyManager; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#endif + diff --git a/src/FDM/JSBSim/math/Makefile.am b/src/FDM/JSBSim/math/Makefile.am new file mode 100644 index 000000000..107e29f29 --- /dev/null +++ b/src/FDM/JSBSim/math/Makefile.am @@ -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 diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp new file mode 100644 index 000000000..63f00754d --- /dev/null +++ b/src/FDM/JSBSim/models/FGAerodynamics.cpp @@ -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 + +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; jHolding()) 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; icacheValue(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 diff --git a/src/FDM/JSBSim/models/FGAerodynamics.h b/src/FDM/JSBSim/models/FGAerodynamics.h new file mode 100644 index 000000000..39713a070 --- /dev/null +++ b/src/FDM/JSBSim/models/FGAerodynamics.h @@ -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 +# ifdef SG_HAVE_STD_INCLUDES +# include +# include +# else +# include +# include +# endif +#else +# include +# include +#endif + +#include "FGModel.h" +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 +
+    \
+       \
+         {Coefficient definitions}
+       \
+       {Additional axis definitions}
+    \ 
+ + @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 AxisIndex; + AxisIndex AxisIdx; + vector variables; + typedef vector 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 + diff --git a/src/FDM/JSBSim/models/FGAircraft.cpp b/src/FDM/JSBSim/models/FGAircraft.cpp new file mode 100644 index 000000000..fd6f9fce3 --- /dev/null +++ b/src/FDM/JSBSim/models/FGAircraft.cpp @@ -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 +#include + +#ifdef FGFS +# ifndef __BORLANDC__ +# include +# endif +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# if defined (sgi) && !defined(__GNUC__) +# include +# else +# include +# endif +#endif + +#include "FGAircraft.h" +#include "FGMassBalance.h" +#include "FGInertial.h" +#include "FGGroundReactions.h" +#include "FGAerodynamics.h" +#include +#include +#include "FGPropagate.h" +#include + +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 diff --git a/src/FDM/JSBSim/models/FGAircraft.h b/src/FDM/JSBSim/models/FGAircraft.h new file mode 100644 index 000000000..29d555df5 --- /dev/null +++ b/src/FDM/JSBSim/models/FGAircraft.h @@ -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 +# ifdef SG_HAVE_STD_INCLUDES +# include +# include +# else +# include +# include +# endif +#else +# include +# include +#endif + +#include "FGModel.h" +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 + diff --git a/src/FDM/JSBSim/models/FGAtmosphere.cpp b/src/FDM/JSBSim/models/FGAtmosphere.cpp new file mode 100644 index 000000000..b7ad76604 --- /dev/null +++ b/src/FDM/JSBSim/models/FGAtmosphere.cpp @@ -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 +#include +#include "FGAircraft.h" +#include "FGPropagate.h" +#include "FGInertial.h" +#include + +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 diff --git a/src/FDM/JSBSim/models/FGAtmosphere.h b/src/FDM/JSBSim/models/FGAtmosphere.h new file mode 100644 index 000000000..fd0500a9e --- /dev/null +++ b/src/FDM/JSBSim/models/FGAtmosphere.h @@ -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 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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. + This function may only be used if Run() is called first. */ + 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 + diff --git a/src/FDM/JSBSim/models/FGAuxiliary.cpp b/src/FDM/JSBSim/models/FGAuxiliary.cpp new file mode 100755 index 000000000..056c1c07e --- /dev/null +++ b/src/FDM/JSBSim/models/FGAuxiliary.cpp @@ -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 +#include +#include "FGAircraft.h" +#include "FGInertial.h" +#include + +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 diff --git a/src/FDM/JSBSim/models/FGAuxiliary.h b/src/FDM/JSBSim/models/FGAuxiliary.h new file mode 100644 index 000000000..297b3a0cc --- /dev/null +++ b/src/FDM/JSBSim/models/FGAuxiliary.h @@ -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 +#include +#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 diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp new file mode 100644 index 000000000..0c106cefa --- /dev/null +++ b/src/FDM/JSBSim/models/FGFCS.cpp @@ -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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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;iHolding()) return false; + + for (i=0; iGetGearUnit(i); + SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() ); + } + + // Cycle through the sensor, autopilot, and flight control components + for (i=0; iRun(); + for (i=0; iRun(); + for (i=0; iRun(); + + 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 *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; iGetGearUnit(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; igetChild(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; + } + } +} + +} diff --git a/src/FDM/JSBSim/models/FGFCS.h b/src/FDM/JSBSim/models/FGFCS.h new file mode 100644 index 000000000..9a99aded1 --- /dev/null +++ b/src/FDM/JSBSim/models/FGFCS.h @@ -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 +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# include +#endif + +#include +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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: + +
+    \
+      \
+        \
+            fcs/elevator-cmd-norm 
+            fcs/pitch-trim-cmd-norm 
+           
+             -1
+             1
+           
+        \
+
+        \
+           fcs/pitch-trim-sum 
+          
+             -50 
+              50 
+          
+        \
+
+        ... etc.
+    
+ + 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 + \ 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, + +
+    \
+    
+ + one can also supply a filename: + +
+    \
+    \
+    
+ + 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 ThrottleCmd; + vector ThrottlePos; + vector MixtureCmd; + vector MixturePos; + vector PropAdvanceCmd; + vector PropAdvance; + vector PropFeatherCmd; + vector PropFeather; + vector SteerPosDeg; + double LeftBrake, RightBrake, CenterBrake; // Brake settings + double GearCmd,GearPos; + + vector FCSComponents; + vector APComponents; + vector interface_properties; + vector sensors; + void bind(void); + void bindModel(void); + void bindThrottle(unsigned int); + void unbind(FGPropertyManager *node); + void Debug(int from); +}; +} + +#endif + diff --git a/src/FDM/JSBSim/models/FGGroundReactions.cpp b/src/FDM/JSBSim/models/FGGroundReactions.cpp new file mode 100644 index 000000000..1ed71ab26 --- /dev/null +++ b/src/FDM/JSBSim/models/FGGroundReactions.cpp @@ -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 +#include + +#include "FGGroundReactions.h" +#include + +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; iHolding()) return false; + + vForces.InitMatrix(); + vMoments.InitMatrix(); + + if ( Propagate->GetDistanceAGL() < 300.0 ) { // Only execute gear code below 300 feet + vector ::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; iFindElement("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; iTie("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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGGroundReactions.h b/src/FDM/JSBSim/models/FGGroundReactions.h new file mode 100644 index 000000000..c67f546eb --- /dev/null +++ b/src/FDM/JSBSim/models/FGGroundReactions.h @@ -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 +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# include +#endif + +#include "FGModel.h" +#include "FGLGear.h" +#include +#include + +#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 lGear; + FGColumnVector3 vForces; + FGColumnVector3 vMoments; + FGColumnVector3 vMaxStaticGrip; + FGColumnVector3 vMaxMomentResist; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/FGInertial.cpp b/src/FDM/JSBSim/models/FGInertial.cpp new file mode 100644 index 000000000..c86ba673a --- /dev/null +++ b/src/FDM/JSBSim/models/FGInertial.cpp @@ -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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGInertial.h b/src/FDM/JSBSim/models/FGInertial.h new file mode 100644 index 000000000..9433af1a6 --- /dev/null +++ b/src/FDM/JSBSim/models/FGInertial.h @@ -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 +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# include +#endif + +#include "FGModel.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 diff --git a/src/FDM/JSBSim/models/FGInput.cpp b/src/FDM/JSBSim/models/FGInput.cpp new file mode 100755 index 000000000..363c34569 --- /dev/null +++ b/src/FDM/JSBSim/models/FGInput.cpp @@ -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 +#include + +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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGInput.h b/src/FDM/JSBSim/models/FGInput.h new file mode 100755 index 000000000..071b48a01 --- /dev/null +++ b/src/FDM/JSBSim/models/FGInput.h @@ -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 +# include STL_IOSTREAM +# include STL_FSTREAM +#else +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# include +# else +# include +# include +# endif +#endif + +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 + diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp new file mode 100644 index 000000000..62fe8cc43 --- /dev/null +++ b/src/FDM/JSBSim/models/FGLGear.cpp @@ -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 + diff --git a/src/FDM/JSBSim/models/FGLGear.h b/src/FDM/JSBSim/models/FGLGear.h new file mode 100644 index 000000000..95b1d11d2 --- /dev/null +++ b/src/FDM/JSBSim/models/FGLGear.h @@ -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 +#endif + +#include +#include +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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: +

+ Physical Characteristics
+

    +
  1. X, Y, Z location, in inches in structural coordinate frame
  2. +
  3. Spring constant, in lbs/ft
  4. +
  5. Damping coefficient, in lbs/ft/sec
  6. +
  7. Dynamic Friction Coefficient
  8. +
  9. Static Friction Coefficient
  10. +

+ Operational Properties
+

    +
  1. Name
  2. +
  3. Steerability attribute {one of STEERABLE | FIXED | CASTERED}
  4. +
  5. Brake Group Membership {one of LEFT | CENTER | RIGHT | NOSE | TAIL | NONE}
  6. +
  7. Max Steer Angle, in degrees
  8. +

+

+ Algorithm and Approach to Modeling
+

    +
  1. 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.
  2. +
  3. 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.
  4. +
  5. The new gear location is now transformed to the local coordinate frame + using the body-to-local matrix. (Mb2l).
  6. +
  7. 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.
  8. +
  9. If the gear is compressed, a Weight-On-Wheels (WOW) flag is set.
  10. +
  11. 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.
  12. +
  13. 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.
  14. +
  15. The compression speed is the Z-component of the vector.
  16. +
  17. 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.
  18. +
  19. Since the friction force takes place solely in the runway plane, the Z + coordinate of the normalized wheel velocity vector is set to zero.
  20. +
  21. 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.
  22. +
  23. 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. +
  24. +
  25. The wheel force in local frame is next converted to body frame.
  26. +
  27. 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.
  28. +
+ @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 diff --git a/src/FDM/JSBSim/models/FGMassBalance.cpp b/src/FDM/JSBSim/models/FGMassBalance.cpp new file mode 100644 index 000000000..73892ba61 --- /dev/null +++ b/src/FDM/JSBSim/models/FGMassBalance.cpp @@ -0,0 +1,377 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGMassBalance.cpp + Author: Jon S. Berndt + Date started: 09/12/2000 + Purpose: This module models weight and balance + + ------------- 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 +-------------------------------------------------------------------------------- + +This class models the change in weight and balance of the aircraft due to fuel +burnoff, etc. + +HISTORY +-------------------------------------------------------------------------------- +09/12/2000 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGMassBalance.h" +#include "FGPropulsion.h" +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_MASSBALANCE; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex) +{ + Name = "FGMassBalance"; + Weight = EmptyWeight = Mass = 0.0; + + vbaseXYZcg.InitMatrix(0.0); + baseJ.InitMatrix(); + mJ.InitMatrix(); + mJinv.InitMatrix(); + pmJ.InitMatrix(); + + bind(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +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()) return true; + if (FDMExec->Holding()) return false; + + Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetPointMassWeight(); + + Mass = lbtoslug*Weight; + +// Calculate new CG + +// 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(); + + 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); + + 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 ); + + Debug(0); + + return false; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGMassBalance::AddPointMass(Element* el) +{ + 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)); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGMassBalance::GetPointMassWeight(void) +{ + double PM_total_weight = 0.0; + + for (unsigned int i=0; iTie("inertia/mass-slugs", this, + &FGMassBalance::GetMass); + PropertyManager->Tie("inertia/weight-lbs", this, + &FGMassBalance::GetWeight); + PropertyManager->Tie("inertia/cg-x-ft", this,1, + (PMF)&FGMassBalance::GetXYZcg); + PropertyManager->Tie("inertia/cg-y-ft", this,2, + (PMF)&FGMassBalance::GetXYZcg); + PropertyManager->Tie("inertia/cg-z-ft", this,3, + (PMF)&FGMassBalance::GetXYZcg); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGMassBalance::unbind(void) +{ + PropertyManager->Untie("inertia/mass-slugs"); + PropertyManager->Untie("inertia/weight-lbs"); + PropertyManager->Untie("inertia/cg-x-ft"); + PropertyManager->Untie("inertia/cg-y-ft"); + PropertyManager->Untie("inertia/cg-z-ft"); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGMassBalance::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + 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 1e9) + cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl; + if (Weight <= 0.0 || Weight > 1e9) + cout << "MassBalance::Weight out of bounds: " << Weight << endl; + if (Mass <= 0.0 || Mass > 1e9) + cout << "MassBalance::Mass out of bounds: " << Mass << endl; + } + } + if (debug_lvl & 64) { + if (from == 0) { // Constructor + cout << IdSrc << endl; + cout << IdHdr << endl; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGMassBalance.h b/src/FDM/JSBSim/models/FGMassBalance.h new file mode 100644 index 000000000..e1cfb4877 --- /dev/null +++ b/src/FDM/JSBSim/models/FGMassBalance.h @@ -0,0 +1,163 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGMassBalance.h + Author: Jon S. Berndt + Date started: 09/12/2000 + + ------------- 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. + +HISTORY +-------------------------------------------------------------------------------- +09/12/2000 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGMASSBALANCE_H +#define FGMASSBALANCE_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGModel.h" +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_MASSBALANCE "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONSS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models weight and balance information. + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGMassBalance : public FGModel +{ + +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 FGColumnVector3& GetXYZcg(void) {return vXYZcg;} + inline double GetXYZcg(int axis) const {return vXYZcg(axis);} + + /** Computes the inertia contribution of a pointmass. + Computes and returns the inertia matrix of a pointmass of mass + slugs at the given vector r in the structural frame. The units + should be for the mass in slug and the vector in the structural + frame as usual in inches. + @param slugs the mass of this single pointmass given in slugs + @param r the location of this single pointmass in the structural frame + */ + FGMatrix33 GetPointmassInertia(double slugs, const FGColumnVector3& r) const + { + FGColumnVector3 v = StructuralToBody( r ); + FGColumnVector3 sv = slugs*v; + double xx = sv(1)*v(1); + double yy = sv(2)*v(2); + double zz = sv(3)*v(3); + double xy = -sv(1)*v(2); + double xz = -sv(1)*v(3); + double yz = -sv(2)*v(3); + return FGMatrix33( yy+zz, xy, xz, + xy, xx+zz, yz, + xz, yz, xx+yy ); + } + + /** Conversion from the structural frame to the body frame. + Converts the location given in the structural frame + coordinate system to the body frame. The units of the structural + frame are assumed to be in inches. The unit of the result is in + ft. + @param r vector coordinate in the structural reference frame (X positive + aft, measurements in inches). + @return vector coordinate in the body frame, in feet. + */ + FGColumnVector3 StructuralToBody(const FGColumnVector3& r) const; + + inline void SetEmptyWeight(double EW) { EmptyWeight = EW;} + inline void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = vXYZcg = CG;} + + 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;} + + void bind(void); + void unbind(void); + +private: + double Weight; + double EmptyWeight; + double Mass; + FGMatrix33 mJ; + FGMatrix33 mJinv; + FGMatrix33 pmJ; + FGMatrix33 baseJ; + FGColumnVector3 vXYZcg; + FGColumnVector3 vXYZtank; + FGColumnVector3 vbaseXYZcg; + FGColumnVector3 vPMxyz; + 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 PointMasses; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/models/FGModel.cpp b/src/FDM/JSBSim/models/FGModel.cpp new file mode 100644 index 000000000..53f2500fc --- /dev/null +++ b/src/FDM/JSBSim/models/FGModel.cpp @@ -0,0 +1,193 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGModel.cpp + Author: Jon Berndt + Date started: 11/11/98 + Purpose: Base class for all models + Called by: FGSimExec, et. al. + + ------------- 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 base class for the FGAerodynamics, FGPropagate, etc. classes defines methods +common to all models. + +HISTORY +-------------------------------------------------------------------------------- +11/11/98 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGModel.h" +#include "FGState.h" +#include "FGFDMExec.h" +#include "FGAtmosphere.h" +#include "FGFCS.h" +#include "FGPropulsion.h" +#include "FGMassBalance.h" +#include "FGAerodynamics.h" +#include "FGInertial.h" +#include "FGGroundReactions.h" +#include "FGAircraft.h" +#include "FGPropagate.h" +#include "FGAuxiliary.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_MODEL; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +GLOBAL DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGModel::FGModel(FGFDMExec* fdmex) +{ + FDMExec = fdmex; + NextModel = 0L; + + State = 0; + Atmosphere = 0; + FCS = 0; + Propulsion = 0; + MassBalance = 0; + Aerodynamics = 0; + Inertial = 0; + GroundReactions = 0; + Aircraft = 0; + Propagate = 0; + Auxiliary = 0; + + //in order for FGModel derived classes to self-bind (that is, call + //their bind function in the constructor, the PropertyManager pointer + //must be brought up now. + PropertyManager = FDMExec->GetPropertyManager(); + + exe_ctr = 1; + rate = 1; + + if (debug_lvl & 2) cout << " FGModel Base Class" << endl; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGModel::~FGModel() +{ + if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGModel::InitModel(void) +{ + State = FDMExec->GetState(); + Atmosphere = FDMExec->GetAtmosphere(); + FCS = FDMExec->GetFCS(); + Propulsion = FDMExec->GetPropulsion(); + MassBalance = FDMExec->GetMassBalance(); + Aerodynamics = FDMExec->GetAerodynamics(); + Inertial = FDMExec->GetInertial(); + GroundReactions = FDMExec->GetGroundReactions(); + Aircraft = FDMExec->GetAircraft(); + Propagate = FDMExec->GetPropagate(); + Auxiliary = FDMExec->GetAuxiliary(); + + if (!State || + !Atmosphere || + !FCS || + !Propulsion || + !MassBalance || + !Aerodynamics || + !Inertial || + !GroundReactions || + !Aircraft || + !Propagate || + !Auxiliary) return(false); + else return(true); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGModel::Run() +{ + if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; + + if (exe_ctr == 1) { + if (exe_ctr++ >= rate) exe_ctr = 1; + return false; + } else { + if (exe_ctr++ >= rate) exe_ctr = 1; + 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 FGModel::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: FGModel" << endl; + if (from == 1) cout << "Destroyed: FGModel" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGModel.h b/src/FDM/JSBSim/models/FGModel.h new file mode 100644 index 000000000..d1907e3c2 --- /dev/null +++ b/src/FDM/JSBSim/models/FGModel.h @@ -0,0 +1,151 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGModel.h + Author: Jon Berndt + Date started: 11/21/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/22/98 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGMODEL_H +#define FGMODEL_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include + +#ifdef FGFS +# include +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# else +# include +# endif +#endif + +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_MODEL "$Id$" + +using namespace std; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGFDMExec; +class FGState; +class FGAtmosphere; +class FGFCS; +class FGPropulsion; +class FGMassBalance; +class FGAerodynamics; +class FGInertial; +class FGGroundReactions; +class FGAircraft; +class FGPropagate; +class FGAuxiliary; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Base class for all scheduled JSBSim models + @author Jon S. Berndt + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGModel : public FGJSBBase +{ +public: + + /// Constructor + FGModel(FGFDMExec*); + /// Destructor + virtual ~FGModel(); + + /** Loads this model. + @param el a pointer to the element + @return true if model is successfully loaded*/ + virtual bool Load(Element* el) {return true;} + + FGModel* NextModel; + string Name; + + /** Runs the model; called by the Executive + @see JSBSim.cpp documentation + @return false if no error */ + virtual bool Run(void); + virtual bool InitModel(void); + virtual void SetRate(int tt) {rate = tt;} + virtual int GetRate(void) {return rate;} + + void SetPropertyManager(FGPropertyManager *fgpm) { PropertyManager=fgpm;} + +protected: + int exe_ctr; + int rate; + + virtual void Debug(int from); + + FGFDMExec* FDMExec; + FGState* State; + FGAtmosphere* Atmosphere; + FGFCS* FCS; + FGPropulsion* Propulsion; + FGMassBalance* MassBalance; + FGAerodynamics* Aerodynamics; + FGInertial* Inertial; + FGGroundReactions* GroundReactions; + FGAircraft* Aircraft; + FGPropagate* Propagate; + FGAuxiliary* Auxiliary; + FGPropertyManager* PropertyManager; +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/FGOutput.cpp b/src/FDM/JSBSim/models/FGOutput.cpp new file mode 100644 index 000000000..4f1e6694f --- /dev/null +++ b/src/FDM/JSBSim/models/FGOutput.cpp @@ -0,0 +1,740 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGOutput.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 "FGOutput.h" +#include "FGState.h" +#include "FGFDMExec.h" +#include "FGAtmosphere.h" +#include "FGFCS.h" +#include "FGAerodynamics.h" +#include "FGGroundReactions.h" +#include "FGAircraft.h" +#include "FGMassBalance.h" +#include "FGPropagate.h" +#include "FGAuxiliary.h" +#include "FGInertial.h" + +#include +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_OUTPUT; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex) +{ + Name = "FGOutput"; + sFirstPass = dFirstPass = true; + socket = 0; + Type = otNone; + SubSystems = 0; + enabled = true; + delimeter = ", "; + Filename = ""; + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGOutput::~FGOutput() +{ + if (socket) delete socket; + OutputProperties.clear(); + + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGOutput::Run(void) +{ + if (FGModel::Run()) return true; + + if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) { + if (Type == otSocket) { + SocketOutput(); + } else if (Type == otCSV || Type == otTab) { + DelimitedOutput(Filename); + } else if (Type == otTerminal) { + // Not done yet + } else if (Type == otNone) { + // Do nothing + } else { + // Not a valid type of output + } + } + return false; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGOutput::SetType(string type) +{ + if (type == "CSV") { + Type = otCSV; + delimeter = ", "; + } else if (type == "TABULAR") { + Type = otTab; + delimeter = "\t"; + } else if (type == "SOCKET") { + Type = otSocket; + } else if (type == "TERMINAL") { + Type = otTerminal; + } else if (type != string("NONE")) { + Type = otUnknown; + cerr << "Unknown type of output specified in config file" << endl; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGOutput::DelimitedOutput(string fname) +{ + streambuf* buffer; + string scratch = ""; + + if (fname == "COUT" || fname == "cout") { + buffer = cout.rdbuf(); + } else { + datafile.open(fname.c_str()); + buffer = datafile.rdbuf(); + } + + ostream outstream(buffer); + + if (dFirstPass) { + outstream << "Time"; + if (SubSystems & ssSimulation) { + // Nothing here, yet + } + if (SubSystems & ssAerosurfaces) { + outstream << delimeter; + outstream << "Aileron Cmd" + delimeter; + outstream << "Elevator Cmd" + delimeter; + outstream << "Rudder Cmd" + delimeter; + outstream << "Flap Cmd" + delimeter; + outstream << "Left Aileron Pos" + delimeter; + outstream << "Right Aileron Pos" + delimeter; + outstream << "Elevator Pos" + delimeter; + outstream << "Rudder Pos" + delimeter; + outstream << "Flap Pos"; + } + if (SubSystems & ssRates) { + outstream << delimeter; + outstream << "P" + delimeter + "Q" + delimeter + "R" + delimeter; + outstream << "Pdot" + delimeter + "Qdot" + delimeter + "Rdot"; + } + if (SubSystems & ssVelocities) { + outstream << delimeter; + outstream << "QBar" + delimeter; + outstream << "Vtotal" + delimeter; + outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter; + outstream << "UAero" + delimeter + "VAero" + delimeter + "WAero" + delimeter; + outstream << "Vn" + delimeter + "Ve" + delimeter + "Vd"; + } + if (SubSystems & ssForces) { + outstream << delimeter; + outstream << "Drag" + delimeter + "Side" + delimeter + "Lift" + delimeter; + outstream << "L/D" + delimeter; + outstream << "Xforce" + delimeter + "Yforce" + delimeter + "Zforce"; + } + if (SubSystems & ssMoments) { + outstream << delimeter; + outstream << "L" + delimeter + "M" + delimeter + "N"; + } + 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) { + outstream << delimeter; + outstream << "Ixx" + delimeter; + outstream << "Ixy" + delimeter; + outstream << "Ixz" + delimeter; + outstream << "Iyx" + delimeter; + outstream << "Iyy" + delimeter; + outstream << "Iyz" + delimeter; + outstream << "Izx" + delimeter; + outstream << "Izy" + delimeter; + outstream << "Izz" + delimeter; + outstream << "Mass" + delimeter; + outstream << "Xcg" + delimeter + "Ycg" + delimeter + "Zcg"; + } + if (SubSystems & ssPropagate) { + outstream << delimeter; + outstream << "Altitude" + delimeter; + outstream << "Phi" + delimeter + "Tht" + delimeter + "Psi" + delimeter; + outstream << "Alpha" + delimeter; + outstream << "Beta" + delimeter; + outstream << "Latitude (Deg)" + delimeter; + outstream << "Longitude (Deg)" + delimeter; + outstream << "Distance AGL" + delimeter; + outstream << "Runway Radius"; + } + if (SubSystems & ssCoefficients) { + scratch = Aerodynamics->GetCoefficientStrings(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssFCS) { + scratch = FCS->GetComponentStrings(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssGroundReactions) { + outstream << delimeter; + outstream << GroundReactions->GetGroundReactionStrings(delimeter); + } + if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { + outstream << delimeter; + outstream << Propulsion->GetPropulsionStrings(delimeter); + } + if (OutputProperties.size() > 0) { + for (unsigned int i=0;iGetName(); + } + } + + outstream << endl; + dFirstPass = false; + } + + outstream << State->Getsim_time(); + if (SubSystems & ssSimulation) { + } + if (SubSystems & ssAerosurfaces) { + outstream << delimeter; + outstream << FCS->GetDaCmd() << delimeter; + outstream << FCS->GetDeCmd() << delimeter; + outstream << FCS->GetDrCmd() << delimeter; + outstream << FCS->GetDfCmd() << delimeter; + outstream << FCS->GetDaLPos() << delimeter; + outstream << FCS->GetDaRPos() << delimeter; + outstream << FCS->GetDePos() << delimeter; + outstream << FCS->GetDrPos() << delimeter; + outstream << FCS->GetDfPos(); + } + if (SubSystems & ssRates) { + outstream << delimeter; + outstream << Propagate->GetPQR().Dump(delimeter) << delimeter; + outstream << Propagate->GetPQRdot().Dump(delimeter); + } + if (SubSystems & ssVelocities) { + outstream << delimeter; + outstream << Auxiliary->Getqbar() << delimeter; + outstream << setprecision(12) << Auxiliary->GetVt() << delimeter; + outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter; + outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter; + outstream << Propagate->GetVel().Dump(delimeter); + } + if (SubSystems & ssForces) { + outstream << delimeter; + outstream << Aerodynamics->GetvFs() << delimeter; + outstream << Aerodynamics->GetLoD() << delimeter; + outstream << Aircraft->GetForces().Dump(delimeter); + } + if (SubSystems & ssMoments) { + outstream << delimeter; + outstream << Aircraft->GetMoments().Dump(delimeter); + } + 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) { + outstream << delimeter; + outstream << MassBalance->GetJ() << delimeter; + outstream << MassBalance->GetMass() << delimeter; + outstream << MassBalance->GetXYZcg(); + } + if (SubSystems & ssPropagate) { + outstream << delimeter; + outstream << Propagate->Geth() << delimeter; + outstream << Propagate->GetEuler().Dump(delimeter) << delimeter; + outstream << Auxiliary->Getalpha(inDegrees) << delimeter; + outstream << Auxiliary->Getbeta(inDegrees) << delimeter; + outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter; + outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter; + outstream << Propagate->GetDistanceAGL() << delimeter; + outstream << Propagate->GetRunwayRadius(); + } + if (SubSystems & ssCoefficients) { + scratch = Aerodynamics->GetCoefficientValues(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssFCS) { + scratch = FCS->GetComponentValues(delimeter); + if (scratch.length() != 0) outstream << delimeter << scratch; + } + if (SubSystems & ssGroundReactions) { + outstream << delimeter; + outstream << GroundReactions->GetGroundReactionValues(delimeter); + } + if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) { + outstream << delimeter; + outstream << Propulsion->GetPropulsionValues(delimeter); + } + + for (unsigned int i=0;igetDoubleValue(); + } + + outstream << endl; + outstream.flush(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGOutput::SocketOutput(void) +{ + string asciiData, scratch; + + if (socket == NULL) return; + if (!socket->GetConnectStatus()) return; + + socket->Clear(); + if (sFirstPass) { + socket->Clear(""); + socket->Append("Time"); + + 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;iAppend(OutputProperties[i]->GetName()); + } + } + + sFirstPass = false; + socket->Send(); + } + + socket->Clear(); + socket->Append(State->Getsim_time()); + + 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;iAppend(OutputProperties[i]->getDoubleValue()); + } + + socket->Send(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGOutput::SocketStatusOutput(string out_str) +{ + string asciiData; + + if (socket == NULL) return; + + socket->Clear(); + asciiData = string("") + out_str; + socket->Append(asciiData.c_str()); + socket->Send(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGOutput::Load(Element* element) +{ + string type="", parameter=""; + string name="", fname=""; + int OutRate = 0; + string property; + unsigned int port; + FGXMLParse output_file_parser; + Element *document, *property_element; + ifstream* output_file = new ifstream(); + + string separator = "/"; +# ifdef macintosh + separator = ";"; +# endif + + fname = element->GetAttributeValue("file"); + if (!fname.empty()) { + output_file_name = FDMExec->GetAircraftPath() + separator + + FDMExec->GetModelName() + separator + fname + ".xml"; + + output_file->open(output_file_name.c_str()); + readXML(*output_file, output_file_parser); + delete output_file; + document = output_file_parser.GetDocument(); + } else { + document = element; + } + + 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 (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); + rate = (int)(0.5 + 1.0/(State->Getdt()*OutRate)); + + 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 FGOutput::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 (output_file_name.empty()) + cout << " " << "Output parameters read inline" << endl; + else + cout << " Output parameters read from file: " << output_file_name << endl; + + if (Filename == "cout" || Filename == "COUT") { + scratch = " Log output goes to screen console"; + } else if (!Filename.empty()) { + scratch = " Log output goes to file: " + Filename; + } + switch (Type) { + case otCSV: + cout << scratch << " in CSV format output at rate " << 120/rate << " Hz" << endl; + break; + case otNone: + cout << " No log output" << endl; + break; + } + + if (SubSystems & ssSimulation) cout << " Simulation parameters logged" << endl; + if (SubSystems & ssAerosurfaces) cout << " Aerosurface parameters logged" << endl; + if (SubSystems & ssRates) cout << " Rate parameters logged" << endl; + if (SubSystems & ssVelocities) cout << " Velocity parameters logged" << endl; + if (SubSystems & ssForces) cout << " Force parameters logged" << endl; + if (SubSystems & ssMoments) cout << " Moments parameters logged" << endl; + if (SubSystems & ssAtmosphere) cout << " Atmosphere parameters logged" << endl; + if (SubSystems & ssMassProps) cout << " Mass parameters logged" << endl; + if (SubSystems & ssCoefficients) cout << " Coefficient parameters logged" << endl; + if (SubSystems & ssPropagate) cout << " Propagate parameters logged" << endl; + if (SubSystems & ssGroundReactions) cout << " Ground parameters logged" << endl; + if (SubSystems & ssFCS) cout << " FCS parameters logged" << endl; + if (SubSystems & ssPropulsion) cout << " Propulsion parameters logged" << endl; + if (OutputProperties.size() > 0) cout << " Properties logged:" << endl; + for (unsigned int i=0;iGetName() << endl; + } + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGOutput" << endl; + if (from == 1) cout << "Destroyed: FGOutput" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGOutput.h b/src/FDM/JSBSim/models/FGOutput.h new file mode 100644 index 000000000..35bc338d4 --- /dev/null +++ b/src/FDM/JSBSim/models/FGOutput.h @@ -0,0 +1,174 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGOutput.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 FGOUTPUT_H +#define FGOUTPUT_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGModel.h" + +#ifdef FGFS +# include +# include STL_IOSTREAM +# include STL_FSTREAM +#else +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# include +# else +# include +# include +# endif +#endif + +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_OUTPUT "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Handles simulation output. + OUTPUT section definition + + The following specifies the way that JSBSim writes out data. + + NAME is the filename you want the output to go to + + TYPE can be: + CSV Comma separated data. If a filename is supplied then the data + goes to that file. If COUT or cout is specified, the data goes + to stdout. If the filename is a null filename the data goes to + stdout, as well. + SOCKET Will eventually send data to a socket output, where NAME + would then be the IP address of the machine the data should be + sent to. DON'T USE THIS YET! + TABULAR Columnar data. NOT IMPLEMENTED YET! + TERMINAL Output to terminal. NOT IMPLEMENTED YET! + NONE Specifies to do nothing. THis setting makes it easy to turn on and + off the data output without having to mess with anything else. + + The arguments that can be supplied, currently, are + + RATE_IN_HZ An integer rate in times-per-second that the data is output. This + value may not be *exactly* what you want, due to the dependence + on dt, the cycle rate for the FDM. + + The following parameters tell which subsystems of data to output: + + SIMULATION ON|OFF + ATMOSPHERE ON|OFF + MASSPROPS ON|OFF + AEROSURFACES ON|OFF + RATES ON|OFF + VELOCITIES ON|OFF + FORCES ON|OFF + MOMENTS ON|OFF + POSITION ON|OFF + COEFFICIENTS ON|OFF + GROUND_REACTIONS ON|OFF + FCS ON|OFF + PROPULSION ON|OFF + + NOTE that Time is always output with the data. + @version $Id$ + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGOutput : public FGModel +{ +public: + FGOutput(FGFDMExec*); + ~FGOutput(); + + bool Run(void); + + void DelimitedOutput(string); + void SocketOutput(void); + void SocketStatusOutput(string); + 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(Element* el); + + /// Subsystem types for specifying which will be output in the FDM data logging + enum eSubSystems { + /** Subsystem: Simulation (= 1) */ ssSimulation = 1, + /** Subsystem: Aerosurfaces (= 2) */ ssAerosurfaces = 2, + /** Subsystem: Body rates (= 4) */ ssRates = 4, + /** Subsystem: Velocities (= 8) */ ssVelocities = 8, + /** Subsystem: Forces (= 16) */ ssForces = 16, + /** Subsystem: Moments (= 32) */ ssMoments = 32, + /** Subsystem: Atmosphere (= 64) */ ssAtmosphere = 64, + /** Subsystem: Mass Properties (= 128) */ ssMassProps = 128, + /** Subsystem: Coefficients (= 256) */ ssCoefficients = 256, + /** Subsystem: Propagate (= 512) */ ssPropagate = 512, + /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024, + /** Subsystem: FCS (= 2048) */ ssFCS = 2048, + /** Subsystem: Propulsion (= 4096) */ ssPropulsion = 4096 + } subsystems; + +private: + bool sFirstPass, dFirstPass, enabled; + int SubSystems; + string output_file_name, delimeter, Filename; + enum {otNone, otCSV, otTab, otSocket, otTerminal, otUnknown} Type; + ofstream datafile; + FGfdmSocket* socket; + vector OutputProperties; + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/FGPropagate.cpp b/src/FDM/JSBSim/models/FGPropagate.cpp new file mode 100644 index 000000000..fcd7861bf --- /dev/null +++ b/src/FDM/JSBSim/models/FGPropagate.cpp @@ -0,0 +1,418 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGPropagate.cpp + Author: Jon S. Berndt + Date started: 01/05/99 + Purpose: Integrate the EOM to determine instantaneous position + 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 +-------------------------------------------------------------------------------- +This class encapsulates the integration of rates and accelerations to get the +current position of the aircraft. + +HISTORY +-------------------------------------------------------------------------------- +01/05/99 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +COMMENTS, REFERENCES, and NOTES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling + Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate + School, January 1994 +[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices", + JSC 12960, July 1977 +[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at + NASA-Ames", NASA CR-2497, January 1975 +[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics", + Wiley & Sons, 1979 ISBN 0-471-03032-5 +[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons, + 1982 ISBN 0-471-08936-2 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# ifdef SG_HAVE_STD_INCLUDES +# include +# include +# else +# include +# include +# endif +#else +# if defined(sgi) && !defined(__GNUC__) +# include +# if (_COMPILER_VERSION < 740) +# include +# else +# include +# endif +# else +# include +# include +# endif +#endif + +#include "FGPropagate.h" +#include +#include +#include "FGAircraft.h" +#include "FGMassBalance.h" +#include "FGInertial.h" +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_PROPAGATE; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex) +{ + Name = "FGPropagate"; + + bind(); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGPropagate::~FGPropagate(void) +{ + unbind(); + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropagate::InitModel(void) +{ + FGModel::InitModel(); + + SeaLevelRadius = Inertial->RefRadius(); // For initialization ONLY + RunwayRadius = SeaLevelRadius; + + VState.vLocation.SetRadius( SeaLevelRadius + 4.0 ); + + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropagate::SetInitialState(const FGInitialCondition *FGIC) +{ + SeaLevelRadius = FGIC->GetSeaLevelRadiusFtIC(); + RunwayRadius = SeaLevelRadius; + + // Set the position lat/lon/radius + VState.vLocation = FGLocation( FGIC->GetLongitudeRadIC(), + FGIC->GetLatitudeRadIC(), + FGIC->GetAltitudeFtIC() + FGIC->GetSeaLevelRadiusFtIC() ); + + // Set the Orientation from the euler angles + VState.vQtrn = FGQuaternion( FGIC->GetPhiRadIC(), + FGIC->GetThetaRadIC(), + FGIC->GetPsiRadIC() ); + + // Set the velocities in the instantaneus body frame + VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(), + FGIC->GetVBodyFpsIC(), + FGIC->GetWBodyFpsIC() ); + + // Set the angular velocities in the instantaneus body frame. + VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(), + FGIC->GetQRadpsIC(), + FGIC->GetRRadpsIC() ); + + // Compute some derived values. + vVel = VState.vQtrn.GetTInv()*VState.vUVW; + + // Finally, make sure that the quaternion stays normalized. + VState.vQtrn.Normalize(); + + // Recompute the RunwayRadius level. + RecomputeRunwayRadius(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/* +Purpose: Called on a schedule to perform EOM integration +Notes: [JB] Run in standalone mode, SeaLevelRadius will be reference radius. + In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass. + +At the top of this Run() function, see several "shortcuts" (or, aliases) being +set up for use later, rather than using the longer class->function() notation. + +Here, propagation of state is done using a simple explicit Euler scheme (see the +bottom of the function). This propagation is done using the current state values +and current derivatives. Based on these values we compute an approximation to the +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(); + + double dt = State->Getdt()*rate; // The 'stepsize' + const FGColumnVector3 omega( 0.0, 0.0, Inertial->omega() ); // earth rotation + const FGColumnVector3& vForces = Aircraft->GetForces(); // current forces + const FGColumnVector3& vMoments = Aircraft->GetMoments(); // current moments + + double mass = MassBalance->GetMass(); // mass + const FGMatrix33& J = MassBalance->GetJ(); // inertia matrix + const FGMatrix33& Jinv = MassBalance->GetJinv(); // inertia matrix inverse + double r = GetRadius(); // radius + if (r == 0.0) {cerr << "radius = 0 !" << endl; r = 1e-16;} // radius check + double rInv = 1.0/r; + FGColumnVector3 gAccel( 0.0, 0.0, Inertial->GetGAccel(r) ); + + // The rotation matrices: + const FGMatrix33& Tl2b = GetTl2b(); // local to body frame + const FGMatrix33& Tb2l = GetTb2l(); // body to local frame + const FGMatrix33& Tec2l = VState.vLocation.GetTec2l(); // earth centered to local frame + const FGMatrix33& Tl2ec = VState.vLocation.GetTl2ec(); // local to earth centered frame + + // Inertial angular velocity measured in the body frame. + const FGColumnVector3 pqri = VState.vPQR + Tl2b*(Tec2l*omega); + + // Compute vehicle velocity wrt EC frame, expressed in Local horizontal frame. + vVel = Tb2l * VState.vUVW; + + // First compute the time derivatives of the vehicle state values: + + // Compute body frame rotational accelerations based on the current body moments + vPQRdot = Jinv*(vMoments - pqri*(J*pqri)); + + // Compute body frame accelerations based on the current body forces + vUVWdot = VState.vUVW*VState.vPQR + vForces/mass; + + // Coriolis acceleration. + FGColumnVector3 ecVel = Tl2ec*vVel; + FGColumnVector3 ace = 2.0*omega*ecVel; + vUVWdot -= Tl2b*(Tec2l*ace); + + if (!GroundReactions->GetWOW()) { + // Centrifugal acceleration. + FGColumnVector3 aeec = omega*(omega*VState.vLocation); + vUVWdot -= Tl2b*(Tec2l*aeec); + } + + // Gravitation accel + vUVWdot += Tl2b*gAccel; + + // Compute vehicle velocity wrt EC frame, expressed in EC frame + FGColumnVector3 vLocationDot = Tl2ec * vVel; + + FGColumnVector3 omegaLocal( rInv*vVel(eEast), + -rInv*vVel(eNorth), + -rInv*vVel(eEast)*VState.vLocation.GetTanLatitude() ); + + // Compute quaternion orientation derivative on current body rates + FGQuaternion vQtrndot = VState.vQtrn.GetQDot( VState.vPQR - Tl2b*omegaLocal ); + + // Propagate velocities + VState.vPQR += dt*vPQRdot; + VState.vUVW += dt*vUVWdot; + + // Propagate positions + VState.vQtrn += dt*vQtrndot; + VState.vLocation += dt*vLocationDot; + + return false; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropagate::RecomputeRunwayRadius(void) +{ + // Get the runway radius. + FGLocation contactloc; + FGColumnVector3 dv; + FGGroundCallback* gcb = FDMExec->GetGroundCallback(); + double t = State->Getsim_time(); + gcb->GetAGLevel(t, VState.vLocation, contactloc, dv, dv); + RunwayRadius = contactloc.GetRadius(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropagate::Seth(double tt) +{ + VState.vLocation.SetRadius( tt + SeaLevelRadius ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGPropagate::GetRunwayRadius(void) const +{ + return RunwayRadius; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGPropagate::GetDistanceAGL(void) const +{ + return VState.vLocation.GetRadius() - RunwayRadius; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropagate::SetDistanceAGL(double tt) +{ + VState.vLocation.SetRadius( tt + RunwayRadius ); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropagate::bind(void) +{ + typedef double (FGPropagate::*PMF)(int) const; + PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot); + + PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel); + PropertyManager->Tie("velocities/v-east-fps", this, eEast, (PMF)&FGPropagate::GetVel); + PropertyManager->Tie("velocities/v-down-fps", this, eDown, (PMF)&FGPropagate::GetVel); + + PropertyManager->Tie("velocities/u-fps", this, eU, (PMF)&FGPropagate::GetUVW); + PropertyManager->Tie("velocities/v-fps", this, eV, (PMF)&FGPropagate::GetUVW); + PropertyManager->Tie("velocities/w-fps", this, eW, (PMF)&FGPropagate::GetUVW); + + PropertyManager->Tie("velocities/p-rad_sec", this, eP, (PMF)&FGPropagate::GetPQR); + PropertyManager->Tie("velocities/q-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQR); + PropertyManager->Tie("velocities/r-rad_sec", this, eR, (PMF)&FGPropagate::GetPQR); + + PropertyManager->Tie("accelerations/pdot-rad_sec", this, eP, (PMF)&FGPropagate::GetPQRdot); + PropertyManager->Tie("accelerations/qdot-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQRdot); + PropertyManager->Tie("accelerations/rdot-rad_sec", this, eR, (PMF)&FGPropagate::GetPQRdot); + + PropertyManager->Tie("accelerations/udot-fps", this, eU, (PMF)&FGPropagate::GetUVWdot); + PropertyManager->Tie("accelerations/vdot-fps", this, eV, (PMF)&FGPropagate::GetUVWdot); + PropertyManager->Tie("accelerations/wdot-fps", this, eW, (PMF)&FGPropagate::GetUVWdot); + + PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::Geth, &FGPropagate::Seth, true); + PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude); + PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude); + PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL); + PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius); + + PropertyManager->Tie("metrics/runway-radius", this, &FGPropagate::GetRunwayRadius); + + PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); + + PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); + PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropagate::unbind(void) +{ + PropertyManager->Untie("velocities/v-north-fps"); + PropertyManager->Untie("velocities/v-east-fps"); + PropertyManager->Untie("velocities/v-down-fps"); + PropertyManager->Untie("velocities/h-dot-fps"); + PropertyManager->Untie("velocities/u-fps"); + PropertyManager->Untie("velocities/v-fps"); + PropertyManager->Untie("velocities/w-fps"); + PropertyManager->Untie("velocities/p-rad_sec"); + PropertyManager->Untie("velocities/q-rad_sec"); + PropertyManager->Untie("velocities/r-rad_sec"); + PropertyManager->Untie("accelerations/udot-fps"); + PropertyManager->Untie("accelerations/vdot-fps"); + PropertyManager->Untie("accelerations/wdot-fps"); + PropertyManager->Untie("accelerations/pdot-rad_sec"); + PropertyManager->Untie("accelerations/qdot-rad_sec"); + PropertyManager->Untie("accelerations/rdot-rad_sec"); + PropertyManager->Untie("position/h-sl-ft"); + PropertyManager->Untie("position/lat-gc-rad"); + PropertyManager->Untie("position/long-gc-rad"); + PropertyManager->Untie("position/h-agl-ft"); + PropertyManager->Untie("position/radius-to-vehicle-ft"); + PropertyManager->Untie("metrics/runway-radius"); + PropertyManager->Untie("attitude/phi-rad"); + PropertyManager->Untie("attitude/theta-rad"); + PropertyManager->Untie("attitude/psi-rad"); + PropertyManager->Untie("attitude/roll-rad"); + PropertyManager->Untie("attitude/pitch-rad"); + PropertyManager->Untie("attitude/heading-true-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 FGPropagate::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: FGPropagate" << endl; + if (from == 1) cout << "Destroyed: FGPropagate" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGPropagate.h b/src/FDM/JSBSim/models/FGPropagate.h new file mode 100644 index 000000000..2c0fef1d4 --- /dev/null +++ b/src/FDM/JSBSim/models/FGPropagate.h @@ -0,0 +1,166 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGPropagate.h + Author: Jon S. Berndt + Date started: 1/5/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 +-------------------------------------------------------------------------------- +01/05/99 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGPROPAGATE_H +#define FGPROPAGATE_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_PROPAGATE "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models the EOM and integration/propagation of state + @author Jon S. Berndt, Mathias Froehlich + @version $Id$ + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +// state vector + +struct VehicleState { + FGLocation vLocation; + FGColumnVector3 vUVW; + FGColumnVector3 vPQR; + FGQuaternion vQtrn; +}; + +class FGPropagate : public FGModel { +public: + /** Constructor + @param Executive a pointer to the parent executive object */ + FGPropagate(FGFDMExec* Executive); + + /// Destructor + ~FGPropagate(); + + bool InitModel(void); + + /** Runs the Propagate model; called by the Executive + @return false if no error */ + bool Run(void); + + const FGColumnVector3& GetVel(void) const { return vVel; } + const FGColumnVector3& GetUVW(void) const { return VState.vUVW; } + const FGColumnVector3& GetUVWdot(void) const { return vUVWdot; } + const FGColumnVector3& GetPQR(void) const {return VState.vPQR;} + const FGColumnVector3& GetPQRdot(void) const {return vPQRdot;} + const FGColumnVector3& GetEuler(void) const { return VState.vQtrn.GetEuler(); } + + double GetUVW (int idx) const { return VState.vUVW(idx); } + double GetUVWdot(int idx) const { return vUVWdot(idx); } + double GetVel(int idx) const { return vVel(idx); } + double Geth(void) const { return VState.vLocation.GetRadius() - SeaLevelRadius; } + double GetPQR(int axis) const {return VState.vPQR(axis);} + double GetPQRdot(int idx) const {return vPQRdot(idx);} + double GetEuler(int axis) const { return VState.vQtrn.GetEuler(axis); } + double GetCosEuler(int idx) const { return VState.vQtrn.GetCosEuler(idx); } + double GetSinEuler(int idx) const { return VState.vQtrn.GetSinEuler(idx); } + double Gethdot(void) const { return -vVel(eDown); } + + /** Returns the "constant" RunwayRadius. + The RunwayRadius parameter is set by the calling application or set to + zero if JSBSim is running in standalone mode. + @return distance of the runway from the center of the earth. + @units feet */ + double GetRunwayRadius(void) const; + double GetSeaLevelRadius(void) const { return SeaLevelRadius; } + double GetDistanceAGL(void) const; + double GetRadius(void) const { return VState.vLocation.GetRadius(); } + double GetLongitude(void) const { return VState.vLocation.GetLongitude(); } + double GetLatitude(void) const { return VState.vLocation.GetLatitude(); } + const FGLocation& GetLocation(void) const { return VState.vLocation; } + + /** Retrieves the local-to-body transformation matrix. + @return a reference to the local-to-body transformation matrix. */ + const FGMatrix33& GetTl2b(void) const { return VState.vQtrn.GetT(); } + + /** Retrieves the body-to-local transformation matrix. + @return a reference to the body-to-local matrix. */ + const FGMatrix33& GetTb2l(void) const { return VState.vQtrn.GetTInv(); } + +// SET functions + + void SetLongitude(double lon) { VState.vLocation.SetLongitude(lon); } + void SetLatitude(double lat) { VState.vLocation.SetLatitude(lat); } + void SetRadius(double r) { VState.vLocation.SetRadius(r); } + void SetLocation(const FGLocation& l) { VState.vLocation = l; } + void Seth(double tt); + void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; } + void SetDistanceAGL(double tt); + void SetInitialState(const FGInitialCondition *); + void RecomputeRunwayRadius(void); + + void bind(void); + void unbind(void); + +private: + +// state vector + + struct VehicleState VState; + + FGColumnVector3 vVel; + FGColumnVector3 vPQRdot; + FGColumnVector3 vUVWdot; + + double RunwayRadius, SeaLevelRadius; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp new file mode 100644 index 000000000..306126cca --- /dev/null +++ b/src/FDM/JSBSim/models/FGPropulsion.cpp @@ -0,0 +1,632 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGPropulsion.cpp + Author: Jon S. Berndt + Date started: 08/20/00 + Purpose: Encapsulates the set of engines and tanks associated + with this aircraft + + ------------- 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 +-------------------------------------------------------------------------------- +The Propulsion class is the container for the entire propulsion system, which is +comprised of engines and tanks. Once the Propulsion class gets the config file, +it reads in information which is specific to a type of engine. Then: + +1) The appropriate engine type instance is created +2) At least one tank object is created, and is linked to an engine. + +At Run time each engines Calculate() method is called. + +HISTORY +-------------------------------------------------------------------------------- +08/20/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGPropulsion.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_PROPULSION; + +extern short debug_lvl; + + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec) +{ + Name = "FGPropulsion"; + + numSelectedFuelTanks = numSelectedOxiTanks = 0; + numTanks = numEngines = 0; + numOxiTanks = numFuelTanks = 0; + ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ... + tankJ.InitMatrix(); + refuel = false; + fuel_freeze = false; + TotalFuelQuantity = 0.0; + IsBound = + HavePistonEngine = + HaveTurbineEngine = + HaveRocketEngine = + HaveTurboPropEngine = + HaveElectricEngine = false; + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGPropulsion::~FGPropulsion() +{ + for (unsigned int i=0; iHolding()) return false; + + double dt = State->Getdt(); + + vForces.InitMatrix(); + vMoments.InitMatrix(); + + for (i=0; iCalculate(); + vForces += Engines[i]->GetBodyForces(); // sum body frame forces + vMoments += Engines[i]->GetMoments(); // sum body frame moments + } + + TotalFuelQuantity = 0.0; + for (i=0; iCalculate( dt * rate ); + if (Tanks[i]->GetType() == FGTank::ttFUEL) { + TotalFuelQuantity += Tanks[i]->GetContents(); + } + } + + if (refuel) DoRefuel( dt * rate ); + + return false; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropulsion::GetSteadyState(void) +{ + double currentThrust = 0, lastThrust=-1; + int steady_count,j=0; + bool steady=false; + + vForces.InitMatrix(); + vMoments.InitMatrix(); + + if (!FGModel::Run()) { + for (unsigned int i=0; iSetTrimMode(true); + steady=false; + steady_count=0; + while (!steady && j < 6000) { + Engines[i]->Calculate(); + lastThrust = currentThrust; + currentThrust = Engines[i]->GetThrust(); + if (fabs(lastThrust-currentThrust) < 0.0001) { + steady_count++; + if (steady_count > 120) { steady=true; } + } else { + steady_count=0; + } + j++; + } + vForces += Engines[i]->GetBodyForces(); // sum body frame forces + vMoments += Engines[i]->GetMoments(); // sum body frame moments + Engines[i]->SetTrimMode(false); + } + + return false; + } else { + return true; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropulsion::ICEngineStart(void) +{ + int j; + + vForces.InitMatrix(); + vMoments.InitMatrix(); + + for (unsigned int i=0; iSetTrimMode(true); + j=0; + while (!Engines[i]->GetRunning() && j < 2000) { + Engines[i]->Calculate(); + j++; + } + vForces += Engines[i]->GetBodyForces(); // sum body frame forces + vMoments += Engines[i]->GetMoments(); // sum body frame moments + Engines[i]->SetTrimMode(false); + } + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGPropulsion::Load(Element* el) +{ + string type, engine_filename; + int Feed; + bool ThrottleAdded = false; + Element* document; + FGXMLParse engine_file_parser; + ifstream* engine_file; + + Debug(2); + + Element* engine_element = el->FindElement("engine"); + while (engine_element) { + engine_filename = engine_element->GetAttributeValue("file"); + + if (engine_filename.empty()) { + cerr << "Engine definition did not supply an engine file." << endl; + return false; + } + + 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 + + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +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; + + string PropulsionStrings = ""; + bool firstime = true; + stringstream buf; + + for (i=0; iGetEngineLabels(delimeter); + } + for (i=0; iGetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i; + else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i; + } + + return PropulsionStrings; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPropulsion::GetPropulsionValues(string delimeter) +{ + unsigned int i; + + string PropulsionValues = ""; + bool firstime = true; + stringstream buf; + + for (i=0; iGetEngineValues(delimeter); + } + for (i=0; iGetContents(); + } + + return PropulsionValues; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGColumnVector3& FGPropulsion::GetTanksMoment(void) +{ + iTank = Tanks.begin(); + vXYZtank_arm.InitMatrix(); + while (iTank < Tanks.end()) { + vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents(); + vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents(); + vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents(); + iTank++; + } + return vXYZtank_arm; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGPropulsion::GetTanksWeight(void) +{ + double Tw = 0.0; + + iTank = Tanks.begin(); + while (iTank < Tanks.end()) { + Tw += (*iTank)->GetContents(); + iTank++; + } + return Tw; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33& FGPropulsion::CalculateTankInertias(void) +{ + unsigned int size; + + size = Tanks.size(); + if (size == 0) return tankJ; + + tankJ = FGMatrix33(); + + for (unsigned int i=0; iGetPointmassInertia( lbtoslug * Tanks[i]->GetContents(), + Tanks[i]->GetXYZ() ); + + return tankJ; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropulsion::SetMagnetos(int setting) +{ + if (ActiveEngine < 0) { + for (unsigned i=0; iSetMagnetos(setting); + } + } else { + ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropulsion::SetStarter(int setting) +{ + if (ActiveEngine < 0) { + for (unsigned i=0; iSetStarter(false); + else + Engines[i]->SetStarter(true); + } + } else { + if (setting == 0) + Engines[ActiveEngine]->SetStarter(false); + else + Engines[ActiveEngine]->SetStarter(true); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropulsion::SetCutoff(int setting) +{ + if (ActiveEngine < 0) { + for (unsigned i=0; iSetCutoff(false); + else + ((FGTurbine*)Engines[i])->SetCutoff(true); + } + } else { + if (setting == 0) + ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false); + else + ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropulsion::SetActiveEngine(int engine) +{ + if (engine >= Engines.size() || engine < 0) + ActiveEngine = -1; + else + ActiveEngine = engine; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGPropulsion::Transfer(int source, int target, double amount) +{ + double shortage, overage; + + if (source == -1) { + shortage = 0.0; + } else { + shortage = Tanks[source]->Drain(amount); + } + if (target == -1) { + overage = 0.0; + } else { + overage = Tanks[target]->Fill(amount - shortage); + } + return overage; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropulsion::DoRefuel(double time_slice) +{ + unsigned int i; + + double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min + int TanksNotFull = 0; + + for (i=0; iGetPctFull() < 99.99) ++TanksNotFull; + } + + if (TanksNotFull) { + for (i=0; iGetPctFull() < 99.99) + Transfer(-1, i, fillrate/TanksNotFull); + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropulsion::SetFuelFreeze(bool f) +{ + fuel_freeze = f; + for (unsigned int i=0; iSetFuelFreeze(f); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropulsion::bind(void) +{ + typedef double (FGPropulsion::*PMF)(int) const; + typedef int (FGPropulsion::*iPMF)(void) const; + + IsBound = true; + + if (HaveTurbineEngine) { + PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true); + PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, 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) +{ + 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("propulsion/total-fuel-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 FGPropulsion::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 2) { // Loader + cout << endl << " Propulsion:" << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPropulsion" << endl; + if (from == 1) cout << "Destroyed: FGPropulsion" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/FGPropulsion.h b/src/FDM/JSBSim/models/FGPropulsion.h new file mode 100644 index 000000000..6ae3324ac --- /dev/null +++ b/src/FDM/JSBSim/models/FGPropulsion.h @@ -0,0 +1,219 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGPropulsion.h + Author: Jon S. Berndt + Date started: 08/20/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 +-------------------------------------------------------------------------------- +08/20/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGPROPULSION_H +#define FGPROPULSION_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# ifdef SG_HAVE_STD_INCLUDES +# include +# include +# include +# else +# include +# include +# include +# endif +#else +# include +# include +# include +#endif + +#include "FGModel.h" +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_PROPULSION "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Propulsion management class. + The Propulsion class is the container for the entire propulsion system, which is + comprised of engines, and tanks. Once the Propulsion class gets the config file, + it reads in information which is specific to a type of engine. Then: + + -# The appropriate engine type instance is created + -# At least one tank object is created, and is linked to an engine. + + At Run time each engines Calculate() method is called. + @author Jon S. Berndt + @version $Id$ + @see + FGEngine + FGTank +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGPropulsion : public FGModel +{ +public: + /// Constructor + FGPropulsion(FGFDMExec*); + /// Destructor + ~FGPropulsion(); + + /** Executes the propulsion model. + The initial plan for the FGPropulsion class calls for Run() to be executed, + calculating the power available from the engine. + + [Note: Should we be checking the Starved flag here?] */ + bool Run(void); + + /** Loads the propulsion system (engine[s] and tank[s]). + Characteristics of the propulsion system are read in from the config file. + @param el pointer to an XML element that contains the engine information. + @return true if successfully loaded, otherwise false */ + bool Load(Element* el); + + /// Retrieves the number of engines defined for the aircraft. + inline unsigned int GetNumEngines(void) const {return Engines.size();} + + /** Retrieves an engine object pointer from the list of engines. + @param index the engine index within the vector container + @return the address of the specific engine, or zero if no such engine is + available */ + inline FGEngine* GetEngine(unsigned int index) { + if (index <= Engines.size()-1) return Engines[index]; + else return 0L; } + + /// Retrieves the number of tanks defined for the aircraft. + inline unsigned int GetNumTanks(void) const {return Tanks.size();} + + /** Retrieves a tank object pointer from the list of tanks. + @param index the tank index within the vector container + @return the address of the specific tank, or zero if no such tank is + available */ + inline FGTank* GetTank(unsigned int index) { + if (index <= Tanks.size()-1) return Tanks[index]; + else return 0L; } + + /** Returns the number of fuel tanks currently actively supplying fuel */ + inline int GetnumSelectedFuelTanks(void) const {return numSelectedFuelTanks;} + + /** Returns the number of oxidizer tanks currently actively supplying oxidizer */ + inline int GetnumSelectedOxiTanks(void) const {return numSelectedOxiTanks;} + + /** Loops the engines until thrust output steady (used for trimming) */ + bool GetSteadyState(void); + + /** starts the engines in IC mode (dt=0). All engine-specific setup must + be done before calling this (i.e. magnetos, starter engage, etc.) */ + bool ICEngineStart(void); + + string GetPropulsionStrings(string delimeter); + string GetPropulsionValues(string delimeter); + + inline FGColumnVector3& GetForces(void) {return vForces; } + inline double GetForces(int n) const { return vForces(n);} + inline FGColumnVector3& GetMoments(void) {return vMoments;} + inline double GetMoments(int n) const {return vMoments(n);} + + inline bool GetRefuel(void) {return refuel;} + 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); + + 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); + FGMatrix33& CalculateTankInertias(void); + + void bind(); + void unbind(); + +private: + vector Engines; + vector Tanks; + vector ::iterator iTank; + unsigned int numSelectedFuelTanks; + unsigned int numSelectedOxiTanks; + unsigned int numFuelTanks; + unsigned int numOxiTanks; + unsigned int numEngines; + unsigned int numTanks; + int ActiveEngine; + FGColumnVector3 vForces; + FGColumnVector3 vMoments; + FGColumnVector3 vTankXYZ; + FGColumnVector3 vXYZtank_arm; + 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); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/Makefile.am b/src/FDM/JSBSim/models/Makefile.am new file mode 100644 index 000000000..10c65a77e --- /dev/null +++ b/src/FDM/JSBSim/models/Makefile.am @@ -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 diff --git a/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp b/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp new file mode 100755 index 000000000..1930b3fab --- /dev/null +++ b/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp @@ -0,0 +1,1667 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGMSIS.cpp + Author: David Culp + (incorporated into C++ JSBSim class heirarchy, see model authors below) + Date started: 12/14/03 + Purpose: Models the MSIS-00 atmosphere + + ------------- 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. + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- +Models the MSIS-00 atmosphere. Provides temperature and density to FGAtmosphere, +given day-of-year, time-of-day, altitude, latitude, longitude and local time. + +HISTORY +-------------------------------------------------------------------------------- +12/14/03 DPC Created +01/11/04 DPC Derived from FGAtmosphere + + -------------------------------------------------------------------- + --------- 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. +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGMSIS.h" +#include "FGState.h" +#include /* maths functions */ +#include /* for malloc/free */ +#include /* for printf */ +#include // for cout, endl + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_MSIS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +EXTERNAL GLOBAL DATA +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + /* POWER7 */ + extern double pt[150]; + extern double pd[9][150]; + extern double ps[150]; + extern double pdl[2][25]; + extern double ptl[4][100]; + extern double pma[10][100]; + extern double sam[100]; + + /* LOWER7 */ + extern double ptm[10]; + extern double pdm[8][10]; + extern double pavgm[10]; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +MSIS::MSIS(FGFDMExec* fdmex) : FGAtmosphere(fdmex) +{ + Name = "MSIS"; + bind(); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +MSIS::~MSIS() +{ + unbind(); + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool MSIS::InitModel(void) +{ + FGModel::InitModel(); + + unsigned int i; + + flags.switches[0] = 0; + for (i=1;i<24;i++) flags.switches[i] = 1; + + for (i=0;i<7;i++) aph.a[i] = 100.0; + + // set some common magnetic flux values + input.f107A = 150.0; + input.f107 = 150.0; + input.ap = 4.0; + + SLtemperature = intTemperature = 518.0; + SLpressure = intPressure = 2116.7; + SLdensity = intDensity = 0.002378; + SLsoundspeed = sqrt(2403.0832 * SLtemperature); + 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 MSIS::Run(void) +{ + if (FGModel::Run()) return true; + if (FDMExec->Holding()) return false; + + //do temp, pressure, and density first + if (!useExternal) { + // get sea-level values + Calculate(Auxiliary->GetDayOfYear(), + Auxiliary->GetSecondsInDay(), + 0.0, + Propagate->GetLocation().GetLatitudeDeg(), + Propagate->GetLocation().GetLongitudeDeg()); + SLtemperature = output.t[1] * 1.8; + SLdensity = output.d[5] * 1.940321; + SLpressure = 1716.488 * SLdensity * SLtemperature; + SLsoundspeed = sqrt(2403.0832 * SLtemperature); + rSLtemperature = 1.0/SLtemperature; + rSLpressure = 1.0/SLpressure; + rSLdensity = 1.0/SLdensity; + rSLsoundspeed = 1.0/SLsoundspeed; + + // get at-altitude values + Calculate(Auxiliary->GetDayOfYear(), + Auxiliary->GetSecondsInDay(), + Propagate->Geth(), + Propagate->GetLocation().GetLatitudeDeg(), + Propagate->GetLocation().GetLongitudeDeg()); + intTemperature = output.t[1] * 1.8; + intDensity = output.d[5] * 1.940321; + intPressure = 1716.488 * intDensity * intTemperature; + soundspeed = sqrt(2403.0832 * intTemperature); + //cout << "T=" << intTemperature << " D=" << intDensity << " P="; + //cout << intPressure << " a=" << soundspeed << endl; + } + + if (turbType != ttNone) { + Turbulence(); + vWindNED += vTurbulence; + } + + if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) ); + + if (psiw < 0) psiw += 2*M_PI; + + Debug(2); + + return false; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::Calculate(int day, double sec, double alt, double lat, double lon) +{ + input.year = 2000; + input.doy = day; + input.sec = sec; + input.alt = alt / 3281; //feet to kilometers + input.g_lat = lat; + input.g_long = lon; + + input.lst = (sec/3600) + (lon/15); + if (input.lst > 24.0) input.lst -= 24.0; + if (input.lst < 0.0) input.lst = 24 - input.lst; + + gtd7d(&input, &flags, &output); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +void MSIS::UseExternal(void){ + // do nothing, external control not allowed +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +void MSIS::tselec(struct nrlmsise_flags *flags) +{ + int i; + for (i=0;i<24;i++) { + if (i!=9) { + if (flags->switches[i]==1) + flags->sw[i]=1; + else + flags->sw[i]=0; + if (flags->switches[i]>0) + flags->swc[i]=1; + else + flags->swc[i]=0; + } else { + flags->sw[i]=flags->switches[i]; + flags->swc[i]=flags->switches[i]; + } + } +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::glatf(double lat, double *gv, double *reff) +{ + double dgtr = 1.74533E-2; + double c2; + c2 = cos(2.0*dgtr*lat); + *gv = 980.616 * (1.0 - 0.0026373 * c2); + *reff = 2.0 * (*gv) / (3.085462E-6 + 2.27E-9 * c2) * 1.0E-5; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::ccor(double alt, double r, double h1, double zh) +{ +/* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS + * ALT - altitude + * R - target ratio + * H1 - transition scale length + * ZH - altitude of 1/2 R + */ + double e; + double ex; + e = (alt - zh) / h1; + if (e>70) + return exp(0.0); + if (e<-70) + return exp(r); + ex = exp(e); + e = r / (1.0 + ex); + return exp(e); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::ccor2(double alt, double r, double h1, double zh, double h2) +{ +/* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS + * ALT - altitude + * R - target ratio + * H1 - transition scale length + * ZH - altitude of 1/2 R + * H2 - transition scale length #2 ? + */ + double e1, e2; + double ex1, ex2; + double ccor2v; + e1 = (alt - zh) / h1; + e2 = (alt - zh) / h2; + if ((e1 > 70) || (e2 > 70)) + return exp(0.0); + if ((e1 < -70) && (e2 < -70)) + return exp(r); + ex1 = exp(e1); + ex2 = exp(e2); + ccor2v = r / (1.0 + 0.5 * (ex1 + ex2)); + return exp(ccor2v); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::scalh(double alt, double xm, double temp) +{ + double g; + double rgas=831.4; + g = gsurf / (pow((1.0 + alt/re),2.0)); + g = rgas * temp / (g * xm); + return g; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::dnet (double dd, double dm, double zhm, double xmm, double xm) +{ +/* TURBOPAUSE CORRECTION FOR MSIS MODELS + * Root mean density + * DD - diffusive density + * DM - full mixed density + * ZHM - transition scale length + * XMM - full mixed molecular weight + * XM - species molecular weight + * DNET - combined density + */ + double a; + double ylog; + a = zhm / (xmm-xm); + if (!((dm>0) && (dd>0))) { + printf("dnet log error %e %e %e\n",dm,dd,xm); + if ((dd==0) && (dm==0)) + dd=1; + if (dm==0) + return dd; + if (dd==0) + return dm; + } + ylog = a * log(dm/dd); + if (ylog<-10) + return dd; + if (ylog>10) + return dm; + a = dd*pow((1.0 + exp(ylog)),(1.0/a)); + return a; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::splini (double *xa, double *ya, double *y2a, int n, double x, double *y) +{ +/* INTEGRATE CUBIC SPLINE FUNCTION FROM XA(1) TO X + * XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X + * Y2A: ARRAY OF SECOND DERIVATIVES + * N: SIZE OF ARRAYS XA,YA,Y2A + * X: ABSCISSA ENDPOINT FOR INTEGRATION + * Y: OUTPUT VALUE + */ + double yi=0; + int klo=0; + int khi=1; + double xx, h, a, b, a2, b2; + while ((x>xa[klo]) && (khi1) { + k=(khi+klo)/2; + if (xa[k]>x) + khi=k; + else + klo=k; + } + h = xa[khi] - xa[klo]; + if (h==0.0) + printf("bad XA input to splint"); + a = (xa[khi] - x)/h; + b = (x - xa[klo])/h; + yi = a * ya[klo] + b * ya[khi] + ((a*a*a - a) * y2a[klo] + (b*b*b - b) * y2a[khi]) * h * h/6.0; + *y = yi; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::spline (double *x, double *y, int n, double yp1, double ypn, double *y2) +{ +/* CALCULATE 2ND DERIVATIVES OF CUBIC SPLINE INTERP FUNCTION + * ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL + * X,Y: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X + * N: SIZE OF ARRAYS X,Y + * YP1,YPN: SPECIFIED DERIVATIVES AT X[0] AND X[N-1]; VALUES + * >= 1E30 SIGNAL SIGNAL SECOND DERIVATIVE ZERO + * Y2: OUTPUT ARRAY OF SECOND DERIVATIVES + */ + double *u; + double sig, p, qn, un; + int i, k; + u=(double*)malloc(sizeof(double)*n); + if (u==NULL) { + printf("Out Of Memory in spline - ERROR"); + return; + } + if (yp1>0.99E30) { + y2[0]=0; + u[0]=0; + } else { + y2[0]=-0.5; + u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yp1); + } + for (i=1;i<(n-1);i++) { + sig = (x[i]-x[i-1])/(x[i+1] - x[i-1]); + p = sig * y2[i-1] + 2.0; + y2[i] = (sig - 1.0) / p; + u[i] = (6.0 * ((y[i+1] - y[i])/(x[i+1] - x[i]) -(y[i] - y[i-1]) / (x[i] - x[i-1]))/(x[i+1] - x[i-1]) - sig * u[i-1])/p; + } + if (ypn>0.99E30) { + qn = 0; + un = 0; + } else { + qn = 0.5; + un = (3.0 / (x[n-1] - x[n-2])) * (ypn - (y[n-1] - y[n-2])/(x[n-1] - x[n-2])); + } + y2[n-1] = (un - qn * u[n-2]) / (qn * y2[n-2] + 1.0); + for (k=n-2;k>=0;k--) + y2[k] = y2[k] * y2[k+1] + u[k]; + + free(u); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::zeta(double zz, double zl) +{ + return ((zz-zl)*(re+zl)/(re+zz)); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::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) +{ +/* Calculate Temperature and Density Profiles for lower atmos. */ + double xs[10], ys[10], y2out[10]; + double rgas = 831.4; + double z, z1, z2, t1, t2, zg, zgdif; + double yd1, yd2; + double x, y, yi; + double expl, gamm, glb; + double densm_tmp; + int mn; + int k; + densm_tmp=d0; + if (alt>zn2[0]) { + if (xm==0.0) + return *tz; + else + return d0; + } + + /* STRATOSPHERE/MESOSPHERE TEMPERATURE */ + if (alt>zn2[mn2-1]) + z=alt; + else + z=zn2[mn2-1]; + mn=mn2; + z1=zn2[0]; + z2=zn2[mn-1]; + t1=tn2[0]; + t2=tn2[mn-1]; + zg = zeta(z, z1); + zgdif = zeta(z2, z1); + + /* set up spline nodes */ + for (k=0;k50.0) + expl=50.0; + + /* Density at altitude */ + densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl); + } + + if (alt>zn3[0]) { + if (xm==0.0) + return *tz; + else + return densm_tmp; + } + + /* troposhere / stratosphere temperature */ + z = alt; + mn = mn3; + z1=zn3[0]; + z2=zn3[mn-1]; + t1=tn3[0]; + t2=tn3[mn-1]; + zg=zeta(z,z1); + zgdif=zeta(z2,z1); + + /* set up spline nodes */ + for (k=0;k50.0) + expl=50.0; + + /* Density at altitude */ + densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl); + } + if (xm==0.0) + return *tz; + else + return densm_tmp; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::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) +{ +/* Calculate Temperature and Density Profiles for MSIS models + * New lower thermo polynomial + */ + double yd2, yd1, x=0.0, y=0.0; + double rgas=831.4; + double densu_temp=1.0; + double za, z, zg2, tt, ta=0.0; + double dta, z1=0.0, z2, t1=0.0, t2, zg, zgdif=0.0; + int mn=0; + int k; + double glb; + double expl; + double yi; + double densa; + double gamma, gamm; + double xs[5], ys[5], y2out[5]; + /* joining altitudes of Bates and spline */ + za=zn1[0]; + if (alt>za) + z=alt; + else + z=za; + + /* geopotential altitude difference from ZLB */ + zg2 = zeta(z, zlb); + + /* Bates temperature */ + tt = tinf - (tinf - tlb) * exp(-s2*zg2); + ta = tt; + *tz = tt; + densu_temp = *tz; + + if (altzn1[mn1-1]) + z=alt; + else + z=zn1[mn1-1]; + mn=mn1; + z1=zn1[0]; + z2=zn1[mn-1]; + t1=tn1[0]; + t2=tn1[mn-1]; + /* geopotental difference from z1 */ + zg = zeta (z, z1); + zgdif = zeta(z2, z1); + /* set up spline nodes */ + for (k=0;k50.0) + expl=50.0; + if (tt<=0) + expl=50.0; + + /* density at altitude */ + densa = dlb * pow((tlb/tt),((1.0+alpha+gamma))) * expl; + densu_temp=densa; + if (alt>=za) + return densu_temp; + + /* calculate density below za */ + glb = gsurf / pow((1.0 + z1/re),2.0); + gamm = xm * glb * zgdif / rgas; + + /* integrate spline temperatures */ + splini (xs, ys, y2out, mn, x, &yi); + expl = gamm * yi; + if (expl>50.0) + expl=50.0; + if (*tz<=0) + expl=50.0; + + /* density at altitude */ + densu_temp = densu_temp * pow ((t1 / *tz),(1.0 + alpha)) * exp(-expl); + return densu_temp; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/* 3hr Magnetic activity functions */ +/* Eq. A24d */ +double MSIS::g0(double a, double *p) +{ + return (a - 4.0 + (p[25] - 1.0) * (a - 4.0 + (exp(-sqrt(p[24]*p[24]) * + (a - 4.0)) - 1.0) / sqrt(p[24]*p[24]))); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/* Eq. A24c */ +double MSIS::sumex(double ex) +{ + return (1.0 + (1.0 - pow(ex,19.0)) / (1.0 - ex) * pow(ex,0.5)); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/* Eq. A24a */ +double MSIS::sg0(double ex, double *p, double *ap) +{ + return (g0(ap[1],p) + (g0(ap[2],p)*ex + g0(ap[3],p)*ex*ex + + g0(ap[4],p)*pow(ex,3.0) + (g0(ap[5],p)*pow(ex,4.0) + + g0(ap[6],p)*pow(ex,12.0))*(1.0-pow(ex,8.0))/(1.0-ex)))/sumex(ex); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::globe7(double *p, struct nrlmsise_input *input, + struct nrlmsise_flags *flags) +{ +/* CALCULATE G(L) FUNCTION + * Upper Thermosphere Parameters */ + double t[15]; + int i,j; + int sw9=1; + double apd; + double xlong; + double tloc; + double c, s, c2, c4, s2; + double sr = 7.2722E-5; + double dgtr = 1.74533E-2; + double dr = 1.72142E-2; + double hr = 0.2618; + double cd32, cd18, cd14, cd39; + double p32, p18, p14, p39; + double df, dfa; + double f1, f2; + double tinf; + struct ap_array *ap; + + tloc=input->lst; + for (j=0;j<14;j++) + t[j]=0; + if (flags->sw[9]>0) + sw9=1; + else if (flags->sw[9]<0) + sw9=-1; + xlong = input->g_long; + + /* calculate legendre polynomials */ + c = sin(input->g_lat * dgtr); + s = cos(input->g_lat * dgtr); + c2 = c*c; + c4 = c2*c2; + s2 = s*s; + + plg[0][1] = c; + plg[0][2] = 0.5*(3.0*c2 -1.0); + plg[0][3] = 0.5*(5.0*c*c2-3.0*c); + plg[0][4] = (35.0*c4 - 30.0*c2 + 3.0)/8.0; + plg[0][5] = (63.0*c2*c2*c - 70.0*c2*c + 15.0*c)/8.0; + plg[0][6] = (11.0*c*plg[0][5] - 5.0*plg[0][4])/6.0; +/* plg[0][7] = (13.0*c*plg[0][6] - 6.0*plg[0][5])/7.0; */ + plg[1][1] = s; + plg[1][2] = 3.0*c*s; + plg[1][3] = 1.5*(5.0*c2-1.0)*s; + plg[1][4] = 2.5*(7.0*c2*c-3.0*c)*s; + plg[1][5] = 1.875*(21.0*c4 - 14.0*c2 +1.0)*s; + plg[1][6] = (11.0*c*plg[1][5]-6.0*plg[1][4])/5.0; +/* plg[1][7] = (13.0*c*plg[1][6]-7.0*plg[1][5])/6.0; */ +/* plg[1][8] = (15.0*c*plg[1][7]-8.0*plg[1][6])/7.0; */ + plg[2][2] = 3.0*s2; + plg[2][3] = 15.0*s2*c; + plg[2][4] = 7.5*(7.0*c2 -1.0)*s2; + plg[2][5] = 3.0*c*plg[2][4]-2.0*plg[2][3]; + plg[2][6] =(11.0*c*plg[2][5]-7.0*plg[2][4])/4.0; + plg[2][7] =(13.0*c*plg[2][6]-8.0*plg[2][5])/5.0; + plg[3][3] = 15.0*s2*s; + plg[3][4] = 105.0*s2*s*c; + plg[3][5] =(9.0*c*plg[3][4]-7.*plg[3][3])/2.0; + plg[3][6] =(11.0*c*plg[3][5]-8.*plg[3][4])/3.0; + + if (!(((flags->sw[7]==0)&&(flags->sw[8]==0))&&(flags->sw[14]==0))) { + stloc = sin(hr*tloc); + ctloc = cos(hr*tloc); + s2tloc = sin(2.0*hr*tloc); + c2tloc = cos(2.0*hr*tloc); + s3tloc = sin(3.0*hr*tloc); + c3tloc = cos(3.0*hr*tloc); + } + + cd32 = cos(dr*(input->doy-p[31])); + cd18 = cos(2.0*dr*(input->doy-p[17])); + cd14 = cos(dr*(input->doy-p[13])); + cd39 = cos(2.0*dr*(input->doy-p[38])); + p32=p[31]; + p18=p[17]; + p14=p[13]; + p39=p[38]; + + /* F10.7 EFFECT */ + df = input->f107 - input->f107A; + dfa = input->f107A - 150.0; + t[0] = p[19]*df*(1.0+p[59]*dfa) + p[20]*df*df + p[21]*dfa + p[29]*pow(dfa,2.0); + f1 = 1.0 + (p[47]*dfa +p[19]*df+p[20]*df*df)*flags->swc[1]; + f2 = 1.0 + (p[49]*dfa+p[19]*df+p[20]*df*df)*flags->swc[1]; + + /* TIME INDEPENDENT */ + t[1] = (p[1]*plg[0][2]+ p[2]*plg[0][4]+p[22]*plg[0][6]) + + (p[14]*plg[0][2])*dfa*flags->swc[1] +p[26]*plg[0][1]; + + /* SYMMETRICAL ANNUAL */ + t[2] = p[18]*cd32; + + /* SYMMETRICAL SEMIANNUAL */ + t[3] = (p[15]+p[16]*plg[0][2])*cd18; + + /* ASYMMETRICAL ANNUAL */ + t[4] = f1*(p[9]*plg[0][1]+p[10]*plg[0][3])*cd14; + + /* ASYMMETRICAL SEMIANNUAL */ + t[5] = p[37]*plg[0][1]*cd39; + + /* DIURNAL */ + if (flags->sw[7]) { + double t71, t72; + t71 = (p[11]*plg[1][2])*cd14*flags->swc[5]; + t72 = (p[12]*plg[1][2])*cd14*flags->swc[5]; + t[6] = f2*((p[3]*plg[1][1] + p[4]*plg[1][3] + p[27]*plg[1][5] + t71) * \ + ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + p[28]*plg[1][5] \ + + t72)*stloc); +} + + /* SEMIDIURNAL */ + if (flags->sw[8]) { + double t81, t82; + t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5]; + t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5]; + t[7] = f2*((p[5]*plg[2][2]+ p[41]*plg[2][4] + t81)*c2tloc +(p[8]*plg[2][2] + p[42]*plg[2][4] + t82)*s2tloc); + } + + /* TERDIURNAL */ + if (flags->sw[14]) { + t[13] = f2 * ((p[39]*plg[3][3]+(p[93]*plg[3][4]+p[46]*plg[3][6])*cd14*flags->swc[5])* s3tloc +(p[40]*plg[3][3]+(p[94]*plg[3][4]+p[48]*plg[3][6])*cd14*flags->swc[5])* c3tloc); +} + + /* magnetic activity based on daily ap */ + if (flags->sw[9]==-1) { + ap = input->ap_a; + if (p[51]!=0) { + double exp1; + exp1 = exp(-10800.0*sqrt(p[51]*p[51])/(1.0+p[138]*(45.0-sqrt(input->g_lat*input->g_lat)))); + if (exp1>0.99999) + exp1=0.99999; + if (p[24]<1.0E-4) + p[24]=1.0E-4; + apt[0]=sg0(exp1,p,ap->a); + /* apt[1]=sg2(exp1,p,ap->a); + apt[2]=sg0(exp2,p,ap->a); + apt[3]=sg2(exp2,p,ap->a); + */ + if (flags->sw[9]) { + t[8] = apt[0]*(p[50]+p[96]*plg[0][2]+p[54]*plg[0][4]+ \ + (p[125]*plg[0][1]+p[126]*plg[0][3]+p[127]*plg[0][5])*cd14*flags->swc[5]+ \ + (p[128]*plg[1][1]+p[129]*plg[1][3]+p[130]*plg[1][5])*flags->swc[7]* \ + cos(hr*(tloc-p[131]))); + } + } + } else { + double p44, p45; + apd=input->ap-4.0; + p44=p[43]; + p45=p[44]; + if (p44<0) + p44 = 1.0E-5; + apdf = apd + (p45-1.0)*(apd + (exp(-p44 * apd) - 1.0)/p44); + if (flags->sw[9]) { + t[8]=apdf*(p[32]+p[45]*plg[0][2]+p[34]*plg[0][4]+ \ + (p[100]*plg[0][1]+p[101]*plg[0][3]+p[102]*plg[0][5])*cd14*flags->swc[5]+ + (p[121]*plg[1][1]+p[122]*plg[1][3]+p[123]*plg[1][5])*flags->swc[7]* + cos(hr*(tloc-p[124]))); + } + } + + if ((flags->sw[10])&&(input->g_long>-1000.0)) { + + /* longitudinal */ + if (flags->sw[11]) { + t[10] = (1.0 + p[80]*dfa*flags->swc[1])* \ + ((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ + +p[103]*plg[1][1]+p[104]*plg[1][3]+p[105]*plg[1][5]\ + +flags->swc[5]*(p[109]*plg[1][1]+p[110]*plg[1][3]+p[111]*plg[1][5])*cd14)* \ + cos(dgtr*input->g_long) \ + +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ + +p[106]*plg[1][1]+p[107]*plg[1][3]+p[108]*plg[1][5]\ + +flags->swc[5]*(p[112]*plg[1][1]+p[113]*plg[1][3]+p[114]*plg[1][5])*cd14)* \ + sin(dgtr*input->g_long)); + } + + /* ut and mixed ut, longitude */ + if (flags->sw[12]){ + t[11]=(1.0+p[95]*plg[0][1])*(1.0+p[81]*dfa*flags->swc[1])*\ + (1.0+p[119]*plg[0][1]*flags->swc[5]*cd14)*\ + ((p[68]*plg[0][1]+p[69]*plg[0][3]+p[70]*plg[0][5])*\ + cos(sr*(input->sec-p[71]))); + t[11]+=flags->swc[11]*\ + (p[76]*plg[2][3]+p[77]*plg[2][5]+p[78]*plg[2][7])*\ + cos(sr*(input->sec-p[79])+2.0*dgtr*input->g_long)*(1.0+p[137]*dfa*flags->swc[1]); + } + + /* ut, longitude magnetic activity */ + if (flags->sw[13]) { + if (flags->sw[9]==-1) { + if (p[51]) { + t[12]=apt[0]*flags->swc[11]*(1.+p[132]*plg[0][1])*\ + ((p[52]*plg[1][2]+p[98]*plg[1][4]+p[67]*plg[1][6])*\ + cos(dgtr*(input->g_long-p[97])))\ + +apt[0]*flags->swc[11]*flags->swc[5]*\ + (p[133]*plg[1][1]+p[134]*plg[1][3]+p[135]*plg[1][5])*\ + cd14*cos(dgtr*(input->g_long-p[136])) \ + +apt[0]*flags->swc[12]* \ + (p[55]*plg[0][1]+p[56]*plg[0][3]+p[57]*plg[0][5])*\ + cos(sr*(input->sec-p[58])); + } + } else { + t[12] = apdf*flags->swc[11]*(1.0+p[120]*plg[0][1])*\ + ((p[60]*plg[1][2]+p[61]*plg[1][4]+p[62]*plg[1][6])*\ + cos(dgtr*(input->g_long-p[63])))\ + +apdf*flags->swc[11]*flags->swc[5]* \ + (p[115]*plg[1][1]+p[116]*plg[1][3]+p[117]*plg[1][5])* \ + cd14*cos(dgtr*(input->g_long-p[118])) \ + + apdf*flags->swc[12]* \ + (p[83]*plg[0][1]+p[84]*plg[0][3]+p[85]*plg[0][5])* \ + cos(sr*(input->sec-p[75])); + } + } + } + + /* parms not used: 82, 89, 99, 139-149 */ + tinf = p[30]; + for (i=0;i<14;i++) + tinf = tinf + abs(flags->sw[i+1])*t[i]; + return tinf; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double MSIS::glob7s(double *p, struct nrlmsise_input *input, + struct nrlmsise_flags *flags) +{ +/* VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99 + */ + double pset=2.0; + double t[14]; + double tt; + double cd32, cd18, cd14, cd39; + double p32, p18, p14, p39; + int i,j; + double dr=1.72142E-2; + double dgtr=1.74533E-2; + /* confirm parameter set */ + if (p[99]==0) + p[99]=pset; + if (p[99]!=pset) { + printf("Wrong parameter set for glob7s\n"); + return -1; + } + for (j=0;j<14;j++) + t[j]=0.0; + cd32 = cos(dr*(input->doy-p[31])); + cd18 = cos(2.0*dr*(input->doy-p[17])); + cd14 = cos(dr*(input->doy-p[13])); + cd39 = cos(2.0*dr*(input->doy-p[38])); + p32=p[31]; + p18=p[17]; + p14=p[13]; + p39=p[38]; + + /* F10.7 */ + t[0] = p[21]*dfa; + + /* time independent */ + t[1]=p[1]*plg[0][2] + p[2]*plg[0][4] + p[22]*plg[0][6] + p[26]*plg[0][1] + p[14]*plg[0][3] + p[59]*plg[0][5]; + + /* SYMMETRICAL ANNUAL */ + t[2]=(p[18]+p[47]*plg[0][2]+p[29]*plg[0][4])*cd32; + + /* SYMMETRICAL SEMIANNUAL */ + t[3]=(p[15]+p[16]*plg[0][2]+p[30]*plg[0][4])*cd18; + + /* ASYMMETRICAL ANNUAL */ + t[4]=(p[9]*plg[0][1]+p[10]*plg[0][3]+p[20]*plg[0][5])*cd14; + + /* ASYMMETRICAL SEMIANNUAL */ + t[5]=(p[37]*plg[0][1])*cd39; + + /* DIURNAL */ + if (flags->sw[7]) { + double t71, t72; + t71 = p[11]*plg[1][2]*cd14*flags->swc[5]; + t72 = p[12]*plg[1][2]*cd14*flags->swc[5]; + t[6] = ((p[3]*plg[1][1] + p[4]*plg[1][3] + t71) * ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + t72) * stloc) ; + } + + /* SEMIDIURNAL */ + if (flags->sw[8]) { + double t81, t82; + t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5]; + t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5]; + t[7] = ((p[5]*plg[2][2] + p[41]*plg[2][4] + t81) * c2tloc + (p[8]*plg[2][2] + p[42]*plg[2][4] + t82) * s2tloc); + } + + /* TERDIURNAL */ + if (flags->sw[14]) { + t[13] = p[39] * plg[3][3] * s3tloc + p[40] * plg[3][3] * c3tloc; + } + + /* MAGNETIC ACTIVITY */ + if (flags->sw[9]) { + if (flags->sw[9]==1) + t[8] = apdf * (p[32] + p[45] * plg[0][2] * flags->swc[2]); + if (flags->sw[9]==-1) + t[8]=(p[50]*apt[0] + p[96]*plg[0][2] * apt[0]*flags->swc[2]); + } + + /* LONGITUDINAL */ + if (!((flags->sw[10]==0) || (flags->sw[11]==0) || (input->g_long<=-1000.0))) { + t[10] = (1.0 + plg[0][1]*(p[80]*flags->swc[5]*cos(dr*(input->doy-p[81]))\ + +p[85]*flags->swc[6]*cos(2.0*dr*(input->doy-p[86])))\ + +p[83]*flags->swc[3]*cos(dr*(input->doy-p[84]))\ + +p[87]*flags->swc[4]*cos(2.0*dr*(input->doy-p[88])))\ + *((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ + +p[74]*plg[1][1]+p[75]*plg[1][3]+p[76]*plg[1][5]\ + )*cos(dgtr*input->g_long)\ + +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ + +p[77]*plg[1][1]+p[78]*plg[1][3]+p[79]*plg[1][5]\ + )*sin(dgtr*input->g_long)); + } + tt=0; + for (i=0;i<14;i++) + tt+=abs(flags->sw[i+1])*t[i]; + return tt; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::gtd7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, + struct nrlmsise_output *output) +{ + double xlat; + double xmm; + int mn3 = 5; + double zn3[5]={32.5,20.0,15.0,10.0,0.0}; + int mn2 = 4; + double zn2[4]={72.5,55.0,45.0,32.5}; + double altt; + double zmix=62.5; + double tmp; + double dm28m; + double tz; + double dmc; + double dmr; + double dz28; + struct nrlmsise_output soutput; + int i; + + tselec(flags); + + /* Latitude variation of gravity (none for sw[2]=0) */ + xlat=input->g_lat; + if (flags->sw[2]==0) + xlat=45.0; + glatf(xlat, &gsurf, &re); + + xmm = pdm[2][4]; + + /* THERMOSPHERE / MESOSPHERE (above zn2[0]) */ + if (input->alt>zn2[0]) + altt=input->alt; + else + altt=zn2[0]; + + tmp=input->alt; + input->alt=altt; + gts7(input, flags, &soutput); + altt=input->alt; + input->alt=tmp; + if (flags->sw[0]) /* metric adjustment */ + dm28m=dm28*1.0E6; + else + dm28m=dm28; + output->t[0]=soutput.t[0]; + output->t[1]=soutput.t[1]; + if (input->alt>=zn2[0]) { + for (i=0;i<9;i++) + output->d[i]=soutput.d[i]; + return; + } + +/* LOWER MESOSPHERE/UPPER STRATOSPHERE (between zn3[0] and zn2[0]) + * Temperature at nodes and gradients at end nodes + * Inverse temperature a linear function of spherical harmonics + */ + meso_tgn2[0]=meso_tgn1[1]; + meso_tn2[0]=meso_tn1[4]; + meso_tn2[1]=pma[0][0]*pavgm[0]/(1.0-flags->sw[20]*glob7s(pma[0], input, flags)); + meso_tn2[2]=pma[1][0]*pavgm[1]/(1.0-flags->sw[20]*glob7s(pma[1], input, flags)); + meso_tn2[3]=pma[2][0]*pavgm[2]/(1.0-flags->sw[20]*flags->sw[22]*glob7s(pma[2], input, flags)); + meso_tgn2[1]=pavgm[8]*pma[9][0]*(1.0+flags->sw[20]*flags->sw[22]*glob7s(pma[9], input, flags))*meso_tn2[3]*meso_tn2[3]/(pow((pma[2][0]*pavgm[2]),2.0)); + meso_tn3[0]=meso_tn2[3]; + + if (input->altsw[22]*glob7s(pma[3], input, flags)); + meso_tn3[2]=pma[4][0]*pavgm[4]/(1.0-flags->sw[22]*glob7s(pma[4], input, flags)); + meso_tn3[3]=pma[5][0]*pavgm[5]/(1.0-flags->sw[22]*glob7s(pma[5], input, flags)); + meso_tn3[4]=pma[6][0]*pavgm[6]/(1.0-flags->sw[22]*glob7s(pma[6], input, flags)); + meso_tgn3[1]=pma[7][0]*pavgm[7]*(1.0+flags->sw[22]*glob7s(pma[7], input, flags)) *meso_tn3[4]*meso_tn3[4]/(pow((pma[6][0]*pavgm[6]),2.0)); + } + + /* LINEAR TRANSITION TO FULL MIXING BELOW zn2[0] */ + + dmc=0; + if (input->alt>zmix) + dmc = 1.0 - (zn2[0]-input->alt)/(zn2[0] - zmix); + dz28=soutput.d[2]; + + /**** N2 density ****/ + dmr=soutput.d[2] / dm28m - 1.0; + output->d[2]=densm(input->alt,dm28m,xmm, &tz, mn3, zn3, meso_tn3, meso_tgn3, mn2, zn2, meso_tn2, meso_tgn2); + output->d[2]=output->d[2] * (1.0 + dmr*dmc); + + /**** HE density ****/ + dmr = soutput.d[0] / (dz28 * pdm[0][1]) - 1.0; + output->d[0] = output->d[2] * pdm[0][1] * (1.0 + dmr*dmc); + + /**** O density ****/ + output->d[1] = 0; + output->d[8] = 0; + + /**** O2 density ****/ + dmr = soutput.d[3] / (dz28 * pdm[3][1]) - 1.0; + output->d[3] = output->d[2] * pdm[3][1] * (1.0 + dmr*dmc); + + /**** AR density ***/ + dmr = soutput.d[4] / (dz28 * pdm[4][1]) - 1.0; + output->d[4] = output->d[2] * pdm[4][1] * (1.0 + dmr*dmc); + + /**** Hydrogen density ****/ + output->d[6] = 0; + + /**** Atomic nitrogen density ****/ + output->d[7] = 0; + + /**** Total mass density */ + output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] + + 28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4] + + output->d[6] + 14.0 * output->d[7]); + + if (flags->sw[0]) + output->d[5]=output->d[5]/1000; + + /**** temperature at altitude ****/ + dd = densm(input->alt, 1.0, 0, &tz, mn3, zn3, meso_tn3, meso_tgn3, + mn2, zn2, meso_tn2, meso_tgn2); + output->t[1]=tz; + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::gtd7d(struct nrlmsise_input *input, struct nrlmsise_flags *flags, + struct nrlmsise_output *output) +{ + gtd7(input, flags, output); + output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] + + 28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4] + + output->d[6] + 14.0 * output->d[7] + 16.0 * output->d[8]); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::ghp7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, + struct nrlmsise_output *output, double press) +{ + double bm = 1.3806E-19; + double rgas = 831.4; + double test = 0.00043; + double ltest = 12; + double pl, p; + double zi = 0.0; + double z; + double cl, cl2; + double ca, cd; + double xn, xm, diff; + double g, sh; + int l; + pl = log10(press); + if (pl >= -5.0) { + if (pl>2.5) + zi = 18.06 * (3.00 - pl); + else if ((pl>0.075) && (pl<=2.5)) + zi = 14.98 * (3.08 - pl); + else if ((pl>-1) && (pl<=0.075)) + zi = 17.80 * (2.72 - pl); + else if ((pl>-2) && (pl<=-1)) + zi = 14.28 * (3.64 - pl); + else if ((pl>-4) && (pl<=-2)) + zi = 12.72 * (4.32 -pl); + else if (pl<=-4) + zi = 25.3 * (0.11 - pl); + cl = input->g_lat/90.0; + cl2 = cl*cl; + if (input->doy<182) + cd = (1.0 - (double) input->doy) / 91.25; + else + cd = ((double) input->doy) / 91.25 - 3.0; + ca = 0; + if ((pl > -1.11) && (pl<=-0.23)) + ca = 1.0; + if (pl > -0.23) + ca = (2.79 - pl) / (2.79 + 0.23); + if ((pl <= -1.11) && (pl>-3)) + ca = (-2.93 - pl)/(-2.93 + 1.11); + z = zi - 4.87 * cl * cd * ca - 1.64 * cl2 * ca + 0.31 * ca * cl; + } else + z = 22.0 * pow((pl + 4.0),2.0) + 110.0; + + /* iteration loop */ + l = 0; + do { + l++; + input->alt = z; + gtd7(input, flags, output); + z = input->alt; + xn = output->d[0] + output->d[1] + output->d[2] + output->d[3] + output->d[4] + output->d[6] + output->d[7]; + p = bm * xn * output->t[1]; + if (flags->sw[0]) + p = p*1.0E-6; + diff = pl - log10(p); + if (sqrt(diff*diff)d[5] / xn / 1.66E-24; + if (flags->sw[0]) + xm = xm * 1.0E3; + g = gsurf / (pow((1.0 + z/re),2.0)); + sh = rgas * output->t[1] / (xm * g); + + /* new altitude estimate using scale height */ + if (l < 6) + z = z - sh * diff * 2.302; + else + z = z - sh * diff; + } while (1==1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void MSIS::gts7(struct nrlmsise_input *input, struct nrlmsise_flags *flags, + struct nrlmsise_output *output) +{ +/* Thermospheric portion of NRLMSISE-00 + * See GTD7 for more extensive comments + * alt > 72.5 km! + */ + double za; + int i, j; + double ddum, z; + double zn1[5] = {120.0, 110.0, 100.0, 90.0, 72.5}; + double tinf; + int mn1 = 5; + double g0; + double tlb; + double s, z0, t0, tr12; + double db01, db04, db14, db16, db28, db32, db40, db48; + double zh28, zh04, zh16, zh32, zh40, zh01, zh14; + double zhm28, zhm04, zhm16, zhm32, zhm40, zhm01, zhm14; + double xmd; + double b28, b04, b16, b32, b40, b01, b14; + double tz; + double g28, g4, g16, g32, g40, g1, g14; + double zhf, xmm; + double zc04, zc16, zc32, zc40, zc01, zc14; + double hc04, hc16, hc32, hc40, hc01, hc14; + double hcc16, hcc32, hcc01, hcc14; + double zcc16, zcc32, zcc01, zcc14; + double rc16, rc32, rc01, rc14; + double rl; + double g16h, db16h, tho, zsht, zmho, zsho; + double dgtr=1.74533E-2; + double dr=1.72142E-2; + double alpha[9]={-0.38, 0.0, 0.0, 0.0, 0.17, 0.0, -0.38, 0.0, 0.0}; + double altl[8]={200.0, 300.0, 160.0, 250.0, 240.0, 450.0, 320.0, 450.0}; + double dd; + double hc216, hcc232; + za = pdl[1][15]; + zn1[0] = za; + for (j=0;j<9;j++) + output->d[j]=0; + + /* TINF VARIATIONS NOT IMPORTANT BELOW ZA OR ZN1(1) */ + if (input->alt>zn1[0]) + tinf = ptm[0]*pt[0] * \ + (1.0+flags->sw[16]*globe7(pt,input,flags)); + else + tinf = ptm[0]*pt[0]; + output->t[0]=tinf; + + /* GRADIENT VARIATIONS NOT IMPORTANT BELOW ZN1(5) */ + if (input->alt>zn1[4]) + g0 = ptm[3]*ps[0] * \ + (1.0+flags->sw[19]*globe7(ps,input,flags)); + else + g0 = ptm[3]*ps[0]; + tlb = ptm[1] * (1.0 + flags->sw[17]*globe7(pd[3],input,flags))*pd[3][0]; + s = g0 / (tinf - tlb); + +/* Lower thermosphere temp variations not significant for + * density above 300 km */ + if (input->alt<300.0) { + meso_tn1[1]=ptm[6]*ptl[0][0]/(1.0-flags->sw[18]*glob7s(ptl[0], input, flags)); + meso_tn1[2]=ptm[2]*ptl[1][0]/(1.0-flags->sw[18]*glob7s(ptl[1], input, flags)); + meso_tn1[3]=ptm[7]*ptl[2][0]/(1.0-flags->sw[18]*glob7s(ptl[2], input, flags)); + meso_tn1[4]=ptm[4]*ptl[3][0]/(1.0-flags->sw[18]*flags->sw[20]*glob7s(ptl[3], input, flags)); + meso_tgn1[1]=ptm[8]*pma[8][0]*(1.0+flags->sw[18]*flags->sw[20]*glob7s(pma[8], input, flags))*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); + } else { + meso_tn1[1]=ptm[6]*ptl[0][0]; + meso_tn1[2]=ptm[2]*ptl[1][0]; + meso_tn1[3]=ptm[7]*ptl[2][0]; + meso_tn1[4]=ptm[4]*ptl[3][0]; + meso_tgn1[1]=ptm[8]*pma[8][0]*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); + } + + z0 = zn1[3]; + t0 = meso_tn1[3]; + tr12 = 1.0; + + /* N2 variation factor at Zlb */ + g28=flags->sw[21]*globe7(pd[2], input, flags); + + /* VARIATION OF TURBOPAUSE HEIGHT */ + zhf=pdl[1][24]*(1.0+flags->sw[5]*pdl[0][24]*sin(dgtr*input->g_lat)*cos(dr*(input->doy-pt[13]))); + output->t[0]=tinf; + xmm = pdm[2][4]; + z = input->alt; + + + /**** N2 DENSITY ****/ + + /* Diffusive density at Zlb */ + db28 = pdm[2][0]*exp(g28)*pd[2][0]; + /* Diffusive density at Alt */ + output->d[2]=densu(z,db28,tinf,tlb,28.0,alpha[2],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[2]; + /* Turbopause */ + zh28=pdm[2][2]*zhf; + zhm28=pdm[2][3]*pdl[1][5]; + xmd=28.0-xmm; + /* Mixed density at Zlb */ + b28=densu(zh28,db28,tinf,tlb,xmd,(alpha[2]-1.0),&tz,ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + if ((flags->sw[15])&&(z<=altl[2])) { + /* Mixed density at Alt */ + dm28=densu(z,b28,tinf,tlb,xmm,alpha[2],&tz,ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Net density at Alt */ + output->d[2]=dnet(output->d[2],dm28,zhm28,xmm,28.0); + } + + + /**** HE DENSITY ****/ + + /* Density variation factor at Zlb */ + g4 = flags->sw[21]*globe7(pd[0], input, flags); + /* Diffusive density at Zlb */ + db04 = pdm[0][0]*exp(g4)*pd[0][0]; + /* Diffusive density at Alt */ + output->d[0]=densu(z,db04,tinf,tlb, 4.,alpha[0],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[0]; + if ((flags->sw[15]) && (zt[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm04=densu(z,b04,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm04=zhm28; + /* Net density at Alt */ + output->d[0]=dnet(output->d[0],dm04,zhm04,xmm,4.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[0][1]/b04); + zc04=pdm[0][4]*pdl[1][0]; + hc04=pdm[0][5]*pdl[1][1]; + /* Net density corrected at Alt */ + output->d[0]=output->d[0]*ccor(z,rl,hc04,zc04); + } + + + /**** O DENSITY ****/ + + /* Density variation factor at Zlb */ + g16= flags->sw[21]*globe7(pd[1],input,flags); + /* Diffusive density at Zlb */ + db16 = pdm[1][0]*exp(g16)*pd[1][0]; + /* Diffusive density at Alt */ + output->d[1]=densu(z,db16,tinf,tlb, 16.,alpha[1],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + dd=output->d[1]; + if ((flags->sw[15]) && (z<=altl[1])) { + /* Turbopause */ + zh16=pdm[1][2]; + /* Mixed density at Zlb */ + b16=densu(zh16,db16,tinf,tlb,16.0-xmm,(alpha[1]-1.0), &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm16=densu(z,b16,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm16=zhm28; + /* Net density at Alt */ + output->d[1]=dnet(output->d[1],dm16,zhm16,xmm,16.); + rl=pdm[1][1]*pdl[1][16]*(1.0+flags->sw[1]*pdl[0][23]*(input->f107A-150.0)); + hc16=pdm[1][5]*pdl[1][3]; + zc16=pdm[1][4]*pdl[1][2]; + hc216=pdm[1][5]*pdl[1][4]; + output->d[1]=output->d[1]*ccor2(z,rl,hc16,zc16,hc216); + /* Chemistry correction */ + hcc16=pdm[1][7]*pdl[1][13]; + zcc16=pdm[1][6]*pdl[1][12]; + rc16=pdm[1][3]*pdl[1][14]; + /* Net density corrected at Alt */ + output->d[1]=output->d[1]*ccor(z,rc16,hcc16,zcc16); + } + + + /**** O2 DENSITY ****/ + + /* Density variation factor at Zlb */ + g32= flags->sw[21]*globe7(pd[4], input, flags); + /* Diffusive density at Zlb */ + db32 = pdm[3][0]*exp(g32)*pd[4][0]; + /* Diffusive density at Alt */ + output->d[3]=densu(z,db32,tinf,tlb, 32.,alpha[3],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + dd=output->d[3]; + if (flags->sw[15]) { + if (z<=altl[3]) { + /* Turbopause */ + zh32=pdm[3][2]; + /* Mixed density at Zlb */ + b32=densu(zh32,db32,tinf,tlb,32.-xmm,alpha[3]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm32=densu(z,b32,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm32=zhm28; + /* Net density at Alt */ + output->d[3]=dnet(output->d[3],dm32,zhm32,xmm,32.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[3][1]/b32); + hc32=pdm[3][5]*pdl[1][7]; + zc32=pdm[3][4]*pdl[1][6]; + output->d[3]=output->d[3]*ccor(z,rl,hc32,zc32); + } + /* Correction for general departure from diffusive equilibrium above Zlb */ + hcc32=pdm[3][7]*pdl[1][22]; + hcc232=pdm[3][7]*pdl[0][22]; + zcc32=pdm[3][6]*pdl[1][21]; + rc32=pdm[3][3]*pdl[1][23]*(1.+flags->sw[1]*pdl[0][23]*(input->f107A-150.)); + /* Net density corrected at Alt */ + output->d[3]=output->d[3]*ccor2(z,rc32,hcc32,zcc32,hcc232); + } + + + /**** AR DENSITY ****/ + + /* Density variation factor at Zlb */ + g40= flags->sw[20]*globe7(pd[5],input,flags); + /* Diffusive density at Zlb */ + db40 = pdm[4][0]*exp(g40)*pd[5][0]; + /* Diffusive density at Alt */ + output->d[4]=densu(z,db40,tinf,tlb, 40.,alpha[4],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[4]; + if ((flags->sw[15]) && (z<=altl[4])) { + /* Turbopause */ + zh40=pdm[4][2]; + /* Mixed density at Zlb */ + b40=densu(zh40,db40,tinf,tlb,40.-xmm,alpha[4]-1.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm40=densu(z,b40,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm40=zhm28; + /* Net density at Alt */ + output->d[4]=dnet(output->d[4],dm40,zhm40,xmm,40.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[4][1]/b40); + hc40=pdm[4][5]*pdl[1][9]; + zc40=pdm[4][4]*pdl[1][8]; + /* Net density corrected at Alt */ + output->d[4]=output->d[4]*ccor(z,rl,hc40,zc40); + } + + + /**** HYDROGEN DENSITY ****/ + + /* Density variation factor at Zlb */ + g1 = flags->sw[21]*globe7(pd[6], input, flags); + /* Diffusive density at Zlb */ + db01 = pdm[5][0]*exp(g1)*pd[6][0]; + /* Diffusive density at Alt */ + output->d[6]=densu(z,db01,tinf,tlb,1.,alpha[6],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[6]; + if ((flags->sw[15]) && (z<=altl[6])) { + /* Turbopause */ + zh01=pdm[5][2]; + /* Mixed density at Zlb */ + b01=densu(zh01,db01,tinf,tlb,1.-xmm,alpha[6]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm01=densu(z,b01,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm01=zhm28; + /* Net density at Alt */ + output->d[6]=dnet(output->d[6],dm01,zhm01,xmm,1.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[5][1]*sqrt(pdl[1][17]*pdl[1][17])/b01); + hc01=pdm[5][5]*pdl[1][11]; + zc01=pdm[5][4]*pdl[1][10]; + output->d[6]=output->d[6]*ccor(z,rl,hc01,zc01); + /* Chemistry correction */ + hcc01=pdm[5][7]*pdl[1][19]; + zcc01=pdm[5][6]*pdl[1][18]; + rc01=pdm[5][3]*pdl[1][20]; + /* Net density corrected at Alt */ + output->d[6]=output->d[6]*ccor(z,rc01,hcc01,zcc01); +} + + + /**** ATOMIC NITROGEN DENSITY ****/ + + /* Density variation factor at Zlb */ + g14 = flags->sw[21]*globe7(pd[7],input,flags); + /* Diffusive density at Zlb */ + db14 = pdm[6][0]*exp(g14)*pd[7][0]; + /* Diffusive density at Alt */ + output->d[7]=densu(z,db14,tinf,tlb,14.,alpha[7],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + dd=output->d[7]; + if ((flags->sw[15]) && (z<=altl[7])) { + /* Turbopause */ + zh14=pdm[6][2]; + /* Mixed density at Zlb */ + b14=densu(zh14,db14,tinf,tlb,14.-xmm,alpha[7]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + /* Mixed density at Alt */ + dm14=densu(z,b14,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); + zhm14=zhm28; + /* Net density at Alt */ + output->d[7]=dnet(output->d[7],dm14,zhm14,xmm,14.); + /* Correction to specified mixing ratio at ground */ + rl=log(b28*pdm[6][1]*sqrt(pdl[0][2]*pdl[0][2])/b14); + hc14=pdm[6][5]*pdl[0][1]; + zc14=pdm[6][4]*pdl[0][0]; + output->d[7]=output->d[7]*ccor(z,rl,hc14,zc14); + /* Chemistry correction */ + hcc14=pdm[6][7]*pdl[0][4]; + zcc14=pdm[6][6]*pdl[0][3]; + rc14=pdm[6][3]*pdl[0][5]; + /* Net density corrected at Alt */ + output->d[7]=output->d[7]*ccor(z,rc14,hcc14,zcc14); + } + + + /**** Anomalous OXYGEN DENSITY ****/ + + g16h = flags->sw[21]*globe7(pd[8],input,flags); + db16h = pdm[7][0]*exp(g16h)*pd[8][0]; + tho = pdm[7][9]*pdl[0][6]; + dd=densu(z,db16h,tho,tho,16.,alpha[8],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); + zsht=pdm[7][5]; + zmho=pdm[7][4]; + zsho=scalh(zmho,16.0,tho); + output->d[8]=dd*exp(-zsht/zsho*(exp(-(z-zmho)/zsht)-1.)); + + + /* total mass density */ + output->d[5] = 1.66E-24*(4.0*output->d[0]+16.0*output->d[1]+28.0*output->d[2]+32.0*output->d[3]+40.0*output->d[4]+ output->d[6]+14.0*output->d[7]); + db48=1.66E-24*(4.0*db04+16.0*db16+28.0*db28+32.0*db32+40.0*db40+db01+14.0*db14); + + + + /* temperature */ + z = sqrt(input->alt*input->alt); + ddum = densu(z,1.0, tinf, tlb, 0.0, 0.0, &output->t[1], ptm[5], s, mn1, zn1, meso_tn1, meso_tgn1); + if (flags->sw[0]) { + for(i=0;i<9;i++) + output->d[i]=output->d[i]*1.0E6; + output->d[5]=output->d[5]/1000; + } +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 MSIS::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: MSIS" << endl; + if (from == 1) cout << "Destroyed: MSIS" << 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 + diff --git a/src/FDM/JSBSim/models/atmosphere/FGMSIS.h b/src/FDM/JSBSim/models/atmosphere/FGMSIS.h new file mode 100755 index 000000000..8f2b65293 --- /dev/null +++ b/src/FDM/JSBSim/models/atmosphere/FGMSIS.h @@ -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 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 + diff --git a/src/FDM/JSBSim/models/atmosphere/FGMSISData.cpp b/src/FDM/JSBSim/models/atmosphere/FGMSISData.cpp new file mode 100755 index 000000000..d77e1c51f --- /dev/null +++ b/src/FDM/JSBSim/models/atmosphere/FGMSISData.cpp @@ -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 diff --git a/src/FDM/JSBSim/models/atmosphere/FGMars.cpp b/src/FDM/JSBSim/models/atmosphere/FGMars.cpp new file mode 100755 index 000000000..2f9eec416 --- /dev/null +++ b/src/FDM/JSBSim/models/atmosphere/FGMars.cpp @@ -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 diff --git a/src/FDM/JSBSim/models/atmosphere/FGMars.h b/src/FDM/JSBSim/models/atmosphere/FGMars.h new file mode 100755 index 000000000..68f24e6bb --- /dev/null +++ b/src/FDM/JSBSim/models/atmosphere/FGMars.h @@ -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 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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. + This function may only be used if Run() is called first. */ + 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 + diff --git a/src/FDM/JSBSim/models/atmosphere/Makefile.am b/src/FDM/JSBSim/models/atmosphere/Makefile.am new file mode 100644 index 000000000..c4fc9d844 --- /dev/null +++ b/src/FDM/JSBSim/models/atmosphere/Makefile.am @@ -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 diff --git a/src/FDM/JSBSim/models/flight_control/FGCondition.cpp b/src/FDM/JSBSim/models/flight_control/FGCondition.cpp new file mode 100644 index 000000000..21adb3a78 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGCondition.cpp @@ -0,0 +1,295 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGCondition.cpp + Author: Jon S. Berndt + Date started: 1/2/2003 + + -------------- Copyright (C) 2003 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 +-------------------------------------------------------------------------------- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +COMMENTS, REFERENCES, and NOTES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGCondition.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_CONDITION; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +string FGCondition::indent = " "; + + +FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) : + PropertyManager(PropertyManager), isGroup(true) +{ + string property1, property2, logic; + Element* condition_element; + + InitializeConditionals(); + + TestParam1 = TestParam2 = 0L; + TestValue = 0.0; + Comparison = ecUndef; + Logic = elUndef; + conditions.clear(); + + 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; iGetNumDataLines(); i++) { + conditions.push_back(FGCondition(element->GetDataLine(i), PropertyManager)); + } + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +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); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGCondition::Evaluate(void ) +{ + vector ::iterator iConditions; + bool pass = false; + double compareValue; + + if (Logic == eAND) { + + iConditions = conditions.begin(); + pass = true; + while (iConditions < conditions.end()) { + if (!iConditions->Evaluate()) pass = false; + *iConditions++; + } + + } else if (Logic == eOR) { + + pass = false; + while (iConditions < conditions.end()) { + if (iConditions->Evaluate()) pass = true; + *iConditions++; + } + + } else { + + if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue(); + else compareValue = TestValue; + + switch (Comparison) { + case ecUndef: + cerr << "Undefined comparison operator." << endl; + break; + case eEQ: + pass = TestParam1->getDoubleValue() == compareValue; + break; + case eNE: + pass = TestParam1->getDoubleValue() != compareValue; + break; + case eGT: + pass = TestParam1->getDoubleValue() > compareValue; + break; + case eGE: + pass = TestParam1->getDoubleValue() >= compareValue; + break; + case eLT: + pass = TestParam1->getDoubleValue() < compareValue; + break; + case eLE: + pass = TestParam1->getDoubleValue() <= compareValue; + break; + default: + cerr << "Unknown comparison operator." << endl; + } + } + + return pass; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGCondition::PrintCondition(void ) +{ + vector ::iterator iConditions; + string scratch; + + if (isGroup) { + switch(Logic) { + case (elUndef): + scratch = " UNSET"; + cerr << "unset logic for test condition" << endl; + break; + case (eAND): + scratch = " if all of the following are true"; + break; + case (eOR): + scratch = " if any of the following are true:"; + break; + default: + scratch = " UNKNOWN"; + cerr << "Unknown logic for test condition" << endl; + } + + iConditions = conditions.begin(); + cout << scratch << endl; + while (iConditions < conditions.end()) { + iConditions->PrintCondition(); + *iConditions++; + } + } else { + if (TestParam2 != 0L) + cout << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName(); + else + cout << TestParam1->GetName() << " " << conditional << " " << TestValue; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGCondition::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: FGCondition" << endl; + if (from == 1) cout << "Destroyed: FGCondition" << 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 + diff --git a/src/FDM/JSBSim/models/flight_control/FGCondition.h b/src/FDM/JSBSim/models/flight_control/FGCondition.h new file mode 100644 index 000000000..fbb643bf3 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGCondition.h @@ -0,0 +1,99 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGCondition.h + Author: Jon S. Berndt + Date started: 1/02/2003 + + ------------- Copyright (C) ------------- + + 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 FGCONDITION_H +#define FGCONDITION_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_CONDITION "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a condition, which is used in parts of JSBSim including switches +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGCondition : public FGJSBBase +{ +public: + FGCondition(Element* element, FGPropertyManager* PropertyManager); + FGCondition(string test, FGPropertyManager* PropertyManager); + ~FGCondition(void); + + bool Evaluate(void); + void PrintCondition(void); + +private: + enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE}; + enum eLogic {elUndef=0, eAND, eOR}; + map mComparison; + eLogic Logic; + + FGPropertyManager *TestParam1, *TestParam2, *PropertyManager; + double TestValue; + eComparison Comparison; + bool isGroup; + string conditional; + + static string indent; + + vector conditions; + void InitializeConditionals(void); + + void Debug(int from); +}; +} +#endif + diff --git a/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp b/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp new file mode 100644 index 000000000..bbd8f68f0 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp @@ -0,0 +1,148 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + 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 + 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 "FGDeadBand.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_DEADBAND; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + gain = 1.0; + width = 0.0; + + if (element->FindElement("width")) { + width = element->FindElementValueAsNumber("width"); + } + + if (element->FindElement("gain")) { + gain = element->FindElementValueAsNumber("gain"); + } + + FGFCSComponent::bind(); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGDeadBand::~FGDeadBand() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGDeadBand::Run(void ) +{ + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + + if (Input < -width/2.0) { + Output = (Input + width/2.0)*gain; + } else if (Input > width/2.0) { + Output = (Input - width/2.0)*gain; + } else { + Output = 0.0; + } + + Clip(); + + if (IsOutput) SetOutput(); + + 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 FGDeadBand::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUT: " << InputNodes[0]->getName() << endl; + cout << " DEADBAND WIDTH: " << width << endl; + cout << " GAIN: " << gain << 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: FGDeadBand" << endl; + if (from == 1) cout << "Destroyed: FGDeadBand" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGDeadBand.h b/src/FDM/JSBSim/models/flight_control/FGDeadBand.h new file mode 100644 index 000000000..f94087c95 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGDeadBand.h @@ -0,0 +1,101 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGDeadBand.h + Author: Jon Berndt + Date started: 2001 + + ------------- 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 + 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 FGDEADBAND_H +#define FGDEADBAND_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGFCSComponent.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_DEADBAND "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGFCS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models a deadband object. + Here is the format of the deadband control specification: +
+    \
+       INPUT {input}
+       WIDTH {deadband width}
+       MIN {minimum value}
+       MAX {maximum value}
+       [GAIN {optional deadband gain}]
+       [OUTPUT {optional output parameter to set}]
+    \
+    
+ The WIDTH value is the total deadband region within which an input will + produce no output. For example, say that the WIDTH value is 2.0. If the + input is between -1.0 and +1.0, the output will be zero. + @author Jon S. Berndt + @version $Id$ +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGDeadBand : public FGFCSComponent +{ +public: + FGDeadBand(FGFCS* fcs, Element* element); + ~FGDeadBand(); + + bool Run(void); + +private: + double width; + double gain; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#endif diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp new file mode 100644 index 000000000..d103b20c2 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp @@ -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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h new file mode 100644 index 000000000..eb5bf1b9a --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h @@ -0,0 +1,137 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGFCSComponent.h + Author: Jon S. Berndt + Date started: 05/01/2000 + + ------------- Copyright (C) ------------- + + 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 FGFCSCOMPONENT_H +#define FGFCSCOMPONENT_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +#endif + +#include +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_FCSCOMPONENT "$Id$" + +using std::string; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGFCS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Base class for JSBSim Flight Control System Components. + The Flight Control System (FCS) for JSBSim consists of the FCS container + class (see \URL[FGFCS]{FGFCS.html}), the FGFCSComponent base class, and the + component classes from which can be constructed a string, or channel. See: + + - FGSwitch + - FGGain + - FGKinemat + - FGFilter + - FGDeadBand + - FGSummer + - FGGradient + + @author Jon S. Berndt + @version $Id$ + @see Documentation for the FGFCS class, and for the configuration file class +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGFCSComponent : public FGJSBBase +{ +public: + /// Constructor + FGFCSComponent(FGFCS* fcs, Element* el); + /// Destructor + virtual ~FGFCSComponent(); + + virtual bool Run(void); + virtual void SetOutput(void); + inline double GetOutput (void) const {return Output;} + inline FGPropertyManager* GetOutputNode(void) { return OutputNode; } + inline string GetName(void) const {return Name;} + inline string GetType(void) const { return Type; } + virtual double GetOutputPct(void) const { return 0; } + +protected: + FGFCS* fcs; + FGPropertyManager* PropertyManager; + FGPropertyManager* treenode; + FGPropertyManager* OutputNode; + FGPropertyManager* ClipMinPropertyNode; + FGPropertyManager* ClipMaxPropertyNode; + vector InputNodes; + vector InputSigns; + string Type; + string Name; + double Input; + double Output; + double clipmax, clipmin; + bool IsOutput; + bool clip; + + void Clip(void); + virtual void bind(); + FGPropertyManager* resolveSymbol(string token); + + virtual void Debug(int from); +}; + +} //namespace JSBSim + +#include "../FGFCS.h" + +#endif + diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp new file mode 100755 index 000000000..4c19f4ef9 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp @@ -0,0 +1,138 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGFCSFunction.cpp + Author: Jon S. Berndt + 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 + 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 "FGFCSFunction.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_FCSFUNCTION; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGFCSFunction::FGFCSFunction(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + Element *function_element = element->FindElement("function"); + + function = new FGFunction(PropertyManager, function_element); + + FGFCSComponent::bind(); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGFCSFunction::~FGFCSFunction() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGFCSFunction::Run(void ) +{ + Output = function->GetValue(); + + if (InputNodes.size() > 0) { + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + Output*= Input; + } + + Clip(); + + if (IsOutput) SetOutput(); + + 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 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: FGFCSFunction" << endl; + if (from == 1) cout << "Destroyed: FGFCSFunction" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSFunction.h b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.h new file mode 100755 index 000000000..9f1c5317e --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.h @@ -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 +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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 diff --git a/src/FDM/JSBSim/models/flight_control/FGFilter.cpp b/src/FDM/JSBSim/models/flight_control/FGFilter.cpp new file mode 100644 index 000000000..79ec7e1ed --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGFilter.cpp @@ -0,0 +1,229 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGFilter.cpp + Author: Jon S. Berndt + Date started: 11/2000 + + ------------- 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 "FGFilter.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_FILTER; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGFilter::FGFilter(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + double denom; + + dt = fcs->GetState()->Getdt(); + Trigger = 0; + + C1 = C2 = C3 = C4 = C5 = C6 = 0.0; + + if (Type == "LAG_FILTER") FilterType = eLag ; + else if (Type == "LEAD_LAG_FILTER") FilterType = eLeadLag ; + else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2 ; + else if (Type == "WASHOUT_FILTER") FilterType = eWashout ; + else if (Type == "INTEGRATOR") FilterType = eIntegrator ; + else FilterType = eUnknown ; + + 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; + + switch (FilterType) { + case eLag: + denom = 2.00 + dt*C1; + ca = dt*C1 / denom; + cb = (2.00 - dt*C1) / denom; + break; + case eLeadLag: + denom = 2.00*C3 + dt*C4; + ca = (2.00*C1 + dt*C2) / denom; + cb = (dt*C2 - 2.00*C1) / denom; + cc = (2.00*C3 - dt*C4) / denom; + break; + case eOrder2: + denom = 4.0*C4 + 2.0*C5*dt + C6*dt*dt; + ca = (4.0*C1 + 2.0*C2*dt + C3*dt*dt) / denom; + cb = (2.0*C3*dt*dt - 8.0*C1) / denom; + cc = (4.0*C1 - 2.0*C2*dt + C3*dt*dt) / denom; + cd = (2.0*C6*dt*dt - 8.0*C4) / denom; + ce = (4.0*C4 - 2.0*C5*dt + C6*dt*dt) / denom; + break; + case eWashout: + denom = 2.00 + dt*C1; + ca = 2.00 / denom; + cb = (2.00 - dt*C1) / denom; + break; + case eIntegrator: + ca = dt*C1 / 2.00; + break; + case eUnknown: + cerr << "Unknown filter type" << endl; + break; + } + FGFCSComponent::bind(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGFilter::~FGFilter() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGFilter::Run(void) +{ + double test = 0.0; + + if (Initialize) { + + PreviousOutput1 = PreviousInput1 = Output = Input; + Initialize = false; + + } else { + + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + switch (FilterType) { + case eLag: + Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb; + break; + case eLeadLag: + Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc; + break; + case eOrder2: + Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc + - PreviousOutput1 * cd - PreviousOutput2 * ce; + break; + case eWashout: + Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb; + 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: + break; + } + + } + + PreviousOutput2 = PreviousOutput1; + PreviousOutput1 = Output; + PreviousInput2 = PreviousInput1; + PreviousInput1 = Input; + + Clip(); + if (IsOutput) SetOutput(); + + 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 FGFilter::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUT: " << InputNodes[0]->getName() << endl; + cout << " C1: " << C1 << endl; + cout << " C2: " << C2 << endl; + cout << " C3: " << C3 << endl; + cout << " C4: " << C4 << endl; + cout << " C5: " << C5 << endl; + cout << " C6: " << C6 << endl; + if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGFilter" << endl; + if (from == 1) cout << "Destroyed: FGFilter" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGFilter.h b/src/FDM/JSBSim/models/flight_control/FGFilter.h new file mode 100644 index 000000000..694018e13 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGFilter.h @@ -0,0 +1,223 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGFilter.h + Author: Jon S. Berndt + Date started: 4/2000 + + ------------- Copyright (C) ------------- + + 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 FGFILTER_H +#define FGFILTER_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGFCSComponent.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_FILTER "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a filter for the flight control system. +The filter component can simulate any filter up to second order. The +Tustin substitution is used to take filter definitions from LaPlace space to the +time domain. The general format for a filter specification is: + +
+\
+  \ property \
+  \ value \
+  [\ value \]
+  [\ value \]
+  [\ value \]
+  [\ value \]
+  [\ value \]
+  [\ property \]
+\
+
+ +For a lag filter of the form, +
+  C1
+------
+s + C1
+
+the corresponding filter definition is: +
+\
+  \ property \
+  \ value \
+  [\ property \]
+\
+
+As an example, for the specific filter: +
+  600
+------
+s + 600
+
+the corresponding filter definition could be: +
+\
+  \ fcs/heading-command \
+  \ 600 \
+\
+
+For a lead-lag filter of the form: +
+C1*s + C2
+---------
+C3*s + C4
+
+The corresponding filter definition is: +
+\
+  \ property \
+  \ value \
+  \ value \
+  \ value \
+  \ value \
+  [\ property \]
+\
+
+For a washout filter of the form: +
+  s
+------
+s + C1
+
+The corresponding filter definition is: +
+\
+  \ property \
+  \ value \
+  [\ property \]
+\
+
+For a second order filter of the form: +
+C1*s^2 + C2*s + C3
+------------------
+C4*s^2 + C5*s + C6
+
+The corresponding filter definition is: +
+\
+  \ property \
+  \ value \
+  \ value \
+  \ value \
+  \ value \
+  \ value \
+  \ value \
+  [\ property \]
+\
+
+For an integrator of the form: +
+ C1
+ ---
+  s
+
+The corresponding filter definition is: +
+\
+  \ property \
+  \ value \
+  [\ property \]
+  [\ property \]
+\
+
+For the integrator, the trigger features the following behavior. If the trigger +property value is: + - 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 \ 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 +{ +public: + FGFilter(FGFCS* fcs, Element* element); + ~FGFilter(); + + bool Run (void); + + /** When true, causes previous values to be set to current values. This + is particularly useful for first pass. */ + bool Initialize; + + enum {eLag, eLeadLag, eOrder2, eWashout, eIntegrator, eUnknown} FilterType; + +private: + double dt; + double ca; + double cb; + double cc; + double cd; + double ce; + double C1; + double C2; + double C3; + double C4; + double C5; + double C6; + double PreviousInput1; + double PreviousInput2; + double PreviousOutput1; + double PreviousOutput2; + FGPropertyManager* Trigger; + void Debug(int from); +}; +} +#endif + diff --git a/src/FDM/JSBSim/models/flight_control/FGGain.cpp b/src/FDM/JSBSim/models/flight_control/FGGain.cpp new file mode 100644 index 000000000..b46e7721e --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGGain.cpp @@ -0,0 +1,234 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGGain.cpp + Author: Jon S. Berndt + Date started: 4/2000 + + ------------- 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 "FGGain.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_GAIN; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + Element *scale_element, *zero_centered; + string strScheduledBy, gain_string, sZeroCentered; + + GainPropertyNode = 0; + Gain = 1.000; + Rows = 0; + Table = 0; + InMin = -1.0; + InMax = 1.0; + OutMin = OutMax = 0.0; + + if (Type == "PURE_GAIN") { + if ( !element->FindElement("gain") ) { + cout << highint << " No GAIN specified (default: 1.0)" << normint << endl; + } + } + + 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 { + 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(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGGain::~FGGain() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGGain::Run(void ) +{ + double SchedGain = 1.0; + + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + + if (GainPropertyNode != 0) Gain = GainPropertyNode->getDoubleValue(); + + if (Type == "PURE_GAIN") { // PURE_GAIN + + Output = Gain * Input; + + } else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN + + SchedGain = Table->GetValue(); + Output = Gain * SchedGain * Input; + + } else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE + + 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; + } + + Clip(); + if (IsOutput) SetOutput(); + + 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 FGGain::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + 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; + 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(); + } + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGGain" << endl; + if (from == 1) cout << "Destroyed: FGGain" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGGain.h b/src/FDM/JSBSim/models/flight_control/FGGain.h new file mode 100644 index 000000000..778ad0376 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGGain.h @@ -0,0 +1,188 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGGain.h + Author: + Date started: + + ------------- Copyright (C) ------------- + + 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 FGGAIN_H +#define FGGAIN_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# include STL_STRING + SG_USING_STD(string); +#else +# include +#endif + +#include "FGFCSComponent.h" +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_GAIN "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGFCS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a gain component for the flight control system. + The gain component merely multiplies the input by a gain. The form of the + gain component specification is: +
+    \
+      \ property \
+      \ value \
+      [\ property \]
+    \
+    
+ 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. + + The scheduled gain component multiplies the input by a variable gain that is + dependent on another property (such as qbar, altitude, etc.). The lookup + mapping is in the form of a table. This kind of component might be used, for + example, in a case where aerosurface deflection must only be commanded to + acceptable settings - i.e at higher qbar the commanded elevator setting might + be attenuated. The form of the scheduled gain component specification is: +
+    \
+      INPUT \
+      [GAIN  \]
+      SCHEDULED_BY \
+      ROWS \
+      \
+      ?
+      [CLIPTO \ \ 1]
+      [OUTPUT \]
+    \
+    
+ An overall GAIN may be supplied that is multiplicative with the scheduled gain. + + 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. + + Here is an example of a scheduled gain component specification: +
+    \
+      INPUT        fcs/pitch-gain-1
+      GAIN         0.017
+      SCHEDULED_BY fcs/elevator-pos-rad
+      ROWS         22
+      -0.68  -26.548
+      -0.595 -20.513
+      -0.51  -15.328
+      -0.425 -10.993
+      -0.34   -7.508
+      -0.255  -4.873
+      -0.17   -3.088
+      -0.085  -2.153
+       0      -2.068
+       0.085  -2.833
+       0.102  -3.088
+       0.119  -3.377
+       0.136  -3.7
+       0.153  -4.057
+       0.17   -4.448
+       0.187  -4.873
+       0.272  -7.508
+       0.357 -10.993
+       0.442 -15.328
+       0.527 -20.513
+       0.612 -26.548
+       0.697 -33.433
+    \
+    
+ In the example above, we see the utility of the overall GAIN value in + effecting a degrees-to-radians conversion. + + The aerosurface scale component is a modified version of the simple gain + component. The normal purpose + for this component is to take control inputs that range from -1 to +1 or + from 0 to +1 and scale them to match the expected inputs to a flight control + system. For instance, the normal and expected ability of a pilot to push or + pull on a control stick is about 50 pounds. The input to the pitch channelb + lock diagram of a flight control system is in units of pounds. Yet, the + joystick control input is usually in a range from -1 to +1. The form of the + aerosurface scaling component specification is: +
+    \
+      INPUT \
+      MIN \
+      MAX \
+      [GAIN  \]
+      [OUTPUT \]
+    \
+
+ 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. + + @author Jon S. Berndt + @version $Id$ +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGGain : public FGFCSComponent +{ +public: + FGGain(FGFCS* fcs, Element* element); + ~FGGain(); + + bool Run (void); + +private: + FGTable* Table; + FGPropertyManager* GainPropertyNode; + double Gain; + double InMin, InMax, OutMin, OutMax; + int Rows; + bool ZeroCentered; + + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/models/flight_control/FGGradient.cpp b/src/FDM/JSBSim/models/flight_control/FGGradient.cpp new file mode 100644 index 000000000..c42d9b97a --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGGradient.cpp @@ -0,0 +1,118 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGGradient.cpp + Author: + Date started: + + ------------- 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 "FGGradient.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_GRADIENT; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +FGGradient::FGGradient(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + FGFCSComponent::bind(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGGradient::~FGGradient() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGGradient::Run(void ) +{ + 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 FGGradient::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: FGGradient" << endl; + if (from == 1) cout << "Destroyed: FGGradient" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGGradient.h b/src/FDM/JSBSim/models/flight_control/FGGradient.h new file mode 100644 index 000000000..b51dee519 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGGradient.h @@ -0,0 +1,80 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGGradient.h + Author: + Date started: + + ------------- Copyright (C) ------------- + + 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 FGGRADIENT_H +#define FGGRADIENT_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGFCSComponent.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_GRADIENT "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGFCS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a gradient component for the flight control system. + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGGradient : public FGFCSComponent +{ +public: + FGGradient(FGFCS* fcs, Element* element); + ~FGGradient(); + + bool Run (void); + +private: + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp b/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp new file mode 100644 index 000000000..dffcce746 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp @@ -0,0 +1,215 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGKinemat.cpp + Author: Tony Peden, for flight control system authored by Jon S. Berndt + Date started: 12/02/01 + + ------------- Copyright (C) 2000 Anthony K. Peden ------------- + + 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 +#include + +#include "FGKinemat.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_FLAPS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGKinemat::FGKinemat(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + Element *traverse_element, *setting_element; + double tmpDetent; + double tmpTime; + + Detents.clear(); + TransitionTimes.clear(); + + Output = OutputPct = 0; + DoScale = true; + + if (element->FindElement("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 ); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGKinemat::~FGKinemat() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGKinemat::Run(void ) +{ + double dt = fcs->GetState()->Getdt(); + + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + + if (DoScale) Input *= Detents[NumDetents-1]; + + if (IsOutput) Output = OutputNode->getDoubleValue(); + + if (Input < Detents[0]) + Input = Detents[0]; + else if (Detents[NumDetents-1] < Input) + Input = Detents[NumDetents-1]; + + // Process all detent intervals the movement traverses until either the + // final value is reached or the time interval has finished. + while ( 0.0 < dt && !EqualToRoundoff(Input, Output) ) { + + // Find the area where Output is in + int ind; + for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind) + if (NumDetents <= ind) + break; + + // A transition time of 0.0 means an infinite rate. + // The output is reached in one step + if (TransitionTimes[ind] <= 0.0) { + Output = Input; + break; + } else { + // Compute the rate in this area + double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind]; + // Compute the maximum input value inside this area + double ThisInput = Input; + if (ThisInput < Detents[ind-1]) ThisInput = Detents[ind-1]; + if (Detents[ind] < ThisInput) ThisInput = Detents[ind]; + // Compute the time to reach the value in ThisInput + double ThisDt = fabs((ThisInput-Output)/Rate); + + // and clip to the timestep size + if (dt < ThisDt) { + ThisDt = dt; + if (Output < Input) + Output += ThisDt*Rate; + else + Output -= ThisDt*Rate; + } else + // Handle this case separate to make shure the termination condition + // is met even in inexact arithmetics ... + Output = ThisInput; + + dt -= ThisDt; + } + } + + OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]); + + Clip(); + if (IsOutput) SetOutput(); + + 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 FGKinemat::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUT: " << InputNodes[0]->getName() << endl; + cout << " DETENTS: " << NumDetents << endl; + for (int i=0;igetName() << endl; + if (!DoScale) cout << " NOSCALE" << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGKinemat" << endl; + if (from == 1) cout << "Destroyed: FGKinemat" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGKinemat.h b/src/FDM/JSBSim/models/flight_control/FGKinemat.h new file mode 100644 index 000000000..43508dec8 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGKinemat.h @@ -0,0 +1,115 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGKinemat.h + Author: Tony Peden, for flight control system authored by Jon S. Berndt + Date started: 12/02/01 + + ------------- Copyright (C) Anthony K. Peden ------------- + + 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 FGKinemat_H +#define FGKinemat_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# include +#endif + +#include +#include "FGFCSComponent.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_FLAPS "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a kinematic component for the flight control system. + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGKinemat : public FGFCSComponent { +public: + /** Initializer. + @param fcs A reference to the ccurrent flightcontrolsystem. + @param AC_cfg reference to the current aircraft configuration file. + Initializes the FGKinemat object from the given configuration + file. The Configuration file is expected to be at the stream + position where the KINEMAT object starts. Also it is expected to + be past the end of the current KINEMAT configuration on exit. + */ + FGKinemat(FGFCS* fcs, Element* element); + + /** Destructor. + */ + ~FGKinemat(); + + /** Kinemat output value. + @return the current output of the kinemat object on the range of [0,1]. + */ + double GetOutputPct() const { return OutputPct; } + + /** Run method, overwrites FGModel::Run(). + @return false on success, true on failure. + The routine doing the work. + */ + bool Run (void); + +private: + vector Detents; + vector TransitionTimes; + int NumDetents; + double OutputPct; + bool DoScale; + + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.cpp b/src/FDM/JSBSim/models/flight_control/FGSensor.cpp new file mode 100755 index 000000000..b2d541d32 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGSensor.cpp @@ -0,0 +1,264 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGSensor.cpp + Author: Jon Berndt + Date started: 9 July 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 + 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 "FGSensor.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_SENSOR; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + double denom; + dt = fcs->GetState()->Getdt(); + + // inputs are read from the base class constructor + + dt = fcs->GetState()->Getdt(); + + bits = quantized = divisions = 0; + PreviousInput = PreviousOutput = 0.0; + min = max = bias = noise_variance = lag = drift_rate = drift = span = 0.0; + granularity = 0.0; + noise_type = 0; + fail_low = fail_high = fail_stuck = false; + + Element* quantization_element = element->FindElement("quantization"); + if ( quantization_element) { + if ( quantization_element->FindElement("bits") ) { + bits = (int)quantization_element->FindElementValueAsNumber("bits"); + } + divisions = (1<FindElement("min") ) { + min = quantization_element->FindElementValueAsNumber("min"); + } + if ( quantization_element->FindElement("max") ) { + max = quantization_element->FindElementValueAsNumber("max"); + } + span = max - min; + granularity = span/divisions; + } + if ( element->FindElement("bias") ) { + bias = element->FindElementValueAsNumber("bias"); + } + if ( element->FindElement("drift_rate") ) { + drift_rate = element->FindElementValueAsNumber("drift_rate"); + } + if ( element->FindElement("lag") ) { + lag = element->FindElementValueAsNumber("lag"); + denom = 2.00 + dt*lag; + ca = dt*lag / denom; + cb = (2.00 - dt*lag) / denom; + } + if ( element->FindElement("noise") ) { + noise_variance = element->FindElementValueAsNumber("noise"); + string variation = element->FindElement("noise")->GetAttributeValue("variation"); + if (variation == "PERCENT") { + NoiseType = ePercent; + } else if (variation == "ABSOLUTE") { + NoiseType = eAbsolute; + } else { + NoiseType = ePercent; + cerr << "Unknown noise type in sensor: " << Name << endl; + cerr << " defaulting to PERCENT." << endl; + } + } + + FGFCSComponent::bind(); + bind(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGSensor::~FGSensor() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGSensor::Run(void ) +{ + Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + + Output = Input; // perfect sensor + + // Degrade signal as specified + + if (fail_stuck) { + Output = PreviousOutput; + return true; + } + + if (lag != 0.0) Lag(); // models sensor lag + if (noise_variance != 0.0) Noise(); // models noise + if (drift_rate != 0.0) Drift(); // models drift over time + if (bias != 0.0) Bias(); // models a finite bias + + if (fail_low) Output = -HUGE_VAL; + if (fail_high) Output = HUGE_VAL; + + if (bits != 0) Quantize(); // models quantization degradation +// if (delay != 0.0) Delay(); // models system signal transport latencies + + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGSensor::Noise(void) +{ + double random_value = ((double)rand()/(double)RAND_MAX) - 0.5; + + switch( NoiseType ) { + case ePercent: + Output *= (1.0 + noise_variance*random_value); + break; + + case eAbsolute: + Output += noise_variance*random_value; + break; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGSensor::Bias(void) +{ + Output += bias; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGSensor::Drift(void) +{ + drift += drift_rate*dt; + Output += drift; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGSensor::Quantize(void) +{ + if (Output < min) Output = min; + if (Output > max) Output = max; + double portion = Output - min; + quantized = (int)(portion/granularity); + Output = quantized*granularity + min; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGSensor::Lag(void) +{ + // "Output" on the right side of the "=" is the current frame input + Output = ca * (Output + PreviousInput) + PreviousOutput * cb; + + PreviousOutput = Output; + PreviousInput = Input; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGSensor::bind(void) +{ + string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); + const string tmp_low = tmp + "/malfunction/fail_low"; + const string tmp_high = tmp + "/malfunction/fail_high"; + const string tmp_stuck = tmp + "/malfunction/fail_stuck"; + + PropertyManager->Tie( tmp_low, this, &FGSensor::GetFailLow, &FGSensor::SetFailLow); + PropertyManager->Tie( tmp_high, this, &FGSensor::GetFailHigh, &FGSensor::SetFailHigh); + PropertyManager->Tie( tmp_stuck, this, &FGSensor::GetFailStuck, &FGSensor::SetFailStuck); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGSensor::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: FGSensor" << endl; + if (from == 1) cout << "Destroyed: FGSensor" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.h b/src/FDM/JSBSim/models/flight_control/FGSensor.h new file mode 100755 index 000000000..a21644ae4 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGSensor.h @@ -0,0 +1,158 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGSensor.h + Author: Jon Berndt + Date started: 9 July 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 + 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 FGSENSOR_H +#define FGSENSOR_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGFCSComponent.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_SENSOR "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGFCS; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a Sensor component for the flight control system. + +Syntax: + + + property + number + number + + number + number + number + + number + number + + +Example: + + + aero/qbar + 0.5 + 2 + + 12 + 0 + 400 + + 0.5 + + +The only required element in the sensor definition is the input element. In that +case, no degradation would be modeled, and the output would simply be the input. + +For noise, if the type is PERCENT, then the value supplied is understood to be a +percentage variance. That is, if the number given is 0.05, the the variance is +understood to be +/-0.05 percent maximum variance. So, the actual value for the sensor +will be *anywhere* from 0.95 to 1.05 of the actual "perfect" value at any time - +even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the delta +time. + + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGSensor : public FGFCSComponent +{ +public: + FGSensor(FGFCS* fcs, Element* element); + ~FGSensor(); + + inline void SetFailLow(double val) {if (val > 0.0) fail_low = true; else fail_low = false;} + inline void SetFailHigh(double val) {if (val > 0.0) fail_high = true; else fail_high = false;} + inline void SetFailStuck(double val) {if (val > 0.0) fail_stuck = true; else fail_stuck = false;} + + inline double GetFailLow(void) const {if (fail_low) return 1.0; else return 0.0;} + inline double GetFailHigh(void) const {if (fail_high) return 1.0; else return 0.0;} + inline double GetFailStuck(void) const {if (fail_stuck) return 1.0; else return 0.0;} + + bool Run (void); + +private: + enum eNoiseType {ePercent=0, eAbsolute} NoiseType; + double dt; + double min, max; + double span; + double bias; + double drift_rate; + double drift; + double noise_variance; + double lag; + double granularity; + double ca; /// lag filter coefficient "a" + double cb; /// lag filter coefficient "b" + double PreviousOutput; + double PreviousInput; + int noise_type; + int bits; + int quantized; + int divisions; + bool fail_low; + bool fail_high; + bool fail_stuck; + + void Noise(void); + void Bias(void); + void Drift(void); + void Quantize(void); + void Lag(void); + + void bind(void); + + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/models/flight_control/FGSummer.cpp b/src/FDM/JSBSim/models/flight_control/FGSummer.cpp new file mode 100644 index 000000000..06b575f4c --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGSummer.cpp @@ -0,0 +1,146 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGSummer.cpp + Author: Jon S. Berndt + Date started: 4/2000 + + ------------- 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 "FGSummer.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_SUMMER; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGSummer::FGSummer(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + Bias = 0.0; + + if (element->FindElement("bias")) Bias = element->FindElementValueAsNumber("bias"); + + FGFCSComponent::bind(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGSummer::~FGSummer() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGSummer::Run(void ) +{ + unsigned int idx; + + Output = 0.0; + + for (idx=0; idxgetDoubleValue() * InputSigns[idx]; + } + + Output += Bias; + + Clip(); + if (IsOutput) SetOutput(); + + 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 FGSummer::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " INPUTS: " << endl; + for (unsigned i=0;igetName() << endl; + else + cout << " " << InputNodes[i]->getName() << endl; + } + if (Bias != 0.0) cout << " Bias: " << Bias << endl; + if (clip) cout << " CLIPTO: " << clipmin + << ", " << clipmax << endl; + if (IsOutput) cout << " OUTPUT: " <getName() << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGSummer" << endl; + if (from == 1) cout << "Destroyed: FGSummer" << 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 + diff --git a/src/FDM/JSBSim/models/flight_control/FGSummer.h b/src/FDM/JSBSim/models/flight_control/FGSummer.h new file mode 100644 index 000000000..ede4b261f --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGSummer.h @@ -0,0 +1,124 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGSummer.h + Author: + Date started: + + ------------- Copyright (C) ------------- + + 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 FGSUMMER_H +#define FGSUMMER_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# include +#endif + +#include +#include "FGFCSComponent.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_SUMMER "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models a flight control system summing component. + The Summer component sums two or more inputs. These can be pilot control + inputs or state variables, and a bias can also be added in using the BIAS + keyword. The form of the summer component specification is: +
+    \
+      INPUT \
+      INPUT \
+      [BIAS \]
+      [?]
+      [CLIPTO \ \ 1]
+      [OUTPUT \]
+    \
+
+ Note that in the case of an input property the property name may be + immediately preceded by a minus sign. Here's an example of a summer + component specification: +
+    \
+      INPUT  velocities/p-rad_sec
+      INPUT -fcs/roll-ap-wing-leveler
+      INPUT  fcs/roll-ap-error-integrator
+      CLIPTO -1 1
+    \
+
+ Note that there can be only one BIAS statement per component. + + @author Jon S. Berndt + @version $Id$ +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGSummer : public FGFCSComponent +{ +public: + /** Constructor. + @param fcs a pointer to the parent FGFCS object. + @param AC_cfg a pointer to the configuration file object. */ + FGSummer(FGFCS* fcs, Element* element); + /// Destructor + ~FGSummer(); + + /// The execution method for this FCS component. + bool Run(void); + +private: + double Bias; + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp b/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp new file mode 100644 index 000000000..0ac768416 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp @@ -0,0 +1,280 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGSwitch.cpp + Author: Jon S. Berndt + Date started: 4/2000 + + ------------- 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 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +The SWITCH component is defined as follows (see the API documentation for more +information): + + + + {property} {conditional} {property|value} + + {property} {conditional} {property|value} + ... + + ... + + + {property} {conditional} {property|value} + ... + + ... + + +Also, see the header file (FGSwitch.h) for further details. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGSwitch.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_SWITCH; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) +{ + string value, logic; + struct test *current_test; + Element *test_element, *condition_element; + + test_element = element->GetElement(); + while (test_element) { + if (test_element->GetName() == "default") { + tests.push_back(test()); + current_test = &tests.back(); + current_test->Logic = eDefault; + } else if (test_element->GetName() == "test") { // here's a test + tests.push_back(test()); + current_test = &tests.back(); + logic = test_element->GetAttributeValue("logic"); + if (logic == "OR") current_test->Logic = eOR; + else if (logic == "AND") current_test->Logic = eAND; + else if (logic.size() == 0) current_test->Logic == eAND; // default + else { // error + cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl; + } + for (int i=0; iGetNumDataLines(); i++) + current_test->conditions.push_back(FGCondition(test_element->GetDataLine(i), PropertyManager)); + + condition_element = test_element->GetElement(); // retrieve condition groups + while (condition_element) { + current_test->conditions.push_back(FGCondition(condition_element, PropertyManager)); + condition_element = test_element->GetNextElement(); + } + + } + + if (test_element->GetName() != "output") { // this is not an output element + value = test_element->GetAttributeValue("value"); + if (value.empty()) { + cerr << "No VALUE supplied for switch component: " << Name << endl; + } else { + if (value.find_first_not_of("-.0123456789eE") == string::npos) { + // if true (and execution falls into this block), "value" is a number. + current_test->OutputVal = atof(value.c_str()); + } else { + // "value" must be a property if execution passes to here. + if (value[0] == '-') { + current_test->sign = -1.0; + value.erase(0,1); + } else { + current_test->sign = 1.0; + } + current_test->OutputProp = PropertyManager->GetNode(value); + } + } + } + + test_element = element->GetNextElement(); + } + + FGFCSComponent::bind(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGSwitch::~FGSwitch() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGSwitch::Run(void ) +{ + vector ::iterator iTests = tests.begin(); + vector ::iterator iConditions; + bool pass = false; + + while (iTests < tests.end()) { + iConditions = iTests->conditions.begin(); + + if (iTests->Logic == eDefault) { + Output = iTests->GetValue(); + } else if (iTests->Logic == eAND) { + pass = true; + while (iConditions < iTests->conditions.end()) { + if (!iConditions->Evaluate()) pass = false; + *iConditions++; + } + } else if (iTests->Logic == eOR) { + pass = false; + while (iConditions < iTests->conditions.end()) { + if (iConditions->Evaluate()) pass = true; + *iConditions++; + } + } else { + cerr << "Invalid logic test" << endl; + } + + if (pass) { + Output = iTests->GetValue(); + break; + } + *iTests++; + } + + Clip(); + if (IsOutput) SetOutput(); + + 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 FGSwitch::Debug(int from) +{ + vector ::iterator iTests = tests.begin(); + vector ::iterator iConditions; + string comp, scratch; + string indent = " "; + bool first = false; + + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + while (iTests < tests.end()) { + + scratch = " if "; + + switch(iTests->Logic) { + case (elUndef): + comp = " UNSET "; + cerr << "Unset logic for test condition" << endl; + break; + case (eAND): + comp = " AND "; + break; + case (eOR): + comp=" OR "; + break; + case (eDefault): + scratch = " by default."; + break; + default: + comp = " UNKNOWN "; + cerr << "Unknown logic for test condition" << endl; + } + + if (iTests->OutputProp != 0L) + if (iTests->sign < 0) + cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl; + else + cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl; + else + cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl; + + iConditions = iTests->conditions.begin(); + first = true; + while (iConditions < iTests->conditions.end()) { + if (!first) cout << indent << comp << " "; + else cout << indent << " "; + first = false; + iConditions->PrintCondition(); + cout << endl; + *iConditions++; + } + cout << endl; + *iTests++; + } + if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGSwitch" << endl; + if (from == 1) cout << "Destroyed: FGSwitch" << 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 + diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.h b/src/FDM/JSBSim/models/flight_control/FGSwitch.h new file mode 100644 index 000000000..a6ef0db17 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/FGSwitch.h @@ -0,0 +1,169 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGSwitch.h + Author: Jon S. Berndt + Date started: 12/23/2002 + + ------------- Copyright (C) ------------- + + 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 FGSWITCH_H +#define FGSWITCH_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGFCSComponent.h" +#include +#include "FGCondition.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_SWITCH "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Encapsulates a switch for the flight control system. + +The SWITCH component models a switch - either on/off or a multi-choice rotary +switch. The switch can represent a physical cockpit switch, or can represent a +logical switch, where several conditions might need to be satisfied before a +particular state is reached. The VALUE of the switch - the output value for the +component - is chosen depending on the state of the switch. Each switch is +comprised of two or more TESTs. Each TEST has a VALUE associated with it. The +first TEST that evaluates to TRUE will set the output value of the switch +according to the VALUE parameter belonging to that TEST. Each TEST contains one +or more CONDITIONS, which each must be logically related (if there are more than +one) given the value of the LOGIC parameter, and which takes the form: + + property conditional property|value + +e.g. + + qbar GE 21.0 + +or, + + roll_rate < pitch_rate + +Within a TEST, a CONDITION_GROUP can be specified. A CONDITION_GROUP allows for +complex groupings of logical comparisons. Each CONDITION_GROUP contains +additional conditions, as well as possibly additional CONDITION_GROUPs. + +
+\
+  \
+    {property} {conditional} {property|value}
+    \
+      {property} {conditional} {property|value}
+      ...
+    \
+    ...
+  \
+  \
+    {property} {conditional} {property|value}
+    ...
+  \
+  ...
+  [OUTPUT \]
+\
+
+ +Here's an example: +
+\
+  \
+  \
+  \
+    ap/attitude_hold == 1
+  \
+\
+
+The above example specifies that the default value of the component (i.e. the +output property of the component, addressed by the property, ap/roll-ap-autoswitch) +is 0.0. If or when the attitude hold switch is selected (property +ap/attitude_hold takes the value 1), the value of the switch component will be +whatever value fcs/roll-ap-error-summer is. +@author Jon S. Berndt +@version $Id$ +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGSwitch : public FGFCSComponent +{ +public: + FGSwitch(FGFCS* fcs, Element* element); + ~FGSwitch(); + + bool Run(void); + + enum eLogic {elUndef=0, eAND, eOR, eDefault}; + enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE}; + +private: + FGFCS* fcs; + + struct test { + vector conditions; + eLogic Logic; + double OutputVal; + FGPropertyManager *OutputProp; + float sign; + + double GetValue(void) { + if (OutputProp == 0L) return OutputVal; + else return OutputProp->getDoubleValue()*sign; + } + + test(void) { // constructor for the test structure + Logic = elUndef; + OutputVal = 0.0; + OutputProp = 0L; + sign = 1.0; + } + + }; + + vector tests; + + void Debug(int from); +}; +} +#endif diff --git a/src/FDM/JSBSim/models/flight_control/Makefile.am b/src/FDM/JSBSim/models/flight_control/Makefile.am new file mode 100644 index 000000000..4ae764df0 --- /dev/null +++ b/src/FDM/JSBSim/models/flight_control/Makefile.am @@ -0,0 +1,11 @@ +noinst_LIBRARIES = libFlightControl.a + +libFlightControl_a_SOURCES = FGCondition.cpp FGDeadBand.cpp FGFCSComponent.cpp \ + FGFilter.cpp FGGain.cpp FGGradient.cpp FGKinemat.cpp \ + FGSummer.cpp FGSwitch.cpp FGFCSFunction.cpp FGSensor.cpp + +noinst_HEADERS = FGCondition.h FGDeadBand.h FGFCSComponent.h FGFilter.h \ + FGGain.h FGGradient.h FGKinemat.h FGSummer.h FGSwitch.h FGFCSFunction.h \ + FGSensor.h + +INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp new file mode 100644 index 000000000..3740ed911 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp @@ -0,0 +1,163 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGElectric.cpp + Author: David Culp + Date started: 04/07/2004 + Purpose: This module models an electric motor + + --------- Copyright (C) 2004 David 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. + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +This class descends from the FGEngine class and models an electric motor based on +parameters given in the engine config file for this class + +HISTORY +-------------------------------------------------------------------------------- +04/07/2004 DPC Created +01/06/2005 DPC Converted to new XML format + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGElectric.h" +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_ELECTRIC; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGElectric::FGElectric(FGFDMExec* exec, Element *el, int engine_number) + : FGEngine(exec, el, engine_number) +{ + string token; + + Type = etElectric; + PowerWatts = 745.7; + hptowatts = 745.7; + + dt = State->Getdt(); + + if (el->FindElement("power")) + PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS"); + + Debug(0); // Call Debug() routine from constructor if needed +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGElectric::~FGElectric() +{ + Debug(1); // Call Debug() routine from constructor if needed +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGElectric::Calculate(void) +{ + Throttle = FCS->GetThrottlePos(EngineNumber); + + RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); + + HP = PowerWatts * Throttle / hptowatts; + + PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); + + return Thruster->Calculate(PowerAvailable); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGElectric::GetEngineLabels(string delimeter) +{ + return ""; // currently no labels are returned for this engine +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGElectric::GetEngineValues(string delimeter) +{ + return ""; // currently no values are returned for this engine +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// +// 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 FGElectric::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + cout << "\n Engine Name: " << Name << endl; + cout << " Power Watts: " << PowerWatts << endl; + + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGElectric" << endl; + if (from == 1) cout << "Destroyed: FGElectric" << 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; + } + } +} + +double +FGElectric::CalcFuelNeed(void) +{ + return 0; +} + +} // namespace JSBSim diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.h b/src/FDM/JSBSim/models/propulsion/FGElectric.h new file mode 100644 index 000000000..84aa37837 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGElectric.h @@ -0,0 +1,107 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGElectric.h + Author: David Culp + Date started: 04/07/2004 + + ----- Copyright (C) 2004 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 +-------------------------------------------------------------------------------- +04/07/2004 DPC Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGELECTRIC_H +#define FGELECTRIC_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGEngine.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_ELECTRIC "$Id$"; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models and electric motor. + FGElectric models an electric motor based on the configuration file + POWER_WATTS parameter. The throttle controls motor output linearly from + zero to POWER_WATTS. This power value (converted internally to horsepower) + is then used by FGPropeller to apply torque to the propeller. + @author David Culp + @version "$Id$" + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGElectric : public FGEngine +{ +public: + /// Constructor + FGElectric(FGFDMExec* exec, Element *el, int engine_number); + /// Destructor + ~FGElectric(); + + double Calculate(void); + double GetPowerAvailable(void) {return PowerAvailable;} + double CalcFuelNeed(void); + double getRPM(void) {return RPM;} + string GetEngineLabels(string delimeter); + string GetEngineValues(string delimeter); + +private: + + double BrakeHorsePower; + double PowerAvailable; + + // timestep + double dt; + + // constants + double hptowatts; + + double PowerWatts; // maximum engine power + double RPM; // revolutions per minute + double HP; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp new file mode 100644 index 000000000..a385088ae --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp @@ -0,0 +1,358 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGEngine.cpp + Author: Jon Berndt + Date started: 01/21/99 + 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 +-------------------------------------------------------------------------------- +See header file. + +HISTORY +-------------------------------------------------------------------------------- +01/21/99 JSB Created +09/03/99 JSB Changed Rocket thrust equation to correct -= Thrust instead of + += Thrust (thanks to Tony Peden) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) +# include +# else +# include +# endif +#endif + +#include "FGEngine.h" +#include "FGTank.h" +#include "FGPropeller.h" +#include "FGNozzle.h" +#include +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_ENGINE; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number) + : EngineNumber(engine_number) +{ + Element* local_element; + FGColumnVector3 location, orientation; + + Name = ""; + Type = etUnknown; + X = Y = Z = 0.0; + EnginePitch = EngineYaw = 0.0; + SLFuelFlowMax = SLOxiFlowMax = 0.0; + MaxThrottle = 1.0; + MinThrottle = 0.0; + Thrust = 0.0; + Throttle = 0.0; + Mixture = 1.0; + Starter = false; + FuelNeed = OxidizerNeed = 0.0; + Starved = Running = Cranking = false; + PctPower = 0.0; + TrimMode = false; + FuelFlow_gph = 0.0; + FuelFlow_pph = 0.0; + FuelFreeze = false; + + FDMExec = exec; + State = FDMExec->GetState(); + Atmosphere = FDMExec->GetAtmosphere(); + FCS = FDMExec->GetFCS(); + Propulsion = FDMExec->GetPropulsion(); + Aircraft = FDMExec->GetAircraft(); + Propagate = FDMExec->GetPropagate(); + Auxiliary = FDMExec->GetAuxiliary(); + + PropertyManager = FDMExec->GetPropertyManager(); + + Name = engine_element->GetAttributeValue("name"); + +// Find and set engine location + + local_element = engine_element->GetParent()->FindElement("location"); + if (local_element) location = local_element->FindElementTripletConvertTo("IN"); + else cerr << "No engine location found for this engine." << endl; + + local_element = engine_element->GetParent()->FindElement("orient"); + if (local_element) orientation = local_element->FindElementTripletConvertTo("IN"); + else cerr << "No engine orientation found for this engine." << endl; + + SetPlacement(location, orientation); + + // Load thruster + local_element = engine_element->GetParent()->FindElement("thruster"); + if (local_element) { + LoadThruster(local_element); + } else { + cerr << "No thruster definition supplied with engine definition." << endl; + } + + // Load feed tank[s] references + local_element = engine_element->GetParent()->FindElement("feed"); + if (local_element) { + while (local_element) { + AddFeedTank((int)local_element->GetDataAsNumber()); + local_element = engine_element->GetParent()->FindNextElement("feed"); + } + } else { + cerr << "No feed tank specified in engine definition." << endl; + } + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGEngine::~FGEngine() +{ + if (Thruster) delete Thruster; + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// This base class function should be called from within the +// derived class' Calculate() function before any other calculations are done. +// This base class method removes fuel from the fuel tanks as appropriate, +// and sets the starved flag if necessary. + +void FGEngine::ConsumeFuel(void) +{ + if (FuelFreeze) return; + if (TrimMode) return; + + unsigned int i; + double Fshortage, Oshortage, TanksWithFuel, TanksWithOxidizer; + FGTank* Tank; + bool haveOxTanks = false; + Fshortage = Oshortage = TanksWithFuel = TanksWithOxidizer = 0.0; + + // count how many assigned tanks have fuel + for (i=0; iGetTank(SourceTanks[i]); + if (Tank->GetType() == FGTank::ttFUEL){ + if (Tank->GetContents() > 0.0) ++TanksWithFuel; + } else if (Tank->GetType() == FGTank::ttOXIDIZER) { + haveOxTanks = true; + if (Tank->GetContents() > 0.0) ++TanksWithOxidizer; + } + } + if (TanksWithFuel==0 || (haveOxTanks && TanksWithOxidizer==0)) return; + + for (i=0; iGetTank(SourceTanks[i]); + if (Tank->GetType() == FGTank::ttFUEL) { + Fshortage += Tank->Drain(CalcFuelNeed()/TanksWithFuel); + } else if (Tank->GetType() == FGTank::ttOXIDIZER) { + Oshortage += Tank->Drain(CalcOxidizerNeed()/TanksWithOxidizer); + } + } + + if (Fshortage < 0.00 || Oshortage < 0.00) Starved = true; + else Starved = false; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGEngine::CalcFuelNeed(void) +{ + FuelNeed = SLFuelFlowMax*PctPower*State->Getdt()*Propulsion->GetRate(); + return FuelNeed; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGEngine::CalcOxidizerNeed(void) +{ + OxidizerNeed = SLOxiFlowMax*PctPower*State->Getdt()*Propulsion->GetRate(); + return OxidizerNeed; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGEngine::SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation) +{ + X = location(eX); + Y = location(eY); + Z = location(eZ); + EnginePitch = orientation(ePitch); + EngineYaw = orientation (eYaw); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGEngine::AddFeedTank(int tkID) +{ + SourceTanks.push_back(tkID); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGColumnVector3& FGEngine::GetBodyForces(void) +{ + return Thruster->GetBodyForces(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGColumnVector3& FGEngine::GetMoments(void) +{ + return Thruster->GetMoments(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGEngine::LoadThruster(Element *thruster_element) +{ + string token, fullpath, localpath; + string thruster_filename, thruster_fullpathname, thrType; + double xLoc, yLoc, zLoc, Pitch, Yaw; + double P_Factor = 0, Sense = 0.0; + string enginePath = FDMExec->GetEnginePath(); + string aircraftPath = FDMExec->GetAircraftPath(); + FGXMLParse thruster_file_parser; + Element *document, *element; + ifstream thruster_file; + FGColumnVector3 location, orientation; + +# ifndef macintosh + string separator = "/"; +# else + string separator = ";"; +# endif + + fullpath = enginePath + separator; + localpath = aircraftPath + separator + "Engines" + separator; + + thruster_filename = thruster_element->GetAttributeValue("file"); + if ( !thruster_filename.empty()) { + thruster_fullpathname = fullpath + thruster_filename + ".xml"; + thruster_file.open(thruster_fullpathname.c_str()); + if ( !thruster_file.is_open()) { + thruster_fullpathname = localpath + thruster_filename + ".xml"; + thruster_file.open(thruster_fullpathname.c_str()); + if ( !thruster_file.is_open()) { + cerr << "Could not open thruster file: " << thruster_filename << ".xml" << endl; + return false; + } else { + thruster_file.close(); + } + } else { + thruster_file.close(); + } + } else { + cerr << "No thruster filename given." << endl; + return false; + } + + readXML(thruster_fullpathname, thruster_file_parser); + document = thruster_file_parser.GetDocument(); // document holds the thruster description + document->SetParent(thruster_element); + + thrType = document->GetName(); + + if (thrType == "propeller") { + Thruster = new FGPropeller(FDMExec, document, EngineNumber); + } else if (thrType == "nozzle") { + Thruster = new FGNozzle(FDMExec, document, EngineNumber); + } else if (thrType == "direct") { + Thruster = new FGThruster( FDMExec, document, EngineNumber); + } + + Thruster->SetdeltaT(State->Getdt() * Propulsion->GetRate()); + + 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 FGEngine::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + } + if (from == 2) { // After thruster loading + cout << " X = " << Thruster->GetLocationX() << endl; + cout << " Y = " << Thruster->GetLocationY() << endl; + cout << " Z = " << Thruster->GetLocationZ() << endl; + cout << " Pitch = " << Thruster->GetAnglesToBody(ePitch) << endl; + cout << " Yaw = " << Thruster->GetAnglesToBody(eYaw) << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGEngine" << endl; + if (from == 1) cout << "Destroyed: FGEngine" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.h b/src/FDM/JSBSim/models/propulsion/FGEngine.h new file mode 100644 index 000000000..a6e820aaa --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.h @@ -0,0 +1,236 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGEngine.h + Author: Jon S. Berndt + Date started: 01/21/99 + + ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) ------------- + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 Temple + Place - Suite 330, Boston, MA 02111-1307, USA. + + Further information about the GNU General Public License can also be found on + the world wide web at http://www.gnu.org. + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +Based on Flightgear code, which is based on LaRCSim. This class simulates +a generic engine. + +HISTORY +-------------------------------------------------------------------------------- +01/21/99 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGENGINE_H +#define FGENGINE_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifdef FGFS +# include +# include STL_STRING + SG_USING_STD(string); +# ifdef SG_HAVE_STD_INCLUDES +# include +# else +# include +# endif +#else +# include +# include +#endif + +#include +#include "FGThruster.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_ENGINE "$Id$" + +using std::string; +using std::vector; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGFDMExec; +class FGState; +class FGAtmosphere; +class FGFCS; +class FGAircraft; +class FGPropagate; +class FGPropulsion; +class FGAuxiliary; +class FGThruster; +class Element; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Base class for all engines. + This base class contains methods and members common to all engines, such as + logic to drain fuel from the appropriate tank, etc. + @author Jon S. Berndt + @version $Id$ +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGEngine : public FGJSBBase +{ +public: + FGEngine(FGFDMExec* exec, Element* el, int engine_number); + virtual ~FGEngine(); + + enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etTurboprop, etElectric}; + + EngineType GetType(void) { return Type; } + virtual string GetName(void) { return Name; } + + // Engine controls + virtual double GetThrottleMin(void) { return MinThrottle; } + virtual double GetThrottleMax(void) { return MaxThrottle; } + virtual double GetThrottle(void) { return Throttle; } + virtual double GetMixture(void) { return Mixture; } + virtual bool GetStarter(void) { return Starter; } + + virtual double getFuelFlow_gph () const {return FuelFlow_gph;} + virtual double getFuelFlow_pph () const {return FuelFlow_pph;} + virtual double GetThrust(void) { return Thrust; } + virtual bool GetStarved(void) { return Starved; } + virtual bool GetRunning(void) { return Running; } + virtual bool GetCranking(void) { return Cranking; } + + virtual void SetStarved(bool tt) { Starved = tt; } + virtual void SetStarved(void) { Starved = true; } + + virtual void SetRunning(bool bb) { Running=bb; } + virtual void SetName(string name) { Name = name; } + virtual void AddFeedTank(int tkID); + virtual void SetFuelFreeze(bool f) { FuelFreeze = f; } + + virtual void SetStarter(bool s) { Starter = s; } + + /** Calculates the thrust of the engine, and other engine functions. + @return Thrust in pounds */ + virtual double Calculate(void) {return 0.0;} + + /** Reduces the fuel in the active tanks by the amount required. + This function should be called from within the + derived class' Calculate() function before any other calculations are + done. This base class method removes fuel from the fuel tanks as + appropriate, and sets the starved flag if necessary. */ + virtual void ConsumeFuel(void); + + /** The fuel need is calculated based on power levels and flow rate for that + power level. It is also turned from a rate into an actual amount (pounds) + by multiplying it by the delta T and the rate. + @return Total fuel requirement for this engine in pounds. */ + virtual double CalcFuelNeed(void); + + /** The oxidizer need is calculated based on power levels and flow rate for that + power level. It is also turned from a rate into an actual amount (pounds) + by multiplying it by the delta T and the rate. + @return Total oxidizer requirement for this engine in pounds. */ + virtual double CalcOxidizerNeed(void); + + /// Sets engine placement information + virtual void SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation); + + virtual double GetPowerAvailable(void) {return 0.0;}; + + virtual bool GetTrimMode(void) {return TrimMode;} + virtual void SetTrimMode(bool state) {TrimMode = state;} + + virtual FGColumnVector3& GetBodyForces(void); + virtual FGColumnVector3& GetMoments(void); + + bool LoadThruster(Element *el); + FGThruster* GetThruster(void) {return Thruster;} + + virtual string GetEngineLabels(string delimeter) = 0; + virtual string GetEngineValues(string delimeter) = 0; + +protected: + FGPropertyManager* PropertyManager; + string Name; + const int EngineNumber; + EngineType Type; + double X, Y, Z; + double EnginePitch; + double EngineYaw; + double SLFuelFlowMax; + double SLOxiFlowMax; + double MaxThrottle; + double MinThrottle; + + double Thrust; + double Throttle; + double Mixture; + double FuelNeed; + double OxidizerNeed; + double PctPower; + bool Starter; + bool Starved; + bool Running; + bool Cranking; + bool TrimMode; + bool FuelFreeze; + + double FuelFlow_gph; + double FuelFlow_pph; + + FGFDMExec* FDMExec; + FGState* State; + FGAtmosphere* Atmosphere; + FGFCS* FCS; + FGPropulsion* Propulsion; + FGAircraft* Aircraft; + FGPropagate* Propagate; + FGAuxiliary* Auxiliary; + FGThruster* Thruster; + + vector SourceTanks; + void Debug(int from); +}; +} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGForce.cpp b/src/FDM/JSBSim/models/propulsion/FGForce.cpp new file mode 100644 index 000000000..f54ac9996 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGForce.cpp @@ -0,0 +1,183 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Source: FGForce.cpp + Author: Tony Peden + Date started: 6/10/00 + + ------------- 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 +-------------------------------------------------------------------------------- +6/10/00 TP Created + + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +The purpose of this class is to provide storage for computed forces and +encapsulate all the functionality associated with transforming those +forces from their native coord system to the body system. This includes +computing the moments due to the difference between the point of application +and the cg. + +*/ + +#include +#include +#include +#include +#include +#include "FGForce.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_FORCE; + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGForce::FGForce(FGFDMExec *FDMExec) : + ttype(tNone), + fdmex(FDMExec) +{ + mT(1,1) = 1; //identity matrix + mT(2,2) = 1; + mT(3,3) = 1; + vSense.InitMatrix(1); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGForce::~FGForce() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGColumnVector3& FGForce::GetBodyForces(void) +{ + vFb = Transform()*(vFn.multElementWise(vSense)); + + // Find the distance from this vector's acting location to the cg; this + // needs to be done like this to convert from structural to body coords. + // CG and RP values are in inches + + vDXYZ = fdmex->GetMassBalance()->StructuralToBody(vActingXYZn); + + vM = vMn + vDXYZ*vFb; + + return vFb; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGMatrix33 FGForce::Transform(void) +{ + switch(ttype) { + case tWindBody: + return fdmex->GetState()->GetTs2b(); + case tLocalBody: + return fdmex->GetPropagate()->GetTl2b(); + case tCustom: + case tNone: + return mT; + default: + cout << "Unrecognized tranform requested from FGForce::Transform()" << endl; + exit(1); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGForce::SetAnglesToBody(double broll, double bpitch, double byaw) +{ + if (ttype == tCustom) { + double cp,sp,cr,sr,cy,sy; + vOrient(ePitch) = bpitch; + vOrient(eRoll) = broll; + vOrient(eYaw) = byaw; + + cp=cos(bpitch); sp=sin(bpitch); + cr=cos(broll); sr=sin(broll); + cy=cos(byaw); sy=sin(byaw); + + mT(1,1)=cp*cy; + mT(1,2)=cp*sy; + mT(1,3)=-1*sp; + + mT(2,1)=sr*sp*cy-cr*sy; + mT(2,2)=sr*sp*sy+cr*cy; + mT(2,3)=sr*cp; + + mT(3,1)=cr*sp*cy+sr*sy; + mT(3,2)=cr*sp*sy-sr*cy; + mT(3,3)=cr*cp; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGForce::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: FGForce" << endl; + if (from == 1) cout << "Destroyed: FGForce" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGForce.h b/src/FDM/JSBSim/models/propulsion/FGForce.h new file mode 100644 index 000000000..0f69897af --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGForce.h @@ -0,0 +1,341 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGForce.h + Author: Tony Peden + Date started: 5/20/00 + + ------------- 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 +-------------------------------------------------------------------------------- +5/20/00 TP Created + + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +The purpose of this class is to provide storage for computed forces and +encapsulate all the functionality associated with transforming those +forces from their native coord system to the body system. This includes +computing the moments due to the difference between the point of application +and the cg. + +CAVEAT: if the custom transform is used for wind-to-body transforms then the + user *must* always pass this class the negative of beta. This is true + because sideslip angle does not follow the right hand rule i.e. it is + positive for aircraft nose left sideslip. Note that use of the custom + transform for this purpose shouldn't be necessary as it is already + provided by SetTransform(tWindBody) and is not subject to the same + restriction. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGFORCE_H +#define FGFORCE_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_FORCE "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Utility class that aids in the conversion of forces between coordinate systems + and calculation of moments. +

Resolution of Applied Forces into Moments and Body Axes Components

+

+All forces acting on the aircraft that cannot be considered a change in weight +need to be resolved into body axis components so that the aircraft acceleration +vectors, both translational and rotational, can be computed. Furthermore, the +moments produced by each force that does not act at a location corresponding to +the center of gravity also need to be computed. Unfortunately, the math required +to do this can be a bit messy and errors are easily introduced so the class +FGForce was created to provide these services in a consistent and reusable +manner.

+ +

Basic usage

+ +

FGForce requires that its users supply it with the location of the applied +force vector in JSBSim structural coordinates, the sense of each axis in that +coordinate system relative to the body system, the orientation of the vector +also relative to body coordinates and, of course, the force vector itself. With +this information it will compute both the body axis force components and the +resulting moments. Any moments inherently produced by the native system can be +supplied as well and they will be summed with those computed.

+ +

A good example for demonstrating the use of this class are the aerodynamic +forces: lift, drag, and side force and the aerodynamic moments about the pitch, +roll and yaw axes. These "native" forces and moments are computed and stored +in the FGColumnVector objects vFs and vMoments. Their native coordinate system +is often referred to as the wind system and is defined as a right-handed system +having its x-axis aligned with the relative velocity vector and pointing towards +the rear of the aircraft , the y-axis extending out the right wing, and the +z-axis directed upwards. This is different than body axes; they are defined such +that the x-axis is lies on the aircraft's roll axis and positive forward, the +y-axis is positive out the right wing, and the z-axis is positive downwards. In +this instance, JSBSim already provides the needed transform and FGForce can make +use of it by calling SetTransformType() once an object is created:

+ +

FGForce fgf(FDMExec);
+fgf.SetTransformType(tWindBody);

+ +This call need only be made once for each object. The available transforms are +defined in the enumerated type TransformType and are tWindBody, tLocalBody, +tCustom, and tNone. The local-to-body transform, like the wind-to-body, also +makes use of that already available in JSBSim. tNone sets FGForce to do no +angular transform at all, and tCustom allows for modeling force vectors at +arbitrary angles relative to the body system such as that produced by propulsion +systems. Setting up and using a custom transform is covered in more detail below. +Continuing with the example, the point of application of the aerodynamic forces, +the aerodynamic reference point in JSBSim, also needs to be set:

+

+fgf.SetLocation(x, y, z)

+ +

where x, y, and z are in JSBSim structural coordinates.

+ +

Initialization is complete and the FGForce object is ready to do its job. As +stated above, the lift, drag, and side force are computed and stored in the +vector vFs and need to be passed to FGForce:

+ +

fgf.SetNativeForces(vFs);

+ +

The same applies to the aerodynamic pitching, rolling and yawing moments:

+ +

fgf.SetNativeMoments(vMoments);

+ +

Note that storing the native forces and moments outside of this class is not +strictly necessary, overloaded SetNativeForces() and SetNativeMoments() methods +which each accept three doubles (rather than a vector) are provided and can be +repeatedly called without incurring undue overhead. The body axes force vector +can now be retrieved by calling:

+ +

vFb=fgf.GetBodyForces();

+ +

This method is where the bulk of the work gets done so calling it more than +once for the same set of native forces and moments should probably be avoided. +Note that the moment calculations are done here as well so they should not be +retrieved after calling the GetBodyForces() method:

+ +

vM=fgf.GetMoments();

+ +

As an aside, the native moments are not needed to perform the computations +correctly so, if the FGForce object is not being used to store them then an +alternate approach is to avoid the SetNativeMoments call and perform the sum

+ +

vMoments+=fgf.GetMoments();

+ +after the forces have been retrieved.

+ +

Use of the Custom Transform Type

+ +

In cases where the native force vector is not aligned with the body, wind, or +local coordinate systems a custom transform type is provided. A vectorable engine +nozzle will be used to demonstrate its usage. Initialization is much the same:

+ +

FGForce fgf(FDMExec);
+fgf.SetTransformType(tCustom);
+fgf.SetLocation(x,y,z);

+ +

Except that here the tCustom transform type is specified and the location of +the thrust vector is used rather than the aerodynamic reference point. Thrust is +typically considered to be positive when directed aft while the body x-axis is +positive forward and, if the native system is right handed, the z-axis will be +reversed as well. These differences in sense need to be specified using by the +call:

+ +

fgf.SetSense(-1,1,-1);

+ +

The angles are specified by calling the method:

+ +

fgf.SetAnglesToBody(pitch, roll, yaw);

+ +

in which the transform matrix is computed. Note that these angles should be +taken relative to the body system and not the local as the names might suggest. +For an aircraft with vectorable thrust, this method will need to be called +every time the nozzle angle changes, a fixed engine/nozzle installation, on the +other hand, will require it to be be called only once.

+ +

Retrieval of the computed forces and moments is done as detailed above.

+
+
+

CAVEAT: If the custom system is used to compute + the wind-to-body transform, then the sign of the sideslip + angle must be reversed when calling SetAnglesToBody(). + This is true because sideslip angle does not follow the right + hand rule. Using the custom transform type this way + should not be necessary, as it is already provided as a built + in type (and the sign differences are correctly accounted for). +

+
+ +

Use as a Base Type

+ +

For use as a base type, the native force and moment vector data members are +defined as protected. In this case the SetNativeForces() and SetNativeMoments() +methods need not be used and, instead, the assignments to vFn, the force vector, +and vMn, the moments, can be made directly. Otherwise, the usage is similar.
+

+ + @author Tony Peden + @version $Id$ +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGForce : public FGJSBBase +{ +public: + /// Constructor + FGForce(FGFDMExec *FDMExec); + /// Destructor + ~FGForce(); + + enum TransformType { tNone, tWindBody, tLocalBody, tCustom } ttype; + + inline void SetNativeForces(double Fnx, double Fny, double Fnz) { + vFn(1)=Fnx; + vFn(2)=Fny; + vFn(3)=Fnz; + } + inline void SetNativeForces(FGColumnVector3 vv) { vFn = vv; }; + + inline void SetNativeMoments(double Ln,double Mn, double Nn) { + vMn(1)=Ln; + vMn(2)=Mn; + vMn(3)=Nn; + } + inline void SetNativeMoments(FGColumnVector3 vv) { vMn = vv; } + + inline FGColumnVector3& GetNativeForces(void) { return vFn; } + inline FGColumnVector3& GetNativeMoments(void) { return vMn; } + + FGColumnVector3& GetBodyForces(void); + + inline FGColumnVector3& GetMoments(void) { return vM; } + + // Normal point of application, JSBsim structural coords + // (inches, x +back, y +right, z +up) + inline void SetLocation(double x, double y, double z) { + vXYZn(eX) = x; + vXYZn(eY) = y; + vXYZn(eZ) = z; + SetActingLocation(x, y, z); + } + + /** Acting point of application. + JSBsim structural coords used (inches, x +back, y +right, z +up). + This function sets the point at which the force acts - this may + not be the same as where the object resides. One area where this + is true is P-Factor modeling. + @param x acting location of force + @param y acting location of force + @param z acting location of force */ + inline void SetActingLocation(double x, double y, double z) { + vActingXYZn(eX) = x; + vActingXYZn(eY) = y; + vActingXYZn(eZ) = z; + } + inline void SetLocationX(double x) {vXYZn(eX) = x; vActingXYZn(eX) = x;} + inline void SetLocationY(double y) {vXYZn(eY) = y; vActingXYZn(eY) = y;} + inline void SetLocationZ(double z) {vXYZn(eZ) = z; vActingXYZn(eZ) = z;} + inline double SetActingLocationX(double x) {vActingXYZn(eX) = x; return x;} + inline double SetActingLocationY(double y) {vActingXYZn(eY) = y; return y;} + inline double SetActingLocationZ(double z) {vActingXYZn(eZ) = z; return z;} + inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; SetActingLocation(vv);} + inline void SetActingLocation(FGColumnVector3 vv) { vActingXYZn = vv; } + + inline double GetLocationX( void ) { return vXYZn(eX);} + inline double GetLocationY( void ) { return vXYZn(eY);} + inline double GetLocationZ( void ) { return vXYZn(eZ);} + inline double GetActingLocationX( void ) { return vActingXYZn(eX);} + inline double GetActingLocationY( void ) { return vActingXYZn(eY);} + inline double GetActingLocationZ( void ) { return vActingXYZn(eZ);} + FGColumnVector3& GetLocation(void) { return vXYZn; } + FGColumnVector3& GetActingLocation(void) { return vActingXYZn; } + + //these angles are relative to body axes, not earth!!!!! + //I'm using these because pitch, roll, and yaw are easy to visualize, + //there's no equivalent to roll in wind axes i.e. alpha, ? , beta + //making up new names or using these is a toss-up: either way people + //are going to get confused. + //They are in radians. + + void SetAnglesToBody(double broll, double bpitch, double byaw); + inline void SetAnglesToBody(FGColumnVector3 vv) { + SetAnglesToBody(vv(eRoll), vv(ePitch), vv(eYaw)); + } + + inline void SetSense(double x, double y, double z) { vSense(eX)=x, vSense(eY)=y, vSense(eZ)=z; } + inline void SetSense(FGColumnVector3 vv) { vSense=vv; } + + inline FGColumnVector3& GetAnglesToBody(void) {return vOrient;} + inline double GetAnglesToBody(int axis) {return vOrient(axis);} + inline FGColumnVector3& GetSense(void) { return vSense; } + + inline void SetTransformType(TransformType ii) { ttype=ii; } + inline TransformType GetTransformType(void) { return ttype; } + + FGMatrix33 Transform(void); + +protected: + FGFDMExec *fdmex; + FGColumnVector3 vFn; + FGColumnVector3 vMn; + FGColumnVector3 vH; + FGColumnVector3 vOrient; + +private: + FGColumnVector3 vFb; + FGColumnVector3 vM; + FGColumnVector3 vXYZn; + FGColumnVector3 vActingXYZn; + FGColumnVector3 vDXYZ; + FGColumnVector3 vSense; + + FGMatrix33 mT; + + void Debug(int from); +}; +} +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp b/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp new file mode 100644 index 000000000..bb5d91955 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp @@ -0,0 +1,196 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGNozzle.cpp + Author: Jon S. Berndt + Date started: 08/24/00 + Purpose: Encapsulates the nozzle object + + ------------- 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 +-------------------------------------------------------------------------------- +08/24/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include "FGNozzle.h" +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_NOZZLE; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +FGNozzle::FGNozzle(FGFDMExec* FDMExec, Element* nozzle_element, int num) : FGThruster(FDMExec) +{ + + if (nozzle_element->FindElement("pe")) + PE = nozzle_element->FindElementValueAsNumberConvertTo("pe", "PSF"); + else { + cerr << "Fatal Error: Nozzle exit pressure must be given in nozzle config file." << endl; + exit(-1); + } + if (nozzle_element->FindElement("expr")) + ExpR = nozzle_element->FindElementValueAsNumber("expr"); + else { + cerr << "Fatal Error: Nozzle expansion ratio must be given in nozzle config file." << endl; + exit(-1); + } + if (nozzle_element->FindElement("nzl_eff")) + nzlEff = nozzle_element->FindElementValueAsNumber("nzl_eff"); + else { + cerr << "Fatal Error: Nozzle efficiency must be given in nozzle config file." << endl; + exit(-1); + } + if (nozzle_element->FindElement("diam")) + Diameter = nozzle_element->FindElementValueAsNumberConvertTo("diam", "FT"); + else { + cerr << "Fatal Error: Nozzle diameter must be given in nozzle config file." << endl; + exit(-1); + } + + Thrust = 0; + ReverserAngle = 0.0; + Type = ttNozzle; + Area2 = (Diameter*Diameter/4.0)*M_PI; + AreaT = Area2/ExpR; + +// char property_name[80]; +// snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); +// PropertyManager->Tie( property_name, &ThrustCoeff ); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGNozzle::~FGNozzle() +{ +// char property_name[80]; +// snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); +// PropertyManager->Untie( property_name ); + + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGNozzle::Calculate(double CfPc) +{ + double pAtm = fdmex->GetAtmosphere()->GetPressure(); + Thrust = max((double)0.0, (CfPc * AreaT + (PE - pAtm)*Area2) * nzlEff); + vFn(1) = Thrust * cos(ReverserAngle); + + ThrustCoeff = max((double)0.0, CfPc / ((pAtm - PE) * Area2)); + + return Thrust; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGNozzle::GetPowerRequired(void) +{ + return PE; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGNozzle::GetThrusterLabels(int id, string delimeter) +{ + std::ostringstream buf; + + buf << Name << "_Thrust[" << id << ']'; + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGNozzle::GetThrusterValues(int id, string delimeter) +{ + std::ostringstream buf; + + buf << Thrust; + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGNozzle::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Nozzle Name: " << Name << endl; + cout << " Nozzle Exit Pressure = " << PE << endl; + cout << " Nozzle Expansion Ratio = " << ExpR << endl; + cout << " Nozzle Efficiency = " << nzlEff << endl; + cout << " Nozzle Diameter = " << Diameter << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGNozzle" << endl; + if (from == 1) cout << "Destroyed: FGNozzle" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGNozzle.h b/src/FDM/JSBSim/models/propulsion/FGNozzle.h new file mode 100644 index 000000000..4b7f3085d --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGNozzle.h @@ -0,0 +1,94 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGNozzle.h + Author: Jon S. Berndt + Date started: 08/24/00 + + ------------- 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. + +HISTORY +-------------------------------------------------------------------------------- +08/24/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGNOZZLE_H +#define FGNOZZLE_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGThruster.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_NOZZLE "$Id$"; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models a rocket nozzle. + @author Jon S. Berndt + @version $Id$ +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGNozzle : public FGThruster { + +public: + /// Constructor + FGNozzle(FGFDMExec* exec, Element* el, int num = 0); + /// Destructor + ~FGNozzle(); + + double Calculate(double CfPc); + double GetPowerRequired(void); + string GetThrusterLabels(int id, string delimeter); + string GetThrusterValues(int id, string delimeter); + +private: + double ReverserAngle; + double PE; + double ExpR; + double nzlEff; + double Diameter; + double AreaT; + double Area2; + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp new file mode 100644 index 000000000..e40a01736 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp @@ -0,0 +1,827 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGPiston.cpp + Author: Jon S. Berndt, JSBSim framework + Dave Luff, Piston engine model + Date started: 09/12/2000 + Purpose: This module models a Piston engine + + ------------- 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 +-------------------------------------------------------------------------------- + +This class descends from the FGEngine class and models a Piston engine based on +parameters given in the engine config file for this class + +HISTORY +-------------------------------------------------------------------------------- +09/12/2000 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include "FGPiston.h" +#include +#include "FGPropeller.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_PISTON; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number) + : FGEngine(exec, el, engine_number), + R_air(287.3), // Gas constant for air J/Kg/K + rho_fuel(800), // estimate + calorific_value_fuel(47.3e6), + Cp_air(1005), // Specific heat (constant pressure) J/Kg/K + Cp_fuel(1700) +{ + string token; + + // Defaults and initializations + + Type = etPiston; + + // These items are read from the configuration file + + Cycles = 2; + IdleRPM = 600; + Displacement = 360; + MaxHP = 200; + MinManifoldPressure_inHg = 6.5; + MaxManifoldPressure_inHg = 28.5; + + // These are internal program variables + + crank_counter = 0; + OilTemp_degK = 298; + ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg + minMAP = 21950; + maxMAP = 96250; + MAP = Atmosphere->GetPressure() * psftopa; + CylinderHeadTemp_degK = 0.0; + Magnetos = 0; + ExhaustGasTemp_degK = 0.0; + EGT_degC = 0.0; + + dt = State->Getdt(); + + // Supercharging + BoostSpeeds = 0; // Default to no supercharging + BoostSpeed = 0; + Boosted = false; + BoostOverride = 0; + bBoostOverride = false; + bTakeoffBoost = false; + TakeoffBoost = 0.0; // Default to no extra takeoff-boost + int i; + for (i=0; iFindElement("minmp")) // Should have ELSE statement telling default value used? + MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG"); + if (el->FindElement("maxmp")) + MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG"); + if (el->FindElement("displacement")) + Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3"); + if (el->FindElement("maxhp")) + MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP"); + if (el->FindElement("cycles")) + Cycles = el->FindElementValueAsNumber("cycles"); + if (el->FindElement("idlerpm")) + IdleRPM = el->FindElementValueAsNumber("idlerpm"); + if (el->FindElement("maxthrottle")) + MaxThrottle = el->FindElementValueAsNumber("maxthrottle"); + if (el->FindElement("minthrottle")) + MinThrottle = el->FindElementValueAsNumber("minthrottle"); + if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters + BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds"); + if (el->FindElement("boostoverride")) + BoostOverride = (int)el->FindElementValueAsNumber("boostoverride"); + if (el->FindElement("takeoffboost")) + TakeoffBoost = el->FindElementValueAsNumberConvertTo("takeoffboost", "PSI"); + if (el->FindElement("ratedboost1")) + RatedBoost[0] = el->FindElementValueAsNumberConvertTo("ratedboost1", "PSI"); + if (el->FindElement("ratedboost2")) + RatedBoost[1] = el->FindElementValueAsNumberConvertTo("ratedboost2", "PSI"); + if (el->FindElement("ratedboost3")) + RatedBoost[2] = el->FindElementValueAsNumberConvertTo("ratedboost3", "PSI"); + if (el->FindElement("ratedpower1")) + RatedPower[0] = el->FindElementValueAsNumberConvertTo("ratedpower1", "HP"); + if (el->FindElement("ratedpower2")) + RatedPower[1] = el->FindElementValueAsNumberConvertTo("ratedpower2", "HP"); + if (el->FindElement("ratedpower3")) + RatedPower[2] = el->FindElementValueAsNumberConvertTo("ratedpower3", "HP"); + if (el->FindElement("ratedrpm1")) + RatedRPM[0] = el->FindElementValueAsNumber("ratedrpm1"); + if (el->FindElement("ratedrpm2")) + RatedRPM[1] = el->FindElementValueAsNumber("ratedrpm2"); + if (el->FindElement("ratedrpm3")) + RatedRPM[2] = el->FindElementValueAsNumber("ratedrpm3"); + if (el->FindElement("ratedaltitude1")) + RatedAltitude[0] = el->FindElementValueAsNumberConvertTo("ratedaltitude1", "FT"); + if (el->FindElement("ratedaltitude2")) + RatedAltitude[1] = el->FindElementValueAsNumberConvertTo("ratedaltitude2", "FT"); + if (el->FindElement("ratedaltitude3")) + RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT"); + } + minMAP = MinManifoldPressure_inHg * 3376.85; // inHg to Pa + maxMAP = MaxManifoldPressure_inHg * 3376.85; + + // Set up and sanity-check the turbo/supercharging configuration based on the input values. + if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true; + for (i=0; i 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true; + if (bad) { + // We can't recover from the above - don't use this supercharger speed. + BoostSpeeds--; + // TODO - put out a massive error message! + break; + } + // Now sanity-check stuff that is recoverable. + if (i < BoostSpeeds - 1) { + if (BoostSwitchAltitude[i] < RatedAltitude[i]) { + // TODO - put out an error message + // But we can also make a reasonable estimate, as below. + BoostSwitchAltitude[i] = RatedAltitude[i] + 1000; + } + BoostSwitchPressure[i] = Atmosphere->GetPressure(BoostSwitchAltitude[i]) * psftopa; + //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n'; + // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now + BoostSwitchHysteresis = 1000; + } + // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude. + RatedMAP[i] = Atmosphere->GetPressureSL() * psftopa + RatedBoost[i] * 6895; // psi*6895 = Pa. + // Sometimes a separate BCV setting for takeoff or extra power is fitted. + if (TakeoffBoost > RatedBoost[0]) { + // Assume that the effect on the BCV is the same whichever speed is in use. + TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895); + bTakeoffBoost = true; + } else { + TakeoffMAP[i] = RatedMAP[i]; + bTakeoffBoost = false; + } + BoostMul[i] = RatedMAP[i] / (Atmosphere->GetPressure(RatedAltitude[i]) * psftopa); + + } + + if (BoostSpeeds > 0) { + Boosted = true; + BoostSpeed = 0; + } + bBoostOverride = (BoostOverride == 1 ? true : false); + + Debug(0); // Call Debug() routine from constructor if needed +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGPiston::~FGPiston() +{ + Debug(1); // Call Debug() routine from constructor if needed +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGPiston::Calculate(void) +{ + if (FuelFlow_gph > 0.0) ConsumeFuel(); + + Throttle = FCS->GetThrottlePos(EngineNumber); + Mixture = FCS->GetMixturePos(EngineNumber); + + // + // Input values. + // + + p_amb = Atmosphere->GetPressure() * psftopa; + p_amb_sea_level = Atmosphere->GetPressureSL() * psftopa; + T_amb = Atmosphere->GetTemperature() * (5.0 / 9.0); // convert from Rankine to Kelvin + + RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); + + IAS = Auxiliary->GetVcalibratedKTS(); + + doEngineStartup(); + if (Boosted) doBoostControl(); + doMAP(); + doAirFlow(); + doFuelFlow(); + + //Now that the fuel flow is done check if the mixture is too lean to run the engine + //Assume lean limit at 22 AFR for now - thats a thi of 0.668 + //This might be a bit generous, but since there's currently no audiable warning of impending + //cutout in the form of misfiring and/or rough running its probably reasonable for now. + if (equivalence_ratio < 0.668) + Running = false; + + doEnginePower(); + doEGT(); + doCHT(); + doOilTemperature(); + doOilPressure(); + + if (Thruster->GetType() == FGThruster::ttPropeller) { + ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); + } + + PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired(); + + return Thruster->Calculate(PowerAvailable); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Start or stop the engine. + */ + +void FGPiston::doEngineStartup(void) +{ + // Check parameters that may alter the operating state of the engine. + // (spark, fuel, starter motor etc) + bool spark; + bool fuel; + + // Check for spark + Magneto_Left = false; + Magneto_Right = false; + // Magneto positions: + // 0 -> off + // 1 -> left only + // 2 -> right only + // 3 -> both + if (Magnetos != 0) { + spark = true; + } else { + spark = false; + } // neglects battery voltage, master on switch, etc for now. + + if ((Magnetos == 1) || (Magnetos > 2)) Magneto_Left = true; + if (Magnetos > 1) Magneto_Right = true; + + // Assume we have fuel for now + fuel = !Starved; + + // Check if we are turning the starter motor + if (Cranking != Starter) { + // This check saves .../cranking from getting updated every loop - they + // only update when changed. + Cranking = Starter; + crank_counter = 0; + } + + if (Cranking) crank_counter++; //Check mode of engine operation + + if (!Running && spark && fuel) { // start the engine if revs high enough + if (Cranking) { + if ((RPM > 450) && (crank_counter > 175)) // Add a little delay to startup + Running = true; // on the starter + } else { + if (RPM > 450) // This allows us to in-air start + Running = true; // when windmilling + } + } + + // Cut the engine *power* - Note: the engine may continue to + // spin if the prop is in a moving airstream + + if ( Running && (!spark || !fuel) ) Running = false; + + // Check for stalling (RPM = 0). + if (Running) { + if (RPM == 0) { + Running = false; + } else if ((RPM <= 480) && (Cranking)) { + Running = false; + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/** + * Calculate the Current Boost Speed + * + * This function calculates the current turbo/supercharger boost speed + * based on altitude and the (automatic) boost-speed control valve configuration. + * + * Inputs: p_amb, BoostSwitchPressure, BoostSwitchHysteresis + * + * Outputs: BoostSpeed + */ + +void FGPiston::doBoostControl(void) +{ + if(BoostSpeed < BoostSpeeds - 1) { + // Check if we need to change to a higher boost speed + if(p_amb < BoostSwitchPressure[BoostSpeed] - BoostSwitchHysteresis) { + BoostSpeed++; + } + } else if(BoostSpeed > 0) { + // Check if we need to change to a lower boost speed + if(p_amb > BoostSwitchPressure[BoostSpeed - 1] + BoostSwitchHysteresis) { + BoostSpeed--; + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/** + * Calculate the manifold absolute pressure (MAP) in inches hg + * + * This function calculates manifold absolute pressure (MAP) + * from the throttle position, turbo/supercharger boost control + * system, engine speed and local ambient air density. + * + * TODO: changes in MP should not be instantaneous -- introduce + * a lag between throttle changes and MP changes, to allow pressure + * to build up or disperse. + * + * Inputs: minMAP, maxMAP, p_amb, Throttle + * + * Outputs: MAP, ManifoldPressure_inHg + */ + +void FGPiston::doMAP(void) +{ + if(RPM > 10) { + // Naturally aspirated + MAP = minMAP + (Throttle * (maxMAP - minMAP)); + MAP *= p_amb / p_amb_sea_level; + if(Boosted) { + // If takeoff boost is fitted, we currently assume the following throttle map: + // (In throttle % - actual input is 0 -> 1) + // 99 / 100 - Takeoff boost + // 96 / 97 / 98 - Rated boost + // 0 - 95 - Idle to Rated boost (MinManifoldPressure to MaxManifoldPressure) + // In real life, most planes would be fitted with a mechanical 'gate' between + // the rated boost and takeoff boost positions. + double T = Throttle; // processed throttle value. + bool bTakeoffPos = false; + if(bTakeoffBoost) { + if(Throttle > 0.98) { + //cout << "Takeoff Boost!!!!\n"; + bTakeoffPos = true; + } else if(Throttle <= 0.95) { + bTakeoffPos = false; + T *= 1.0 / 0.95; + } else { + bTakeoffPos = false; + //cout << "Rated Boost!!\n"; + T = 1.0; + } + } + // Boost the manifold pressure. + MAP *= BoostMul[BoostSpeed]; + // Now clip the manifold pressure to BCV or Wastegate setting. + if(bTakeoffPos) { + if(MAP > TakeoffMAP[BoostSpeed]) { + MAP = TakeoffMAP[BoostSpeed]; + } + } else { + if(MAP > RatedMAP[BoostSpeed]) { + MAP = RatedMAP[BoostSpeed]; + } + } + } + } else { + // rpm < 10 - effectively stopped. + // TODO - add a better variation of MAP with engine speed + MAP = Atmosphere->GetPressure() * psftopa; + } + + // And set the value in American units as well + ManifoldPressure_inHg = MAP / 3376.85; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Calculate the air flow through the engine. + * Also calculates ambient air density + * (used in CHT calculation for air-cooled engines). + * + * Inputs: p_amb, R_air, T_amb, MAP, Displacement, + * RPM, volumetric_efficiency + * + * TODO: Model inlet manifold air temperature. + * + * Outputs: rho_air, m_dot_air + */ + +void FGPiston::doAirFlow(void) +{ + rho_air = p_amb / (R_air * T_amb); + double rho_air_manifold = MAP / (R_air * T_amb); + double displacement_SI = Displacement * in3tom3; + double swept_volume = (displacement_SI * (RPM/60)) / 2; + double v_dot_air = swept_volume * volumetric_efficiency; + m_dot_air = v_dot_air * rho_air_manifold; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Calculate the fuel flow into the engine. + * + * Inputs: Mixture, thi_sea_level, p_amb_sea_level, p_amb, m_dot_air + * + * Outputs: equivalence_ratio, m_dot_fuel + */ + +void FGPiston::doFuelFlow(void) +{ + double thi_sea_level = 1.3 * Mixture; + equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb; + m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio; + FuelFlow_gph = m_dot_fuel + * 3600 // seconds to hours + * 2.2046 // kg to lb + / 6.6; // lb to gal_us of kerosene +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Calculate the power produced by the engine. + * + * Currently, the JSBSim propellor model does not allow the + * engine to produce enough RPMs to get up to a high horsepower. + * When tested with sufficient RPM, it has no trouble reaching + * 200HP. + * + * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb, + * equivalence_ratio, Cycles, MaxHP + * + * Outputs: Percentage_Power, HP + */ + +void FGPiston::doEnginePower(void) +{ + if (Running) { + double T_amb_degF = KelvinToFahrenheit(T_amb); + double T_amb_sea_lev_degF = KelvinToFahrenheit(288); + + // FIXME: this needs to be generalized + double ManXRPM; // Convienience term for use in the calculations + if(Boosted) { + // Currently a simple linear fit. + // The zero crossing is moved up the speed-load range to reduce the idling power. + // This will change! + double zeroOffset = (minMAP / 2.0) * (IdleRPM / 2.0); + ManXRPM = MAP * (RPM > RatedRPM[BoostSpeed] ? RatedRPM[BoostSpeed] : RPM); + // The speed clip in the line above is deliberate. + Percentage_Power = ((ManXRPM - zeroOffset) / ((RatedMAP[BoostSpeed] * RatedRPM[BoostSpeed]) - zeroOffset)) * 107.0; + Percentage_Power -= 7.0; // Another idle power reduction offset - see line above with 107. + if (Percentage_Power < 0.0) Percentage_Power = 0.0; + // Note that %power is allowed to go over 100 for boosted powerplants + // such as for the BCV-override or takeoff power settings. + // TODO - currently no altitude effect (temperature & exhaust back-pressure) modelled + // for boosted engines. + } else { + ManXRPM = ManifoldPressure_inHg * RPM; // Note that inHg must be used for the following correlation. + Percentage_Power = (6e-9 * ManXRPM * ManXRPM) + (8e-4 * ManXRPM) - 1.0; + Percentage_Power += ((T_amb_sea_lev_degF - T_amb_degF) * 7 /120); + if (Percentage_Power < 0.0) Percentage_Power = 0.0; + else if (Percentage_Power > 100.0) Percentage_Power = 100.0; + } + + double Percentage_of_best_power_mixture_power = + Power_Mixture_Correlation->GetValue(14.7 / equivalence_ratio); + + Percentage_Power *= Percentage_of_best_power_mixture_power / 100.0; + + if (Boosted) { + HP = Percentage_Power * RatedPower[BoostSpeed] / 100.0; + } else { + HP = Percentage_Power * MaxHP / 100.0; + } + + } else { + + // Power output when the engine is not running + if (Cranking) { + if (RPM < 10) { + HP = 3.0; // This is a hack to prevent overshooting the idle rpm in + // the first time step. It may possibly need to be changed + // if the prop model is changed. + } else if (RPM < 480) { + HP = 3.0 + ((480 - RPM) / 10.0); + // This is a guess - would be nice to find a proper starter moter torque curve + } else { + HP = 3.0; + } + } else { + // Quick hack until we port the FMEP stuff + if (RPM > 0.0) + HP = -1.5; + else + HP = 0.0; + } + } + //cout << "Power = " << HP << '\n'; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Calculate the exhaust gas temperature. + * + * Inputs: equivalence_ratio, m_dot_fuel, calorific_value_fuel, + * Cp_air, m_dot_air, Cp_fuel, m_dot_fuel, T_amb, Percentage_Power + * + * Outputs: combustion_efficiency, ExhaustGasTemp_degK + */ + +void FGPiston::doEGT(void) +{ + double delta_T_exhaust; + double enthalpy_exhaust; + double heat_capacity_exhaust; + double dEGTdt; + + if ((Running) && (m_dot_air > 0.0)) { // do the energy balance + combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio); + enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * + combustion_efficiency * 0.33; + heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel); + delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust; + ExhaustGasTemp_degK = T_amb + delta_T_exhaust; + ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * Percentage_Power / 100.0); + } else { // Drop towards ambient - guess an appropriate time constant for now + dEGTdt = (298.0 - ExhaustGasTemp_degK) / 100.0; + delta_T_exhaust = dEGTdt * dt; + ExhaustGasTemp_degK += delta_T_exhaust; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Calculate the cylinder head temperature. + * + * Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel, + * combustion_efficiency, RPM + * + * Outputs: CylinderHeadTemp_degK + */ + +void FGPiston::doCHT(void) +{ + double h1 = -95.0; + double h2 = -3.95; + double h3 = -0.05; + + double arbitary_area = 1.0; + double CpCylinderHead = 800.0; + double MassCylinderHead = 8.0; + + double temperature_difference = CylinderHeadTemp_degK - T_amb; + double v_apparent = IAS * 0.5144444; + double v_dot_cooling_air = arbitary_area * v_apparent; + double m_dot_cooling_air = v_dot_cooling_air * rho_air; + double dqdt_from_combustion = + m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33; + double dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) + + (h3 * RPM * temperature_difference); + double dqdt_free = h1 * temperature_difference; + double dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free; + + double HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead; + + CylinderHeadTemp_degK += + (dqdt_cylinder_head / HeatCapacityCylinderHead) * dt; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Calculate the oil temperature. + * + * Inputs: Percentage_Power, running flag. + * + * Outputs: OilTemp_degK + */ + +void FGPiston::doOilTemperature(void) +{ + double idle_percentage_power = 2.3; // approximately + double target_oil_temp; // Steady state oil temp at the current engine conditions + double time_constant; // The time constant for the differential equation + + if (Running) { + target_oil_temp = 363; + time_constant = 500; // Time constant for engine-on idling. + if (Percentage_Power > idle_percentage_power) { + time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power + } + } else { + target_oil_temp = 298; + time_constant = 1000; // Time constant for engine-off; reflects the fact + // that oil is no longer getting circulated + } + + double dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant; + + OilTemp_degK += (dOilTempdt * dt); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** + * Calculate the oil pressure. + * + * Inputs: RPM + * + * Outputs: OilPressure_psi + */ + +void FGPiston::doOilPressure(void) +{ + double Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine + double Oil_Press_RPM_Max = 1800; // FIXME: may vary by engine + double Design_Oil_Temp = 358; // degK; FIXME: may vary by engine + double Oil_Viscosity_Index = 0.25; + + OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM; + + if (OilPressure_psi >= Oil_Press_Relief_Valve) { + OilPressure_psi = Oil_Press_Relief_Valve; + } + + OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPiston::GetEngineLabels(string delimeter) +{ + std::ostringstream buf; + + buf << Name << "_PwrAvail[" << EngineNumber << "]" << delimeter + << Name << "_HP[" << EngineNumber << "]" << delimeter + << Name << "_equiv_ratio[" << EngineNumber << "]" << delimeter + << Name << "_MAP[" << EngineNumber << "]" << delimeter + << Thruster->GetThrusterLabels(EngineNumber, delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPiston::GetEngineValues(string delimeter) +{ + std::ostringstream buf; + + buf << PowerAvailable << delimeter << HP << delimeter + << equivalence_ratio << delimeter << MAP << delimeter + << Thruster->GetThrusterValues(EngineNumber, delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// +// 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 FGPiston::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + cout << "\n Engine Name: " << Name << endl; + cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl; + cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl; + cout << " MinMaP (Pa): " << minMAP << endl; + cout << " MaxMaP (Pa): " << maxMAP << endl; + cout << " Displacement: " << Displacement << endl; + cout << " MaxHP: " << MaxHP << endl; + cout << " Cycles: " << Cycles << endl; + cout << " IdleRPM: " << IdleRPM << endl; + cout << " MaxThrottle: " << MaxThrottle << endl; + cout << " MinThrottle: " << MinThrottle << endl; + + cout << endl; + cout << " Combustion Efficiency table:" << endl; + Lookup_Combustion_Efficiency->Print(); + cout << endl; + + cout << endl; + cout << " Power Mixture Correlation table:" << endl; + Power_Mixture_Correlation->Print(); + cout << endl; + + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPiston" << endl; + if (from == 1) cout << "Destroyed: FGPiston" << 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; + } + } +} + +double +FGPiston::CalcFuelNeed(void) +{ + return FuelFlow_gph / 3600 * 6 * State->Getdt() * Propulsion->GetRate(); +} + +} // namespace JSBSim diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.h b/src/FDM/JSBSim/models/propulsion/FGPiston.h new file mode 100644 index 000000000..3bb09ede7 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGPiston.h @@ -0,0 +1,273 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGPiston.h + Author: Jon S. Berndt + Date started: 09/12/2000 + + ------------- 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. + +HISTORY +-------------------------------------------------------------------------------- +09/12/2000 JSB Created +10/01/2001 DPM Modified to use equations from Dave Luff's piston model. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGPISTON_H +#define FGPISTON_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGEngine.h" +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_PISTON "$Id$"; +#define FG_MAX_BOOST_SPEEDS 3 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models Dave Luff's Turbo/Supercharged Piston engine model. + Additional elements are required for a supercharged engine. These can be + left off a non-supercharged engine, ie. the changes are all backward + compatible at present. + + - NUMBOOSTSPEEDS - zero (or not present) for a naturally-aspirated engine, + either 1, 2 or 3 for a boosted engine. This corresponds to the number of + supercharger speeds. Merlin XII had 1 speed, Merlin 61 had 2, a late + Griffon engine apparently had 3. No known engine more than 3, although + some German engines apparently had a continuously variable-speed + supercharger. + + - BOOSTOVERRIDE - whether the boost pressure control system (either a boost + control valve for superchargers or wastegate for turbochargers) can be + overriden by the pilot. During wartime this was commonly possible, and + known as "War Emergency Power" by the Brits. 1 or 0 in the config file. + This isn't implemented in the model yet though, there would need to be + some way of getting the boost control cutout lever position (on or off) + from FlightGear first. + + - The next items are all appended with either 1, 2 or 3 depending on which + boost speed they refer to, eg RATEDBOOST1. The rated values seems to have + been a common convention at the time to express the maximum continuously + available power, and the conditions to attain that power. + + - RATEDBOOST[123] - the absolute rated boost above sea level ambient for a + given boost speed, in psi. Eg the Merlin XII had a rated boost of 9psi, + giving approximately 42inHg manifold pressure up to the rated altitude. + + - RATEDALTITUDE[123] - The altitude up to which rated boost can be + maintained. Up to this altitude the boost is maintained constant for a + given throttle position by the BCV or wastegate. Beyond this altitude the + manifold pressure must drop, since the supercharger is now at maximum + unregulated output. The actual pressure multiplier of the supercharger + system is calculated at initialisation from this value. + + - RATEDPOWER[123] - The power developed at rated boost at rated altitude at + rated rpm. + + - RATEDRPM[123] - The rpm at which rated power is developed. + + - TAKEOFFBOOST - Takeoff boost in psi above ambient. Many aircraft had an + extra boost setting beyond rated boost, but not totally uncontrolled as in + the already mentioned boost-control-cutout, typically attained by pushing + the throttle past a mechanical 'gate' preventing its inadvertant use. This + was typically used for takeoff, and emergency situations, generally for + not more than five minutes. This is a change in the boost control + setting, not the actual supercharger speed, and so would only give extra + power below the rated altitude. When TAKEOFFBOOST is specified in the + config file (and is above RATEDBOOST1), then the throttle position is + interpreted as: + + - 0 to 0.95 : idle manifold pressure to rated boost (where attainable) + - 0.96, 0.97, 0.98 : rated boost (where attainable). + - 0.99, 1.0 : takeoff boost (where attainable). + + A typical takeoff boost for an earlyish Merlin was about 12psi, compared + with a rated boost of 9psi. + + It is quite possible that other boost control settings could have been used + on some aircraft, or that takeoff/extra boost could have activated by other + means than pushing the throttle full forward through a gate, but this will + suffice for now. + + Note that MAXMP is still the non-boosted max manifold pressure even for + boosted engines - effectively this is simply a measure of the pressure drop + through the fully open throttle. + + @author Jon S. Berndt (Engine framework code and framework-related mods) + @author Dave Luff (engine operational code) + @author David Megginson (initial porting and additional code) + @version $Id$ + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGPiston : public FGEngine +{ +public: + /// Constructor + FGPiston(FGFDMExec* exec, Element* el, int engine_number); + /// Destructor + ~FGPiston(); + + string GetEngineLabels(string delimeter); + string GetEngineValues(string delimeter); + + double Calculate(void); + double GetPowerAvailable(void) {return PowerAvailable;} + double CalcFuelNeed(void); + + void SetMagnetos(int magnetos) {Magnetos = magnetos;} + + double GetEGT(void) { return EGT_degC; } + int GetMagnetos(void) {return Magnetos;} + + double getExhaustGasTemp_degF(void) {return KelvinToFahrenheit(ExhaustGasTemp_degK);} + double getManifoldPressure_inHg(void) const {return ManifoldPressure_inHg;} + double getCylinderHeadTemp_degF(void) {return KelvinToFahrenheit(CylinderHeadTemp_degK);} + double getOilPressure_psi(void) const {return OilPressure_psi;} + double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} + double getRPM(void) {return RPM;} + +private: + int crank_counter; + + double BrakeHorsePower; + double SpeedSlope; + double SpeedIntercept; + double AltitudeSlope; + double PowerAvailable; + + // timestep + double dt; + + void doEngineStartup(void); + void doBoostControl(void); + void doMAP(void); + void doAirFlow(void); + void doFuelFlow(void); + void doEnginePower(void); + void doEGT(void); + void doCHT(void); + void doOilPressure(void); + void doOilTemperature(void); + + // + // constants + // + + const double R_air; + const double rho_fuel; // kg/m^3 + const double calorific_value_fuel; // W/Kg (approximate) + const double Cp_air; // J/KgK + const double Cp_fuel; // J/KgK + + FGTable *Lookup_Combustion_Efficiency; + FGTable *Power_Mixture_Correlation; + + // + // Configuration + // + double MinManifoldPressure_inHg; // Inches Hg + double MaxManifoldPressure_inHg; // Inches Hg + double Displacement; // cubic inches + double MaxHP; // horsepower + double Cycles; // cycles/power stroke + double IdleRPM; // revolutions per minute + int BoostSpeeds; // Number of super/turbocharger boost speeds - zero implies no turbo/supercharging. + int BoostSpeed; // The current boost-speed (zero-based). + bool Boosted; // Set true for boosted engine. + int BoostOverride; // The raw value read in from the config file - should be 1 or 0 - see description below. + bool bBoostOverride; // Set true if pilot override of the boost regulator was fitted. + // (Typically called 'war emergency power'). + bool bTakeoffBoost; // Set true if extra takeoff / emergency boost above rated boost could be attained. + // (Typically by extra throttle movement past a mechanical 'gate'). + double TakeoffBoost; // Sea-level takeoff boost in psi. (if fitted). + double RatedBoost[FG_MAX_BOOST_SPEEDS]; // Sea-level rated boost in psi. + double RatedAltitude[FG_MAX_BOOST_SPEEDS]; // Altitude at which full boost is reached (boost regulation ends) + // and at which power starts to fall with altitude [ft]. + double RatedRPM[FG_MAX_BOOST_SPEEDS]; // Engine speed at which the rated power for each boost speed is delivered [rpm]. + double RatedPower[FG_MAX_BOOST_SPEEDS]; // Power at rated throttle position at rated altitude [HP]. + double BoostSwitchAltitude[FG_MAX_BOOST_SPEEDS - 1]; // Altitude at which switchover (currently assumed automatic) + // from one boost speed to next occurs [ft]. + double BoostSwitchPressure[FG_MAX_BOOST_SPEEDS - 1]; // Pressure at which boost speed switchover occurs [Pa] + double BoostMul[FG_MAX_BOOST_SPEEDS]; // Pressure multipier of unregulated supercharger + double RatedMAP[FG_MAX_BOOST_SPEEDS]; // Rated manifold absolute pressure [Pa] (BCV clamp) + double TakeoffMAP[FG_MAX_BOOST_SPEEDS]; // Takeoff setting manifold absolute pressure [Pa] (BCV clamp) + double BoostSwitchHysteresis; // Pa. + + double minMAP; // Pa + double maxMAP; // Pa + double MAP; // Pa + + // + // Inputs (in addition to those in FGEngine). + // + double p_amb; // Pascals + double p_amb_sea_level; // Pascals + double T_amb; // degrees Kelvin + double RPM; // revolutions per minute + double IAS; // knots + bool Magneto_Left; + bool Magneto_Right; + int Magnetos; + + // + // Outputs (in addition to those in FGEngine). + // + double rho_air; + double volumetric_efficiency; + double m_dot_air; + double equivalence_ratio; + double m_dot_fuel; + double Percentage_Power; + double HP; + double combustion_efficiency; + double ExhaustGasTemp_degK; + double EGT_degC; + double ManifoldPressure_inHg; + double CylinderHeadTemp_degK; + double OilPressure_psi; + double OilTemp_degK; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp b/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp new file mode 100644 index 000000000..40ef4a5de --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp @@ -0,0 +1,382 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGPropeller.cpp + Author: Jon S. Berndt + Date started: 08/24/00 + Purpose: Encapsulates the propeller object + + ------------- 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 +-------------------------------------------------------------------------------- +08/24/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include "FGPropeller.h" +#include +#include +#include + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_PROPELLER; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +// This class currently makes certain assumptions when calculating torque and +// p-factor. That is, that the axis of rotation is the X axis of the aircraft - +// not just the X-axis of the engine/propeller. This may or may not work for a +// helicopter. + +FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num) + : FGThruster(exec, prop_element, num) +{ + string token; + int rows, cols; + Element *table_element, *local_element; + string name=""; + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); + + MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0; + Sense = 1; // default clockwise rotation + ReversePitch = 0.0; + Reversed = false; + Feathered = false; + Reverse_coef = 0.0; + GearRatio = 1.0; + + if (prop_element->FindElement("ixx")) + Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); + if (prop_element->FindElement("diameter")) + Diameter = prop_element->FindElementValueAsNumberConvertTo("diameter", "FT"); + if (prop_element->FindElement("numblades")) + numBlades = (int)prop_element->FindElementValueAsNumber("numblades"); + if (prop_element->FindElement("gearratio")) + GearRatio = prop_element->FindElementValueAsNumber("gearratio"); + if (prop_element->FindElement("minpitch")) + MinPitch = prop_element->FindElementValueAsNumber("minpitch"); + if (prop_element->FindElement("maxpitch")) + MaxPitch = prop_element->FindElementValueAsNumber("maxpitch"); + if (prop_element->FindElement("minrpm")) + MinRPM = prop_element->FindElementValueAsNumber("minrpm"); + if (prop_element->FindElement("maxrpm")) + MaxRPM = prop_element->FindElementValueAsNumber("maxrpm"); + if (prop_element->FindElement("reversepitch")) + ReversePitch = prop_element->FindElementValueAsNumber("reversepitch"); + for (int i=0; i<2; i++) { + table_element = prop_element->FindNextElement("table"); + name = table_element->GetAttributeValue("name"); + if (name == "C_THRUST") { + cThrust = new FGTable(PropertyManager, table_element); + } else if (name == "C_POWER") { + cPower = new FGTable(PropertyManager, table_element); + } else { + cerr << "Unknown table type: " << name << " in propeller definition." << endl; + } + } + + local_element = prop_element->GetParent()->FindElement("sense"); + if (local_element) { + double Sense = local_element->GetDataAsNumber(); + SetSense(fabs(Sense)/Sense); + } + local_element = prop_element->GetParent()->FindElement("p_factor"); + if (local_element) { + P_Factor = local_element->GetDataAsNumber(); + } + if (P_Factor < 0) { + cerr << "P-Factor value in config file must be greater than zero" << endl; + } + + Type = ttPropeller; + RPM = 0; + vTorque.InitMatrix(); + D4 = Diameter*Diameter*Diameter*Diameter; + D5 = D4*Diameter; + + char property_name[80]; + snprintf(property_name, 80, "propulsion/engine[%d]/advance-ratio", EngineNum); + PropertyManager->Tie( property_name, &J ); + snprintf(property_name, 80, "propulsion/engine[%d]/blade-angle", EngineNum); + PropertyManager->Tie( property_name, &Pitch ); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGPropeller::~FGPropeller() +{ + if (cThrust) delete cThrust; + if (cPower) delete cPower; + + char property_name[80]; + snprintf(property_name, 80, "propulsion/engine[%d]/advance-ratio", EngineNum); + PropertyManager->Untie( property_name ); + snprintf(property_name, 80, "propulsion/engine[%d]/blade-angle", EngineNum); + PropertyManager->Untie( property_name ); + + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// +// We must be getting the aerodynamic velocity here, NOT the inertial velocity. +// We need the velocity with respect to the wind. +// +// Note that PowerAvailable is the excess power available after the drag of the +// propeller has been subtracted. At equilibrium, PowerAvailable will be zero - +// indicating that the propeller will not accelerate or decelerate. +// Remembering that Torque * omega = Power, we can derive the torque on the +// propeller and its acceleration to give a new RPM. The current RPM will be +// used to calculate thrust. +// +// Because RPM could be zero, we need to be creative about what RPM is stated as. + +double FGPropeller::Calculate(double PowerAvailable) +{ + double omega, alpha, beta; + + double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU); + double rho = fdmex->GetAtmosphere()->GetDensity(); + double RPS = RPM/60.0; + + if (RPS > 0.00) J = Vel / (Diameter * RPS); // Calculate J normally + else J = 1000.0; // Set J to a high number + + if (MaxPitch == MinPitch) ThrustCoeff = cThrust->GetValue(J); + else ThrustCoeff = cThrust->GetValue(J, Pitch); + + if (P_Factor > 0.0001) { + alpha = fdmex->GetAuxiliary()->Getalpha(); + beta = fdmex->GetAuxiliary()->Getbeta(); + SetActingLocationY( GetLocationY() + P_Factor*alpha*Sense); + SetActingLocationZ( GetLocationZ() + P_Factor*beta*Sense); + } + + Thrust = ThrustCoeff*RPS*RPS*D4*rho; + omega = RPS*2.0*M_PI; + + vFn(1) = Thrust; + + // The Ixx value and rotation speed given below are for rotation about the + // natural axis of the engine. The transform takes place in the base class + // FGForce::GetBodyForces() function. + + vH(eX) = Ixx*omega*Sense; + vH(eY) = 0.0; + vH(eZ) = 0.0; + + if (omega > 0.0) ExcessTorque = GearRatio * PowerAvailable / omega; + else ExcessTorque = GearRatio * PowerAvailable / 1.0; + + RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0; + + if (RPM < 1.0) RPM = 0; // Engine friction stops rotation arbitrarily at 1 RPM. + + vMn = fdmex->GetPropagate()->GetPQR()*vH + vTorque*Sense; + + return Thrust; // return thrust in pounds +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGPropeller::GetPowerRequired(void) +{ + double cPReq, J; + double rho = fdmex->GetAtmosphere()->GetDensity(); + double RPS = RPM / 60.0; + + if (RPS != 0) J = fdmex->GetAuxiliary()->GetAeroUVW(eU) / (Diameter * RPS); + else J = 1000.0; // Set J to a high number + + if (MaxPitch == MinPitch) { // Fixed pitch prop + Pitch = MinPitch; + cPReq = cPower->GetValue(J); + } else { // Variable pitch prop + + if (MaxRPM != MinRPM) { // fixed-speed prop + + // do normal calculation when propeller is neither feathered nor reversed + if (!Feathered) { + if (!Reversed) { + + double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance; + double dRPM = rpmReq - RPM; + // The pitch of a variable propeller cannot be changed when the RPMs are + // too low - the oil pump does not work. + if (RPM > 200) Pitch -= dRPM / 10; + + if (Pitch < MinPitch) Pitch = MinPitch; + else if (Pitch > MaxPitch) Pitch = MaxPitch; + + } else { // Reversed propeller + + // when reversed calculate propeller pitch depending on throttle lever position + // (beta range for taxing full reverse for braking) + double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef; + // The pitch of a variable propeller cannot be changed when the RPMs are + // too low - the oil pump does not work. + if (RPM > 200) Pitch += (PitchReq - Pitch) / 200; + if (RPM > MaxRPM) { + Pitch += (MaxRPM - RPM) / 50; + if (Pitch < ReversePitch) Pitch = ReversePitch; + else if (Pitch > MaxPitch) Pitch = MaxPitch; + } + } + + } else { // Feathered propeller + // ToDo: Make feathered and reverse settings done via FGKinemat + Pitch += (MaxPitch - Pitch) / 300; // just a guess (about 5 sec to fully feathered) + } + + } else { // Variable Speed Prop + Pitch = MinPitch + (MaxPitch - MinPitch) * Advance; + } + cPReq = cPower->GetValue(J, Pitch); + } + + if (RPS > 0) { + PowerRequired = cPReq*RPS*RPS*RPS*D5*rho; + vTorque(eX) = -Sense*PowerRequired / (RPS*2.0*M_PI); + } else { + PowerRequired = 0.0; + vTorque(eX) = 0.0; + } + + return PowerRequired; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGColumnVector3 FGPropeller::GetPFactor() +{ + double px=0.0, py, pz; + + py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0; + pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0; + + return FGColumnVector3(px, py, pz); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPropeller::GetThrusterLabels(int id, string delimeter) +{ + std::ostringstream buf; + + buf << Name << "_Torque[" << id << "]" << delimeter + << Name << "_PFactor_Pitch[" << id << "]" << delimeter + << Name << "_PFactor_Yaw[" << id << "]" << delimeter + << Name << "_Thrust[" << id << "]" << delimeter; + if (IsVPitch()) + buf << Name << "_Pitch[" << id << "]" << delimeter; + buf << Name << "_RPM[" << id << "]"; + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGPropeller::GetThrusterValues(int id, string delimeter) +{ + std::ostringstream buf; + + FGColumnVector3 vPFactor = GetPFactor(); + buf << vTorque(eX) << delimeter + << vPFactor(ePitch) << delimeter + << vPFactor(eYaw) << delimeter + << Thrust << delimeter; + if (IsVPitch()) + buf << Pitch << delimeter; + buf << RPM; + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGPropeller::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << "\n Propeller Name: " << Name << endl; + cout << " IXX = " << Ixx << endl; + cout << " Diameter = " << Diameter << " ft." << endl; + cout << " Number of Blades = " << numBlades << endl; + cout << " Gear Ratio = " << GearRatio << endl; + cout << " Minimum Pitch = " << MinPitch << endl; + cout << " Maximum Pitch = " << MaxPitch << endl; + cout << " Minimum RPM = " << MinRPM << endl; + cout << " Maximum RPM = " << MaxRPM << endl; +// cout << " Thrust Coefficient: " << endl; +// cThrust->Print(); +// cout << " Power Coefficient: " << endl; +// cPower->Print(); + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGPropeller" << endl; + if (from == 1) cout << "Destroyed: FGPropeller" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGPropeller.h b/src/FDM/JSBSim/models/propulsion/FGPropeller.h new file mode 100644 index 000000000..c0ddcde12 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGPropeller.h @@ -0,0 +1,194 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGPropeller.h + Author: Jon S. Berndt + Date started: 08/24/00 + + ------------- 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. + +HISTORY +-------------------------------------------------------------------------------- +08/24/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGPROPELLER_H +#define FGPROPELLER_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGThruster.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_PROPELLER "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Propeller modeling class. + FGPropeller models a propeller given the tabular data for Ct and Cp + indexed by advance ratio "J". The data for the propeller is + stored in a config file named "prop_name.xml". The propeller config file + is referenced from the main aircraft config file in the "Propulsion" section. + See the constructor for FGPropeller to see what is read in and what should + be stored in the config file.
+ Several references were helpful, here:
    +
  • Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics", + Wiley & Sons, 1979 ISBN 0-471-03032-5
  • +
  • Edwin Hartman, David Biermann, "The Aerodynamic Characteristics of + Full Scale Propellers Having 2, 3, and 4 Blades of Clark Y and R.A.F. 6 + Airfoil Sections", NACA Report TN-640, 1938 (?)
  • +
  • Various NACA Technical Notes and Reports
  • +
+ @author Jon S. Berndt + @version $Id$ + @see FGEngine + @see FGThruster +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGPropeller : public FGThruster { + +public: + /** Constructor for FGPropeller. + @param exec a pointer to the main executive object + @param el a pointer to the thruster config file XML element*/ + FGPropeller(FGFDMExec* exec, Element* el, int num = 0); + + /// Destructor for FGPropeller - deletes the FGTable objects + ~FGPropeller(); + + /** Sets the Revolutions Per Minute for the propeller. Normally the propeller + instance will calculate its own rotational velocity, given the Torque + produced by the engine and integrating over time using the standard + equation for rotational acceleration "a": a = Q/I , where Q is Torque and + I is moment of inertia for the propeller. + @param rpm the rotational velocity of the propeller */ + void SetRPM(double rpm) {RPM = rpm;} + + /// Returns true of this propeller is variable pitch + bool IsVPitch(void) {return MaxPitch != MinPitch;} + + /** This commands the pitch of the blade to change to the value supplied. + This call is meant to be issued either from the cockpit or by the flight + control system (perhaps to maintain constant RPM for a constant-speed + propeller). This value will be limited to be within whatever is specified + in the config file for Max and Min pitch. It is also one of the lookup + indices to the power and thrust tables for variable-pitch propellers. + @param pitch the pitch of the blade in degrees. */ + void SetPitch(double pitch) {Pitch = pitch;} + + void SetAdvance(double advance) {Advance = advance;} + + /// Sets the P-Factor constant + void SetPFactor(double pf) {P_Factor = pf;} + + /** Sets the rotation sense of the propeller. + @param s this value should be +/- 1 ONLY. +1 indicates clockwise rotation as + viewed by someone standing behind the engine looking forward into + the direction of flight. */ + void SetSense(double s) { Sense = s;} + + /// Retrieves the pitch of the propeller in degrees. + double GetPitch(void) { return Pitch; } + + /// Retrieves the RPMs of the propeller + double GetRPM(void) { return RPM; } + + /// Retrieves the propeller moment of inertia + double GetIxx(void) { return Ixx; } + + /// Retrieves the Torque in foot-pounds (Don't you love the English system?) + double GetTorque(void) { return vTorque(eX); } + + /** Retrieves the power required (or "absorbed") by the propeller - + i.e. the power required to keep spinning the propeller at the current + velocity, air density, and rotational rate. */ + double GetPowerRequired(void); + + /** Calculates and returns the thrust produced by this propeller. + Given the excess power available from the engine (in foot-pounds), the thrust is + calculated, as well as the current RPM. The RPM is calculated by integrating + the torque provided by the engine over what the propeller "absorbs" + (essentially the "drag" of the propeller). + @param PowerAvailable this is the excess power provided by the engine to + accelerate the prop. It could be negative, dictating that the propeller + would be slowed. + @return the thrust in pounds */ + double Calculate(double PowerAvailable); + FGColumnVector3 GetPFactor(void); + string GetThrusterLabels(int id, string delimeter); + string GetThrusterValues(int id, string delimeter); + + void SetReverseCoef (double c) { Reverse_coef = c; } + double GetReverseCoef (void) { return Reverse_coef; } + void SetReverse (bool r) { Reversed = r; } + bool GetReverse (void) { return Reversed; } + void SetFeather (bool f) { Feathered = f; } + bool GetFeather (void) { return Feathered; } + +private: + int numBlades; + double J; + double RPM; + double Ixx; + double Diameter; + double MaxPitch; + double MinPitch; + double MinRPM; + double MaxRPM; + double Pitch; + double P_Factor; + double Sense; + double Advance; + double ExcessTorque; + double D4; + double D5; + FGColumnVector3 vTorque; + FGTable *cThrust; + FGTable *cPower; + void Debug(int from); + double ReversePitch; // Pitch, when fully reversed + bool Reversed; // true, when propeller is reversed + double Reverse_coef; // 0 - 1 defines AdvancePitch (0=MIN_PITCH 1=REVERSE_PITCH) + bool Feathered; // true, if feather command +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp new file mode 100644 index 000000000..2bcbcca20 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp @@ -0,0 +1,195 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGRocket.cpp + Author: Jon S. Berndt + Date started: 09/12/2000 + Purpose: This module models a rocket engine + + ------------- 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 +-------------------------------------------------------------------------------- + +This class descends from the FGEngine class and models a rocket engine based on +parameters given in the engine config file for this class + +HISTORY +-------------------------------------------------------------------------------- +09/12/2000 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include "FGRocket.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_ROCKET; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number) + : FGEngine(exec, el, engine_number) +{ + if (el->FindElement("shr")) + SHR = el->FindElementValueAsNumber("shr"); + if (el->FindElement("max_pc")) + maxPC = el->FindElementValueAsNumberConvertTo("max_pc", "PSF"); + if (el->FindElement("prop_eff")) + propEff = el->FindElementValueAsNumber("prop_eff"); + if (el->FindElement("maxthrottle")) + MaxThrottle = el->FindElementValueAsNumber("maxthrottle"); + if (el->FindElement("minthrottle")) + MinThrottle = el->FindElementValueAsNumber("minthrottle"); + if (el->FindElement("slfuelflowmax")) + SLFuelFlowMax = el->FindElementValueAsNumberConvertTo("slfuelflowmax", "LBS/SEC"); + if (el->FindElement("sloxiflowmax")) + SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC"); + if (el->FindElement("variance")) + Variance = el->FindElementValueAsNumber("variance"); + + Debug(0); + + Type = etRocket; + Flameout = false; + + PC = 0.0; + kFactor = (2.0*SHR*SHR/(SHR-1.0))*pow(2.0/(SHR+1), (SHR+1)/(SHR-1)); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGRocket::~FGRocket(void) +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGRocket::Calculate(void) +{ + double Cf=0; + + if (!Flameout && !Starved) ConsumeFuel(); + + Throttle = FCS->GetThrottlePos(EngineNumber); + + if (Throttle < MinThrottle || Starved) { + PctPower = Thrust = 0.0; // desired thrust + Flameout = true; + PC = 0.0; + } else { + PctPower = Throttle / MaxThrottle; + //todo: remove Variance? + PC = maxPC*PctPower * (1.0 + Variance * ((double)rand()/(double)RAND_MAX - 0.5)); + // The Cf (below) is CF from Eqn. 3-30, "Rocket Propulsion Elements", Fifth Edition, + // George P. Sutton. Note that the thruster function GetPowerRequired() might + // be better called GetResistance() or something; this function returns the + // nozzle exit pressure. + Cf = sqrt(kFactor*(1 - pow(Thruster->GetPowerRequired()/(PC), (SHR-1)/SHR))); + Flameout = false; + } + + return Thruster->Calculate(Cf*maxPC*PctPower*propEff); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGRocket::GetEngineLabels(string delimeter) +{ + std::ostringstream buf; + + buf << Name << "_ChamberPress[" << EngineNumber << "]" << delimeter + << Thruster->GetThrusterLabels(EngineNumber, delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGRocket::GetEngineValues(string delimeter) +{ + std::ostringstream buf; + + buf << PC << delimeter << Thruster->GetThrusterValues(EngineNumber, delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGRocket::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " Engine Name: " << Name << endl; + cout << " Specific Heat Ratio = " << SHR << endl; + cout << " Maximum Chamber Pressure = " << maxPC << endl; + cout << " Propulsive Efficiency = " << propEff << endl; + cout << " MaxThrottle = " << MaxThrottle << endl; + cout << " MinThrottle = " << MinThrottle << endl; + cout << " FuelFlowMax = " << SLFuelFlowMax << endl; + cout << " OxiFlowMax = " << SLOxiFlowMax << endl; + cout << " Variance = " << Variance << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGRocket" << endl; + if (from == 1) cout << "Destroyed: FGRocket" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.h b/src/FDM/JSBSim/models/propulsion/FGRocket.h new file mode 100644 index 000000000..d21ad4c89 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGRocket.h @@ -0,0 +1,143 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGRocket.h + Author: Jon S. Berndt + Date started: 09/12/2000 + + ------------- 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. + +HISTORY +-------------------------------------------------------------------------------- +09/12/2000 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGROCKET_H +#define FGROCKET_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGEngine.h" +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_ROCKET "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models a generic rocket engine. + The rocket engine is modeled given the following parameters: +
    +
  • Chamber pressure (in psf)
  • +
  • Specific heat ratio (usually about 1.2 for hydrocarbon fuel and LOX)
  • +
  • Propulsive efficiency (in percent, from 0 to 1.0)
  • +
  • Variance (in percent, from 0 to 1.0, nominally 0.05)
  • +
+ Additionally, the following control inputs, operating characteristics, and + location are required, as with all other engine types: +
    +
  • Throttle setting (in percent, from 0 to 1.0)
  • +
  • Maximum allowable throttle setting
  • +
  • Minimum working throttle setting
  • +
  • Sea level fuel flow at maximum thrust
  • +
  • Sea level oxidizer flow at maximum thrust
  • +
  • X, Y, Z location in structural coordinate frame
  • +
  • Pitch and Yaw
  • +
+ The nozzle exit pressure (p2) is returned via a + call to FGNozzle::GetPowerRequired(). This exit pressure is used, + along with chamber pressure and specific heat ratio, to get the + thrust coefficient for the throttle setting. This thrust + coefficient is multiplied by the chamber pressure and then passed + to the nozzle Calculate() routine, where the thrust force is + determined. + + @author Jon S. Berndt + $Id$ + @see FGNozzle, + FGThruster, + FGForce, + FGEngine, + FGPropulsion, + FGTank +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGRocket : public FGEngine +{ +public: + /** Constructor. + @param exec pointer to JSBSim parent object, the FDM Executive. + @param el a pointer to the XML Element instance representing the engine. + @param engine_number engine number */ + FGRocket(FGFDMExec* exec, Element *el, int engine_number); + + /** Destructor */ + ~FGRocket(void); + + /** Determines the thrust coefficient. + @return thrust coefficient times chamber pressure */ + double Calculate(void); + + /** Gets the chamber pressure. + @return chamber pressure in psf. */ + double GetChamberPressure(void) {return PC;} + + /** Gets the flame-out status. + The engine will "flame out" if the throttle is set below the minimum + sustainable setting. + @return true if engine has flamed out. */ + bool GetFlameout(void) {return Flameout;} + string GetEngineLabels(string delimeter); + string GetEngineValues(string delimeter); + +private: + double SHR; + double maxPC; + double propEff; + double kFactor; + double Variance; + double PC; + bool Flameout; + + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGRotor.cpp b/src/FDM/JSBSim/models/propulsion/FGRotor.cpp new file mode 100644 index 000000000..b1efdde76 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGRotor.cpp @@ -0,0 +1,128 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGRotor.cpp + Author: Jon S. Berndt + Date started: 08/24/00 + Purpose: Encapsulates the rotor object + + ------------- 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 +-------------------------------------------------------------------------------- +08/24/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGRotor.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_ROTOR; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +FGRotor::FGRotor(FGFDMExec *FDMExec) : FGThruster(FDMExec) +{ + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGRotor::~FGRotor() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGRotor::Calculate(double PowerAvailable) +{ + return 0.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGRotor::GetThrusterLabels(int id, string delimeter) +{ + return ""; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGRotor::GetThrusterValues(int id, string delimeter) +{ + return ""; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGRotor::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: FGRotor" << endl; + if (from == 1) cout << "Destroyed: FGRotor" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGRotor.h b/src/FDM/JSBSim/models/propulsion/FGRotor.h new file mode 100644 index 000000000..2e4b3b34d --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGRotor.h @@ -0,0 +1,81 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGRotor.h + Author: Jon S. Berndt + Date started: 08/24/00 + + ------------- 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. + +HISTORY +-------------------------------------------------------------------------------- +08/24/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGROTOR_H +#define FGROTOR_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGThruster.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_ROTOR "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models a rotor (such as for a helicopter); NOT YET IMPLEMENTED. + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGRotor : public FGThruster { + +public: + FGRotor(FGFDMExec *FDMExec); + ~FGRotor(); + + double Calculate(double); + string GetThrusterLabels(int id, string delimeter); + string GetThrusterValues(int id, string delimeter); + +private: + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/models/propulsion/FGTank.cpp b/src/FDM/JSBSim/models/propulsion/FGTank.cpp new file mode 100644 index 000000000..57bebd7dc --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGTank.cpp @@ -0,0 +1,220 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGTank.cpp + Author: Jon Berndt + Date started: 01/21/99 + 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 +-------------------------------------------------------------------------------- +See header file. + +HISTORY +-------------------------------------------------------------------------------- +01/21/99 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include "FGTank.h" + +#if !defined ( sgi ) || defined( __GNUC__ ) && (_COMPILER_VERSION < 740) +using std::cerr; +using std::endl; +using std::cout; +#endif + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_TANK; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGTank::FGTank(FGFDMExec* exec, Element* el) +{ + string token; + Element* element; + Area = 1.0; + Temperature = -9999.0; + Auxiliary = exec->GetAuxiliary(); + Radius = Capacity = Contents = 0.0; + + type = el->GetAttributeValue("type"); + if (type == "FUEL") Type = ttFUEL; + else if (type == "OXIDIZER") Type = ttOXIDIZER; + else Type = ttUNKNOWN; + + element = el->FindElement("location"); + if (element) vXYZ = element->FindElementTripletConvertTo("IN"); + else cerr << "No location found for this tank." << endl; + + if (el->FindElement("radius")) + Radius = el->FindElementValueAsNumberConvertTo("radius", "IN"); + if (el->FindElement("capacity")) + Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS"); + if (el->FindElement("contents")) + Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS"); + if (el->FindElement("temperature")) + Temperature = el->FindElementValueAsNumber("temperature"); + + Selected = true; + + if (Capacity != 0) { + PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0 + } else { + Contents = 0; + PctFull = 0; + } + + if (Temperature != -9999.0) Temperature = FahrenheitToCelsius(Temperature); + Area = 40.0 * pow(Capacity/1975, 0.666666667); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTank::~FGTank() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTank::Drain(double used) +{ + double shortage = Contents - used; + + if (shortage >= 0) { + Contents -= used; + PctFull = 100.0*Contents/Capacity; + } else { + Contents = 0.0; + PctFull = 0.0; + Selected = false; + } + return shortage; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTank::Fill(double amount) +{ + double overage = 0.0; + + Contents += amount; + + if (Contents > Capacity) { + overage = Contents - Capacity; + Contents = Capacity; + PctFull = 100.0; + } else { + PctFull = Contents/Capacity*100.0; + } + return overage; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTank::SetContents(double amount) +{ + Contents = amount; + if (Contents > Capacity) { + Contents = Capacity; + PctFull = 100.0; + } else { + PctFull = Contents/Capacity*100.0; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTank::Calculate(double dt) +{ + if (Temperature == -9999.0) return 0.0; + double HeatCapacity = 900.0; // Joules/lbm/C + double TempFlowFactor = 1.115; // Watts/sqft/C + double TAT = Auxiliary->GetTAT_C(); + double Tdiff = TAT - Temperature; + double dT = 0.0; // Temp change due to one surface + if (fabs(Tdiff) > 0.1) { + dT = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity); + } + return Temperature += (dT + dT); // For now, assume upper/lower the same +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGTank::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + cout << " " << type << " tank holds " << Capacity << " lbs. " << type << endl; + cout << " currently at " << PctFull << "% of maximum capacity" << endl; + cout << " Tank location (X, Y, Z): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl; + cout << " Effective radius: " << Radius << " inches" << endl; + cout << " Initial temperature: " << Temperature << " Fahrenheit" << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTank" << endl; + if (from == 1) cout << "Destroyed: FGTank" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGTank.h b/src/FDM/JSBSim/models/propulsion/FGTank.h new file mode 100644 index 000000000..33e3430d0 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGTank.h @@ -0,0 +1,174 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTank.h + Author: Jon S. Berndt + Date started: 01/21/99 + + ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) ------------- + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 Temple + Place - Suite 330, Boston, MA 02111-1307, USA. + + Further information about the GNU General Public License can also be found on + the world wide web at http://www.gnu.org. + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +Based on Flightgear code, which is based on LaRCSim. This class simulates +a generic Tank. + +HISTORY +-------------------------------------------------------------------------------- +01/21/99 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGTank_H +#define FGTank_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include +// #include + +#ifdef FGFS +# include +# include STL_STRING + SG_USING_STD(string); + SG_USING_STD(cerr); + SG_USING_STD(endl); + SG_USING_STD(cout); +#else +# include + using std::string; +# if !defined(sgi) || defined(__GNUC__) || (_COMPILER_VERSION >= 740) + using std::cerr; + using std::endl; + using std::cout; +# endif +#endif + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_TANK "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Models a fuel tank. + @author Jon Berndt + @see Akbar, Raza et al. "A Simple Analysis of Fuel Addition to the CWT of + 747", California Institute of Technology, 1998 +

+ Fuel temperature is calculated using the following assumptions: +

+ Fuel temperature will only be calculated for tanks which have an initial fuel + temperature specified in the configuration file. +

+ The surface area of the tank is estimated from the capacity in pounds. It + is assumed that the tank is a wing tank with dimensions h by 4h by 10h. The + volume of the tank is then 40(h)(h)(h). The area of the upper or lower + surface is then 40(h)(h). The volume is also equal to the capacity divided + by 49.368 lbs/cu-ft, for jet fuel. The surface area of one side can then be + derived from the tank's capacity. +

+ The heat capacity of jet fuel is assumed to be 900 Joules/lbm/K, and the + heat transfer factor of the tank is 1.115 Watts/sq-ft/K. +

+Configuration File Format +

+\
+  XLOC        \
+  YLOC        \
+  ZLOC        \
+  RADIUS      \
+  CAPACITY    \
+  CONTENTS    \
+  TEMPERATURE \
+\
+
+Definition of the tank configuration file parameters: +
+TYPE - One of FUEL or OXIDIZER.
+XLOC - Location of tank on aircraft's x-axis, inches.
+YLOC - Location of tank on aircraft's y-axis, inches.
+ZLOC - Location of tank on aircraft's z-axis, inches.
+RADIUS - Equivalent radius of tank, inches, for modeling slosh.
+CAPACITY - Capacity in pounds.
+CONTENTS - Initial contents in pounds.
+TEMPERATURE - Initial temperature in degrees Fahrenheit.
+
+ */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGTank : public FGJSBBase +{ +public: + FGTank(FGFDMExec* exec, Element* el); + ~FGTank(); + + double Drain(double); + double Calculate(double dt); + int GetType(void) {return Type;} + bool GetSelected(void) {return Selected;} + double GetPctFull(void) {return PctFull;} + double GetContents(void) {return Contents;} + double GetTemperature_degC(void) {return Temperature;} + double GetTemperature(void) {return CelsiusToFahrenheit(Temperature);} + const FGColumnVector3& GetXYZ(void) {return vXYZ;} + double GetXYZ(int idx) {return vXYZ(idx);} + + double Fill(double amount); + void SetContents(double amount); + void SetTemperature(double temp) { Temperature = temp; } + + enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER}; + +private: + TankType Type; + string type; + FGColumnVector3 vXYZ; + double Capacity; + double Radius; + double PctFull; + double Contents; + double Area; + double Temperature; + bool Selected; + FGAuxiliary* Auxiliary; + void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGThruster.cpp b/src/FDM/JSBSim/models/propulsion/FGThruster.cpp new file mode 100644 index 000000000..9d1dc336a --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGThruster.cpp @@ -0,0 +1,181 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGThruster.cpp + Author: Jon S. Berndt + Date started: 08/23/00 + Purpose: Encapsulates the thruster object + + ------------- 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 +-------------------------------------------------------------------------------- +08/23/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include "FGThruster.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_THRUSTER; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +FGThruster::FGThruster(FGFDMExec *FDMExec) : FGForce(FDMExec) +{ + Type = ttDirect; + SetTransformType(FGForce::tCustom); + + EngineNum = 0; + PropertyManager = FDMExec->GetPropertyManager(); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMExec) +{ + Element* thruster_element = el->GetParent(); + Element* element; + FGColumnVector3 location, orientation; + + Type = ttDirect; + SetTransformType(FGForce::tCustom); + + Name = el->GetName(); + + GearRatio = 1.0; + + EngineNum = num; + ThrustCoeff = 0.0; + PropertyManager = FDMExec->GetPropertyManager(); + +// Determine the initial location and orientation of this thruster and load the +// thruster with this information. + + element = thruster_element->FindElement("location"); + if (element) location = element->FindElementTripletConvertTo("IN"); + else cerr << "No thruster location found." << endl; + + element = thruster_element->FindElement("orient"); + if (element) orientation = element->FindElementTripletConvertTo("IN"); + else cerr << "No thruster orientation found." << endl; + + SetLocation(location); + SetAnglesToBody(orientation); + +// char property_name[80]; +// snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); +// PropertyManager->Tie( property_name, &ThrustCoeff ); + + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGThruster::~FGThruster() +{ +// char property_name[80]; +// snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum); +// PropertyManager->Untie( property_name ); + + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGThruster::GetThrusterLabels(int id, string delimeter) +{ + std::ostringstream buf; + + buf << Name << "_Thrust[" << id << "]"; + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGThruster::GetThrusterValues(int id, string delimeter) +{ + std::ostringstream buf; + + buf << Thrust; + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGThruster::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: FGThruster" << endl; + if (from == 1) cout << "Destroyed: FGThruster" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGThruster.h b/src/FDM/JSBSim/models/propulsion/FGThruster.h new file mode 100644 index 000000000..8c6e6da5c --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGThruster.h @@ -0,0 +1,116 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGThruster.h + Author: Jon S. Berndt + Date started: 08/23/00 + + ------------- 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. + +HISTORY +-------------------------------------------------------------------------------- +08/24/00 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGTHRUSTER_H +#define FGTHRUSTER_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGForce.h" +#include +#include +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_THRUSTER "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Base class for specific thrusting devices such as propellers, nozzles, etc. + @author Jon Berndt + @version $Id$ + */ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGThruster : public FGForce { + +public: + /// Constructor + FGThruster(FGFDMExec *FDMExec); + FGThruster(FGFDMExec *FDMExec, Element *el, int num ); + /// Destructor + virtual ~FGThruster(); + + enum eType {ttNozzle, ttRotor, ttPropeller, ttDirect}; + + virtual double Calculate(double tt) { + Thrust = tt; vFn(1) = Thrust; + return Thrust; + } + void SetName(string name) {Name = name;} + virtual void SetRPM(double rpm) {}; + virtual double GetPowerRequired(void) {return 0.0;} + virtual void SetdeltaT(double dt) {deltaT = dt;} + double GetThrust(void) {return Thrust;} + eType GetType(void) {return Type;} + string GetName(void) {return Name;} + virtual double GetRPM(void) { return 0.0; }; + double GetGearRatio(void) {return GearRatio; } + virtual string GetThrusterLabels(int id, string delimeter); + virtual string GetThrusterValues(int id, string delimeter); + + inline void SetThrustCoefficient(double ct) { ThrustCoeff = ct; } + +protected: + eType Type; + string Name; + double Thrust; + double PowerRequired; + double deltaT; + double GearRatio; + double ThrustCoeff; + int EngineNum; + FGPropertyManager* PropertyManager; + virtual void Debug(int from); +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp new file mode 100644 index 000000000..9554e553f --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp @@ -0,0 +1,578 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGTurbine.cpp + Author: David Culp + Date started: 03/11/2003 + Purpose: This module models a turbine engine. + + ------------- Copyright (C) 2003 David 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. + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- + +This class descends from the FGEngine class and models a turbine engine based +on parameters given in the engine config file for this class + +HISTORY +-------------------------------------------------------------------------------- +03/11/2003 DPC Created +09/08/2003 DPC Changed Calculate() and added engine phases + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include + +#include "FGTurbine.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_TURBINE; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number) + : FGEngine(exec, el, engine_number) +{ + SetDefaults(); + + Load(exec, el); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTurbine::~FGTurbine() +{ + if (IdleThrustLookup) delete IdleThrustLookup; + if (MilThrustLookup) delete MilThrustLookup; + if (MaxThrustLookup) delete MaxThrustLookup; + if (InjectionLookup) delete InjectionLookup; + unbind(); + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// The main purpose of Calculate() is to determine what phase the engine should +// be in, then call the corresponding function. + +double FGTurbine::Calculate(void) +{ + TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; + dt = State->Getdt() * Propulsion->GetRate(); + ThrottlePos = FCS->GetThrottlePos(EngineNumber); + if (ThrottlePos > 1.0) { + AugmentCmd = ThrottlePos - 1.0; + ThrottlePos -= AugmentCmd; + } else { + AugmentCmd = 0.0; + } + + // When trimming is finished check if user wants engine OFF or RUNNING + if ((phase == tpTrim) && (dt > 0)) { + if (Running && !Starved) { + phase = tpRun; + N2 = IdleN2 + ThrottlePos * N2_factor; + N1 = IdleN1 + ThrottlePos * N1_factor; + OilTemp_degK = 366.0; + Cutoff = false; + } + else { + phase = tpOff; + Cutoff = true; + EGT_degC = TAT; + } + } + + if (!Running && Cutoff && Starter) { + if (phase == tpOff) phase = tpSpinUp; + } + if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart; + if (Cutoff && (phase != tpSpinUp)) phase = tpOff; + if (dt == 0) phase = tpTrim; + if (Starved) phase = tpOff; + if (Stalled) phase = tpStall; + if (Seized) phase = tpSeize; + + switch (phase) { + case tpOff: Thrust = Off(); break; + case tpRun: Thrust = Run(); break; + case tpSpinUp: Thrust = SpinUp(); break; + case tpStart: Thrust = Start(); break; + case tpStall: Thrust = Stall(); break; + case tpSeize: Thrust = Seize(); break; + case tpTrim: Thrust = Trim(); break; + default: Thrust = Off(); + } + + Thrust = Thruster->Calculate(Thrust); // allow thruster to modify thrust (i.e. reversing) + + return Thrust; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::Off(void) +{ + double qbar = Auxiliary->Getqbar(); + Running = false; + FuelFlow_pph = Seek(&FuelFlow_pph, 0, 1000.0, 10000.0); + N1 = Seek(&N1, qbar/10.0, N1/2.0, N1/2.0); + N2 = Seek(&N2, qbar/15.0, N2/2.0, N2/2.0); + EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); + OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); + OilPressure_psi = N2 * 0.62; + NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); + EPR = Seek(&EPR, 1.0, 0.2, 0.2); + Augmentation = false; + return 0.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::Run() +{ + double idlethrust, milthrust, thrust; + double N2norm; // 0.0 = idle N2, 1.0 = maximum N2 + + idlethrust = MilThrust * IdleThrustLookup->GetValue(); + milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue(); + + Running = true; + Starter = false; + + N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, delay, delay * 3.0); + N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, delay, delay * 2.4); + N2norm = (N2 - IdleN2) / N2_factor; + thrust = idlethrust + (milthrust * N2norm * N2norm); + EGT_degC = TAT + 363.1 + ThrottlePos * 357.1; + OilPressure_psi = N2 * 0.62; + OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1); + + if (!Augmentation) { + correctedTSFC = TSFC * (0.84 + (1-N2norm)*(1-N2norm)); + FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 100000); + if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF; + NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8); + thrust = thrust * (1.0 - BleedDemand); + EPR = 1.0 + thrust/MilThrust; + } + + if (AugMethod == 1) { + if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;} + else {Augmentation = false;} + } + + if ((Augmented == 1) && Augmentation && (AugMethod < 2)) { + thrust = MaxThrustLookup->GetValue() * MaxThrust; + FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); + NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); + } + + if (AugMethod == 2) { + if (AugmentCmd > 0.0) { + Augmentation = true; + double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust; + thrust += (tdiff * AugmentCmd); + FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0); + NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8); + } else { + Augmentation = false; + } + } + + if ((Injected == 1) && Injection) { + thrust = thrust * InjectionLookup->GetValue(); + } + + ConsumeFuel(); + if (Cutoff) phase = tpOff; + if (Starved) phase = tpOff; + + return thrust; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::SpinUp(void) +{ + Running = false; + FuelFlow_pph = 0.0; + N2 = Seek(&N2, 25.18, 3.0, N2/2.0); + N1 = Seek(&N1, 5.21, 1.0, N1/2.0); + EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3); + OilPressure_psi = N2 * 0.62; + OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2); + EPR = 1.0; + NozzlePosition = 1.0; + return 0.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::Start(void) +{ + if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start + Cranking = true; // provided for sound effects signal + if (N2 < IdleN2) { + N2 = Seek(&N2, IdleN2, 2.0, N2/2.0); + N1 = Seek(&N1, IdleN1, 1.4, N1/2.0); + EGT_degC = Seek(&EGT_degC, TAT + 363.1, 21.3, 7.3); + FuelFlow_pph = Seek(&FuelFlow_pph, IdleFF, 103.7, 103.7); + OilPressure_psi = N2 * 0.62; + ConsumeFuel(); + } + else { + phase = tpRun; + Running = true; + Starter = false; + Cranking = false; + } + } + else { // no start if N2 < 15% + phase = tpOff; + Starter = false; + } + + return 0.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::Stall(void) +{ + double qbar = Auxiliary->Getqbar(); + EGT_degC = TAT + 903.14; + FuelFlow_pph = IdleFF; + N1 = Seek(&N1, qbar/10.0, 0, N1/10.0); + N2 = Seek(&N2, qbar/15.0, 0, N2/10.0); + ConsumeFuel(); + if (ThrottlePos < 0.01) phase = tpRun; // clear the stall with throttle + + return 0.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::Seize(void) +{ + double qbar = Auxiliary->Getqbar(); + N2 = 0.0; + N1 = Seek(&N1, qbar/20.0, 0, N1/15.0); + FuelFlow_pph = IdleFF; + ConsumeFuel(); + OilPressure_psi = 0.0; + OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0, 0.2); + Running = false; + return 0.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::Trim() +{ + double idlethrust, milthrust, thrust, tdiff; + idlethrust = MilThrust * IdleThrustLookup->GetValue(); + milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue(); + thrust = (idlethrust + (milthrust * ThrottlePos * ThrottlePos)) + * (1.0 - BleedDemand); + + if (AugMethod == 1) { + if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;} + else {Augmentation = false;} + } + + if ((Augmented == 1) && Augmentation && (AugMethod < 2)) { + thrust = MaxThrust * MaxThrustLookup->GetValue(); + } + + if (AugMethod == 2) { + if (AugmentCmd > 0.0) { + tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust; + thrust += (tdiff * AugmentCmd); + } + } + + if ((Injected == 1) && Injection) { + thrust = thrust * InjectionLookup->GetValue(); + } + + return thrust; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::CalcFuelNeed(void) +{ + return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::GetPowerAvailable(void) { + if( ThrottlePos <= 0.77 ) + return 64.94*ThrottlePos; + else + return 217.38*ThrottlePos - 117.38; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurbine::Seek(double *var, double target, double accel, double decel) { + double v = *var; + if (v > target) { + v -= dt * decel; + if (v < target) v = target; + } else if (v < target) { + v += dt * accel; + if (v > target) v = target; + } + return v; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTurbine::SetDefaults(void) +{ + N1 = N2 = 0.0; + Type = etTurbine; + MilThrust = 10000.0; + MaxThrust = 10000.0; + BypassRatio = 0.0; + TSFC = 0.8; + correctedTSFC = TSFC; + ATSFC = 1.7; + IdleN1 = 30.0; + IdleN2 = 60.0; + MaxN1 = 100.0; + MaxN2 = 100.0; + Augmented = 0; + AugMethod = 0; + Injected = 0; + BleedDemand = 0.0; + ThrottlePos = 0.0; + AugmentCmd = 0.0; + InletPosition = 1.0; + NozzlePosition = 1.0; + Augmentation = false; + Injection = false; + Reversed = false; + Cutoff = true; + phase = tpOff; + Stalled = false; + Seized = false; + Overtemp = false; + Fire = false; + EGT_degC = 0.0; + IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGTurbine::Load(FGFDMExec* exec, Element *el) +{ + char property_prefix[80]; + snprintf(property_prefix, 80, "propulsion/engine[%u]/", EngineNumber); + + if (el->FindElement("milthrust")) + MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); + if (el->FindElement("maxthrust")) + MaxThrust = el->FindElementValueAsNumberConvertTo("maxthrust","LBS"); + if (el->FindElement("bypassratio")) + BypassRatio = el->FindElementValueAsNumber("bypassratio"); + if (el->FindElement("bleed")) + BleedDemand = el->FindElementValueAsNumber("bleed"); + if (el->FindElement("tsfc")) + TSFC = el->FindElementValueAsNumber("tsfc"); + if (el->FindElement("atsfc")) + ATSFC = el->FindElementValueAsNumber("atsfc"); + if (el->FindElement("idlen1")) + IdleN1 = el->FindElementValueAsNumber("idlen1"); + if (el->FindElement("idlen2")) + IdleN2 = el->FindElementValueAsNumber("idlen2"); + if (el->FindElement("maxn1")) + MaxN1 = el->FindElementValueAsNumber("maxn1"); + if (el->FindElement("maxn2")) + MaxN2 = el->FindElementValueAsNumber("maxn2"); + if (el->FindElement("augmented")) + Augmented = (int)el->FindElementValueAsNumber("augmented"); + if (el->FindElement("augmethod")) + AugMethod = (int)el->FindElementValueAsNumber("augmethod"); + if (el->FindElement("injected")) + Injected = (int)el->FindElementValueAsNumber("injected"); + + Element *function_element; + string name; + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); + + while (true) { + function_element = el->FindNextElement("function"); + if (!function_element) break; + name = function_element->GetAttributeValue("name"); + if (name == "IdleThrust") { + IdleThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); + } else if (name == "MilThrust") { + MilThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); + } else if (name == "AugThrust") { + MaxThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); + } else if (name == "Injection") { + InjectionLookup = new FGFunction(PropertyManager, function_element, property_prefix); + } else { + cerr << "Unknown function type: " << name << " in turbine definition." << + endl; + } + } + + // Pre-calculations and initializations + + delay = 60.0 / (BypassRatio + 3.0); + N1_factor = MaxN1 - IdleN1; + N2_factor = MaxN2 - IdleN2; + OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; + IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate + + bindmodel(); + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGTurbine::GetEngineLabels(string delimeter) +{ + std::ostringstream buf; + + buf << Name << "_N1[" << EngineNumber << "]" << delimeter + << Name << "_N2[" << EngineNumber << "]" << delimeter + << Thruster->GetThrusterLabels(EngineNumber, delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGTurbine::GetEngineValues(string delimeter) +{ + std::ostringstream buf; + + buf << N1 << delimeter + << N2 << delimeter + << Thruster->GetThrusterValues(EngineNumber, delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTurbine::bindmodel() +{ + char property_name[80]; + + snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber); + PropertyManager->Tie( property_name, &N1); + snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber); + PropertyManager->Tie( property_name, &N2); + snprintf(property_name, 80, "propulsion/engine[%u]/thrust", EngineNumber); + PropertyManager->Tie( property_name, this, &FGTurbine::GetThrust); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTurbine::unbind() +{ + char property_name[80]; + + snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber); + PropertyManager->Untie(property_name); + snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber); + PropertyManager->Untie(property_name); + snprintf(property_name, 80, "propulsion/engine[%u]/thrust", EngineNumber); + PropertyManager->Untie(property_name); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGTurbine::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + } + if (from == 2) { // called from Load() + cout << "\n Engine Name: " << Name << endl; + cout << " MilThrust: " << MilThrust << endl; + cout << " MaxThrust: " << MaxThrust << endl; + cout << " BypassRatio: " << BypassRatio << endl; + cout << " TSFC: " << TSFC << endl; + cout << " ATSFC: " << ATSFC << endl; + cout << " IdleN1: " << IdleN1 << endl; + cout << " IdleN2: " << IdleN2 << endl; + cout << " MaxN1: " << MaxN1 << endl; + cout << " MaxN2: " << MaxN2 << endl; + cout << " Augmented: " << Augmented << endl; + cout << " AugMethod: " << AugMethod << endl; + cout << " Injected: " << Injected << endl; + cout << " MinThrottle: " << MinThrottle << endl; + + cout << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTurbine" << endl; + if (from == 1) cout << "Destroyed: FGTurbine" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.h b/src/FDM/JSBSim/models/propulsion/FGTurbine.h new file mode 100644 index 000000000..0b2740ddf --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.h @@ -0,0 +1,257 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTurbine.h + Author: David Culp + Date started: 03/11/2003 + + ------------- Copyright (C) 2003 David 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 +-------------------------------------------------------------------------------- +03/11/2003 DPC Created, based on FGTurbine +09/22/2003 DPC Added starting, stopping, new framework +04/29/2004 DPC Renamed from FGSimTurbine to FGTurbine + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGTURBINE_H +#define FGTURBINE_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include "FGEngine.h" +#include +#include + +#define ID_TURBINE "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** This class models a turbine engine. Based on Jon Berndt's FGTurbine module. + Here the term "phase" signifies the engine's mode of operation. At any given + time the engine is in only one phase. At simulator startup the engine will be + placed in the Trim phase in order to provide a simplified thrust value without + throttle lag. When trimming is complete the engine will go to the Off phase, + unless the value FGEngine::Running has been previously set to true, in which + case the engine will go to the Run phase. Once an engine is in the Off phase + the full starting procedure (or airstart) must be used to get it running. +

+ - STARTING (on ground): + -# Set the control FGEngine::Starter to true. The engine will spin up to + a maximum of about %25 N2 (%5.2 N1). This simulates the action of a + pneumatic starter. + -# After reaching %15 N2 set the control FGEngine::Cutoff to false. If fuel + is available the engine will now accelerate to idle. The starter will + automatically be set to false after the start cycle. +

+ - STARTING (in air): + -# Increase speed to obtain a minimum of %15 N2. If this is not possible, + the starter may be used to assist. + -# Place the control FGEngine::Cutoff to false. +

+ Ignition is assumed to be on anytime the Cutoff control is set to false, + therefore a seperate ignition system is not modeled. + +Configuration File Format +

+\
+  MILTHRUST   \
+  MAXTHRUST   \
+  BYPASSRATIO \
+  TSFC        \
+  ATSFC       \
+  IDLEN1      \
+  IDLEN2      \
+  MAXN1       \
+  MAXN2       \
+  AUGMENTED   \<0|1>
+  AUGMETHOD   \<0|1>
+  INJECTED    \<0|1>
+  ...
+\
+
+Definition of the turbine engine configuration file parameters: +
+MILTHRUST - Maximum thrust, static, at sea level, lbf.
+MAXTHRUST - Afterburning thrust, static, at sea level, lbf
+[this value will be ignored when AUGMENTED is zero (false)].
+BYPASSRATIO - Ratio of bypass air flow to core air flow.
+TSFC - Thrust-specific fuel consumption, lbm/hr/lbf
+[i.e. fuel flow divided by thrust].
+ATSFC - Afterburning TSFC, lbm/hr/lbf
+[this value will be ignored when AUGMENTED is zero (false)]
+IDLEN1 - Fan rotor rpm (% of max) at idle
+IDLEN2 - Core rotor rpm (% of max) at idle
+MAXN1 - Fan rotor rpm (% of max) at full throttle [not always 100!]
+MAXN2 - Core rotor rpm (% of max) at full throttle [not always 100!]
+AUGMENTED
+  0 == afterburner not installed
+  1 == afterburner installed
+AUGMETHOD
+  0 == afterburner activated by property /engines/engine[n]/augmentation
+  1 == afterburner activated by pushing throttle above 99% position
+  2 == throttle range is expanded in the FCS, and values above 1.0 are afterburner range
+  [this item will be ignored when AUGMENTED == 0]
+INJECTED
+  0 == Water injection not installed
+  1 == Water injection installed
+
+ @author David P. Culp + @version "$Id$" +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGTurbine : public FGEngine +{ +public: + /** Constructor + @param Executive pointer to executive structure + @param el pointer to the XML element representing the turbine engine + @param engine_number engine number*/ + FGTurbine(FGFDMExec* Executive, Element *el, int engine_number); + /// Destructor + ~FGTurbine(); + + enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; + + double Calculate(void); + double CalcFuelNeed(void); + double GetPowerAvailable(void); + double GetThrust(void) const {return Thrust;} + double Seek(double* var, double target, double accel, double decel); + + phaseType GetPhase(void) { return phase; } + + bool GetOvertemp(void) const {return Overtemp; } + bool GetInjection(void) const {return Injection;} + bool GetFire(void) const { return Fire; } + bool GetAugmentation(void) const {return Augmentation;} + bool GetReversed(void) const { return Reversed; } + bool GetCutoff(void) const { return Cutoff; } + int GetIgnition(void) const {return Ignition;} + + double GetInlet(void) const { return InletPosition; } + double GetNozzle(void) const { return NozzlePosition; } + double GetBleedDemand(void) const {return BleedDemand;} + double GetN1(void) const {return N1;} + double GetN2(void) const {return N2;} + double GetEPR(void) const {return EPR;} + double GetEGT(void) const {return EGT_degC;} + + double getOilPressure_psi () const {return OilPressure_psi;} + double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} + + void SetInjection(bool injection) {Injection = injection;} + void SetIgnition(int ignition) {Ignition = ignition;} + void SetAugmentation(bool augmentation) {Augmentation = augmentation;} + void SetPhase( phaseType p ) { phase = p; } + void SetEPR(double epr) {EPR = epr;} + void SetBleedDemand(double bleedDemand) {BleedDemand = bleedDemand;} + void SetReverse(bool reversed) { Reversed = reversed; } + void SetCutoff(bool cutoff) { Cutoff = cutoff; } + + string GetEngineLabels(string delimeter); + string GetEngineValues(string delimeter); + +private: + + phaseType phase; ///< Operating mode, or "phase" + double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) + double MaxThrust; ///< Maximum Augmented Thrust, static @ S.L. (lbf) + double BypassRatio; ///< Bypass Ratio + double TSFC; ///< Thrust Specific Fuel Consumption (lbm/hr/lbf) + double ATSFC; ///< Augmented TSFC (lbm/hr/lbf) + double IdleN1; ///< Idle N1 + double IdleN2; ///< Idle N2 + double N1; ///< N1 + double N2; ///< N2 + double MaxN1; ///< N1 at 100% throttle + double MaxN2; ///< N2 at 100% throttle + double IdleFF; ///< Idle Fuel Flow (lbm/hr) + double delay; ///< Inverse spool-up time from idle to 100% (seconds) + double dt; ///< Simulator time slice + double N1_factor; ///< factor to tie N1 and throttle + double N2_factor; ///< factor to tie N2 and throttle + double ThrottlePos; ///< FCS-supplied throttle position + double AugmentCmd; ///< modulated afterburner command (0.0 to 1.0) + double TAT; ///< total air temperature (deg C) + bool Stalled; ///< true if engine is compressor-stalled + bool Seized; ///< true if inner spool is seized + bool Overtemp; ///< true if EGT exceeds limits + bool Fire; ///< true if engine fire detected + bool Injection; + bool Augmentation; + bool Reversed; + bool Cutoff; + int Injected; ///< = 1 if water injection installed + int Ignition; + int Augmented; ///< = 1 if augmentation installed + int AugMethod; ///< = 0 if using property /engine[n]/augmentation + ///< = 1 if using last 1% of throttle movement + ///< = 2 if using FCS-defined throttle + double EGT_degC; + double EPR; + double OilPressure_psi; + double OilTemp_degK; + double BleedDemand; + double InletPosition; + double NozzlePosition; + double correctedTSFC; + + double Off(void); + double Run(); + double SpinUp(void); + double Start(void); + double Stall(void); + double Seize(void); + double Trim(); + + FGFunction *IdleThrustLookup; + FGFunction *MilThrustLookup; + FGFunction *MaxThrustLookup; + FGFunction *InjectionLookup; + + void SetDefaults(void); + bool Load(FGFDMExec *exec, Element *el); + void bindmodel(void); + void unbind(void); + void Debug(int from); + +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif + diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp new file mode 100755 index 000000000..e6bd2dc26 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp @@ -0,0 +1,578 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGTurboProp.cpp + Author: Jiri "Javky" Javurek + based on SimTurbine and Turbine engine from David Culp + Date started: 05/14/2004 + Purpose: This module models a turbo propeller engine. + + ------------- Copyright (C) 2004 (javky@email.cz) --------- + + 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 descends from the FGEngine class and models a Turbo propeller engine +based on parameters given in the engine config file for this class + +HISTORY +-------------------------------------------------------------------------------- +05/14/2004 Created + +//JVK (mark) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include +#include "FGTurboProp.h" + +#include "FGPropeller.h" + +namespace JSBSim { + +static const char *IdSrc = "$Id$"; +static const char *IdHdr = ID_TURBOPROP; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number) + : FGEngine(exec, el, engine_number) +{ + SetDefaults(); + + Load(exec, el); + Debug(0); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +FGTurboProp::~FGTurboProp() +{ + Debug(1); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGTurboProp::Load(FGFDMExec* exec, Element *el) +{ + char property_prefix[80]; + snprintf(property_prefix, 80, "propulsion/engine[%u]/", EngineNumber); + + IdleFF=-1; + MaxStartingTime = 999999; //very big timeout -> infinite + Ielu_max_torque=-1; + +// ToDo: Need to make sure units are properly accounted for below. + + if (el->FindElement("milthrust")) + MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); + if (el->FindElement("idlen1")) + IdleN1 = el->FindElementValueAsNumber("idlen1"); + if (el->FindElement("idlen2")) + IdleN2 = el->FindElementValueAsNumber("idlen1"); + if (el->FindElement("maxn1")) + MaxN1 = el->FindElementValueAsNumber("maxn1"); + if (el->FindElement("maxn2")) + MaxN2 = el->FindElementValueAsNumber("maxn2"); + if (el->FindElement("betarangeend")) + BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0; + if (el->FindElement("reversemaxpower")) + ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0; + + if (el->FindElement("maxpower")) + MaxPower = el->FindElementValueAsNumber("maxpower"); + if (el->FindElement("idlefuelflow")) + IdleFF = el->FindElementValueAsNumber("idlefuelflow"); + if (el->FindElement("psfc")) + PSFC = el->FindElementValueAsNumber("psfc"); + if (el->FindElement("n1idle_max_delay")) + Idle_Max_Delay = el->FindElementValueAsNumber("n1idle_max_delay"); + if (el->FindElement("maxstartingtime")) + MaxStartingTime = el->FindElementValueAsNumber("maxstartingtime"); + if (el->FindElement("startern1")) + StarterN1 = el->FindElementValueAsNumber("startern1"); + if (el->FindElement("ielumaxtorque")) + Ielu_max_torque = el->FindElementValueAsNumber("ielumaxtorque"); + if (el->FindElement("itt_delay")) + ITT_Delay = el->FindElementValueAsNumber("itt_delay"); + + Element *table_element; + string name; + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); + + while (true) { + table_element = el->FindNextElement("table"); + if (!table_element) break; + name = table_element->GetAttributeValue("name"); + if (name == "EnginePowerVC") { + EnginePowerVC = new FGTable(PropertyManager, table_element); + } else if (name == "EnginePowerRPM_N1") { + EnginePowerRPM_N1 = new FGTable(PropertyManager, table_element); + } else if (name == "ITT_N1") { + ITT_N1 = new FGTable(PropertyManager, table_element); + } else { + cerr << "Unknown table type: " << name << " in turbine definition." << + endl; + } + } + + // Pre-calculations and initializations + + delay=1; + N1_factor = MaxN1 - IdleN1; + N2_factor = MaxN2 - IdleN2; + OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; + if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate + + cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n"; + + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// The main purpose of Calculate() is to determine what phase the engine should +// be in, then call the corresponding function. + +double FGTurboProp::Calculate(void) +{ + TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; + dt = State->Getdt() * Propulsion->GetRate(); + + ThrottleCmd = FCS->GetThrottleCmd(EngineNumber); + + Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); + if (Thruster->GetType() == FGThruster::ttPropeller) { + ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); + ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); + ((FGPropeller*)Thruster)->SetReverse(Reversed); + if (Reversed) { + ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd); + } else { + ((FGPropeller*)Thruster)->SetReverseCoef(0.0); + } + } + + if (Reversed) { + if (ThrottleCmd < BetaRangeThrottleEnd) { + ThrottleCmd = 0.0; // idle when in Beta-range + } else { + // when reversed: + ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower; + } + } + + // When trimming is finished check if user wants engine OFF or RUNNING + if ((phase == tpTrim) && (dt > 0)) { + if (Running && !Starved) { + phase = tpRun; + N2 = IdleN2; + N1 = IdleN1; + OilTemp_degK = 366.0; + Cutoff = false; + } else { + phase = tpOff; + Cutoff = true; + Eng_ITT_degC = TAT; + Eng_Temperature = TAT; + OilTemp_degK = TAT+273.15; + } + } + + if (!Running && Starter) { + if (phase == tpOff) { + phase = tpSpinUp; + if (StartTime < 0) StartTime=0; + } + } + if (!Running && !Cutoff && (N1 > 15.0)) { + phase = tpStart; + StartTime = -1; + } + if (Cutoff && (phase != tpSpinUp)) phase = tpOff; + if (dt == 0) phase = tpTrim; + if (Starved) phase = tpOff; + if (Condition >= 10) { + phase = tpOff; + StartTime=-1; + } + + if (Condition < 1) { + if (Ielu_max_torque > 0 + && -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque() + && ThrottleCmd >= OldThrottle ) { + ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down + Ielu_intervent = true; + } else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) { + ThrottleCmd = OldThrottle; + ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up + Ielu_intervent = true; + } else { + Ielu_intervent = false; + } + } else { + Ielu_intervent = false; + } + OldThrottle = ThrottleCmd; + + switch (phase) { + case tpOff: Eng_HP = Off(); break; + case tpRun: Eng_HP = Run(); break; + case tpSpinUp: Eng_HP = SpinUp(); break; + case tpStart: Eng_HP = Start(); break; + default: Eng_HP = 0; + } + + //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power); + return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired()); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurboProp::Off(void) +{ + double qbar = Auxiliary->Getqbar(); + Running = false; EngStarting = false; + + FuelFlow_pph = Seek(&FuelFlow_pph, 0, 800.0, 800.0); + + //allow the air turn with generator + N1 = ExpSeek(&N1, qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5); + + OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); + + Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); + double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi + + ConsumeFuel(); // for possible setting Starved = false when fuel tank + // is refilled (fuel crossfeed etc.) + + if (Prop_RPM>5) return -0.012; // friction in engine when propeller spining (estimate) + return 0.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurboProp::Run(void) +{ + double idlethrust, milthrust, thrust, EngPower_HP, eff_coef; + Running = true; Starter = false; EngStarting = false; + +//--- + double old_N1 = N1; + N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4); + + EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); + EngPower_HP *= EnginePowerVC->GetValue(); + if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; + + eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1 + FuelFlow_pph = PSFC * EngPower_HP * eff_coef; + + Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400); + double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi +//--- + EPR = 1.0 + thrust/MilThrust; + + OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04); + + ConsumeFuel(); + + if (Cutoff) phase = tpOff; + if (Starved) phase = tpOff; + + return EngPower_HP; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurboProp::SpinUp(void) +{ + double EngPower_HP; + Running = false; EngStarting = true; + FuelFlow_pph = 0.0; + + if (!GeneratorPower) { + EngStarting=false; + phase=tpOff; + StartTime = -1; + return 0.0; + } + + N1 = ExpSeek(&N1, StarterN1, Idle_Max_Delay * 6, Idle_Max_Delay * 2.4); + + Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); + double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + + OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); + + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi + NozzlePosition = 1.0; + + EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); + EngPower_HP *= EnginePowerVC->GetValue(); + if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; + + if (StartTime>=0) StartTime+=dt; + if (StartTime > MaxStartingTime && MaxStartingTime > 0) { //start failed due timeout + phase = tpOff; + StartTime = -1; + } + + ConsumeFuel(); // for possible setting Starved = false when fuel tank + // is refilled (fuel crossfeed etc.) + + return EngPower_HP; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurboProp::Start(void) +{ + double EngPower_HP,eff_coef; + EngStarting = false; + if ((N1 > 15.0) && !Starved) { // minimum 15% N2 needed for start + double old_N1 = N1; + Cranking = true; // provided for sound effects signal + if (N1 < IdleN1) { + EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1); + EngPower_HP *= EnginePowerVC->GetValue(); + if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; + N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4); + eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1 + FuelFlow_pph = PSFC * EngPower_HP * eff_coef; + Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400); + double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1); + Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); + + OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi + OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04); + + } else { + phase = tpRun; + Running = true; + Starter = false; + Cranking = false; + FuelFlow_pph = 0; + EngPower_HP=0.0; + } + } else { // no start if N2 < 15% or Starved + phase = tpOff; + Starter = false; + } + + ConsumeFuel(); + + return EngPower_HP; +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurboProp::CalcFuelNeed(void) +{ + return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurboProp::Seek(double *var, double target, double accel, double decel) +{ + double v = *var; + if (v > target) { + v -= dt * decel; + if (v < target) v = target; + } else if (v < target) { + v += dt * accel; + if (v > target) v = target; + } + return v; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double decel_tau) +{ +// exponential delay instead of the linear delay used in Seek + double v = *var; + if (v > target) { + v = (v - target) * exp ( -dt / decel_tau) + target; + } else if (v < target) { + v = (target - v) * (1 - exp ( -dt / accel_tau)) + v; + } + return v; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTurboProp::SetDefaults(void) +{ + Name = "Not defined"; + N1 = N2 = 0.0; + Type = etTurboprop; + MilThrust = 10000.0; + IdleN1 = 30.0; + IdleN2 = 60.0; + MaxN1 = 100.0; + MaxN2 = 100.0; + ThrottleCmd = 0.0; + InletPosition = 1.0; + NozzlePosition = 1.0; + Reversed = false; + Cutoff = true; + phase = tpOff; + Stalled = false; + Seized = false; + Overtemp = false; + Fire = false; + Eng_ITT_degC = 0.0; + + GeneratorPower=true; + Condition = 0; + Ielu_intervent=false; + + Idle_Max_Delay = 1.0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +string FGTurboProp::GetEngineLabels(string delimeter) +{ + std::ostringstream buf; + + buf << Name << "_N1[" << EngineNumber << "]" << delimeter + << Name << "_N2[" << EngineNumber << "]" << delimeter + << Name << "__PwrAvailJVK[" << EngineNumber << "]" << delimeter + << Thruster->GetThrusterLabels(EngineNumber, delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGTurboProp::GetEngineValues(string delimeter) +{ + std::ostringstream buf; + + buf << N1 << delimeter + << N2 << delimeter + << Thruster->GetThrusterValues(EngineNumber,delimeter); + + return buf.str(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTurboProp::bindmodel() +{ + char property_name[80]; + +// ToDo: Do a proper Tie here, this should be read only. + + snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber); + PropertyManager->Tie( property_name, &N1); + snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber); + PropertyManager->Tie( property_name, &N2); + snprintf(property_name, 80, "propulsion/engine[%u]/reverser", EngineNumber); + PropertyManager->Tie( property_name, &Reversed); + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGTurboProp::unbind() +{ + char property_name[80]; + + snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber); + PropertyManager->Untie(property_name); + snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber); + PropertyManager->Untie(property_name); + snprintf(property_name, 80, "propulsion/engine[%u]/reverser", EngineNumber); + PropertyManager->Untie(property_name); +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// 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 FGTurboProp::Debug(int from) +{ + if (debug_lvl <= 0) return; + + if (debug_lvl & 1) { // Standard console startup message output + if (from == 0) { // Constructor + + } + if (from == 2) { // called from Load() + cout << "\n ****MUJ MOTOR TURBOPROP****\n"; + cout << "\n Engine Name: " << Name << endl; + cout << " MilThrust: " << MilThrust << endl; + cout << " IdleN1: " << IdleN1 << endl; + cout << " MaxN1: " << MaxN1 << endl; + + cout << endl; + } + } + if (debug_lvl & 2 ) { // Instantiation/Destruction notification + if (from == 0) cout << "Instantiated: FGTurboProp" << endl; + if (from == 1) cout << "Destroyed: FGTurboProp" << 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; + } + } +} +} diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.h b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h new file mode 100755 index 000000000..d1ac945d9 --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h @@ -0,0 +1,204 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGTurboProp.h + Author: Jiri "Javky" Javurek + based on SimTurbine and Turbine engine from David Culp + Date started: 05/14/2004 + + ------------- Copyright (C) 2004 (javky@email.cz)---------- + + 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/14/2004 Created + +//JVK (mark) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGTURBOPROP_H +#define FGTURBOPROP_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include "FGEngine.h" +#include +#include + +#define ID_TURBOPROP "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/** Turboprop engine model. + +*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGTurboProp : public FGEngine +{ +public: + /** Constructor + @param Executive pointer to executive structure + @param el pointer to the XML element representing the turbine engine + @param engine_number engine number*/ + FGTurboProp(FGFDMExec* Executive, Element *el, int engine_number); + /// Destructor + ~FGTurboProp(); + + enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; + + double Calculate(void); + double CalcFuelNeed(void); + + inline double GetPowerAvailable(void) const {return (Eng_HP * hptoftlbssec);} + inline double GetPowerAvailable_HP(void) const {return (Eng_HP);} + inline double GetPropRPM(void) const {return (Prop_RPM);} + inline double GetThrottleCmd(void) const {return (ThrottleCmd);} + inline bool GetIeluIntervent(void) const { return Ielu_intervent; } + + double Seek(double* var, double target, double accel, double decel); + double ExpSeek(double* var, double target, double accel, double decel); + + phaseType GetPhase(void) const { return phase; } + + bool GetOvertemp(void) const {return Overtemp; } + bool GetFire(void) const { return Fire; } + bool GetReversed(void) const { return Reversed; } + bool GetCutoff(void) const { return Cutoff; } + int GetIgnition(void) const {return Ignition;} + + double GetInlet(void) const { return InletPosition; } + double GetNozzle(void) const { return NozzlePosition; } + double GetN1(void) const {return N1;} + double GetN2(void) const {return N2;} + double GetEPR(void) const {return EPR;} + double GetITT(void) const {return Eng_ITT_degC;} + double GetEngStarting(void) const { return EngStarting; } + + double getOilPressure_psi () const {return OilPressure_psi;} + double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);} + + inline bool GetGeneratorPower(void) const { return GeneratorPower; } + inline int GetCondition(void) const { return Condition; } + + void SetIgnition(int ignition) {Ignition = ignition;} + void SetPhase( phaseType p ) { phase = p; } + void SetEPR(double epr) {EPR = epr;} + void SetReverse(bool reversed) { Reversed = reversed; } + void SetCutoff(bool cutoff) { Cutoff = cutoff; } + + inline void SetGeneratorPower(bool gp) { GeneratorPower=gp; } + inline void SetCondition(bool c) { Condition=c; } + + string GetEngineLabels(string delimeter); // added from Turbine 0.9.6 + string GetEngineValues(string delimeter); // added from Turbine 0.9.6 + +private: + + phaseType phase; ///< Operating mode, or "phase" + double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) + double IdleN1; ///< Idle N1 + double IdleN2; ///< Idle N2 + double N1; ///< N1 + double N2; ///< N2 + double MaxN1; ///< N1 at 100% throttle + double MaxN2; ///< N2 at 100% throttle + double IdleFF; ///< Idle Fuel Flow (lbm/hr) + double delay; ///< Inverse spool-up time from idle to 100% (seconds) + double dt; ///< Simulator time slice + double N1_factor; ///< factor to tie N1 and throttle + double N2_factor; ///< factor to tie N2 and throttle + double ThrottleCmd; ///< FCS-supplied throttle position + double TAT; ///< total air temperature (deg C) + bool Stalled; ///< true if engine is compressor-stalled + bool Seized; ///< true if inner spool is seized + bool Overtemp; ///< true if EGT exceeds limits + bool Fire; ///< true if engine fire detected + bool Reversed; + bool Cutoff; + int Ignition; + + double EPR; + double OilPressure_psi; + double OilTemp_degK; + double InletPosition; + double NozzlePosition; + + double Ielu_max_torque; // max propeller torque (before ielu intervent) + bool Ielu_intervent; + double OldThrottle; + + double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range + double ReverseMaxPower; // coef (0-1) multiplies max throttle on reverse + + double Idle_Max_Delay; // time delay for exponencial + double MaxPower; // max engine power [HP] + double StarterN1; // rotates of generator maked by starter [%] + double MaxStartingTime; // maximal time for start [s] (-1 means not used) + double Prop_RPM; // propeller RPM + double Velocity; + double rho; + double PSFC; // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency + + double Eng_HP; // current engine power + + double StartTime; // engine strating time [s] (0 when start button pushed) + + double ITT_Delay; // time delay for exponencial grow of ITT + double Eng_ITT_degC; + double Eng_Temperature; // temperature inside engine + + bool EngStarting; // logicaly output - TRUE if engine is starting + bool GeneratorPower; + int Condition; + + double Off(void); + double Run(void); + double SpinUp(void); + double Start(void); + + void SetDefaults(void); + bool Load(FGFDMExec *exec, Element *el); + void bindmodel(void); + void unbind(void); + void Debug(int from); + + FGTable* ITT_N1; // ITT temperature depending on throttle command + FGTable* EnginePowerRPM_N1; + FGTable* EnginePowerVC; +}; +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/models/propulsion/Makefile.am b/src/FDM/JSBSim/models/propulsion/Makefile.am new file mode 100644 index 000000000..5d2d72a9f --- /dev/null +++ b/src/FDM/JSBSim/models/propulsion/Makefile.am @@ -0,0 +1,11 @@ +noinst_LIBRARIES = libPropulsion.a + +libPropulsion_a_SOURCES = FGElectric.cpp FGEngine.cpp FGForce.cpp FGNozzle.cpp \ + FGPiston.cpp FGPropeller.cpp FGRocket.cpp FGRotor.cpp \ + FGTank.cpp FGThruster.cpp FGTurbine.cpp FGTurboProp.cpp + +noinst_HEADERS = FGElectric.h FGEngine.h FGForce.h FGNozzle.h FGPiston.h \ + FGPropeller.h FGRocket.h FGRotor.h FGTank.h FGThruster.h \ + FGTurbine.h FGTurboProp.h + +INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index d1c884fb2..484837224 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -25,6 +25,16 @@ else GFX_CODE = fg_os.cxx fg_os.hxx endif +JSBSIM_LIBS = \ + $(top_builddir)/src/FDM/JSBSim/libJSBSim.a \ + $(top_builddir)/src/FDM/JSBSim/initialization/libInit.a \ + $(top_builddir)/src/FDM/JSBSim/models/libModels.a \ + $(top_builddir)/src/FDM/JSBSim/models/flight_control/libFlightControl.a\ + $(top_builddir)/src/FDM/JSBSim/models/atmosphere/libAtmosphere.a \ + $(top_builddir)/src/FDM/JSBSim/models/propulsion/libPropulsion.a \ + $(top_builddir)/src/FDM/JSBSim/input_output/libInputOutput.a \ + $(top_builddir)/src/FDM/JSBSim/math/libMath.a + AM_CXXFLAGS = -DPKGLIBDIR=\"$(pkgdatadir)\" bin_PROGRAMS = fgfs metar @@ -63,7 +73,7 @@ fgfs_LDADD = \ $(top_builddir)/src/FDM/Balloon/libBalloon.a \ $(top_builddir)/src/FDM/ExternalNet/libExternalNet.a \ $(top_builddir)/src/FDM/ExternalPipe/libExternalPipe.a \ - $(top_builddir)/src/FDM/JSBSim/libJSBSim.a \ + $(JSBSIM_LIBS) \ $(top_builddir)/src/FDM/YASim/libYASim.a \ $(top_builddir)/src/FDM/JSBSim/filtersjb/libfiltersjb.a \ $(top_builddir)/src/FDM/LaRCsim/libLaRCsim.a \ @@ -105,4 +115,4 @@ metar_LDADD = \ -lplibnet -lplibul $(network_LIBS) \ -lz $(base_LIBS) -INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/FDM/JSBSim