1
0
Fork 0

Merge branch 'next' of gitorious.org:fg/flightgear into next

This commit is contained in:
Torsten Dreyer 2010-07-16 16:50:11 +02:00
commit 9da9364a98
145 changed files with 4237 additions and 1214 deletions

View file

@ -42,7 +42,6 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGState.h"
#include "models/FGAtmosphere.h" #include "models/FGAtmosphere.h"
#include "models/atmosphere/FGMSIS.h" #include "models/atmosphere/FGMSIS.h"
#include "models/atmosphere/FGMars.h" #include "models/atmosphere/FGMars.h"
@ -72,7 +71,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.78 2010/04/12 12:25:19 jberndt Exp $";
static const char *IdHdr = ID_FDMEXEC; static const char *IdHdr = ID_FDMEXEC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -111,7 +110,6 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
Frame = 0; Frame = 0;
Error = 0; Error = 0;
GroundCallback = 0; GroundCallback = 0;
State = 0;
Atmosphere = 0; Atmosphere = 0;
FCS = 0; FCS = 0;
Propulsion = 0; Propulsion = 0;
@ -129,11 +127,17 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
Trim = 0; Trim = 0;
Script = 0; Script = 0;
RootDir = "";
modelLoaded = false; modelLoaded = false;
IsChild = false; IsChild = false;
holding = false; holding = false;
Terminate = false; Terminate = false;
sim_time = 0.0;
dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
// run in standalone mode with no initialization file.
IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth" IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth"
FDMctr++; // instance. "child" instances are loaded last. FDMctr++; // instance. "child" instances are loaded last.
@ -169,6 +173,9 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim); instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim);
instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions); instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions);
instance->Tie("simulation/terminate", (int *)&Terminate); instance->Tie("simulation/terminate", (int *)&Terminate);
instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
Constructing = false; Constructing = false;
} }
@ -217,15 +224,11 @@ bool FGFDMExec::Allocate(void)
Auxiliary = new FGAuxiliary(this); Auxiliary = new FGAuxiliary(this);
Input = new FGInput(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
// Schedule a model. The second arg (the integer) is the pass number. For // Schedule a model. The second arg (the integer) is the pass number. For
// instance, the atmosphere model could get executed every fifth pass it is called. // instance, the atmosphere model could get executed every fifth pass it is called.
Schedule(Input, 1); Schedule(Input, 1);
Schedule(Atmosphere, 30); Schedule(Atmosphere, 1);
Schedule(FCS, 1); Schedule(FCS, 1);
Schedule(Propulsion, 1); Schedule(Propulsion, 1);
Schedule(MassBalance, 1); Schedule(MassBalance, 1);
@ -267,7 +270,6 @@ bool FGFDMExec::DeAllocate(void)
delete Aircraft; delete Aircraft;
delete Propagate; delete Propagate;
delete Auxiliary; delete Auxiliary;
delete State;
delete Script; delete Script;
for (unsigned i=0; i<Outputs.size(); i++) delete Outputs[i]; for (unsigned i=0; i<Outputs.size(); i++) delete Outputs[i];
@ -280,7 +282,6 @@ bool FGFDMExec::DeAllocate(void)
Error = 0; Error = 0;
State = 0;
Input = 0; Input = 0;
Atmosphere = 0; Atmosphere = 0;
FCS = 0; FCS = 0;
@ -324,13 +325,13 @@ bool FGFDMExec::Run(void)
} }
// returns true if success, false if complete // returns true if success, false if complete
if (Script != 0 && !State->IntegrationSuspended()) success = Script->RunScript(); if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript();
vector <FGModel*>::iterator it; vector <FGModel*>::iterator it;
for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run(); for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run();
Frame++; Frame++;
if (!Holding()) State->IncrTime(); if (!Holding()) IncrTime();
if (Terminate) success = false; if (Terminate) success = false;
return (success); return (success);
@ -341,14 +342,49 @@ bool FGFDMExec::Run(void)
bool FGFDMExec::RunIC(void) bool FGFDMExec::RunIC(void)
{ {
State->SuspendIntegration(); SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0.
State->Initialize(IC); Initialize(IC);
Run(); Run();
State->ResumeIntegration(); ResumeIntegration(); // Restores the integration rate to what it was.
return true; return true;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::Initialize(FGInitialCondition *FGIC)
{
Propagate->SetInitialState( FGIC );
Atmosphere->Run();
Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(),
FGIC->GetWindEFpsIC(),
FGIC->GetWindDFpsIC() );
FGColumnVector3 vAeroUVW;
vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED();
double alpha, beta;
if (vAeroUVW(eW) != 0.0)
alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
else
alpha = 0.0;
if (vAeroUVW(eV) != 0.0)
beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
else
beta = 0.0;
Auxiliary->SetAB(alpha, beta);
double Vt = vAeroUVW.Magnitude();
Auxiliary->SetVt(Vt);
Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed());
double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity();
Auxiliary->Setqbar(qbar);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// //
// A private, internal function call for Tie-ing to a property, so it needs an // A private, internal function call for Tie-ing to a property, so it needs an
@ -388,20 +424,6 @@ void FGFDMExec::SetGroundCallback(FGGroundCallback* p)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGFDMExec::GetSimTime(void)
{
return (State->Getsim_time());
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGFDMExec::GetDeltaT(void)
{
return (State->Getdt());
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
vector <string> FGFDMExec::EnumerateFDMs(void) vector <string> FGFDMExec::EnumerateFDMs(void)
{ {
vector <string> FDMList; vector <string> FDMList;
@ -417,12 +439,12 @@ vector <string> FGFDMExec::EnumerateFDMs(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGFDMExec::LoadScript(string script) bool FGFDMExec::LoadScript(string script, double deltaT)
{ {
bool result; bool result;
Script = new FGScript(this); Script = new FGScript(this);
result = Script->LoadScript(script); result = Script->LoadScript(RootDir + script, deltaT);
return result; return result;
} }
@ -432,9 +454,9 @@ bool FGFDMExec::LoadScript(string script)
bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string SystemsPath, bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string SystemsPath,
string model, bool addModelToPath) string model, bool addModelToPath)
{ {
FGFDMExec::AircraftPath = AircraftPath; FGFDMExec::AircraftPath = RootDir + AircraftPath;
FGFDMExec::EnginePath = EnginePath; FGFDMExec::EnginePath = RootDir + EnginePath;
FGFDMExec::SystemsPath = SystemsPath; FGFDMExec::SystemsPath = RootDir + SystemsPath;
return LoadModel(model, addModelToPath); return LoadModel(model, addModelToPath);
} }
@ -445,7 +467,6 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
{ {
string token; string token;
string aircraftCfgFileName; string aircraftCfgFileName;
string separator = "/";
Element* element = 0L; Element* element = 0L;
bool result = false; // initialize result to false, indicating input file not yet read bool result = false; // initialize result to false, indicating input file not yet read
@ -458,8 +479,8 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
} }
FullAircraftPath = AircraftPath; FullAircraftPath = AircraftPath;
if (addModelToPath) FullAircraftPath += separator + model; if (addModelToPath) FullAircraftPath += "/" + model;
aircraftCfgFileName = FullAircraftPath + separator + model + ".xml"; aircraftCfgFileName = FullAircraftPath + "/" + model + ".xml";
if (modelLoaded) { if (modelLoaded) {
DeAllocate(); DeAllocate();
@ -644,6 +665,9 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
modelLoaded = true; modelLoaded = true;
MassBalance->Run(); // Update all mass properties for the report.
MassBalance->GetMassPropertiesReport();
if (debug_lvl > 0) { if (debug_lvl > 0) {
cout << endl << fgblue << highint cout << endl << fgblue << highint
<< "End of vehicle configuration loading." << endl << "End of vehicle configuration loading." << endl
@ -893,15 +917,17 @@ bool FGFDMExec::SetOutputDirectives(string fname)
bool result; bool result;
FGOutput* Output = new FGOutput(this); FGOutput* Output = new FGOutput(this);
Output->SetDirectivesFile(fname); Output->SetDirectivesFile(RootDir + fname);
Output->InitModel(); Output->InitModel();
Schedule(Output, 1); Schedule(Output, 1);
result = Output->Load(0); result = Output->Load(0);
Outputs.push_back(Output);
typedef int (FGOutput::*iOPMF)(void) const; if (result) {
string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1); Outputs.push_back(Output);
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate); typedef int (FGOutput::*iOPMF)(void) const;
string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1);
instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate);
}
return result; return result;
} }
@ -918,11 +944,11 @@ void FGFDMExec::DoTrim(int mode)
cerr << endl << "Illegal trimming mode!" << endl << endl; cerr << endl << "Illegal trimming mode!" << endl << endl;
return; return;
} }
saved_time = State->Getsim_time(); saved_time = sim_time;
FGTrim trim(this, (JSBSim::TrimMode)mode); FGTrim trim(this, (JSBSim::TrimMode)mode);
if ( !trim.DoTrim() ) cerr << endl << "Trim Failed" << endl << endl; if ( !trim.DoTrim() ) cerr << endl << "Trim Failed" << endl << endl;
trim.Report(); trim.Report();
State->Setsim_time(saved_time); sim_time = saved_time;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -936,7 +962,7 @@ void FGFDMExec::DoTrimAnalysis(int mode)
cerr << endl << "Illegal trimming mode!" << endl << endl; cerr << endl << "Illegal trimming mode!" << endl << endl;
return; return;
} }
saved_time = State->Getsim_time(); saved_time = sim_time;
FGTrimAnalysis trimAnalysis(this, (JSBSim::TrimAnalysisMode)mode); FGTrimAnalysis trimAnalysis(this, (JSBSim::TrimAnalysisMode)mode);
@ -950,7 +976,7 @@ void FGFDMExec::DoTrimAnalysis(int mode)
if ( !result ) cerr << endl << "Trim Failed" << endl << endl; if ( !result ) cerr << endl << "Trim Failed" << endl << endl;
trimAnalysis.Report(); trimAnalysis.Report();
State->Setsim_time(saved_time); Setsim_time(saved_time);
EnableOutput(); EnableOutput();
cout << "\nOutput: " << GetOutputFileName() << endl; cout << "\nOutput: " << GetOutputFileName() << endl;
@ -1025,7 +1051,7 @@ void FGFDMExec::Debug(int from)
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
if (from == 2) { if (from == 2) {
cout << "================== Frame: " << Frame << " Time: " cout << "================== Frame: " << Frame << " Time: "
<< State->Getsim_time() << " dt: " << State->Getdt() << endl; << sim_time << " dt: " << dT << endl;
} }
} }
if (debug_lvl & 8 ) { // Runtime state variables if (debug_lvl & 8 ) { // Runtime state variables

View file

@ -60,7 +60,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FDMEXEC "$Id$" #define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.52 2010/07/04 13:50:21 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -169,7 +169,7 @@ CLASS DOCUMENTATION
property actually maps toa function call of DoTrim(). property actually maps toa function call of DoTrim().
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision$ @version $Revision: 1.52 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -270,23 +270,23 @@ public:
/** Loads a script /** Loads a script
@param Script the full path name and file name for the script to be loaded. @param Script the full path name and file name for the script to be loaded.
@return true if successfully loadsd; false otherwise. */ @return true if successfully loadsd; false otherwise. */
bool LoadScript(string Script); bool LoadScript(string Script, double deltaT);
/** Sets the path to the engine config file directories. /** Sets the path to the engine config file directories.
@param path path to the directory under which engine config @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; } bool SetEnginePath(string path) { EnginePath = RootDir + path; return true; }
/** Sets the path to the aircraft config file directories. /** Sets the path to the aircraft config file directories.
@param path path to the aircraft directory. For instance: @param path path to the aircraft directory. For instance:
"aircraft". Under aircraft, then, would be directories for various "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; } bool SetAircraftPath(string path) { AircraftPath = RootDir + path; return true; }
/** Sets the path to the systems config file directories. /** Sets the path to the systems config file directories.
@param path path to the directory under which systems config @param path path to the directory under which systems config
files are kept, for instance "systems" */ files are kept, for instance "systems" */
bool SetSystemsPath(string path) { SystemsPath = path; return true; } bool SetSystemsPath(string path) { SystemsPath = RootDir + path; return true; }
/// @name Top-level executive State and Model retrieval mechanism /// @name Top-level executive State and Model retrieval mechanism
//@{ //@{
@ -318,8 +318,6 @@ public:
inline FGInput* GetInput(void) {return Input;} inline FGInput* GetInput(void) {return Input;}
/// Returns the FGGroundCallback pointer. /// Returns the FGGroundCallback pointer.
inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;} inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;}
/// Returns the FGState pointer.
inline FGState* GetState(void) {return State;}
/// Retrieves the script object /// Retrieves the script object
inline FGScript* GetScript(void) {return Script;} inline FGScript* GetScript(void) {return Script;}
// Returns a pointer to the FGInitialCondition object // Returns a pointer to the FGInitialCondition object
@ -351,19 +349,19 @@ public:
/// Returns the model name. /// Returns the model name.
string GetModelName(void) { return modelName; } string GetModelName(void) { return modelName; }
/*
/// Returns the current time. /// Returns the current time.
double GetSimTime(void); double GetSimTime(void);
/// Returns the current frame time (delta T). /// Returns the current frame time (delta T).
double GetDeltaT(void); double GetDeltaT(void);
*/
/// Returns a pointer to the property manager object. /// Returns a pointer to the property manager object.
FGPropertyManager* GetPropertyManager(void); FGPropertyManager* GetPropertyManager(void);
/// Returns a vector of strings representing the names of all loaded models (future) /// Returns a vector of strings representing the names of all loaded models (future)
vector <string> EnumerateFDMs(void); vector <string> EnumerateFDMs(void);
/// Gets the number of child FDMs. /// Gets the number of child FDMs.
int GetFDMCount(void) {return ChildFDMList.size();} int GetFDMCount(void) {return (int)ChildFDMList.size();}
/// Gets a particular child FDM. /// Gets a particular child FDM.
childData* GetChildFDM(int i) {return ChildFDMList[i];} childData* GetChildFDM(int i) {return ChildFDMList[i];}
/// Marks this instance of the Exec object as a "child" object. /// Marks this instance of the Exec object as a "child" object.
@ -454,6 +452,8 @@ public:
// Print the contents of the property catalog for the loaded aircraft. // Print the contents of the property catalog for the loaded aircraft.
void PrintPropertyCatalog(void); void PrintPropertyCatalog(void);
vector<string>& GetPropertyCatalog(void) {return PropertyCatalog;}
/// Use the MSIS atmosphere model. /// Use the MSIS atmosphere model.
void UseAtmosphereMSIS(void); void UseAtmosphereMSIS(void);
@ -465,12 +465,61 @@ public:
void SetTrimMode(int mode){ ta_mode = mode; } void SetTrimMode(int mode){ ta_mode = mode; }
int GetTrimMode(void) const { return ta_mode; } int GetTrimMode(void) const { return ta_mode; }
/// Returns the cumulative simulation time in seconds.
double GetSimTime(void) const { return sim_time; }
/// Returns the simulation delta T.
double GetDeltaT(void) {return dT;}
/// Suspends the simulation and sets the delta T to zero.
void SuspendIntegration(void) {saved_dT = dT; dT = 0.0;}
/// Resumes the simulation by resetting delta T to the correct value.
void ResumeIntegration(void) {dT = saved_dT;}
/** Returns the simulation suspension state.
@return true if suspended, false if executing */
bool IntegrationSuspended(void) {return dT == 0.0;}
/** Sets the current sim time.
@param cur_time the current time
@return the current simulation time. */
double Setsim_time(double cur_time) {
sim_time = cur_time;
return sim_time;
}
/** Sets the integration time step for the simulation executive.
@param delta_t the time step in seconds. */
void Setdt(double delta_t) { dT = delta_t; }
/** Sets the root directory where JSBSim starts looking for its system directories.
@param rootDir the string containing the root directory. */
void SetRootDir(string rootDir) {RootDir = rootDir;}
/** Retrieves teh Root Directory.
@return the string representing the root (base) JSBSim directory. */
string GetRootDir(void) const {return RootDir;}
/** Increments the simulation time.
@return the new simulation time. */
double IncrTime(void) {
sim_time += dT;
return sim_time;
}
/** Retrieves the current debug level setting. */
int GetDebugLevel(void) const {return debug_lvl;};
private: private:
static unsigned int FDMctr; static unsigned int FDMctr;
int Error; int Error;
unsigned int Frame; unsigned int Frame;
unsigned int IdFDM; unsigned int IdFDM;
unsigned short Terminate; unsigned short Terminate;
double dT;
double saved_dT;
double sim_time;
bool holding; bool holding;
bool Constructing; bool Constructing;
bool modelLoaded; bool modelLoaded;
@ -482,6 +531,7 @@ private:
string SystemsPath; string SystemsPath;
string CFGVersion; string CFGVersion;
string Release; string Release;
string RootDir;
bool trim_status; bool trim_status;
int ta_mode; int ta_mode;
@ -489,7 +539,6 @@ private:
static FGPropertyManager *master; static FGPropertyManager *master;
FGGroundCallback* GroundCallback; FGGroundCallback* GroundCallback;
FGState* State;
FGAtmosphere* Atmosphere; FGAtmosphere* Atmosphere;
FGFCS* FCS; FGFCS* FCS;
FGPropulsion* Propulsion; FGPropulsion* Propulsion;
@ -521,6 +570,7 @@ private:
void ResetToInitialConditions(int mode); void ResetToInitialConditions(int mode);
bool Allocate(void); bool Allocate(void);
bool DeAllocate(void); bool DeAllocate(void);
void Initialize(FGInitialCondition *FGIC);
void Debug(int from); void Debug(int from);
}; };

View file

@ -44,7 +44,7 @@ INCLUDES
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.29 2010/03/18 13:19:21 jberndt Exp $";
static const char *IdHdr = ID_JSBBASE; static const char *IdHdr = ID_JSBBASE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -77,8 +77,8 @@ CLASS IMPLEMENTATION
char FGJSBBase::fgdef[6] = {'\0' }; char FGJSBBase::fgdef[6] = {'\0' };
#endif #endif
const double FGJSBBase::radtodeg = 57.29578; const double FGJSBBase::radtodeg = 57.295779513082320876798154814105;
const double FGJSBBase::degtorad = 1.745329E-2; const double FGJSBBase::degtorad = 0.017453292519943295769236907684886;
const double FGJSBBase::hptoftlbssec = 550.0; const double FGJSBBase::hptoftlbssec = 550.0;
const double FGJSBBase::psftoinhg = 0.014138; const double FGJSBBase::psftoinhg = 0.014138;
const double FGJSBBase::psftopa = 47.88; const double FGJSBBase::psftopa = 47.88;

View file

@ -63,7 +63,7 @@ namespace std
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_JSBBASE "$Id$" #define ID_JSBBASE "$Id: FGJSBBase.h,v 1.30 2010/07/01 23:13:19 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -79,7 +79,7 @@ CLASS DOCUMENTATION
* This class provides universal constants, utility functions, messaging * This class provides universal constants, utility functions, messaging
* functions, and enumerated constants to JSBSim. * functions, and enumerated constants to JSBSim.
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGJSBBase.h,v 1.30 2010/07/01 23:13:19 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -310,7 +310,7 @@ protected:
static std::queue <Message> Messages; static std::queue <Message> Messages;
void Debug(int from) {}; void Debug(int) {};
static unsigned int messageId; static unsigned int messageId;

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGState.cpp,v 1.15 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_STATE; static const char *IdHdr = ID_STATE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -62,7 +62,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_STATE "$Id$" #define ID_STATE "$Id: FGState.h,v 1.15 2009/10/02 10:30:07 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -78,7 +78,7 @@ CLASS DOCUMENTATION
<h3>Properties</h3> <h3>Properties</h3>
@property sim-time-sec (read only) cumulative simulation in seconds. @property sim-time-sec (read only) cumulative simulation in seconds.
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision$ @version $Revision: 1.15 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -5,20 +5,20 @@
// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org // Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2 of the // published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, but // This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of // WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details. // Lesser General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// //
// $Id$ // $Id: JSBSim.cxx,v 1.62 2010/07/14 05:50:40 ehofman Exp $
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -45,7 +45,6 @@
#include "JSBSim.hxx" #include "JSBSim.hxx"
#include <FDM/JSBSim/FGFDMExec.h> #include <FDM/JSBSim/FGFDMExec.h>
#include <FDM/JSBSim/FGJSBBase.h> #include <FDM/JSBSim/FGJSBBase.h>
#include <FDM/JSBSim/FGState.h>
#include <FDM/JSBSim/initialization/FGInitialCondition.h> #include <FDM/JSBSim/initialization/FGInitialCondition.h>
#include <FDM/JSBSim/initialization/FGTrim.h> #include <FDM/JSBSim/initialization/FGTrim.h>
#include <FDM/JSBSim/models/FGModel.h> #include <FDM/JSBSim/models/FGModel.h>
@ -58,6 +57,8 @@
#include <FDM/JSBSim/models/FGMassBalance.h> #include <FDM/JSBSim/models/FGMassBalance.h>
#include <FDM/JSBSim/models/FGAerodynamics.h> #include <FDM/JSBSim/models/FGAerodynamics.h>
#include <FDM/JSBSim/models/FGLGear.h> #include <FDM/JSBSim/models/FGLGear.h>
#include <FDM/JSBSim/models/FGGroundReactions.h>
#include <FDM/JSBSim/models/FGPropulsion.h>
#include <FDM/JSBSim/models/propulsion/FGEngine.h> #include <FDM/JSBSim/models/propulsion/FGEngine.h>
#include <FDM/JSBSim/models/propulsion/FGPiston.h> #include <FDM/JSBSim/models/propulsion/FGPiston.h>
#include <FDM/JSBSim/models/propulsion/FGTurbine.h> #include <FDM/JSBSim/models/propulsion/FGTurbine.h>
@ -102,7 +103,7 @@ public:
double contact[3], normal[3], vel[3], agl = 0; double contact[3], normal[3], vel[3], agl = 0;
mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal, mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
vel, &agl); vel, &agl);
n = FGColumnVector3( -normal[0], -normal[1], -normal[2] ); n = FGColumnVector3( normal[0], normal[1], normal[2] );
v = FGColumnVector3( vel[0], vel[1], vel[2] ); v = FGColumnVector3( vel[0], vel[1], vel[2] );
cont = FGColumnVector3( contact[0], contact[1], contact[2] ); cont = FGColumnVector3( contact[0], contact[1], contact[2] );
return agl; return agl;
@ -147,7 +148,6 @@ FGJSBsim::FGJSBsim( double dt )
// Register ground callback. // Register ground callback.
fdmex->SetGroundCallback( new FGFSGroundCallback(this) ); fdmex->SetGroundCallback( new FGFSGroundCallback(this) );
State = fdmex->GetState();
Atmosphere = fdmex->GetAtmosphere(); Atmosphere = fdmex->GetAtmosphere();
FCS = fdmex->GetFCS(); FCS = fdmex->GetFCS();
MassBalance = fdmex->GetMassBalance(); MassBalance = fdmex->GetMassBalance();
@ -170,7 +170,13 @@ FGJSBsim::FGJSBsim( double dt )
SGPath systems_path( fgGetString("/sim/aircraft-dir") ); SGPath systems_path( fgGetString("/sim/aircraft-dir") );
systems_path.append( "Systems" ); systems_path.append( "Systems" );
State->Setdt( dt ); // deprecate sim-time-sec for simulation/sim-time-sec
// remove alias with increased configuration file version number (2.1 or later)
SGPropertyNode * node = fgGetNode("/fdm/jsbsim/simulation/sim-time-sec");
fgGetNode("/fdm/jsbsim/sim-time-sec", true)->alias( node );
// end of sim-time-sec deprecation patch
fdmex->Setdt( dt );
result = fdmex->LoadModel( aircraft_path.str(), result = fdmex->LoadModel( aircraft_path.str(),
engine_path.str(), engine_path.str(),
@ -257,6 +263,10 @@ FGJSBsim::FGJSBsim( double dt )
speedbrake_pos_pct->setDoubleValue(0); speedbrake_pos_pct->setDoubleValue(0);
spoilers_pos_pct->setDoubleValue(0); spoilers_pos_pct->setDoubleValue(0);
ab_brake_engaged = fgGetNode("/autopilot/autobrake/engaged", true);
ab_brake_left_pct = fgGetNode("/autopilot/autobrake/brake-left-output", true);
ab_brake_right_pct = fgGetNode("/autopilot/autobrake/brake-right-output", true);
temperature = fgGetNode("/environment/temperature-degc",true); temperature = fgGetNode("/environment/temperature-degc",true);
pressure = fgGetNode("/environment/pressure-inhg",true); pressure = fgGetNode("/environment/pressure-inhg",true);
density = fgGetNode("/environment/density-slugft3",true); density = fgGetNode("/environment/density-slugft3",true);
@ -296,8 +306,6 @@ FGJSBsim::~FGJSBsim(void)
void FGJSBsim::init() void FGJSBsim::init()
{ {
double tmp;
SG_LOG( SG_FLIGHT, SG_INFO, "Starting and initializing JSBsim" ); SG_LOG( SG_FLIGHT, SG_INFO, "Starting and initializing JSBsim" );
// Explicitly call the superclass's // Explicitly call the superclass's
@ -328,6 +336,21 @@ void FGJSBsim::init()
<< ", " << fdmex->GetAtmosphere()->GetPressure() << ", " << fdmex->GetAtmosphere()->GetPressure()
<< ", " << fdmex->GetAtmosphere()->GetDensity() ); << ", " << fdmex->GetAtmosphere()->GetDensity() );
// deprecate egt_degf for egt-degf to have consistent naming
// TODO: raise log-level to ALERT in summer 2010,
// remove alias in fall 2010,
// remove this code in winter 2010
for (unsigned int i=0; i < Propulsion->GetNumEngines(); i++) {
SGPropertyNode * node = fgGetNode("engines/engine", i, true);
SGPropertyNode * egtn = node->getNode( "egt_degf" );
if( egtn != NULL ) {
SG_LOG(SG_FLIGHT,SG_WARN,
"Aircraft uses deprecated node egt_degf. Please upgrade to egt-degf");
node->getNode("egt-degf", true)->alias( egtn );
}
}
// end of egt_degf deprecation patch
if (fgGetBool("/sim/presets/running")) { if (fgGetBool("/sim/presets/running")) {
for (unsigned int i=0; i < Propulsion->GetNumEngines(); i++) { for (unsigned int i=0; i < Propulsion->GetNumEngines(); i++) {
SGPropertyNode * node = fgGetNode("engines/engine", i, true); SGPropertyNode * node = fgGetNode("engines/engine", i, true);
@ -437,7 +460,7 @@ void FGJSBsim::update( double dt )
cart = FGLocation(lon, lat, alt+slr); cart = FGLocation(lon, lat, alt+slr);
} }
double cart_pos[3] = { cart(1), cart(2), cart(3) }; double cart_pos[3] = { cart(1), cart(2), cart(3) };
double t0 = State->Getsim_time(); double t0 = fdmex->GetSimTime();
bool cache_ok = prepare_ground_cache_ft( t0, t0 + dt, cart_pos, bool cache_ok = prepare_ground_cache_ft( t0, t0 + dt, cart_pos,
groundCacheRadius ); groundCacheRadius );
if (!cache_ok) { if (!cache_ok) {
@ -465,7 +488,7 @@ void FGJSBsim::update( double dt )
if ( needTrim ) { if ( needTrim ) {
if ( startup_trim->getBoolValue() ) { if ( startup_trim->getBoolValue() ) {
double contact[3], d[3], agl; double contact[3], d[3], agl;
get_agl_ft(State->Getsim_time(), cart_pos, SG_METER_TO_FEET*2, contact, get_agl_ft(fdmex->GetSimTime(), cart_pos, SG_METER_TO_FEET*2, contact,
d, d, &agl); d, d, &agl);
double terrain_alt = sqrt(contact[0]*contact[0] + contact[1]*contact[1] double terrain_alt = sqrt(contact[0]*contact[0] + contact[1]*contact[1]
+ contact[2]*contact[2]) - fgic->GetSeaLevelRadiusFtIC(); + contact[2]*contact[2]) - fgic->GetSeaLevelRadiusFtIC();
@ -484,7 +507,7 @@ void FGJSBsim::update( double dt )
for ( i=0; i < multiloop; i++ ) { for ( i=0; i < multiloop; i++ ) {
fdmex->Run(); fdmex->Run();
update_external_forces(State->Getsim_time() + i * State->Getdt()); update_external_forces(fdmex->GetSimTime() + i * fdmex->GetDeltaT());
} }
FGJSBBase::Message* msg; FGJSBBase::Message* msg;
@ -543,6 +566,12 @@ bool FGJSBsim::copy_to_JSBsim()
double parking_brake = globals->get_controls()->get_brake_parking(); double parking_brake = globals->get_controls()->get_brake_parking();
double left_brake = globals->get_controls()->get_brake_left(); double left_brake = globals->get_controls()->get_brake_left();
double right_brake = globals->get_controls()->get_brake_right(); double right_brake = globals->get_controls()->get_brake_right();
if (ab_brake_engaged->getBoolValue()) {
left_brake = ab_brake_left_pct->getDoubleValue();
right_brake = ab_brake_right_pct->getDoubleValue();
}
FCS->SetLBrake(FMAX(left_brake, parking_brake)); FCS->SetLBrake(FMAX(left_brake, parking_brake));
FCS->SetRBrake(FMAX(right_brake, parking_brake)); FCS->SetRBrake(FMAX(right_brake, parking_brake));
@ -773,7 +802,7 @@ bool FGJSBsim::copy_from_JSBsim()
FGTurbine* eng = (FGTurbine*)Propulsion->GetEngine(i); FGTurbine* eng = (FGTurbine*)Propulsion->GetEngine(i);
node->setDoubleValue("n1", eng->GetN1()); node->setDoubleValue("n1", eng->GetN1());
node->setDoubleValue("n2", eng->GetN2()); node->setDoubleValue("n2", eng->GetN2());
node->setDoubleValue("egt_degf", 32 + eng->GetEGT()*9/5); node->setDoubleValue("egt-degf", 32 + eng->GetEGT()*9/5);
node->setBoolValue("augmentation", eng->GetAugmentation()); node->setBoolValue("augmentation", eng->GetAugmentation());
node->setBoolValue("water-injection", eng->GetInjection()); node->setBoolValue("water-injection", eng->GetInjection());
node->setBoolValue("ignition", eng->GetIgnition()); node->setBoolValue("ignition", eng->GetIgnition());
@ -817,6 +846,8 @@ bool FGJSBsim::copy_from_JSBsim()
node->setDoubleValue("rpm", eng->getRPM()); node->setDoubleValue("rpm", eng->getRPM());
} // end FGElectric code block } // end FGElectric code block
break; break;
case FGEngine::etUnknown:
break;
} }
{ // FGEngine code block { // FGEngine code block
@ -888,7 +919,7 @@ bool FGJSBsim::copy_from_JSBsim()
// force a sim crashed if crashed (altitude AGL < 0) // force a sim crashed if crashed (altitude AGL < 0)
if (get_Altitude_AGL() < -100.0) { if (get_Altitude_AGL() < -100.0) {
State->SuspendIntegration(); fdmex->SuspendIntegration();
crashed = true; crashed = true;
} }
@ -1138,9 +1169,6 @@ void FGJSBsim::do_trim(void)
} else { } else {
trimmed->setBoolValue(true); trimmed->setBoolValue(true);
} }
// if (FGJSBBase::debug_lvl > 0)
// State->ReportState();
delete fgtrim; delete fgtrim;
pitch_trim->setDoubleValue( FCS->GetPitchTrimCmd() ); pitch_trim->setDoubleValue( FCS->GetPitchTrimCmd() );
@ -1257,7 +1285,6 @@ void FGJSBsim::update_external_forces(double t_off)
FGColumnVector3 hook_tip_body = hook_root_body; FGColumnVector3 hook_tip_body = hook_root_body;
hook_tip_body(1) -= hook_length * cos_fi; hook_tip_body(1) -= hook_length * cos_fi;
hook_tip_body(3) += hook_length * sin_fi; hook_tip_body(3) += hook_length * sin_fi;
bool hook_tip_valid = true;
double contact[3]; double contact[3];
double ground_normal[3]; double ground_normal[3];

View file

@ -8,16 +8,16 @@
------ Copyright (C) 1999 - 2000 Curtis L. Olson (curt@flightgear.org) ------ ------ Copyright (C) 1999 - 2000 Curtis L. Olson (curt@flightgear.org) ------
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@ -86,7 +86,7 @@ CLASS DOCUMENTATION
documentation for main for direction on running JSBSim apart from FlightGear. documentation for main for direction on running JSBSim apart from FlightGear.
@author Curtis L. Olson (original) @author Curtis L. Olson (original)
@author Tony Peden (Maintained and refined) @author Tony Peden (Maintained and refined)
@version $Id$ @version $Id: JSBSim.hxx,v 1.13 2010/07/07 20:46:36 andgi Exp $
@see main in file JSBSim.cpp (use main() wrapper for standalone usage) @see main in file JSBSim.cpp (use main() wrapper for standalone usage)
*/ */
@ -252,6 +252,10 @@ private:
SGPropertyNode_ptr flap_pos_pct; SGPropertyNode_ptr flap_pos_pct;
SGPropertyNode_ptr speedbrake_pos_pct; SGPropertyNode_ptr speedbrake_pos_pct;
SGPropertyNode_ptr spoilers_pos_pct; SGPropertyNode_ptr spoilers_pos_pct;
SGPropertyNode_ptr ab_brake_engaged;
SGPropertyNode_ptr ab_brake_left_pct;
SGPropertyNode_ptr ab_brake_right_pct;
SGPropertyNode_ptr gear_pos_pct; SGPropertyNode_ptr gear_pos_pct;
SGPropertyNode_ptr wing_fold_pos_pct; SGPropertyNode_ptr wing_fold_pos_pct;

View file

@ -56,12 +56,13 @@ INCLUDES
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <cstdlib> #include <cstdlib>
#include "input_output/string_utilities.h"
using namespace std; using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.40 2010/06/02 04:05:13 jberndt Exp $";
static const char *IdHdr = ID_INITIALCONDITION; static const char *IdHdr = ID_INITIALCONDITION;
//****************************************************************************** //******************************************************************************
@ -704,23 +705,22 @@ double FGInitialCondition::calcVcas(double Mach) {
double psl=fdmex->GetAtmosphere()->GetPressureSL(); double psl=fdmex->GetAtmosphere()->GetPressureSL();
double rhosl=fdmex->GetAtmosphere()->GetDensitySL(); double rhosl=fdmex->GetAtmosphere()->GetDensitySL();
double pt,A,B,D,vcas; double pt,A,B,D,vcas;
if(Mach < 0) Mach=0;
if(Mach < 1) //calculate total pressure assuming isentropic flow if (Mach < 0) Mach=0;
if (Mach < 1) //calculate total pressure assuming isentropic flow
pt=p*pow((1 + 0.2*Mach*Mach),3.5); pt=p*pow((1 + 0.2*Mach*Mach),3.5);
else { else {
// shock in front of pitot tube, we'll assume its normal and use // shock in front of pitot tube, we'll assume its normal and use
// the Rayleigh Pitot Tube Formula, i.e. the ratio of total // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
// pressure behind the shock to the static pressure in front // pressure behind the shock to the static pressure in front of
// 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
//the normal shock assumption should not be a bad one -- most supersonic // most point on the aircraft. The real shock would, of course, take
//aircraft place the pitot probe out front so that it is the forward // on something like the shape of a rounded-off cone but, here again,
//most point on the aircraft. The real shock would, of course, take // the assumption should be good since the opening of the pitot probe
//on something like the shape of a rounded-off cone but, here again, // is very small and, therefore, the effects of the shock curvature
//the assumption should be good since the opening of the pitot probe // should be small as well. AFAIK, this approach is fairly well accepted
//is very small and, therefore, the effects of the shock curvature // within the aerospace community
//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); B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8);
@ -842,8 +842,6 @@ double FGInitialCondition::GetWindDirDegIC(void) const {
bool FGInitialCondition::Load(string rstfile, bool useStoredPath) bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
{ {
int n;
string sep = "/"; string sep = "/";
if( useStoredPath ) { if( useStoredPath ) {
init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml"; init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml";
@ -864,6 +862,26 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
exit(-1); exit(-1);
} }
double version = document->GetAttributeValueAsNumber("version");
if (version == HUGE_VAL) {
return Load_v1(); // Default to the old version
} else if (version >= 3.0) {
cerr << "Only initialization file formats 1 and 2 are currently supported" << endl;
exit (-1);
} else if (version >= 2.0) {
return Load_v2();
} else if (version >= 1.0) {
return Load_v1();
}
}
//******************************************************************************
bool FGInitialCondition::Load_v1(void)
{
int n;
if (document->FindElement("latitude")) if (document->FindElement("latitude"))
SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG")); SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
if (document->FindElement("longitude")) if (document->FindElement("longitude"))
@ -941,6 +959,249 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
//****************************************************************************** //******************************************************************************
bool FGInitialCondition::Load_v2(void)
{
int n;
FGColumnVector3 vLoc, vOrient;
bool result = true;
FGInertial* Inertial = fdmex->GetInertial();
FGPropagate* Propagate = fdmex->GetPropagate();
if (document->FindElement("earth_position_angle")) {
double epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD");
Inertial->SetEarthPositionAngle(epa);
}
// Initialize vehicle position
//
// Allowable frames:
// - ECI (Earth Centered Inertial)
// - ECEF (Earth Centered, Earth Fixed)
Element* position = document->FindElement("position");
if (position) {
vLoc = position->FindElementTripletConvertTo("FT");
string frame = position->GetAttributeValue("frame");
frame = to_lower(frame);
if (frame == "eci") {
// Need to transform vLoc to ECEF for storage and use in FGLocation.
vLoc = Propagate->GetTi2ec()*vLoc;
} else if (frame == "ecef") {
// Move vLoc query until after lat/lon/alt query to eliminate spurious warning msgs.
if (vLoc.Magnitude() == 0.0) {
Propagate->SetLatitudeDeg(position->FindElementValueAsNumberConvertTo("latitude", "DEG"));
Propagate->SetLongitudeDeg(position->FindElementValueAsNumberConvertTo("longitude", "DEG"));
if (position->FindElement("radius")) {
radius_to_vehicle = position->FindElementValueAsNumberConvertTo("radius", "FT");
SetAltitudeASLFtIC(radius_to_vehicle - sea_level_radius);
} else if (position->FindElement("altitudeAGL")) {
SetAltitudeAGLFtIC(position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
} else if (position->FindElement("altitudeMSL")) {
SetAltitudeASLFtIC(position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
} else {
cerr << endl << " No altitude or radius initial condition is given." << endl;
result = false;
}
}
} else {
cerr << endl << " Neither ECI nor ECEF frame is specified for initial position." << endl;
result = false;
}
} else {
cerr << endl << " Initial position not specified in this initialization file." << endl;
result = false;
}
// End of position initialization
// Initialize vehicle orientation
// Allowable frames
// - ECI (Earth Centered Inertial)
// - ECEF (Earth Centered, Earth Fixed)
// - Local
//
// Need to convert the provided orientation to an ECI orientation, using
// the given orientation and knowledge of the Earth position angle.
// This could be done using matrices (where in the subscript "b/a",
// it is meant "b with respect to a", and where b=body frame,
// i=inertial frame, and e=ecef frame) as:
//
// C_b/i = C_b/e * C_e/i
//
// Using quaternions (note reverse ordering compared to matrix representation):
//
// Q_b/i = Q_e/i * Q_b/e
//
// Use the specific matrices as needed. The above example of course is for the whole
// body to inertial orientation.
// The new orientation angles can be extracted from the matrix or the quaternion.
// ToDo: Do we need to deal with normalization of the quaternions here?
Element* orientation_el = document->FindElement("orientation");
if (orientation_el) {
string frame = orientation_el->GetAttributeValue("frame");
frame = to_lower(frame);
vOrient = orientation_el->FindElementTripletConvertTo("RAD");
FGQuaternion QuatI2Body;
if (frame == "eci") {
QuatI2Body = FGQuaternion(vOrient);
} else if (frame == "ecef") {
// In this case we are given the Euler angles representing the orientation of
// the body with respect to the ECEF system, represented by the C_b/e Matrix.
// We want the body orientation with respect to the inertial system:
//
// C_b/i = C_b/e * C_e/i
//
// Using quaternions (note reverse ordering compared to matrix representation):
//
// Q_b/i = Q_e/i * Q_b/e
FGQuaternion QuatEC2Body(vOrient); // Store relationship of Body frame wrt ECEF frame, Q_b/e
FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix
QuatI2Body = QuatI2EC * QuatEC2Body; // Q_b/i = Q_e/i * Q_b/e
} else if (frame == "local") {
// In this case, we are supplying the Euler angles for the vehicle with
// respect to the local (NED frame), also called the navigation frame.
// This is the most common way of initializing the orientation of
// aircraft. The matrix representation is:
//
// C_b/i = C_b/n * C_n/e * C_e/i
//
// Or, using quaternions (note reverse ordering compared to matrix representation):
//
// Q_b/i = Q_e/i * Q_n/e * Q_b/n
FGQuaternion QuatLocal2Body = FGQuaternion(vOrient); // Store relationship of Body frame wrt local (NED) frame, Q_b/n
FGQuaternion QuatEC2Local = Propagate->GetTec2l(); // Get Q_n/e from matrix
FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix
QuatI2Body = QuatI2EC * QuatEC2Local * QuatLocal2Body; // Q_b/i = Q_e/i * Q_n/e * Q_b/n
} else {
cerr << endl << fgred << " Orientation frame type: \"" << frame
<< "\" is not supported!" << reset << endl << endl;
result = false;
}
Propagate->SetInertialOrientation(QuatI2Body);
}
// Initialize vehicle velocity
// Allowable frames
// - ECI (Earth Centered Inertial)
// - ECEF (Earth Centered, Earth Fixed)
// - Local
// - Body
// The vehicle will be defaulted to (0,0,0) in the Body frame if nothing is provided.
Element* velocity_el = document->FindElement("velocity");
FGColumnVector3 vInertialVelocity;
FGColumnVector3 vInitVelocity = FGColumnVector3(0.0, 0.0, 0.0);
if (velocity_el) {
string frame = velocity_el->GetAttributeValue("frame");
frame = to_lower(frame);
FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo("FT/SEC");
FGColumnVector3 omega_cross_r = Inertial->omega() * Propagate->GetInertialPosition();
if (frame == "eci") {
vInertialVelocity = vInitVelocity;
} else if (frame == "ecef") {
FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e
vInertialVelocity = mTec2i * vInitVelocity + omega_cross_r;
} else if (frame == "local") {
FGMatrix33 mTl2i = Propagate->GetTl2i();
vInertialVelocity = mTl2i * vInitVelocity + omega_cross_r;
} else if (frame == "body") {
FGMatrix33 mTb2i = Propagate->GetTb2i();
vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r;
} else {
cerr << endl << fgred << " Velocity frame type: \"" << frame
<< "\" is not supported!" << reset << endl << endl;
result = false;
}
} else {
FGMatrix33 mTb2i = Propagate->GetTb2i();
vInertialVelocity = mTb2i * vInitVelocity + (Inertial->omega() * Propagate->GetInertialPosition());
}
Propagate->SetInertialVelocity(vInertialVelocity);
// Allowable frames
// - ECI (Earth Centered Inertial)
// - ECEF (Earth Centered, Earth Fixed)
// - Body
FGColumnVector3 vInertialRate;
Element* attrate_el = document->FindElement("attitude_rate");
if (attrate_el) {
string frame = attrate_el->GetAttributeValue("frame");
frame = to_lower(frame);
FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC");
if (frame == "eci") {
vInertialRate = vAttRate;
} else if (frame == "ecef") {
// vInertialRate = vAttRate + Inertial->omega();
} else if (frame == "body") {
//Todo: determine local frame rate
FGMatrix33 mTb2l = Propagate->GetTb2l();
// vInertialRate = mTb2l*vAttRate + Inertial->omega();
} else if (!frame.empty()) { // misspelling of frame
cerr << endl << fgred << " Attitude rate frame type: \"" << frame
<< "\" is not supported!" << reset << endl << endl;
result = false;
} else if (frame.empty()) {
}
} else { // Body frame attitude rate assumed 0 relative to local.
/*
//Todo: determine local frame rate
FGMatrix33 mTi2l = Propagate->GetTi2l();
vVel = mTi2l * vInertialVelocity;
// Compute the local frame ECEF velocity
vVel = Tb2l * VState.vUVW;
FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vVel(eEast),
-radInv*vVel(eNorth),
-radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
*/
}
// Check to see if any engines are specified to be initialized in a running state
FGPropulsion* propulsion = fdmex->GetPropulsion();
Element* running_elements = document->FindElement("running");
while (running_elements) {
n = int(running_elements->GetDataAsNumber());
propulsion->InitRunning(n);
running_elements = document->FindNextElement("running");
}
// fdmex->RunIC();
return result;
}
//******************************************************************************
void FGInitialCondition::bind(void){ void FGInitialCondition::bind(void){
PropertyManager->Tie("ic/vc-kts", this, PropertyManager->Tie("ic/vc-kts", this,
&FGInitialCondition::GetVcalibratedKtsIC, &FGInitialCondition::GetVcalibratedKtsIC,

View file

@ -56,7 +56,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INITIALCONDITION "$Id$" #define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.20 2010/02/15 03:22:57 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -202,7 +202,7 @@ CLASS DOCUMENTATION
@property ic/r-rad_sec (read/write) Yaw rate initial condition in radians/second @property ic/r-rad_sec (read/write) Yaw rate initial condition in radians/second
@author Tony Peden @author Tony Peden
@version "$Id$" @version "$Id: FGInitialCondition.h,v 1.20 2010/02/15 03:22:57 jberndt Exp $"
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -647,6 +647,9 @@ private:
FGFDMExec *fdmex; FGFDMExec *fdmex;
FGPropertyManager *PropertyManager; FGPropertyManager *PropertyManager;
bool Load_v1(void);
bool Load_v2(void);
bool Constructing; bool Constructing;
bool getAlpha(void); bool getAlpha(void);
bool getTheta(void); bool getTheta(void);

View file

@ -51,6 +51,8 @@ INCLUDES
#include "models/FGGroundReactions.h" #include "models/FGGroundReactions.h"
#include "models/FGInertial.h" #include "models/FGInertial.h"
#include "models/FGAerodynamics.h" #include "models/FGAerodynamics.h"
#include "models/FGPropulsion.h"
#include "models/propulsion/FGEngine.h"
#include "math/FGColumnVector3.h" #include "math/FGColumnVector3.h"
#if _MSC_VER #if _MSC_VER
@ -61,7 +63,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGTrim.cpp,v 1.13 2010/04/23 17:23:40 dpculp Exp $";
static const char *IdHdr = ID_TRIM; static const char *IdHdr = ID_TRIM;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -239,6 +241,8 @@ bool FGTrim::DoTrim(void) {
fdmex->DisableOutput(); fdmex->DisableOutput();
setEngineTrimMode(true);
fgic->SetPRadpsIC(0.0); fgic->SetPRadpsIC(0.0);
fgic->SetQRadpsIC(0.0); fgic->SetQRadpsIC(0.0);
fgic->SetRRadpsIC(0.0); fgic->SetRRadpsIC(0.0);
@ -354,6 +358,7 @@ bool FGTrim::DoTrim(void) {
for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){ for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true); fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
} }
setEngineTrimMode(false);
fdmex->EnableOutput(); fdmex->EnableOutput();
return !trim_failed; return !trim_failed;
} }
@ -620,6 +625,15 @@ void FGTrim::setDebug(void) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTrim::setEngineTrimMode(bool mode) {
FGPropulsion* prop = fdmex->GetPropulsion();
for (unsigned int i=0; i<prop->GetNumEngines(); i++) {
prop->GetEngine(i)->SetTrimMode(mode);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTrim::SetMode(TrimMode tt) { void FGTrim::SetMode(TrimMode tt) {
ClearStates(); ClearStates();
mode=tt; mode=tt;

View file

@ -60,7 +60,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TRIM "$Id$" #define ID_TRIM "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -120,7 +120,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Tony Peden @author Tony Peden
@version "$Id$" @version "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -176,7 +176,7 @@ private:
void setupTurn(void); void setupTurn(void);
void updateRates(void); void updateRates(void);
void setEngineTrimMode(bool mode);
void setDebug(void); void setDebug(void);
public: public:

View file

@ -55,7 +55,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGTrimAxis.cpp,v 1.10 2010/07/08 11:36:28 jberndt Exp $";
static const char *IdHdr = ID_TRIMAXIS; static const char *IdHdr = ID_TRIMAXIS;
/*****************************************************************************/ /*****************************************************************************/
@ -434,6 +434,10 @@ void FGTrimAxis::setThrottlesPct(void) {
/*****************************************************************************/ /*****************************************************************************/
void FGTrimAxis::AxisReport(void) { void FGTrimAxis::AxisReport(void) {
// Save original cout format characteristics
std::ios_base::fmtflags originalFormat = cout.flags();
std::streamsize originalPrecision = cout.precision();
std::streamsize originalWidth = cout.width();
cout << " " << setw(20) << GetControlName() << ": "; cout << " " << setw(20) << GetControlName() << ": ";
cout << setw(6) << setprecision(2) << GetControl()*control_convert << ' '; cout << setw(6) << setprecision(2) << GetControl()*control_convert << ' ';
cout << setw(5) << GetStateName() << ": "; cout << setw(5) << GetStateName() << ": ";
@ -444,6 +448,10 @@ void FGTrimAxis::AxisReport(void) {
cout << " Passed" << endl; cout << " Passed" << endl;
else else
cout << " Failed" << endl; cout << " Failed" << endl;
// Restore original cout format characteristics
cout.flags(originalFormat);
cout.precision(originalPrecision);
cout.width(originalWidth);
} }
/*****************************************************************************/ /*****************************************************************************/

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TRIMAXIS "$Id$" #define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.4 2006/10/01 22:47:47 jberndt Exp $"
#define DEFAULT_TOLERANCE 0.001 #define DEFAULT_TOLERANCE 0.001

View file

@ -71,10 +71,11 @@ double FGGroundCallback::GetAGLevel(double t, const FGLocation& loc,
FGColumnVector3& vel) const FGColumnVector3& vel) const
{ {
vel = FGColumnVector3(0.0, 0.0, 0.0); vel = FGColumnVector3(0.0, 0.0, 0.0);
normal = (-1/FGColumnVector3(loc).Magnitude())*FGColumnVector3(loc); normal = FGColumnVector3(loc).Normalize();
double radius = loc.GetRadius(); double loc_radius = loc.GetRadius(); // Get the radius of the given location
double agl = GetAltitude(loc); // (e.g. the CG)
contact = ((radius-agl)/radius)*FGColumnVector3(loc); double agl = loc_radius - mReferenceRadius;
contact = (mReferenceRadius/loc_radius)*FGColumnVector3(loc);
return agl; return agl;
} }

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_GROUNDCALLBACK "$Id$" #define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $"
namespace JSBSim { namespace JSBSim {
@ -59,7 +59,7 @@ CLASS DOCUMENTATION
ball formed earth. ball formed earth.
@author Mathias Froehlich @author Mathias Froehlich
@version $Id$ @version $Id: FGGroundCallback.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -152,6 +152,19 @@ string FGPropertyManager::GetFullyQualifiedName(void) {
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetRelativeName( const string &path )
{
string temp_string = GetFullyQualifiedName();
size_t len = path.length();
if ( (len > 0) && (temp_string.substr(0,len) == path) ) {
temp_string = temp_string.erase(0,len);
}
return temp_string;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -53,7 +53,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPERTYMANAGER "$Id$" #define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.17 2010/07/08 11:36:28 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -129,6 +129,15 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
*/ */
std::string GetFullyQualifiedName(void); std::string GetFullyQualifiedName(void);
/**
* Get the qualified name of a node relative to given base path,
* otherwise the fully qualified name.
* This function is very slow, so is probably useful for debugging only.
*
* @param path The path to strip off, if found.
*/
std::string GetRelativeName( const std::string &path = "/fdm/jsbsim/" );
/** /**
* Get a bool value for a property. * Get a bool value for a property.
* *

View file

@ -42,17 +42,19 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGScript.h" #include "FGScript.h"
#include "input_output/FGXMLElement.h"
#include "input_output/FGXMLParse.h" #include "input_output/FGXMLParse.h"
#include "initialization/FGTrim.h" #include "initialization/FGTrim.h"
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#include <iomanip>
using namespace std; using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGScript.cpp,v 1.41 2010/07/08 11:36:28 jberndt Exp $";
static const char *IdHdr = ID_FGSCRIPT; static const char *IdHdr = ID_FGSCRIPT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -67,8 +69,8 @@ CLASS IMPLEMENTATION
FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex) FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
{ {
State = FDMExec->GetState();
PropertyManager=FDMExec->GetPropertyManager(); PropertyManager=FDMExec->GetPropertyManager();
Debug(0); Debug(0);
} }
@ -89,7 +91,7 @@ FGScript::~FGScript()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGScript::LoadScript( string script ) bool FGScript::LoadScript(string script, double deltaT)
{ {
string aircraft="", initialize="", comparison = "", prop_name=""; string aircraft="", initialize="", comparison = "", prop_name="";
string notifyPropertyName=""; string notifyPropertyName="";
@ -135,10 +137,18 @@ bool FGScript::LoadScript( string script )
// Set sim timing // Set sim timing
StartTime = run_element->GetAttributeValueAsNumber("start"); StartTime = run_element->GetAttributeValueAsNumber("start");
State->Setsim_time(StartTime); FDMExec->Setsim_time(StartTime);
EndTime = run_element->GetAttributeValueAsNumber("end"); EndTime = run_element->GetAttributeValueAsNumber("end");
dt = run_element->GetAttributeValueAsNumber("dt");
State->Setdt(dt); if (deltaT == 0.0)
dt = run_element->GetAttributeValueAsNumber("dt");
else {
dt = deltaT;
cout << endl << "Overriding simulation step size from the command line. New step size is: "
<< deltaT << " seconds (" << 1/deltaT << " Hz)" << endl << endl;
}
FDMExec->Setdt(dt);
// read aircraft and initialization files // read aircraft and initialization files
@ -175,7 +185,7 @@ bool FGScript::LoadScript( string script )
if (output_file.empty()) { if (output_file.empty()) {
cerr << "No logging directives file was specified." << endl; cerr << "No logging directives file was specified." << endl;
} else { } else {
FDMExec->SetOutputDirectives(output_file); if (!FDMExec->SetOutputDirectives(output_file)) return false;
} }
} }
@ -226,7 +236,12 @@ bool FGScript::LoadScript( string script )
// Process the conditions // Process the conditions
condition_element = event_element->FindElement("condition"); condition_element = event_element->FindElement("condition");
if (condition_element != 0) { if (condition_element != 0) {
newCondition = new FGCondition(condition_element, PropertyManager); try {
newCondition = new FGCondition(condition_element, PropertyManager);
} catch(string str) {
cout << endl << fgred << str << reset << endl << endl;
return false;
}
newEvent->Condition = newCondition; newEvent->Condition = newCondition;
} else { } else {
cerr << "No condition specified in script event " << newEvent->Name << endl; cerr << "No condition specified in script event " << newEvent->Name << endl;
@ -320,7 +335,7 @@ bool FGScript::RunScript(void)
unsigned i, j; unsigned i, j;
unsigned event_ctr = 0; unsigned event_ctr = 0;
double currentTime = State->Getsim_time(); double currentTime = FDMExec->GetSimTime();
double newSetValue = 0; double newSetValue = 0;
if (currentTime > EndTime) return false; //Script done! if (currentTime > EndTime) return false; //Script done!
@ -409,7 +424,7 @@ bool FGScript::RunScript(void)
cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")" cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
<< " executed at time: " << currentTime << endl; << " executed at time: " << currentTime << endl;
for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) { for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
cout << " " << Events[ev_ctr].NotifyProperties[j]->GetName() cout << " " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
<< " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl; << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
} }
cout << endl; cout << endl;
@ -453,7 +468,8 @@ void FGScript::Debug(int from)
cout << endl; cout << endl;
cout << "Script: \"" << ScriptName << "\"" << endl; cout << "Script: \"" << ScriptName << "\"" << endl;
cout << " begins at " << StartTime << " seconds and runs to " << EndTime cout << " begins at " << StartTime << " seconds and runs to " << EndTime
<< " seconds with dt = " << State->Getdt() << endl; << " seconds with dt = " << setprecision(6) << FDMExec->GetDeltaT() << " (" <<
ceil(1.0/FDMExec->GetDeltaT()) << " Hz)" << endl;
cout << endl; cout << endl;
for (unsigned int i=0; i<local_properties.size(); i++) { for (unsigned int i=0; i<local_properties.size(); i++) {
@ -476,7 +492,10 @@ void FGScript::Debug(int from)
Events[i].Condition->PrintCondition(); Events[i].Condition->PrintCondition();
cout << endl << " Actions taken:" << endl << " {"; cout << endl << " Actions taken";
if (Events[i].Delay > 0.0)
cout << " (after a delay of " << Events[i].Delay << " secs)";
cout << ":" << endl << " {";
for (unsigned j=0; j<Events[i].SetValue.size(); j++) { for (unsigned j=0; j<Events[i].SetValue.size(); j++) {
if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) { if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) {
if (Events[i].SetParam[j] == 0) { if (Events[i].SetParam[j] == 0) {
@ -486,7 +505,7 @@ void FGScript::Debug(int from)
<< reset << endl; << reset << endl;
exit(-1); exit(-1);
} }
cout << endl << " set " << Events[i].SetParam[j]->GetName() cout << endl << " set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
<< " to function value"; << " to function value";
} else { } else {
if (Events[i].SetParam[j] == 0) { if (Events[i].SetParam[j] == 0) {
@ -496,7 +515,7 @@ void FGScript::Debug(int from)
<< reset << endl; << reset << endl;
exit(-1); exit(-1);
} }
cout << endl << " set " << Events[i].SetParam[j]->GetName() cout << endl << " set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
<< " to " << Events[i].SetValue[j]; << " to " << Events[i].SetValue[j];
} }
@ -529,8 +548,21 @@ void FGScript::Debug(int from)
if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP) if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP)
cout << " with time constant " << Events[i].TC[j] << ")"; cout << " with time constant " << Events[i].TC[j] << ")";
} }
cout << endl << " }" << endl << endl; cout << endl << " }" << endl;
// Print notifications
if (Events[i].Notify) {
if (Events[i].NotifyProperties.size() > 0) {
cout << " Notifications" << ":" << endl << " {" << endl;
for (unsigned j=0; j<Events[i].NotifyProperties.size();j++) {
cout << " "
<< Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/")
<< endl;
}
cout << " }" << endl;
}
}
cout << endl;
} }
} }
} }

View file

@ -38,7 +38,6 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h" #include "FGJSBBase.h"
#include "FGState.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "math/FGFunction.h" #include "math/FGFunction.h"
#include "math/FGCondition.h" #include "math/FGCondition.h"
@ -49,7 +48,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FGSCRIPT "$Id$" #define ID_FGSCRIPT "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -158,7 +157,7 @@ CLASS DOCUMENTATION
comes the &quot;run&quot; section, where the conditions are comes the &quot;run&quot; section, where the conditions are
described in &quot;event&quot; clauses.</p> described in &quot;event&quot; clauses.</p>
@author Jon S. Berndt @author Jon S. Berndt
@version "$Id$" @version "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -175,10 +174,13 @@ public:
~FGScript(); ~FGScript();
/** Loads a script to drive JSBSim (usually in standalone mode). /** Loads a script to drive JSBSim (usually in standalone mode).
The language is the Script Directives for JSBSim. The language is the Script Directives for JSBSim. If a simulation step size
has been supplied on the command line, it will be override the script-
specified simulation step size.
@param script the filename (including path name, if any) for the script. @param script the filename (including path name, if any) for the script.
@param deltaT a simulation step size from the command line
@return true if successful */ @return true if successful */
bool LoadScript( string script ); bool LoadScript(string script, double deltaT);
/** This function is called each pass through the executive Run() method IF /** This function is called each pass through the executive Run() method IF
scripting is enabled. scripting is enabled.
@ -259,7 +261,6 @@ private:
vector <LocalProps*> local_properties; vector <LocalProps*> local_properties;
FGFDMExec* FDMExec; FGFDMExec* FDMExec;
FGState* State;
FGPropertyManager* PropertyManager; FGPropertyManager* PropertyManager;
void Debug(int from); void Debug(int from);
}; };

View file

@ -42,7 +42,7 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.29 2010/03/18 13:18:31 jberndt Exp $";
static const char *IdHdr = ID_XMLELEMENT; static const char *IdHdr = ID_XMLELEMENT;
bool Element::converterIsInitialized = false; bool Element::converterIsInitialized = false;
@ -114,7 +114,10 @@ Element::Element(const string& nm)
convert["KTS"]["FT/SEC"] = 1.68781; convert["KTS"]["FT/SEC"] = 1.68781;
convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"]; convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
convert["M/S"]["FT/S"] = 3.2808399; convert["M/S"]["FT/S"] = 3.2808399;
convert["M/SEC"]["FT/SEC"] = 3.2808399;
convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"]; convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
convert["M/SEC"]["FT/SEC"] = 3.2808399;
convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"];
// Torque // Torque
convert["FT*LBS"]["N*M"] = 1.35581795; convert["FT*LBS"]["N*M"] = 1.35581795;
convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"]; convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
@ -185,6 +188,7 @@ Element::Element(const string& nm)
convert["FT/SEC"]["FT/SEC"] = 1.00; convert["FT/SEC"]["FT/SEC"] = 1.00;
convert["KTS"]["KTS"] = 1.00; convert["KTS"]["KTS"] = 1.00;
convert["M/S"]["M/S"] = 1.0; convert["M/S"]["M/S"] = 1.0;
convert["M/SEC"]["M/SEC"] = 1.0;
// Torque // Torque
convert["FT*LBS"]["FT*LBS"] = 1.00; convert["FT*LBS"]["FT*LBS"] = 1.00;
convert["N*M"]["N*M"] = 1.00; convert["N*M"]["N*M"] = 1.00;

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_XMLELEMENT "$Id$" #define ID_XMLELEMENT "$Id: FGXMLElement.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -136,7 +136,7 @@ CLASS DOCUMENTATION
- GAL = gallon (U.S. liquid) - GAL = gallon (U.S. liquid)
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGXMLElement.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -43,7 +43,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_XMLFILEREAD "$Id$" #define ID_XMLFILEREAD "$Id: FGXMLFileRead.h,v 1.5 2009/11/28 20:12:47 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -40,7 +40,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGXMLParse.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_XMLPARSE; static const char *IdHdr = ID_XMLPARSE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -40,7 +40,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_XMLPARSE "$Id$" #define ID_XMLPARSE "$Id: FGXMLParse.h,v 1.7 2009/10/24 22:59:30 jberndt Exp $"
#define VALID_CHARS """`!@#$%^&*()_+`1234567890-={}[];':,.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" #define VALID_CHARS """`!@#$%^&*()_+`1234567890-={}[];':,.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -57,7 +57,7 @@ CLASS DOCUMENTATION
/** Encapsulates an XML parser based on the EasyXML parser from the SimGear library. /** Encapsulates an XML parser based on the EasyXML parser from the SimGear library.
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGXMLParse.h,v 1.7 2009/10/24 22:59:30 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -52,7 +52,7 @@ using std::string;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGfdmSocket.cpp,v 1.27 2010/05/13 03:07:59 jberndt Exp $";
static const char *IdHdr = ID_FDMSOCKET; static const char *IdHdr = ID_FDMSOCKET;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -77,7 +77,9 @@ FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol)
cout << "Could not get host net address by name..." << endl; cout << "Could not get host net address by name..." << endl;
} }
} else { } else {
if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) { unsigned int ip;
ip = inet_addr(address.c_str());
if ((host = gethostbyaddr((char*)&ip, address.size(), PF_INET)) == NULL) {
cout << "Could not get host net address by number..." << endl; cout << "Could not get host net address by number..." << endl;
} }
} }

View file

@ -51,6 +51,7 @@ INCLUDES
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <errno.h> #include <errno.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -64,7 +65,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FDMSOCKET "$Id$" #define ID_FDMSOCKET "$Id: FGfdmSocket.h,v 1.19 2010/05/13 03:07:59 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_STRINGUTILS "$Id$" #define ID_STRINGUTILS "$Id: string_utilities.h,v 1.13 2010/07/07 11:59:48 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -64,18 +64,19 @@ CLASS DECLARATION
extern std::string& trim_left(std::string& str); extern std::string& trim_left(std::string& str);
extern std::string& trim_right(std::string& str); extern std::string& trim_right(std::string& str);
extern std::string& trim(std::string& str); extern std::string& trim(std::string& str);
extern std::string& trim_all_space(std::string& str);
extern std::string& to_upper(std::string& str); extern std::string& to_upper(std::string& str);
extern std::string& to_lower(std::string& str); extern std::string& to_lower(std::string& str);
extern bool is_number(const std::string& str); extern bool is_number(const std::string& str);
std::vector <std::string> split(std::string str, char d); std::vector <std::string> split(std::string str, char d);
#else #else
#include <ctype.h> #include <cctype>
using namespace std; using namespace std;
string& trim_left(string& str) string& trim_left(string& str)
{ {
while (str.size() && !isgraph(str[0])) { while (str.size() && isspace((unsigned char)str[0])) {
str = str.erase(0,1); str = str.erase(0,1);
} }
return str; return str;
@ -83,7 +84,7 @@ CLASS DECLARATION
string& trim_right(string& str) string& trim_right(string& str)
{ {
while (str.size() && !isgraph(str[str.size()-1])) { while (str.size() && isspace((unsigned char)str[str.size()-1])) {
str = str.erase(str.size()-1,1); str = str.erase(str.size()-1,1);
} }
return str; return str;
@ -96,6 +97,17 @@ CLASS DECLARATION
return str = trim_left(temp_str); return str = trim_left(temp_str);
} }
string& trim_all_space(string& str)
{
for (size_t i=0; i<str.size(); i++) {
if (isspace((unsigned char)str[i])) {
str = str.erase(i,1);
--i;
}
}
return str;
}
string& to_upper(string& str) string& to_upper(string& str)
{ {
for (size_t i=0; i<str.size(); i++) str[i] = toupper(str[i]); for (size_t i=0; i<str.size(); i++) str[i] = toupper(str[i]);

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGColumnVector3.cpp,v 1.12 2010/06/30 03:13:40 jberndt Exp $";
static const char *IdHdr = ID_COLUMNVECTOR3; static const char *IdHdr = ID_COLUMNVECTOR3;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -65,9 +65,9 @@ FGColumnVector3::FGColumnVector3(void)
string FGColumnVector3::Dump(const string& delimiter) const string FGColumnVector3::Dump(const string& delimiter) const
{ {
ostringstream buffer; ostringstream buffer;
buffer << std::setw(18) << std::setprecision(16) << Entry(1) << delimiter; buffer << std::setw(18) << std::setprecision(16) << data[0] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(2) << delimiter; buffer << std::setw(18) << std::setprecision(16) << data[1] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(3); buffer << std::setw(18) << std::setprecision(16) << data[2];
return buffer.str(); return buffer.str();
} }
@ -110,10 +110,10 @@ FGColumnVector3& FGColumnVector3::operator/=(const double scalar)
double FGColumnVector3::Magnitude(void) const double FGColumnVector3::Magnitude(void) const
{ {
if (Entry(1) == 0.0 && Entry(2) == 0.0 && Entry(3) == 0.0) if (data[0] == 0.0 && data[1] == 0.0 && data[2] == 0.0)
return 0.0; return 0.0;
else else
return sqrt( Entry(1)*Entry(1) + Entry(2)*Entry(2) + Entry(3)*Entry(3) ); return sqrt( data[0]*data[0] + data[1]*data[1] + data[2]*data[2] );
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_COLUMNVECTOR3 "$Id$" #define ID_COLUMNVECTOR3 "$Id: FGColumnVector3.h,v 1.12 2010/06/30 03:13:40 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -61,7 +61,7 @@ CLASS DOCUMENTATION
/** This class implements a 3 element column vector. /** This class implements a 3 element column vector.
@author Jon S. Berndt, Tony Peden, et. al. @author Jon S. Berndt, Tony Peden, et. al.
@version $Id$ @version $Id: FGColumnVector3.h,v 1.12 2010/06/30 03:13:40 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -84,7 +84,7 @@ public:
data[0] = X; data[0] = X;
data[1] = Y; data[1] = Y;
data[2] = Z; data[2] = Z;
Debug(0); // Debug(0);
} }
/** Copy constructor. /** Copy constructor.
@ -94,25 +94,25 @@ public:
data[0] = v.data[0]; data[0] = v.data[0];
data[1] = v.data[1]; data[1] = v.data[1];
data[2] = v.data[2]; data[2] = v.data[2];
Debug(0); // Debug(0);
} }
/// Destructor. /// Destructor.
~FGColumnVector3(void) { Debug(1); } ~FGColumnVector3(void) { /* Debug(1); */ }
/** Read access the entries of the vector. /** Read access the entries of the vector.
@param idx the component index. @param idx the component index.
Return the value of the matrix entry at the given index. Return the value of the matrix entry at the given index.
Indices are counted starting with 1. Indices are counted starting with 1.
Note that the index given in the argument is unchecked. */ Note that the index given in the argument is unchecked. */
double operator()(unsigned int idx) const { return Entry(idx); } double operator()(unsigned int idx) const { return data[idx-1]; }
/** Write access the entries of the vector. /** Write access the entries of the vector.
@param idx the component index. @param idx the component index.
Return a reference to the vector entry at the given index. Return a reference to the vector entry at the given index.
Indices are counted starting with 1. Indices are counted starting with 1.
Note that the index given in the argument is unchecked. */ Note that the index given in the argument is unchecked. */
double& operator()(unsigned int idx) { return Entry(idx); } double& operator()(unsigned int idx) { return data[idx-1]; }
/** Read access the entries of the vector. /** Read access the entries of the vector.
@param idx the component index. @param idx the component index.
@ -166,7 +166,7 @@ public:
@return The resulting vector from the multiplication with that scalar. @return The resulting vector from the multiplication with that scalar.
Multiply the vector with the scalar given in the argument. */ Multiply the vector with the scalar given in the argument. */
FGColumnVector3 operator*(const double scalar) const { FGColumnVector3 operator*(const double scalar) const {
return FGColumnVector3(scalar*Entry(1), scalar*Entry(2), scalar*Entry(3)); return FGColumnVector3(scalar*data[0], scalar*data[1], scalar*data[2]);
} }
/** Multiply by 1/scalar. /** Multiply by 1/scalar.
@ -181,42 +181,42 @@ public:
Compute and return the cross product of the current vector with Compute and return the cross product of the current vector with
the given argument. */ the given argument. */
FGColumnVector3 operator*(const FGColumnVector3& V) const { FGColumnVector3 operator*(const FGColumnVector3& V) const {
return FGColumnVector3( Entry(2) * V(3) - Entry(3) * V(2), return FGColumnVector3( data[1] * V(3) - data[2] * V(2),
Entry(3) * V(1) - Entry(1) * V(3), data[2] * V(1) - data[0] * V(3),
Entry(1) * V(2) - Entry(2) * V(1) ); data[0] * V(2) - data[1] * V(1) );
} }
/// Addition operator. /// Addition operator.
FGColumnVector3 operator+(const FGColumnVector3& B) const { FGColumnVector3 operator+(const FGColumnVector3& B) const {
return FGColumnVector3( Entry(1) + B(1), Entry(2) + B(2), Entry(3) + B(3) ); return FGColumnVector3( data[0] + B(1), data[1] + B(2), data[2] + B(3) );
} }
/// Subtraction operator. /// Subtraction operator.
FGColumnVector3 operator-(const FGColumnVector3& B) const { FGColumnVector3 operator-(const FGColumnVector3& B) const {
return FGColumnVector3( Entry(1) - B(1), Entry(2) - B(2), Entry(3) - B(3) ); return FGColumnVector3( data[0] - B(1), data[1] - B(2), data[2] - B(3) );
} }
/// Subtract an other vector. /// Subtract an other vector.
FGColumnVector3& operator-=(const FGColumnVector3 &B) { FGColumnVector3& operator-=(const FGColumnVector3 &B) {
Entry(1) -= B(1); data[0] -= B(1);
Entry(2) -= B(2); data[1] -= B(2);
Entry(3) -= B(3); data[2] -= B(3);
return *this; return *this;
} }
/// Add an other vector. /// Add an other vector.
FGColumnVector3& operator+=(const FGColumnVector3 &B) { FGColumnVector3& operator+=(const FGColumnVector3 &B) {
Entry(1) += B(1); data[0] += B(1);
Entry(2) += B(2); data[1] += B(2);
Entry(3) += B(3); data[2] += B(3);
return *this; return *this;
} }
/// Scale by a scalar. /// Scale by a scalar.
FGColumnVector3& operator*=(const double scalar) { FGColumnVector3& operator*=(const double scalar) {
Entry(1) *= scalar; data[0] *= scalar;
Entry(2) *= scalar; data[1] *= scalar;
Entry(3) *= scalar; data[2] *= scalar;
return *this; return *this;
} }
@ -237,7 +237,7 @@ public:
Compute and return the euclidean norm of this vector projected into Compute and return the euclidean norm of this vector projected into
the coordinate axis plane idx1-idx2. */ the coordinate axis plane idx1-idx2. */
double Magnitude(int idx1, int idx2) const { double Magnitude(int idx1, int idx2) const {
return sqrt( Entry(idx1)*Entry(idx1) + Entry(idx2)*Entry(idx2) ); return sqrt( data[idx1-1]*data[idx1-1] + data[idx2-1]*data[idx2-1] );
} }
/** Normalize. /** Normalize.
@ -245,21 +245,6 @@ public:
is equal to zero it is left untouched. */ is equal to zero it is left untouched. */
FGColumnVector3& Normalize(void); FGColumnVector3& Normalize(void);
// 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: private:
double data[3]; double data[3];

View file

@ -44,7 +44,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGCondition.cpp,v 1.13 2010/07/14 05:50:40 ehofman Exp $";
static const char *IdHdr = ID_CONDITION; static const char *IdHdr = ID_CONDITION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -122,12 +122,27 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
exit(-1); exit(-1);
} }
TestParam1 = PropertyManager->GetNode(property1, true); TestParam1 = PropertyManager->GetNode(property1, false);
if (!TestParam1) {
cerr << fgred << " In condition: " << test << ". Unknown property "
<< property1 << " referenced." << endl
<< "Creating property. Check usage." << reset << endl;
TestParam1 = PropertyManager->GetNode(property1, true);
}
Comparison = mComparison[conditional]; Comparison = mComparison[conditional];
if (Comparison == ecUndef) {
throw("Comparison operator: \""+conditional+"\" does not exist. Please check the conditional.");
}
if (is_number(property2)) { if (is_number(property2)) {
TestValue = atof(property2.c_str()); TestValue = atof(property2.c_str());
} else { } else {
TestParam2 = PropertyManager->GetNode(property2, true); TestParam2 = PropertyManager->GetNode(property2, false);
if (!TestParam2) {
cerr << fgred << " In condition: " << test << ". Unknown property "
<< property2 << " referenced." << endl
<< "Creating property. Check usage." << reset << endl;
TestParam2 = PropertyManager->GetNode(property2, true);
}
} }
} }
@ -252,9 +267,12 @@ void FGCondition::PrintCondition(void )
} else { } else {
if (TestParam2 != 0L) if (TestParam2 != 0L)
cout << " " << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName(); cout << " " << TestParam1->GetRelativeName() << " "
<< conditional << " "
<< TestParam2->GetRelativeName();
else else
cout << " " << TestParam1->GetName() << " " << conditional << " " << TestValue; cout << " " << TestParam1->GetRelativeName() << " "
<< conditional << " " << TestValue;
} }
} }

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_CONDITION "$Id$" #define ID_CONDITION "$Id: FGCondition.h,v 1.5 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGFunction.cpp,v 1.32 2010/03/18 13:21:24 jberndt Exp $";
static const char *IdHdr = ID_FUNCTION; static const char *IdHdr = ID_FUNCTION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -265,7 +265,10 @@ double FGFunction::GetValue(void) const
} }
break; break;
case eQuotient: case eQuotient:
temp /= Parameters[1]->GetValue(); if (Parameters[1]->GetValue() != 0.0)
temp /= Parameters[1]->GetValue();
else
temp = HUGE_VAL;
break; break;
case ePow: case ePow:
temp = pow(temp,Parameters[1]->GetValue()); temp = pow(temp,Parameters[1]->GetValue());

View file

@ -42,7 +42,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FUNCTION "$Id$" #define ID_FUNCTION "$Id: FGFunction.h,v 1.21 2009/11/18 04:49:02 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -45,7 +45,7 @@ INCLUDES
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGLocation.cpp,v 1.21 2010/07/02 01:48:12 jberndt Exp $";
static const char *IdHdr = ID_LOCATION; static const char *IdHdr = ID_LOCATION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -64,6 +64,19 @@ FGLocation::FGLocation(void)
e = 1.0; e = 1.0;
eps2 = -1.0; eps2 = -1.0;
f = 1.0; f = 1.0;
epa = 0.0;
mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
// initial_longitude = 0.0;
mTl2ec.InitMatrix();
mTec2l.InitMatrix();
mTi2ec.InitMatrix();
mTec2i.InitMatrix();
mTi2l.InitMatrix();
mTl2i.InitMatrix();
mECLoc.InitMatrix();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -76,7 +89,7 @@ FGLocation::FGLocation(double lon, double lat, double radius)
double cosLat = cos(lat); double cosLat = cos(lat);
double sinLon = sin(lon); double sinLon = sin(lon);
double cosLon = cos(lon); double cosLon = cos(lon);
initial_longitude = lon;
a = 0.0; a = 0.0;
b = 0.0; b = 0.0;
a2 = 0.0; a2 = 0.0;
@ -85,9 +98,15 @@ FGLocation::FGLocation(double lon, double lat, double radius)
e = 1.0; e = 1.0;
eps2 = -1.0; eps2 = -1.0;
f = 1.0; f = 1.0;
epa = 0.0;
mECLoc = FGColumnVector3( radius*cosLat*cosLon, mECLoc = FGColumnVector3( radius*cosLat*cosLon,
radius*cosLat*sinLon, radius*cosLat*sinLon,
radius*sinLat ); radius*sinLat );
mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
// initial_longitude = 0.0
ComputeDerived();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -159,7 +178,7 @@ void FGLocation::SetPosition(double lon, double lat, double radius)
double cosLat = cos(lat); double cosLat = cos(lat);
double sinLon = sin(lon); double sinLon = sin(lon);
double cosLon = cos(lon); double cosLon = cos(lon);
initial_longitude = lon; // initial_longitude = lon;
mECLoc = FGColumnVector3( radius*cosLat*cosLon, mECLoc = FGColumnVector3( radius*cosLat*cosLon,
radius*cosLat*sinLon, radius*cosLat*sinLon,
radius*sinLat ); radius*sinLat );
@ -176,7 +195,7 @@ void FGLocation::SetPositionGeodetic(double lon, double lat, double height)
mLon = lon; mLon = lon;
GeodeticAltitude = height; GeodeticAltitude = height;
initial_longitude = mLon; // initial_longitude = mLon;
double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat)); double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat));
@ -204,25 +223,23 @@ void FGLocation::SetEllipse(double semimajor, double semiminor)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Compute the ECEF to ECI transformation matrix using Stevens and Lewis "Aircraft // Compute the ECEF to ECI transformation matrix using Stevens and Lewis "Aircraft
// Control and Simulation", second edition, eqn. 1.4-12, pg. 39 // Control and Simulation", second edition, eqn. 1.4-12, pg. 39. In Stevens and Lewis
// notation, this is C_i/e, a transformation from ECEF to ECI.
const FGMatrix33& FGLocation::GetTec2i(double epa) const FGMatrix33& FGLocation::GetTec2i(void)
{ {
double mu = epa - initial_longitude;
mTec2i = FGMatrix33( cos(mu), -sin(mu), 0.0,
sin(mu), cos(mu), 0.0,
0.0, 0.0, 1.0 );
return mTec2i; return mTec2i;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This is given in Stevens and Lewis "Aircraft
// Control and Simulation", second edition, eqn. 1.4-12, pg. 39
// The notation in Stevens and Lewis is: C_e/i. This represents a transformation
// from ECI to ECEF - and the orientation of the ECEF frame relative to the ECI
// frame.
const FGMatrix33& FGLocation::GetTi2ec(double epa) const FGMatrix33& FGLocation::GetTi2ec(void)
{ {
double mu = epa - initial_longitude;
mTi2ec = FGMatrix33( cos(mu), sin(mu), 0.0,
-sin(mu), cos(mu), 0.0,
0.0, 0.0, 1.0 );
return mTi2ec; return mTi2ec;
} }
@ -235,7 +252,8 @@ void FGLocation::ComputeDerivedUnconditional(void) const
// The distance of the location to the Z-axis, which is the axis // The distance of the location to the Z-axis, which is the axis
// through the poles. // through the poles.
double rxy = sqrt(mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY)); double r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY);
double rxy = sqrt(r02);
// Compute the sin/cos values of the longitude // Compute the sin/cos values of the longitude
double sinLon, cosLon; double sinLon, cosLon;
@ -270,23 +288,42 @@ void FGLocation::ComputeDerivedUnconditional(void) const
// Compute the transform matrices from and to the earth centered frame. // Compute the transform matrices from and to the earth centered frame.
// See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, // See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
// Eqn. 1.4-13, page 40. // Eqn. 1.4-13, page 40. In Stevens and Lewis notation, this is C_n/e - the
// orientation of the navigation (local) frame relative to the ECEF frame,
// and a transformation from ECEF to nav (local) frame.
mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat, cosLat, mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat, cosLat,
-sinLon , cosLon , 0.0 , -sinLon , cosLon , 0.0 ,
-cosLon*cosLat, -sinLon*cosLat, -sinLat ); -cosLon*cosLat, -sinLon*cosLat, -sinLat );
// In Stevens and Lewis notation, this is C_e/n - the
// orientation of the ECEF frame relative to the nav (local) frame,
// and a transformation from nav (local) to ECEF frame.
mTl2ec = mTec2l.Transposed(); mTl2ec = mTec2l.Transposed();
// Calculate the inertial to ECEF and transpose matrices
double cos_epa = cos(epa);
double sin_epa = sin(epa);
mTi2ec = FGMatrix33( cos_epa, sin_epa, 0.0,
-sin_epa, cos_epa, 0.0,
0.0, 0.0, 1.0 );
mTec2i = mTi2ec.Transposed();
// Now calculate the local (or nav, or ned) frame to inertial transform matrix,
// and the inverse.
mTl2i = mTec2i * mTl2ec;
mTi2l = mTl2i.Transposed();
// Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper, // Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper,
// "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and // "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and
// "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited", // "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited",
// author: I. Sofair // author: I. Sofair
if (a != 0.0 && b != 0.0) { if (a != 0.0 && b != 0.0) {
double c, p, q, s, t, u, v, w, z, p2, u2, r02, r0; double c, p, q, s, t, u, v, w, z, p2, u2, r0;
double Ne, P, Q0, Q, signz0, sqrt_q; double Ne, P, Q0, Q, signz0, sqrt_q;
p = fabs(mECLoc(eZ))/eps2; p = fabs(mECLoc(eZ))/eps2;
r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY);
s = r02/(e2*eps2); s = r02/(e2*eps2);
p2 = p*p; p2 = p*p;
q = p2 - b2 + s; q = p2 - b2 + s;
@ -306,7 +343,7 @@ void FGLocation::ComputeDerivedUnconditional(void) const
z = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25)); z = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
Ne = a*sqrt(1+eps2*z*z/b2); Ne = a*sqrt(1+eps2*z*z/b2);
mGeodLat = asin((eps2+1.0)*(z/Ne)); mGeodLat = asin((eps2+1.0)*(z/Ne));
r0 = sqrt(r02); r0 = rxy;
GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne; GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne;
} }
} }

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_LOCATION "$Id$" #define ID_LOCATION "$Id: FGLocation.h,v 1.21 2010/07/09 04:11:45 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -60,79 +60,89 @@ namespace JSBSim {
CLASS DOCUMENTATION CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** Holds an arbitrary location in the earth centered reference frame. /** FGLocation holds an arbitrary location in the Earth centered Earth fixed
This coordinate frame has its center in the middle of the earth. reference frame (ECEF). This coordinate frame has its center in the middle
Its x-axis points from the center of the earth towards a location of the earth. The X-axis points from the center of the Earth towards a
with zero latitude and longitude on the earths surface. The y-axis location with zero latitude and longitude on the Earth surface. The Y-axis
points from the center of the earth towards a location with zero points from the center of the Earth towards a location with zero latitude
latitude and 90deg longitude on the earths surface. The z-axis and 90 deg East longitude on the Earth surface. The Z-axis points from the
points from the earths center to the geographic north pole. Earth center to the geographic north pole.
This class provides access functions to set and get the location as This class provides access functions to set and get the location as either
either the simple x, y and z values in ft or longitude/latitude and the simple X, Y and Z values in ft or longitude/latitude and the radial
the radial distance of the location from the earth center. distance of the location from the Earth center.
It is common to associate a parent frame with a location. This It is common to associate a parent frame with a location. This frame is
frame is usually called the local horizontal frame or simply the local usually called the local horizontal frame or simply the local frame. It is
frame. This frame has its x/y plane parallel to the surface of the earth also called the NED frame (North, East, Down), as well as the Navigation
(with the assumption of a spherical earth). The x-axis points frame. This frame has its X/Y plane parallel to the surface of the Earth
towards north, the y-axis points towards east and the z-axis (with the assumption of a spherical Earth). The X-axis points towards north,
points to the center of the earth. the Y-axis points east and the Z-axis points to the center of the Earth.
Since this frame is determined by the location, this class also Since the local frame is determined by the location (and NOT by the
provides the rotation matrices required to transform from the orientation of the vehicle IN any frame), this class also provides the
earth centered frame to the local horizontal frame and back. There rotation matrices required to transform from the Earth centered (ECEF) frame
are also conversion functions for conversion of position vectors to the local horizontal frame and back. This class also "owns" the
given in the one frame to positions in the other frame. transformations that go from the inertial frame (Earth-centered Inertial, or
ECI) to and from the ECEF frame, as well as to and from the local frame.
Again, this is because the ECI, ECEF, and local frames do not involve the
actual orientation of the vehicle - only the location on the Earth surface,
and the angular difference between the ECI and ECEF frames. There are
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 The Earth centered reference frame is NOT an inertial frame since it rotates
since it rotates with the earth. with the Earth.
The coordinates in the earth centered frame are the master values. The coordinates in the Earth centered frame are the master values. All other
All other values are computed from these master values and are values are computed from these master values and are cached as long as the
cached as long as the location is changed by access through a location is changed by access through a non-const member function. Values
non-const member function. Values are cached to improve performance. are cached to improve performance. It is best practice to work with a
It is best practice to work with a natural set of master values. natural set of master values. Other parameters that are derived from these
Other parameters that are derived from these master values are calculated master values are calculated only when needed, and IF they are needed and
only when needed, and IF they are needed and calculated, then they are calculated, then they are cached (stored and remembered) so they do not need
cached (stored and remembered) so they do not need to be re-calculated to be re-calculated until the master values they are derived from are
until the master values they are derived from are themselves changed themselves changed (and become stale).
(and become stale).
Accuracy and round off: Accuracy and round off
Given that we model a vehicle near the earth, the earths surface Given,
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 -that we model a vehicle near the Earth
without singularities. The singularities are the north and south -that the Earth surface radius is about 2*10^7, ft
pole and most notably the non-steady jump at -pi to pi. It is -that we use double values for the representation of the location
harder to track this jump correctly especially when we need to
work with error norms and derivatives of the equations of motion we have an accuracy of about
within the time-stepping code. Also, the rate of change is of the
same magnitude for all components in this representation which is 1e-16*2e7ft/1 = 2e-9 ft
an advantage for numerical stability in implicit time-stepping too.
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.61 deg north
122.35 deg west, which corresponds to 0.65642 rad north and 2.13541 rad
west. Both values are of magnitude of about 1. But 1 ft corresponds to about
1/(2e7*2*pi) = 7.9577e-09 rad. 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.
Note: The latitude is a GEOCENTRIC value. FlightGear The advantage of this representation is that it is a linear space without
converts latitude to a geodetic value and uses that. In order to get best singularities. The singularities are the north and south pole and most
matching relative to a map, geocentric latitude must be converted to geodetic. 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.
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 Stevens and Lewis, "Aircraft Control and Simulation", Second edition @see Stevens and Lewis, "Aircraft Control and Simulation", Second edition
@see W. C. Durham "Aircraft Dynamics & Control", section 2.2 @see W. C. Durham "Aircraft Dynamics & Control", section 2.2
@author Mathias Froehlich @author Mathias Froehlich
@version $Id$ @version $Id: FGLocation.h,v 1.21 2010/07/09 04:11:45 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -244,6 +254,13 @@ public:
and semiminor axis lengths */ and semiminor axis lengths */
void SetEllipse(double semimajor, double semiminor); void SetEllipse(double semimajor, double semiminor);
/** Sets the Earth position angle.
This is the relative orientation of the ECEF frame with respect to the
Inertial frame.
@param EPA Earth fixed frame (ECEF) rotation offset about the axis with
respect to the Inertial (ECI) frame in radians. */
void SetEarthPositionAngle(double EPA) {epa = EPA; /*mCacheValid = false;*/ ComputeDerived();}
/** Get the longitude. /** Get the longitude.
@return the longitude in rad of the location represented with this @return the longitude in rad of the location represented with this
class instance. The returned values are in the range between class instance. The returned values are in the range between
@ -309,7 +326,7 @@ public:
@return the distance of the location represented with this class @return the distance of the location represented with this class
instance to the center of the earth in ft. The radius value is instance to the center of the earth in ft. The radius value is
always positive. */ always positive. */
double GetRadius() const { ComputeDerived(); return mRadius; } double GetRadius() const { return mECLoc.Magnitude(); }
/** Transform matrix from local horizontal to earth centered frame. /** Transform matrix from local horizontal to earth centered frame.
Returns a const reference to the rotation matrix of the transform from Returns a const reference to the rotation matrix of the transform from
@ -324,12 +341,16 @@ public:
/** Transform matrix from inertial to earth centered frame. /** Transform matrix from inertial to earth centered frame.
Returns a const reference to the rotation matrix of the transform from Returns a const reference to the rotation matrix of the transform from
the inertial frame to the earth centered frame (ECI to ECEF). */ the inertial frame to the earth centered frame (ECI to ECEF). */
const FGMatrix33& GetTi2ec(double epa); const FGMatrix33& GetTi2ec(void);
/** Transform matrix from the earth centered to inertial frame. /** Transform matrix from the earth centered to inertial frame.
Returns a const reference to the rotation matrix of the transform from Returns a const reference to the rotation matrix of the transform from
the earth centered frame to the inertial frame (ECEF to ECI). */ the earth centered frame to the inertial frame (ECEF to ECI). */
const FGMatrix33& GetTec2i(double epa); const FGMatrix33& GetTec2i(void);
const FGMatrix33& GetTi2l(void) const {return mTi2l;}
const FGMatrix33& GetTl2i(void) const {return mTl2i;}
/** Conversion from Local frame coordinates to a location in the /** Conversion from Local frame coordinates to a location in the
earth centered and fixed frame. earth centered and fixed frame.
@ -354,14 +375,14 @@ public:
Return the value of the matrix entry at the given index. Return the value of the matrix entry at the given index.
Indices are counted starting with 1. Indices are counted starting with 1.
Note that the index given in the argument is unchecked. */ Note that the index given in the argument is unchecked. */
double operator()(unsigned int idx) const { return Entry(idx); } double operator()(unsigned int idx) const { return mECLoc.Entry(idx); }
/** Write access the entries of the vector. /** Write access the entries of the vector.
@param idx the component index. @param idx the component index.
@return a reference to the vector entry at the given index. @return a reference to the vector entry at the given index.
Indices are counted starting with 1. Indices are counted starting with 1.
Note that the index given in the argument is unchecked. */ Note that the index given in the argument is unchecked. */
double& operator()(unsigned int idx) { return Entry(idx); } double& operator()(unsigned int idx) { mCacheValid = false; return mECLoc.Entry(idx); }
/** Read access the entries of the vector. /** Read access the entries of the vector.
@param idx the component index. @param idx the component index.
@ -385,6 +406,12 @@ public:
mCacheValid = false; return mECLoc.Entry(idx); mCacheValid = false; return mECLoc.Entry(idx);
} }
/** Sets this location via the supplied vector.
The location can be set by an Earth-centered, Earth-fixed (ECEF) frame
position vector. The cache is marked as invalid, so any future requests
for selected important data will cause the parameters to be calculated.
@param v the ECEF column vector in feet.
@return a reference to the FGLocation object. */
const FGLocation& operator=(const FGColumnVector3& v) const FGLocation& operator=(const FGColumnVector3& v)
{ {
mECLoc(eX) = v(eX); mECLoc(eX) = v(eX);
@ -395,6 +422,9 @@ public:
return *this; return *this;
} }
/** Sets this location via the supplied location object.
@param v A location object reference.
@return a reference to the FGLocation object. */
const FGLocation& operator=(const FGLocation& l) const FGLocation& operator=(const FGLocation& l)
{ {
mECLoc = l.mECLoc; mECLoc = l.mECLoc;
@ -422,31 +452,47 @@ public:
return *this; return *this;
} }
/** This operator returns true if the ECEF location vectors for the two
location objects are equal. */
bool operator==(const FGLocation& l) const { bool operator==(const FGLocation& l) const {
return mECLoc == l.mECLoc; return mECLoc == l.mECLoc;
} }
/** This operator returns true if the ECEF location vectors for the two
location objects are not equal. */
bool operator!=(const FGLocation& l) const { return ! operator==(l); } bool operator!=(const FGLocation& l) const { return ! operator==(l); }
/** This operator adds the ECEF position vectors.
The supplied vector (right side) is added to the ECEF position vector
on the left side of the equality, and a pointer to this object is
returned. */
const FGLocation& operator+=(const FGLocation &l) { const FGLocation& operator+=(const FGLocation &l) {
mCacheValid = false; mCacheValid = false;
mECLoc += l.mECLoc; mECLoc += l.mECLoc;
return *this; return *this;
} }
const FGLocation& operator-=(const FGLocation &l) { const FGLocation& operator-=(const FGLocation &l) {
mCacheValid = false; mCacheValid = false;
mECLoc -= l.mECLoc; mECLoc -= l.mECLoc;
return *this; return *this;
} }
const FGLocation& operator*=(double scalar) { const FGLocation& operator*=(double scalar) {
mCacheValid = false; mCacheValid = false;
mECLoc *= scalar; mECLoc *= scalar;
return *this; return *this;
} }
const FGLocation& operator/=(double scalar) { const FGLocation& operator/=(double scalar) {
return operator*=(1.0/scalar); return operator*=(1.0/scalar);
} }
FGLocation operator+(const FGLocation& l) const { FGLocation operator+(const FGLocation& l) const {
return FGLocation(mECLoc + l.mECLoc); return FGLocation(mECLoc + l.mECLoc);
} }
FGLocation operator-(const FGLocation& l) const { FGLocation operator-(const FGLocation& l) const {
return FGLocation(mECLoc - l.mECLoc); return FGLocation(mECLoc - l.mECLoc);
} }
@ -500,7 +546,11 @@ private:
mutable FGMatrix33 mTec2l; mutable FGMatrix33 mTec2l;
mutable FGMatrix33 mTi2ec; mutable FGMatrix33 mTi2ec;
mutable FGMatrix33 mTec2i; mutable FGMatrix33 mTec2i;
mutable FGMatrix33 mTi2l;
mutable FGMatrix33 mTl2i;
double epa;
/* Terms for geodetic latitude calculation. Values are from WGS84 model */ /* Terms for geodetic latitude calculation. Values are from WGS84 model */
double a; // Earth semimajor axis in feet (6,378,137.0 meters) double a; // Earth semimajor axis in feet (6,378,137.0 meters)
double b; // Earth semiminor axis in feet (6,356,752.3142 meters) double b; // Earth semiminor axis in feet (6,356,752.3142 meters)

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGMatrix33.cpp,v 1.10 2010/07/01 23:13:19 jberndt Exp $";
static const char *IdHdr = ID_MATRIX33; static const char *IdHdr = ID_MATRIX33;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -70,20 +70,94 @@ FGMatrix33::FGMatrix33(void)
string FGMatrix33::Dump(const string& delimiter) const string FGMatrix33::Dump(const string& delimiter) const
{ {
ostringstream buffer; ostringstream buffer;
buffer << std::setw(18) << std::setprecision(16) << Entry(1,1) << delimiter; buffer << setw(12) << setprecision(10) << data[0] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(1,2) << delimiter; buffer << setw(12) << setprecision(10) << data[3] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(1,3) << delimiter; buffer << setw(12) << setprecision(10) << data[6] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(2,1) << delimiter; buffer << setw(12) << setprecision(10) << data[1] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(2,2) << delimiter; buffer << setw(12) << setprecision(10) << data[4] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(2,3) << delimiter; buffer << setw(12) << setprecision(10) << data[7] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(3,1) << delimiter; buffer << setw(12) << setprecision(10) << data[2] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(3,2) << delimiter; buffer << setw(12) << setprecision(10) << data[5] << delimiter;
buffer << std::setw(18) << std::setprecision(16) << Entry(3,3); buffer << setw(12) << setprecision(10) << data[8];
return buffer.str(); return buffer.str();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGMatrix33::Dump(const string& delimiter, const string& prefix) const
{
ostringstream buffer;
buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[0] << delimiter;
buffer << right << fixed << setw(9) << setprecision(6) << data[3] << delimiter;
buffer << right << fixed << setw(9) << setprecision(6) << data[6] << endl;
buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[1] << delimiter;
buffer << right << fixed << setw(9) << setprecision(6) << data[4] << delimiter;
buffer << right << fixed << setw(9) << setprecision(6) << data[7] << endl;
buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[2] << delimiter;
buffer << right << fixed << setw(9) << setprecision(6) << data[5] << delimiter;
buffer << right << fixed << setw(9) << setprecision(6) << data[8];
buffer << setw(0) << left;
return buffer.str();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGQuaternion FGMatrix33::GetQuaternion(void)
{
FGQuaternion Q;
double tempQ[4];
int idx;
tempQ[0] = 1.0 + data[0] + data[4] + data[8];
tempQ[1] = 1.0 + data[0] - data[4] - data[8];
tempQ[2] = 1.0 - data[0] + data[4] - data[8];
tempQ[3] = 1.0 - data[0] - data[4] + data[8];
// Find largest of the above
idx = 0;
for (int i=1; i<4; i++) if (tempQ[i] > tempQ[idx]) idx = i;
switch(idx) {
case 0:
Q(1) = 0.50*sqrt(tempQ[0]);
Q(2) = 0.25*(data[7] - data[5])/Q(1);
Q(3) = 0.25*(data[2] - data[6])/Q(1);
Q(4) = 0.25*(data[3] - data[1])/Q(1);
break;
case 1:
Q(2) = 0.50*sqrt(tempQ[1]);
Q(1) = 0.25*(data[7] - data[5])/Q(2);
Q(3) = 0.25*(data[3] + data[1])/Q(2);
Q(4) = 0.25*(data[2] + data[6])/Q(2);
break;
case 2:
Q(3) = 0.50*sqrt(tempQ[2]);
Q(1) = 0.25*(data[2] - data[6])/Q(3);
Q(2) = 0.25*(data[3] + data[1])/Q(3);
Q(4) = 0.25*(data[7] + data[5])/Q(3);
break;
case 3:
Q(4) = 0.50*sqrt(tempQ[3]);
Q(1) = 0.25*(data[3] - data[1])/Q(4);
Q(2) = 0.25*(data[6] + data[2])/Q(4);
Q(3) = 0.25*(data[7] + data[5])/Q(4);
break;
default:
//error
break;
}
return (Q);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ostream& operator<<(ostream& os, const FGMatrix33& M) ostream& operator<<(ostream& os, const FGMatrix33& M)
{ {
for (unsigned int i=1; i<=M.Rows(); i++) { for (unsigned int i=1; i<=M.Rows(); i++) {
@ -112,9 +186,9 @@ istream& operator>>(istream& is, FGMatrix33& M)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGMatrix33::Determinant(void) const { double FGMatrix33::Determinant(void) const {
return Entry(1,1)*Entry(2,2)*Entry(3,3) + Entry(1,2)*Entry(2,3)*Entry(3,1) return data[0]*data[4]*data[8] + data[3]*data[7]*data[2]
+ Entry(1,3)*Entry(2,1)*Entry(3,2) - Entry(1,3)*Entry(2,2)*Entry(3,1) + data[6]*data[1]*data[5] - data[6]*data[4]*data[2]
- Entry(1,2)*Entry(2,1)*Entry(3,3) - Entry(2,3)*Entry(3,2)*Entry(1,1); - data[3]*data[1]*data[8] - data[7]*data[5]*data[0];
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -123,21 +197,28 @@ FGMatrix33 FGMatrix33::Inverse(void) const {
// Compute the inverse of a general matrix using Cramers rule. // Compute the inverse of a general matrix using Cramers rule.
// I guess googling for cramers rule gives tons of references // I guess googling for cramers rule gives tons of references
// for this. :) // for this. :)
double rdet = 1.0/Determinant();
double i11 = rdet*(Entry(2,2)*Entry(3,3)-Entry(2,3)*Entry(3,2)); if (Determinant() != 0.0) {
double i21 = rdet*(Entry(2,3)*Entry(3,1)-Entry(2,1)*Entry(3,3)); double rdet = 1.0/Determinant();
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, double i11 = rdet*(data[4]*data[8]-data[7]*data[5]);
i21, i22, i23, double i21 = rdet*(data[7]*data[2]-data[1]*data[8]);
i31, i32, i33 ); double i31 = rdet*(data[1]*data[5]-data[4]*data[2]);
double i12 = rdet*(data[6]*data[5]-data[3]*data[8]);
double i22 = rdet*(data[0]*data[8]-data[6]*data[2]);
double i32 = rdet*(data[3]*data[2]-data[0]*data[5]);
double i13 = rdet*(data[3]*data[7]-data[6]*data[4]);
double i23 = rdet*(data[6]*data[1]-data[0]*data[7]);
double i33 = rdet*(data[0]*data[4]-data[3]*data[1]);
return FGMatrix33( i11, i12, i13,
i21, i22, i23,
i31, i32, i33 );
} else {
return FGMatrix33( 0, 0, 0,
0, 0, 0,
0, 0, 0 );
}
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -154,15 +235,15 @@ void FGMatrix33::InitMatrix(void)
FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const
{ {
return FGMatrix33( Entry(1,1) - M(1,1), return FGMatrix33( data[0] - M.data[0],
Entry(1,2) - M(1,2), data[3] - M.data[3],
Entry(1,3) - M(1,3), data[6] - M.data[6],
Entry(2,1) - M(2,1), data[1] - M.data[1],
Entry(2,2) - M(2,2), data[4] - M.data[4],
Entry(2,3) - M(2,3), data[7] - M.data[7],
Entry(3,1) - M(3,1), data[2] - M.data[2],
Entry(3,2) - M(3,2), data[5] - M.data[5],
Entry(3,3) - M(3,3) ); data[8] - M.data[8] );
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -186,30 +267,30 @@ FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M)
FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const
{ {
return FGMatrix33( Entry(1,1) + M(1,1), return FGMatrix33( data[0] + M.data[0],
Entry(1,2) + M(1,2), data[3] + M.data[3],
Entry(1,3) + M(1,3), data[6] + M.data[6],
Entry(2,1) + M(2,1), data[1] + M.data[1],
Entry(2,2) + M(2,2), data[4] + M.data[4],
Entry(2,3) + M(2,3), data[7] + M.data[7],
Entry(3,1) + M(3,1), data[2] + M.data[2],
Entry(3,2) + M(3,2), data[5] + M.data[5],
Entry(3,3) + M(3,3) ); data[8] + M.data[8] );
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M) FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)
{ {
Entry(1,1) += M(1,1); data[0] += M.data[0];
Entry(1,2) += M(1,2); data[3] += M.data[3];
Entry(1,3) += M(1,3); data[6] += M.data[6];
Entry(2,1) += M(2,1); data[1] += M.data[1];
Entry(2,2) += M(2,2); data[4] += M.data[4];
Entry(2,3) += M(2,3); data[7] += M.data[7];
Entry(3,1) += M(3,1); data[2] += M.data[2];
Entry(3,2) += M(3,2); data[5] += M.data[5];
Entry(3,3) += M(3,3); data[8] += M.data[8];
return *this; return *this;
} }
@ -218,19 +299,19 @@ FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)
FGMatrix33 FGMatrix33::operator*(const double scalar) const FGMatrix33 FGMatrix33::operator*(const double scalar) const
{ {
return FGMatrix33( scalar * Entry(1,1), return FGMatrix33( scalar * data[0],
scalar * Entry(1,2), scalar * data[3],
scalar * Entry(1,3), scalar * data[6],
scalar * Entry(2,1), scalar * data[1],
scalar * Entry(2,2), scalar * data[4],
scalar * Entry(2,3), scalar * data[7],
scalar * Entry(3,1), scalar * data[2],
scalar * Entry(3,2), scalar * data[5],
scalar * Entry(3,3) ); scalar * data[8] );
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
FGMatrix33 operator*(double scalar, FGMatrix33 &M) FGMatrix33 operator*(double scalar, FGMatrix33 &M)
{ {
return FGMatrix33( scalar * M(1,1), return FGMatrix33( scalar * M(1,1),
@ -243,20 +324,20 @@ FGMatrix33 operator*(double scalar, FGMatrix33 &M)
scalar * M(3,2), scalar * M(3,2),
scalar * M(3,3) ); scalar * M(3,3) );
} }
*/
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGMatrix33& FGMatrix33::operator*=(const double scalar) FGMatrix33& FGMatrix33::operator*=(const double scalar)
{ {
Entry(1,1) *= scalar; data[0] *= scalar;
Entry(1,2) *= scalar; data[3] *= scalar;
Entry(1,3) *= scalar; data[6] *= scalar;
Entry(2,1) *= scalar; data[1] *= scalar;
Entry(2,2) *= scalar; data[4] *= scalar;
Entry(2,3) *= scalar; data[7] *= scalar;
Entry(3,1) *= scalar; data[2] *= scalar;
Entry(3,2) *= scalar; data[5] *= scalar;
Entry(3,3) *= scalar; data[8] *= scalar;
return *this; return *this;
} }
@ -265,18 +346,17 @@ FGMatrix33& FGMatrix33::operator*=(const double scalar)
FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const
{ {
// FIXME: Make compiler friendlier
FGMatrix33 Product; FGMatrix33 Product;
Product(1,1) = Entry(1,1)*M(1,1) + Entry(1,2)*M(2,1) + Entry(1,3)*M(3,1); Product.data[0] = data[0]*M.data[0] + data[3]*M.data[1] + data[6]*M.data[2];
Product(1,2) = Entry(1,1)*M(1,2) + Entry(1,2)*M(2,2) + Entry(1,3)*M(3,2); Product.data[3] = data[0]*M.data[3] + data[3]*M.data[4] + data[6]*M.data[5];
Product(1,3) = Entry(1,1)*M(1,3) + Entry(1,2)*M(2,3) + Entry(1,3)*M(3,3); Product.data[6] = data[0]*M.data[6] + data[3]*M.data[7] + data[6]*M.data[8];
Product(2,1) = Entry(2,1)*M(1,1) + Entry(2,2)*M(2,1) + Entry(2,3)*M(3,1); Product.data[1] = data[1]*M.data[0] + data[4]*M.data[1] + data[7]*M.data[2];
Product(2,2) = Entry(2,1)*M(1,2) + Entry(2,2)*M(2,2) + Entry(2,3)*M(3,2); Product.data[4] = data[1]*M.data[3] + data[4]*M.data[4] + data[7]*M.data[5];
Product(2,3) = Entry(2,1)*M(1,3) + Entry(2,2)*M(2,3) + Entry(2,3)*M(3,3); Product.data[7] = data[1]*M.data[6] + data[4]*M.data[7] + data[7]*M.data[8];
Product(3,1) = Entry(3,1)*M(1,1) + Entry(3,2)*M(2,1) + Entry(3,3)*M(3,1); Product.data[2] = data[2]*M.data[0] + data[5]*M.data[1] + data[8]*M.data[2];
Product(3,2) = Entry(3,1)*M(1,2) + Entry(3,2)*M(2,2) + Entry(3,3)*M(3,2); Product.data[5] = data[2]*M.data[3] + data[5]*M.data[4] + data[8]*M.data[5];
Product(3,3) = Entry(3,1)*M(1,3) + Entry(3,2)*M(2,3) + Entry(3,3)*M(3,3); Product.data[8] = data[2]*M.data[6] + data[5]*M.data[7] + data[8]*M.data[8];
return Product; return Product;
} }
@ -288,20 +368,20 @@ FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M)
// FIXME: Make compiler friendlier // FIXME: Make compiler friendlier
double a,b,c; double a,b,c;
a = Entry(1,1); b=Entry(1,2); c=Entry(1,3); a = data[0]; b=data[3]; c=data[6];
Entry(1,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); data[0] = a*M.data[0] + b*M.data[1] + c*M.data[2];
Entry(1,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); data[3] = a*M.data[3] + b*M.data[4] + c*M.data[5];
Entry(1,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); data[6] = a*M.data[6] + b*M.data[7] + c*M.data[8];
a = Entry(2,1); b=Entry(2,2); c=Entry(2,3); a = data[1]; b=data[4]; c=data[7];
Entry(2,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); data[1] = a*M.data[0] + b*M.data[1] + c*M.data[2];
Entry(2,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); data[4] = a*M.data[3] + b*M.data[4] + c*M.data[5];
Entry(2,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); data[7] = a*M.data[6] + b*M.data[7] + c*M.data[8];
a = Entry(3,1); b=Entry(3,2); c=Entry(3,3); a = data[2]; b=data[5]; c=data[8];
Entry(3,1) = a*M(1,1) + b*M(2,1) + c*M(3,1); data[2] = a*M.data[0] + b*M.data[1] + c*M.data[2];
Entry(3,2) = a*M(1,2) + b*M(2,2) + c*M(3,2); data[5] = a*M.data[3] + b*M.data[4] + c*M.data[5];
Entry(3,3) = a*M(1,3) + b*M(2,3) + c*M(3,3); data[8] = a*M.data[6] + b*M.data[7] + c*M.data[8];
return *this; return *this;
} }
@ -314,15 +394,15 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const
if ( scalar != 0 ) { if ( scalar != 0 ) {
double tmp = 1.0/scalar; double tmp = 1.0/scalar;
Quot(1,1) = Entry(1,1) * tmp; Quot.data[0] = data[0] * tmp;
Quot(1,2) = Entry(1,2) * tmp; Quot.data[3] = data[3] * tmp;
Quot(1,3) = Entry(1,3) * tmp; Quot.data[6] = data[6] * tmp;
Quot(2,1) = Entry(2,1) * tmp; Quot.data[1] = data[1] * tmp;
Quot(2,2) = Entry(2,2) * tmp; Quot.data[4] = data[4] * tmp;
Quot(2,3) = Entry(2,3) * tmp; Quot.data[7] = data[7] * tmp;
Quot(3,1) = Entry(3,1) * tmp; Quot.data[2] = data[2] * tmp;
Quot(3,2) = Entry(3,2) * tmp; Quot.data[5] = data[5] * tmp;
Quot(3,3) = Entry(3,3) * tmp; Quot.data[8] = data[8] * tmp;
} else { } else {
MatrixException mE; MatrixException mE;
mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"; mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)";
@ -337,15 +417,15 @@ FGMatrix33& FGMatrix33::operator/=(const double scalar)
{ {
if ( scalar != 0 ) { if ( scalar != 0 ) {
double tmp = 1.0/scalar; double tmp = 1.0/scalar;
Entry(1,1) *= tmp; data[0] *= tmp;
Entry(1,2) *= tmp; data[3] *= tmp;
Entry(1,3) *= tmp; data[6] *= tmp;
Entry(2,1) *= tmp; data[1] *= tmp;
Entry(2,2) *= tmp; data[4] *= tmp;
Entry(2,3) *= tmp; data[7] *= tmp;
Entry(3,1) *= tmp; data[2] *= tmp;
Entry(3,2) *= tmp; data[5] *= tmp;
Entry(3,3) *= tmp; data[8] *= tmp;
} else { } else {
MatrixException mE; MatrixException mE;
mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"; mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)";
@ -358,29 +438,40 @@ FGMatrix33& FGMatrix33::operator/=(const double scalar)
void FGMatrix33::T(void) void FGMatrix33::T(void)
{ {
for (unsigned int i=1; i<=3; i++) { double tmp;
for (unsigned int j=i+1; j<=3; j++) {
double tmp = Entry(i,j); tmp = data[3];
Entry(i,j) = Entry(j,i); data[3] = data[1];
Entry(j,i) = tmp; data[1] = tmp;
}
} tmp = data[6];
data[6] = data[2];
data[2] = tmp;
tmp = data[7];
data[7] = data[5];
data[5] = tmp;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const { FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const
double tmp1 = v(1)*Entry(1,1); {
double tmp2 = v(1)*Entry(2,1); double v1 = v(1);
double tmp3 = v(1)*Entry(3,1); double v2 = v(2);
double v3 = v(3);
tmp1 += v(2)*Entry(1,2); double tmp1 = v1*data[0]; //[(col-1)*eRows+row-1]
tmp2 += v(2)*Entry(2,2); double tmp2 = v1*data[1];
tmp3 += v(2)*Entry(3,2); double tmp3 = v1*data[2];
tmp1 += v(3)*Entry(1,3); tmp1 += v2*data[3];
tmp2 += v(3)*Entry(2,3); tmp2 += v2*data[4];
tmp3 += v(3)*Entry(3,3); tmp3 += v2*data[5];
tmp1 += v3*data[6];
tmp2 += v3*data[7];
tmp3 += v3*data[8];
return FGColumnVector3( tmp1, tmp2, tmp3 ); return FGColumnVector3( tmp1, tmp2, tmp3 );
} }

View file

@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MATRIX33 "$Id$" #define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.11 2010/06/30 03:13:40 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -59,6 +59,7 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
class FGColumnVector3; class FGColumnVector3;
class FGQuaternion;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION CLASS DOCUMENTATION
@ -111,17 +112,17 @@ public:
Create copy of the matrix given in the argument. Create copy of the matrix given in the argument.
*/ */
FGMatrix33(const FGMatrix33& M) { FGMatrix33(const FGMatrix33& M) {
Entry(1,1) = M.Entry(1,1); data[0] = M.data[0];
Entry(2,1) = M.Entry(2,1); data[1] = M.data[1];
Entry(3,1) = M.Entry(3,1); data[2] = M.data[2];
Entry(1,2) = M.Entry(1,2); data[3] = M.data[3];
Entry(2,2) = M.Entry(2,2); data[4] = M.data[4];
Entry(3,2) = M.Entry(3,2); data[5] = M.data[5];
Entry(1,3) = M.Entry(1,3); data[6] = M.data[6];
Entry(2,3) = M.Entry(2,3); data[7] = M.data[7];
Entry(3,3) = M.Entry(3,3); data[8] = M.data[8];
Debug(0); // Debug(0);
} }
/** Initialization by given values. /** Initialization by given values.
@ -141,28 +142,34 @@ public:
FGMatrix33(double m11, double m12, double m13, FGMatrix33(double m11, double m12, double m13,
double m21, double m22, double m23, double m21, double m22, double m23,
double m31, double m32, double m33) { double m31, double m32, double m33) {
Entry(1,1) = m11; data[0] = m11;
Entry(2,1) = m21; data[1] = m21;
Entry(3,1) = m31; data[2] = m31;
Entry(1,2) = m12; data[3] = m12;
Entry(2,2) = m22; data[4] = m22;
Entry(3,2) = m32; data[5] = m32;
Entry(1,3) = m13; data[6] = m13;
Entry(2,3) = m23; data[7] = m23;
Entry(3,3) = m33; data[8] = m33;
Debug(0); // Debug(0);
} }
/** Destructor. /** Destructor.
*/ */
~FGMatrix33(void) { Debug(1); } ~FGMatrix33(void) { /* Debug(1); */ }
/** Prints the contents of the matrix. /** Prints the contents of the matrix.
@param delimeter the item separator (tab or comma) @param delimeter the item separator (tab or comma)
@return a string with the delimeter-separated contents of the matrix */ @return a string with the delimeter-separated contents of the matrix */
std::string Dump(const std::string& delimeter) const; std::string Dump(const std::string& delimeter) const;
/** Prints the contents of the matrix.
@param delimeter the item separator (tab or comma, etc.)
@param prefix an additional prefix that is used to indent the 3X3 matrix printout
@return a string with the delimeter-separated contents of the matrix */
std::string Dump(const std::string& delimiter, const std::string& prefix) const;
/** Read access the entries of the matrix. /** Read access the entries of the matrix.
@param row Row index. @param row Row index.
@param col Column index. @param col Column index.
@ -171,7 +178,7 @@ public:
column indices. Indices are counted starting with 1. column indices. Indices are counted starting with 1.
*/ */
double operator()(unsigned int row, unsigned int col) const { double operator()(unsigned int row, unsigned int col) const {
return Entry(row, col); return data[(col-1)*eRows+row-1];
} }
/** Write access the entries of the matrix. /** Write access the entries of the matrix.
@ -184,7 +191,7 @@ public:
column indices. Indices are counted starting with 1. column indices. Indices are counted starting with 1.
*/ */
double& operator()(unsigned int row, unsigned int col) { double& operator()(unsigned int row, unsigned int col) {
return Entry(row, col); return data[(col-1)*eRows+row-1];
} }
/** Read access the entries of the matrix. /** Read access the entries of the matrix.
@ -237,9 +244,9 @@ public:
@return the transposed matrix. @return the transposed matrix.
*/ */
FGMatrix33 Transposed(void) const { FGMatrix33 Transposed(void) const {
return FGMatrix33( Entry(1,1), Entry(2,1), Entry(3,1), return FGMatrix33( data[0], data[1], data[2],
Entry(1,2), Entry(2,2), Entry(3,2), data[3], data[4], data[5],
Entry(1,3), Entry(2,3), Entry(3,3) ); data[6], data[7], data[8] );
} }
/** Transposes this matrix. /** Transposes this matrix.
@ -258,17 +265,21 @@ public:
void InitMatrix(double m11, double m12, double m13, void InitMatrix(double m11, double m12, double m13,
double m21, double m22, double m23, double m21, double m22, double m23,
double m31, double m32, double m33) { double m31, double m32, double m33) {
Entry(1,1) = m11; data[0] = m11;
Entry(2,1) = m21; data[1] = m21;
Entry(3,1) = m31; data[2] = m31;
Entry(1,2) = m12; data[3] = m12;
Entry(2,2) = m22; data[4] = m22;
Entry(3,2) = m32; data[5] = m32;
Entry(1,3) = m13; data[6] = m13;
Entry(2,3) = m23; data[7] = m23;
Entry(3,3) = m33; data[8] = m33;
} }
/** Returns the quaternion associated with this direction cosine (rotation) matrix.
*/
FGQuaternion GetQuaternion(void);
/** Determinant of the matrix. /** Determinant of the matrix.
@return the determinant of the matrix. @return the determinant of the matrix.
*/ */
@ -458,4 +469,6 @@ std::istream& operator>>(std::istream& is, FGMatrix33& M);
} // namespace JSBSim } // namespace JSBSim
#include "FGQuaternion.h"
#endif #endif

View file

@ -40,7 +40,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PARAMETER "$Id$" #define ID_PARAMETER "$Id: FGParameter.h,v 1.5 2009/08/30 03:51:28 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -32,7 +32,7 @@ INCLUDES
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.4 2009/08/30 03:51:28 jberndt Exp $";
static const char *IdHdr = ID_PROPERTYVALUE; static const char *IdHdr = ID_PROPERTYVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -41,7 +41,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPERTYVALUE "$Id$" #define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.6 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -40,6 +40,7 @@ SENTRY
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <iomanip>
#include <cmath> #include <cmath>
using std::cerr; using std::cerr;
using std::cout; using std::cout;
@ -56,18 +57,18 @@ using std::endl;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGQuaternion.cpp,v 1.16 2010/06/30 03:13:40 jberndt Exp $";
static const char *IdHdr = ID_QUATERNION; static const char *IdHdr = ID_QUATERNION;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Initialize from q // Initialize from q
FGQuaternion::FGQuaternion(const FGQuaternion& q) FGQuaternion::FGQuaternion(const FGQuaternion& q) : mCacheValid(q.mCacheValid)
: mCacheValid(q.mCacheValid) { {
Entry(1) = q(1); data[0] = q(1);
Entry(2) = q(2); data[1] = q(2);
Entry(3) = q(3); data[2] = q(3);
Entry(4) = q(4); data[3] = q(4);
if (mCacheValid) { if (mCacheValid) {
mT = q.mT; mT = q.mT;
mTInv = q.mTInv; mTInv = q.mTInv;
@ -80,8 +81,36 @@ FGQuaternion::FGQuaternion(const FGQuaternion& q)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Initialize with the three euler angles // Initialize with the three euler angles
FGQuaternion::FGQuaternion(double phi, double tht, double psi) FGQuaternion::FGQuaternion(double phi, double tht, double psi): mCacheValid(false)
: mCacheValid(false) { {
InitializeFromEulerAngles(phi, tht, psi);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGQuaternion::FGQuaternion(FGColumnVector3 vOrient): mCacheValid(false)
{
double phi = vOrient(ePhi);
double tht = vOrient(eTht);
double psi = vOrient(ePsi);
InitializeFromEulerAngles(phi, tht, psi);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// This function computes the quaternion that describes the relationship of the
// body frame with respect to another frame, such as the ECI or ECEF frames. The
// Euler angles used represent a 3-2-1 (psi, theta, phi) rotation sequence from
// the reference frame to the body frame. See "Quaternions and Rotation
// Sequences", Jack B. Kuipers, sections 9.2 and 7.6.
void FGQuaternion::InitializeFromEulerAngles(double phi, double tht, double psi)
{
mEulerAngles(ePhi) = phi;
mEulerAngles(eTht) = tht;
mEulerAngles(ePsi) = psi;
double thtd2 = 0.5*tht; double thtd2 = 0.5*tht;
double psid2 = 0.5*psi; double psid2 = 0.5*psi;
double phid2 = 0.5*phi; double phid2 = 0.5*phi;
@ -99,10 +128,27 @@ FGQuaternion::FGQuaternion(double phi, double tht, double psi)
double Sphid2Sthtd2 = Sphid2*Sthtd2; double Sphid2Sthtd2 = Sphid2*Sthtd2;
double Sphid2Cthtd2 = Sphid2*Cthtd2; double Sphid2Cthtd2 = Sphid2*Cthtd2;
Entry(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2; data[0] = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2;
Entry(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2; data[1] = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2;
Entry(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2; data[2] = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2;
Entry(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2; data[3] = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2;
Normalize();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Initialize with a direction cosine (rotation) matrix
FGQuaternion::FGQuaternion(const FGMatrix33& m) : mCacheValid(false)
{
data[0] = 0.50*sqrt(1.0 + m(1,1) + m(2,2) + m(3,3));
double t = 0.25/data[0];
data[1] = t*(m(2,3) - m(3,2));
data[2] = t*(m(3,1) - m(1,3));
data[3] = t*(m(1,2) - m(2,1));
ComputeDerivedUnconditional();
Normalize();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -111,37 +157,32 @@ FGQuaternion::FGQuaternion(double phi, double tht, double psi)
angular velocities PQR. angular velocities PQR.
See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
Equation 1.3-36. Equation 1.3-36.
Also see Jack Kuipers, "Quaternions and Rotation Sequences", Equation 11.12.
*/ */
FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR) const { FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR)
double norm = Magnitude(); {
if (norm == 0.0) return FGQuaternion(
return FGQuaternion::zero(); -0.5*( data[1]*PQR(eP) + data[2]*PQR(eQ) + data[3]*PQR(eR)),
double rnorm = 1.0/norm; 0.5*( data[0]*PQR(eP) - data[3]*PQR(eQ) + data[2]*PQR(eR)),
0.5*( data[3]*PQR(eP) + data[0]*PQR(eQ) - data[1]*PQR(eR)),
FGQuaternion QDot; 0.5*(-data[2]*PQR(eP) + data[1]*PQR(eQ) + data[0]*PQR(eR))
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() void FGQuaternion::Normalize()
{ {
// Note: this does not touch the cache // Note: this does not touch the cache since it does not change the orientation
// since it does not change the orientation ...
double norm = Magnitude(); double norm = Magnitude();
if (norm == 0.0) if (norm == 0.0 || fabs(norm - 1.000) < 1e-10) return;
return;
double rnorm = 1.0/norm; double rnorm = 1.0/norm;
Entry(1) *= rnorm;
Entry(2) *= rnorm; data[0] *= rnorm;
Entry(3) *= rnorm; data[1] *= rnorm;
Entry(4) *= rnorm; data[2] *= rnorm;
data[3] *= rnorm;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -150,45 +191,42 @@ void FGQuaternion::Normalize()
void FGQuaternion::ComputeDerivedUnconditional(void) const void FGQuaternion::ComputeDerivedUnconditional(void) const
{ {
mCacheValid = true; mCacheValid = true;
// First normalize the 4-vector
double norm = Magnitude();
if (norm == 0.0)
return;
double rnorm = 1.0/norm; double q0 = data[0]; // use some aliases/shorthand for the quat elements.
double q1 = rnorm*Entry(1); double q1 = data[1];
double q2 = rnorm*Entry(2); double q2 = data[2];
double q3 = rnorm*Entry(3); double q3 = data[3];
double q4 = rnorm*Entry(4);
// Now compute the transformation matrix. // Now compute the transformation matrix.
double q0q0 = q0*q0;
double q1q1 = q1*q1; double q1q1 = q1*q1;
double q2q2 = q2*q2; double q2q2 = q2*q2;
double q3q3 = q3*q3; double q3q3 = q3*q3;
double q4q4 = q4*q4; double q0q1 = q0*q1;
double q0q2 = q0*q2;
double q0q3 = q0*q3;
double q1q2 = q1*q2; double q1q2 = q1*q2;
double q1q3 = q1*q3; double q1q3 = q1*q3;
double q1q4 = q1*q4;
double q2q3 = q2*q3; double q2q3 = q2*q3;
double q2q4 = q2*q4;
double q3q4 = q3*q4;
mT(1,1) = q1q1 + q2q2 - q3q3 - q4q4; mT(1,1) = q0q0 + q1q1 - q2q2 - q3q3; // This is found from Eqn. 1.3-32 in
mT(1,2) = 2.0*(q2q3 + q1q4); mT(1,2) = 2.0*(q1q2 + q0q3); // Stevens and Lewis
mT(1,3) = 2.0*(q2q4 - q1q3); mT(1,3) = 2.0*(q1q3 - q0q2);
mT(2,1) = 2.0*(q2q3 - q1q4); mT(2,1) = 2.0*(q1q2 - q0q3);
mT(2,2) = q1q1 - q2q2 + q3q3 - q4q4; mT(2,2) = q0q0 - q1q1 + q2q2 - q3q3;
mT(2,3) = 2.0*(q3q4 + q1q2); mT(2,3) = 2.0*(q2q3 + q0q1);
mT(3,1) = 2.0*(q2q4 + q1q3); mT(3,1) = 2.0*(q1q3 + q0q2);
mT(3,2) = 2.0*(q3q4 - q1q2); mT(3,2) = 2.0*(q2q3 - q0q1);
mT(3,3) = q1q1 - q2q2 - q3q3 + q4q4; mT(3,3) = q0q0 - q1q1 - q2q2 + q3q3;
// Since this is an orthogonal matrix, the inverse is simply
// the transpose. // Since this is an orthogonal matrix, the inverse is simply the transpose.
mTInv = mT; mTInv = mT;
mTInv.T(); mTInv.T();
// Compute the Euler-angles // Compute the Euler-angles
// Also see Jack Kuipers, "Quaternions and Rotation Sequences", section 7.8..
if (mT(3,3) == 0.0) if (mT(3,3) == 0.0)
mEulerAngles(ePhi) = 0.5*M_PI; mEulerAngles(ePhi) = 0.5*M_PI;
else else
@ -218,6 +256,55 @@ void FGQuaternion::ComputeDerivedUnconditional(void) const
mEulerCosines(ePhi) = cos(mEulerAngles(ePhi)); mEulerCosines(ePhi) = cos(mEulerAngles(ePhi));
mEulerCosines(eTht) = cos(mEulerAngles(eTht)); mEulerCosines(eTht) = cos(mEulerAngles(eTht));
mEulerCosines(ePsi) = cos(mEulerAngles(ePsi)); mEulerCosines(ePsi) = cos(mEulerAngles(ePsi));
// Debug(2);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 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 FGQuaternion::Debug(int from) const
{
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: FGQuaternion" << endl;
if (from == 1) cout << "Destroyed: FGQuaternion" << 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 (!EqualToRoundoff(Magnitude(), 1.0)) {
cout << "Quaternion magnitude differs from 1.0 !" << endl;
cout << "\tdelta from 1.0: " << std::scientific << Magnitude()-1.0 << endl;
}
}
if (debug_lvl & 64) {
if (from == 0) { // Constructor
cout << IdSrc << endl;
cout << IdHdr << endl;
}
}
} }
} // namespace JSBSim } // namespace JSBSim

View file

@ -41,18 +41,18 @@ SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h" #include "FGJSBBase.h"
#include "FGMatrix33.h"
#include "FGColumnVector3.h" #include "FGColumnVector3.h"
#include "input_output/FGPropertyManager.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_QUATERNION "$Id$" #define ID_QUATERNION "$Id: FGQuaternion.h,v 1.17 2010/06/30 03:13:40 jberndt Exp $"
namespace JSBSim { namespace JSBSim {
class FGMatrix33;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -88,14 +88,13 @@ namespace JSBSim {
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGQuaternion class FGQuaternion : virtual FGJSBBase {
: virtual FGJSBBase {
public: public:
/** Default initializer. /** Default initializer.
Default initializer, initializes the class with the identity rotation. */ Default initializer, initializes the class with the identity rotation. */
FGQuaternion() : mCacheValid(false) { FGQuaternion() : mCacheValid(false) {
Entry(1) = 1.0; data[0] = 1.0;
Entry(2) = Entry(3) = Entry(4) = 0.0; data[1] = data[2] = data[3] = 0.0;
} }
/** Copy constructor. /** Copy constructor.
@ -110,6 +109,11 @@ public:
@param psi The euler Z axis (heading) angle in radians */ @param psi The euler Z axis (heading) angle in radians */
FGQuaternion(double phi, double tht, double psi); FGQuaternion(double phi, double tht, double psi);
/** Initializer by euler angle vector.
Initialize the quaternion with the euler angle vector.
@param vOrient The euler axis angle vector in radians (phi, tht, psi) */
FGQuaternion(FGColumnVector3 vOrient);
/** Initializer by one euler angle. /** Initializer by one euler angle.
Initialize the quaternion with the single euler angle where its index Initialize the quaternion with the single euler angle where its index
is given in the first argument. is given in the first argument.
@ -117,43 +121,50 @@ public:
@param angle The euler angle in radians */ @param angle The euler angle in radians */
FGQuaternion(int idx, double angle) FGQuaternion(int idx, double angle)
: mCacheValid(false) { : mCacheValid(false) {
double angle2 = 0.5*angle; double angle2 = 0.5*angle;
double Sangle2 = sin(angle2); double Sangle2 = sin(angle2);
double Cangle2 = cos(angle2); double Cangle2 = cos(angle2);
if (idx == ePhi) { if (idx == ePhi) {
Entry(1) = Cangle2; data[0] = Cangle2;
Entry(2) = Sangle2; data[1] = Sangle2;
Entry(3) = 0.0; data[2] = 0.0;
Entry(4) = 0.0; data[3] = 0.0;
} else if (idx == eTht) { } else if (idx == eTht) {
Entry(1) = Cangle2; data[0] = Cangle2;
Entry(2) = 0.0; data[1] = 0.0;
Entry(3) = Sangle2; data[2] = Sangle2;
Entry(4) = 0.0; data[3] = 0.0;
} else { } else {
Entry(1) = Cangle2; data[0] = Cangle2;
Entry(2) = 0.0; data[1] = 0.0;
Entry(3) = 0.0; data[2] = 0.0;
Entry(4) = Sangle2; data[3] = Sangle2;
} }
} }
/** Initializer by matrix.
Initialize the quaternion with the matrix representing a transform from one frame
to another using the standard aerospace sequence, Yaw-Pitch-Roll (3-2-1).
@param m the rotation matrix */
FGQuaternion(const FGMatrix33& m);
/// Destructor. /// Destructor.
~FGQuaternion() {} ~FGQuaternion() {}
/** Quaternion derivative for given angular rates. /** Quaternion derivative for given angular rates.
Computes the quaternion derivative which results from the given Computes the quaternion derivative which results from the given
angular velocities angular velocities
@param PQR a constant reference to the body rate vector @param PQR a constant reference to a rotation rate vector
@return the quaternion derivative @return the quaternion derivative
@see Stevens and Lewis, "Aircraft Control and Simulation", Second Edition, @see Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
Equation 1.3-36. */ Equation 1.3-36. */
FGQuaternion GetQDot(const FGColumnVector3& PQR) const; FGQuaternion GetQDot(const FGColumnVector3& PQR);
/** Transformation matrix. /** Transformation matrix.
@return a reference to the transformation/rotation matrix @return a reference to the transformation/rotation matrix
@ -220,7 +231,7 @@ public:
Note that the index given in the argument is unchecked. Note that the index given in the argument is unchecked.
*/ */
double operator()(unsigned int idx) const { return Entry(idx); } double operator()(unsigned int idx) const { return data[idx-1]; }
/** Write access the entries of the vector. /** Write access the entries of the vector.
@ -231,7 +242,7 @@ public:
Note that the index given in the argument is unchecked. Note that the index given in the argument is unchecked.
*/ */
double& operator()(unsigned int idx) { return Entry(idx); } double& operator()(unsigned int idx) { mCacheValid = false; return data[idx-1]; }
/** Read access the entries of the vector. /** Read access the entries of the vector.
@ -246,7 +257,7 @@ public:
Note that the index given in the argument is unchecked. Note that the index given in the argument is unchecked.
*/ */
double Entry(unsigned int idx) const { return mData[idx-1]; } double Entry(unsigned int idx) const { return data[idx-1]; }
/** Write access the entries of the vector. /** Write access the entries of the vector.
@ -261,7 +272,10 @@ public:
Note that the index given in the argument is unchecked. Note that the index given in the argument is unchecked.
*/ */
double& Entry(unsigned int idx) { mCacheValid = false; return mData[idx-1]; } double& Entry(unsigned int idx) {
mCacheValid = false;
return data[idx-1];
}
/** Assignment operator "=". /** Assignment operator "=".
Assign the value of q to the current object. Cached values are Assign the value of q to the current object. Cached values are
@ -270,10 +284,11 @@ public:
@return reference to a quaternion object */ @return reference to a quaternion object */
const FGQuaternion& operator=(const FGQuaternion& q) { const FGQuaternion& operator=(const FGQuaternion& q) {
// Copy the master values ... // Copy the master values ...
Entry(1) = q(1); data[0] = q(1);
Entry(2) = q(2); data[1] = q(2);
Entry(3) = q(3); data[2] = q(3);
Entry(4) = q(4); data[3] = q(4);
ComputeDerived();
// .. and copy the derived values if they are valid // .. and copy the derived values if they are valid
mCacheValid = q.mCacheValid; mCacheValid = q.mCacheValid;
if (mCacheValid) { if (mCacheValid) {
@ -286,12 +301,15 @@ public:
return *this; return *this;
} }
/// Conversion from Quat to Matrix
operator FGMatrix33() const { return GetT(); }
/** Comparison operator "==". /** Comparison operator "==".
@param q a quaternion reference @param q a quaternion reference
@return true if both quaternions represent the same rotation. */ @return true if both quaternions represent the same rotation. */
bool operator==(const FGQuaternion& q) const { bool operator==(const FGQuaternion& q) const {
return Entry(1) == q(1) && Entry(2) == q(2) return data[0] == q(1) && data[1] == q(2)
&& Entry(3) == q(3) && Entry(4) == q(4); && data[2] == q(3) && data[3] == q(4);
} }
/** Comparison operator "!=". /** Comparison operator "!=".
@ -300,10 +318,10 @@ public:
bool operator!=(const FGQuaternion& q) const { return ! operator==(q); } bool operator!=(const FGQuaternion& q) const { return ! operator==(q); }
const FGQuaternion& operator+=(const FGQuaternion& q) { const FGQuaternion& operator+=(const FGQuaternion& q) {
// Copy the master values ... // Copy the master values ...
Entry(1) += q(1); data[0] += q(1);
Entry(2) += q(2); data[1] += q(2);
Entry(3) += q(3); data[2] += q(3);
Entry(4) += q(4); data[3] += q(4);
mCacheValid = false; mCacheValid = false;
return *this; return *this;
} }
@ -313,10 +331,10 @@ public:
@return a quaternion reference representing Q, where Q = Q - q. */ @return a quaternion reference representing Q, where Q = Q - q. */
const FGQuaternion& operator-=(const FGQuaternion& q) { const FGQuaternion& operator-=(const FGQuaternion& q) {
// Copy the master values ... // Copy the master values ...
Entry(1) -= q(1); data[0] -= q(1);
Entry(2) -= q(2); data[1] -= q(2);
Entry(3) -= q(3); data[2] -= q(3);
Entry(4) -= q(4); data[3] -= q(4);
mCacheValid = false; mCacheValid = false;
return *this; return *this;
} }
@ -325,10 +343,10 @@ public:
@param scalar a multiplicative value. @param scalar a multiplicative value.
@return a quaternion reference representing Q, where Q = Q * scalar. */ @return a quaternion reference representing Q, where Q = Q * scalar. */
const FGQuaternion& operator*=(double scalar) { const FGQuaternion& operator*=(double scalar) {
Entry(1) *= scalar; data[0] *= scalar;
Entry(2) *= scalar; data[1] *= scalar;
Entry(3) *= scalar; data[2] *= scalar;
Entry(4) *= scalar; data[3] *= scalar;
mCacheValid = false; mCacheValid = false;
return *this; return *this;
} }
@ -344,16 +362,16 @@ public:
@param q a quaternion to be summed. @param q a quaternion to be summed.
@return a quaternion representing Q, where Q = Q + q. */ @return a quaternion representing Q, where Q = Q + q. */
FGQuaternion operator+(const FGQuaternion& q) const { FGQuaternion operator+(const FGQuaternion& q) const {
return FGQuaternion(Entry(1)+q(1), Entry(2)+q(2), return FGQuaternion(data[0]+q(1), data[1]+q(2),
Entry(3)+q(3), Entry(4)+q(4)); data[2]+q(3), data[3]+q(4));
} }
/** Arithmetic operator "-". /** Arithmetic operator "-".
@param q a quaternion to be subtracted. @param q a quaternion to be subtracted.
@return a quaternion representing Q, where Q = Q - q. */ @return a quaternion representing Q, where Q = Q - q. */
FGQuaternion operator-(const FGQuaternion& q) const { FGQuaternion operator-(const FGQuaternion& q) const {
return FGQuaternion(Entry(1)-q(1), Entry(2)-q(2), return FGQuaternion(data[0]-q(1), data[1]-q(2),
Entry(3)-q(3), Entry(4)-q(4)); data[2]-q(3), data[3]-q(4));
} }
/** Arithmetic operator "*". /** Arithmetic operator "*".
@ -361,10 +379,10 @@ public:
@param q a quaternion to be multiplied. @param q a quaternion to be multiplied.
@return a quaternion representing Q, where Q = Q * q. */ @return a quaternion representing Q, where Q = Q * q. */
FGQuaternion operator*(const FGQuaternion& q) const { FGQuaternion operator*(const FGQuaternion& q) const {
return FGQuaternion(Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4), return FGQuaternion(data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4),
Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3), data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3),
Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2), data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2),
Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1)); data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1));
} }
/** Arithmetic operator "*=". /** Arithmetic operator "*=".
@ -372,14 +390,14 @@ public:
@param q a quaternion to be multiplied. @param q a quaternion to be multiplied.
@return a quaternion reference representing Q, where Q = Q * q. */ @return a quaternion reference representing Q, where Q = Q * q. */
const FGQuaternion& operator*=(const FGQuaternion& 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 q0 = data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4);
double q1 = Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3); double q1 = data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3);
double q2 = Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2); double q2 = data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2);
double q3 = Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1); double q3 = data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1);
Entry(1) = q0; data[0] = q0;
Entry(2) = q1; data[1] = q1;
Entry(3) = q2; data[2] = q2;
Entry(4) = q3; data[3] = q3;
mCacheValid = false; mCacheValid = false;
return *this; return *this;
} }
@ -391,12 +409,12 @@ public:
the identity orientation. the identity orientation.
*/ */
FGQuaternion Inverse(void) const { FGQuaternion Inverse(void) const {
double norm = Magnitude(); double norm = SqrMagnitude();
if (norm == 0.0) if (norm == 0.0)
return *this; return *this;
double rNorm = 1.0/norm; double rNorm = 1.0/norm;
return FGQuaternion( Entry(1)*rNorm, -Entry(2)*rNorm, return FGQuaternion( data[0]*rNorm, -data[1]*rNorm,
-Entry(3)*rNorm, -Entry(4)*rNorm ); -data[2]*rNorm, -data[3]*rNorm );
} }
/** Conjugate of the quaternion. /** Conjugate of the quaternion.
@ -405,7 +423,7 @@ public:
to the inverse iff the quaternion is normalized. to the inverse iff the quaternion is normalized.
*/ */
FGQuaternion Conjugate(void) const { FGQuaternion Conjugate(void) const {
return FGQuaternion( Entry(1), -Entry(2), -Entry(3), -Entry(4) ); return FGQuaternion( data[0], -data[1], -data[2], -data[3] );
} }
friend FGQuaternion operator*(double, const FGQuaternion&); friend FGQuaternion operator*(double, const FGQuaternion&);
@ -421,11 +439,11 @@ public:
Compute and return the square of the euclidean norm of this vector. Compute and return the square of the euclidean norm of this vector.
*/ */
double SqrMagnitude(void) const { double SqrMagnitude(void) const {
return Entry(1)*Entry(1)+Entry(2)*Entry(2) return data[0]*data[0] + data[1]*data[1]
+Entry(3)*Entry(3)+Entry(4)*Entry(4); + data[2]*data[2] + data[3]*data[3];
} }
/** Normialze. /** Normalize.
Normalize the vector to have the Magnitude() == 1.0. If the vector Normalize the vector to have the Magnitude() == 1.0. If the vector
is equal to zero it is left untouched. is equal to zero it is left untouched.
@ -439,7 +457,7 @@ public:
private: private:
/** Copying by assigning the vector valued components. */ /** Copying by assigning the vector valued components. */
FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false) FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false)
{ Entry(1) = q1; Entry(2) = q2; Entry(3) = q3; Entry(4) = q4; } { data[0] = q1; data[1] = q2; data[2] = q3; data[3] = q4; }
/** Computation of derived values. /** Computation of derived values.
This function recomputes the derived values like euler angles and This function recomputes the derived values like euler angles and
@ -450,16 +468,15 @@ private:
This function checks if the derived values like euler angles and This function checks if the derived values like euler angles and
transformation matrices are already computed. If so, it transformation matrices are already computed. If so, it
returns. If they need to be computed the real worker routine returns. If they need to be computed the real worker routine
\ref FGQuaternion::ComputeDerivedUnconditional(void) const FGQuaternion::ComputeDerivedUnconditional(void) const
is called. is called. */
This function is inlined to avoid function calls in the fast path. */
void ComputeDerived(void) const { void ComputeDerived(void) const {
if (!mCacheValid) if (!mCacheValid)
ComputeDerivedUnconditional(); ComputeDerivedUnconditional();
} }
/** The quaternion values itself. This is the master copy. */ /** The quaternion values itself. This is the master copy. */
double mData[4]; double data[4];
/** A data validity flag. /** A data validity flag.
This class implements caching of the derived values like the This class implements caching of the derived values like the
@ -479,6 +496,10 @@ private:
/** The cached sines and cosines of the euler angles. */ /** The cached sines and cosines of the euler angles. */
mutable FGColumnVector3 mEulerSines; mutable FGColumnVector3 mEulerSines;
mutable FGColumnVector3 mEulerCosines; mutable FGColumnVector3 mEulerCosines;
void Debug(int from) const;
void InitializeFromEulerAngles(double phi, double tht, double psi);
}; };
/** Scalar multiplication. /** Scalar multiplication.
@ -494,4 +515,6 @@ inline FGQuaternion operator*(double scalar, const FGQuaternion& q) {
} // namespace JSBSim } // namespace JSBSim
#include "FGMatrix33.h"
#endif #endif

View file

@ -32,7 +32,7 @@ INCLUDES
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGRealValue.cpp,v 1.4 2009/08/30 03:51:28 jberndt Exp $";
static const char *IdHdr = ID_REALVALUE; static const char *IdHdr = ID_REALVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -40,7 +40,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_REALVALUE "$Id$" #define ID_REALVALUE "$Id: FGRealValue.h,v 1.4 2009/08/30 03:51:28 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -0,0 +1,230 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGRungeKutta.cpp
Author: Thomas Kreitler
Date started: 04/9/2010
------------- Copyright (C) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser 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 Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser 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 Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <cstdio>
#include <iostream>
#include <cmath>
#include "FGRungeKutta.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
using std::cout;
using std::endl;
namespace JSBSim {
static const char *IdSrc = "$Id: FGRungeKutta.cpp,v 1.1 2010/06/02 04:05:13 jberndt Exp $";
static const char *IdHdr = ID_RUNGEKUTTA;
const double FGRungeKutta::RealLimit = 1e30;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGRungeKutta::~FGRungeKutta() { };
int FGRungeKutta::init(double x_start, double x_end, int intervals)
{
x0 = x_start;
x1 = x_end;
h = (x_end - x_start)/intervals;
safer_x1 = x1 - h*1e-6; // avoid 'intervals*h < x1'
h05 = h*0.5;
err = 0.0;
if (x0>=x1) {
status &= eFaultyInit;
}
return status;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
Make sure that a numerical result is within +/-RealLimit.
This is a hapless try to be portable.
(There will be at least one architecture/compiler combination
where this will fail.)
*/
bool FGRungeKutta::sane_val(double x)
{
// assuming +/- inf behave as expected and 'nan' comparisons yield to false
if ( x < RealLimit && x > -RealLimit ) return true;
return false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGRungeKutta::evolve(double y_0, FGRungeKuttaProblem *pf)
{
double x = x0;
double y = y_0;
pfo = pf;
iterations = 0;
if (!trace_values) {
while (x<safer_x1) {
y = approximate(x,y);
if (!sane_val(y)) { status &= eMathError; }
x += h;
iterations++;
}
} else {
while (x<safer_x1) {
cout << x << " " << y << endl;
y = approximate(x,y);
if (!sane_val(y)) { status &= eMathError; }
x += h;
iterations++;
}
cout << x << " " << y << endl;
}
x_end = x; // twimc, store the last x used.
return y;
}
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGRK4::~FGRK4() { };
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGRK4::approximate(double x, double y)
{
double k1,k2,k3,k4;
k1 = pfo->pFunc(x , y );
k2 = pfo->pFunc(x + h05, y + h05*k1);
k3 = pfo->pFunc(x + h05, y + h05*k2);
k4 = pfo->pFunc(x + h , y + h *k3);
y += h/6.0 * ( k1 + 2.0*k2 + 2.0*k3 + k4 );
return y;
}
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// Butcher tableau
const double FGRKFehlberg::A2[] = { 0.0, 1.0/4.0 };
const double FGRKFehlberg::A3[] = { 0.0, 3.0/32.0, 9.0/32.0 };
const double FGRKFehlberg::A4[] = { 0.0, 1932.0/2197.0, -7200.0/2197.0, 7296.0/2197.0 };
const double FGRKFehlberg::A5[] = { 0.0, 439.0/216.0, -8.0, 3680.0/513.0, -845.0/4104.0 };
const double FGRKFehlberg::A6[] = { 0.0, -8.0/27.0, 2.0, -3544.0/2565.0, 1859.0/4104.0, -11.0/40.0 };
const double FGRKFehlberg::C[] = { 0.0, 0.0, 1.0/4.0, 3.0/8.0, 12.0/13.0, 1.0, 1.0/2.0 };
const double FGRKFehlberg::B[] = { 0.0, 16.0/135.0, 0.0, 6656.0/12825.0, 28561.0/56430.0, -9.0/50.0, 2.0/55.0 };
const double FGRKFehlberg::Bs[] = { 0.0, 25.0/216.0, 0.0, 1408.0/2565.0, 2197.0/4104.0, -1.0/5.0, 0.0 };
// use this if truncation is an issue
// const double Ee[] = { 0.0, 1.0/360.0, 0.0, -128.0/4275.0, -2197.0/75240.0, 1.0/50.0, 2.0/55.0 };
FGRKFehlberg::~FGRKFehlberg() { };
double FGRKFehlberg::approximate(double x, double y)
{
double k1,k2,k3,k4,k5,k6, as;
double y4_val;
double y5_val;
double abs_err;
double est_step;
int done = 0;
while (!done) {
err = h*h*h*h*h; // h might change
k1 = pfo->pFunc(x , y );
as = h*A2[1]*k1;
k2 = pfo->pFunc(x + C[2]*h , y + as );
as = h*(A3[1]*k1 + A3[2]*k2);
k3 = pfo->pFunc(x + C[3]*h , y + as );
as = h*(A4[1]*k1 + A4[2]*k2 + A4[3]*k3);
k4 = pfo->pFunc(x + C[4]*h , y + as );
as = h*(A5[1]*k1 + A5[2]*k2 + A5[3]*k3 + A5[4]*k4);
k5 = pfo->pFunc(x + C[5]*h , y + as );
as = h*(A6[1]*k1 + A6[2]*k2 + A6[3]*k3 + A6[4]*k4 + A6[5]*k5);
k6 = pfo->pFunc(x + C[6]*h , y + as );
/* B[2]*k2 and Bs[2]*k2 are zero */
y5_val = y + h * ( B[1]*k1 + B[3]*k3 + B[4]*k4 + B[5]*k5 + B[6]*k6);
y4_val = y + h * (Bs[1]*k1 + Bs[3]*k3 + Bs[4]*k4 + Bs[5]*k5);
abs_err = fabs(y4_val-y5_val);
// same in green
// abs_err = h * (Ee[1] * k1 + Ee[3] * k3 + Ee[4] * k4 + Ee[5] * k5 + Ee[6] * k6);
// estimate step size
if (abs_err > epsilon) {
est_step = sqrt(sqrt(epsilon*h/abs_err));
} else {
est_step=2.0*h; // cheat
}
// check if a smaller step size is proposed
if (shrink_avail>0 && est_step<h) {
h/=2.0;
shrink_avail--;
} else {
done = 1;
}
}
return y4_val;
}
} // namespace JSBSim

View file

@ -0,0 +1,189 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: FGRungeKutta.h
Author: Thomas Kreitler
Date started: 04/9/2010
------------- Copyright (C) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser 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 Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser 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 Lesser General Public License can also be found on
the world wide web at http://www.gnu.org.
HISTORY
--------------------------------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifndef FGRUNGEKUTTA_H
#define FGRUNGEKUTTA_H
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// #include "FGJSBBase.h" // later
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_RUNGEKUTTA "$Id: FGRungeKutta.h,v 1.1 2010/06/02 04:05:13 jberndt Exp $"
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/**
Minimalistic implementation of some Runge-Kutta methods. Runge-Kutta methods
are a standard for solving ordinary differential equation (ODE) initial
value problems. The code follows closely the description given on
Wikipedia, see http://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods.
For more powerfull routines see GNU Scientific Library (GSL)
or GNU Plotutils 'ode'.
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGRungeKuttaProblem
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/**
Abstract base for the function to solve.
*/
class FGRungeKuttaProblem {
public:
virtual double pFunc(double x, double y) = 0;
};
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGRungeKutta
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/**
Abstract base.
*/
class FGRungeKutta {
public:
enum eStates { eNoError=0, eMathError=1, eFaultyInit=2, eEvolve=4, eUnknown=8} ;
int init(double x_start, double x_end, int intervals = 4);
double evolve(double y_0, FGRungeKuttaProblem *pf);
double getXEnd() { return x_end; }
double getError() { return err; }
int getStatus() { return status; }
int getIterations() { return iterations; }
void clearStatus() { status = eNoError; }
void setTrace(bool t) { trace_values = t; }
protected:
// avoid accidents
FGRungeKutta(): status(eNoError), trace_values(false), iterations(0) {};
virtual ~FGRungeKutta();
FGRungeKuttaProblem *pfo;
double h;
double h05; // h*0.5, halfwidth
double err;
private:
virtual double approximate(double x, double y) = 0;
bool sane_val(double x);
static const double RealLimit;
double x0, x1;
double safer_x1;
double x_end;
int status;
bool trace_values;
int iterations;
};
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGRK4
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/**
Classical RK4.
*/
class FGRK4 : public FGRungeKutta {
virtual ~FGRK4();
private:
double approximate(double x, double y);
};
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DECLARATION: FGRKFehlberg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/**
Runge-Kutta-Fehlberg method.
This is a semi adaptive implementation of rkf - the interval only
shrinks. As a result interval calculations remain trivial, but
sometimes too many calculations are performed.
Rationale: this code is not meant to be a universal pain-reliever
for ode's. Rather it provides some safety if the number of
intervals is set too low, or the problem function behaves a bit
nasty in rare conditions.
*/
class FGRKFehlberg : public FGRungeKutta {
public:
FGRKFehlberg() : shrink_avail(4), epsilon(1e-12) { };
virtual ~FGRKFehlberg();
double getEpsilon() { return epsilon; }
int getShrinkAvail() { return shrink_avail; }
void setEpsilon(double e) { epsilon = e; }
void setShrinkAvail(int s) { shrink_avail = s; }
private:
double approximate(double x, double y);
int shrink_avail;
double epsilon;
static const double A2[], A3[], A4[], A5[], A6[];
static const double B[], Bs[], C[];
};
} // namespace JSBSim
#endif

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGTable.cpp,v 1.21 2010/04/07 03:08:37 jberndt Exp $";
static const char *IdHdr = ID_TABLE; static const char *IdHdr = ID_TABLE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -165,9 +165,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
node = PropertyManager->GetNode(property_string); node = PropertyManager->GetNode(property_string);
if (node == 0) { if (node == 0) {
cerr << "IndependenVar property, " << property_string throw("IndependenVar property, " + property_string + " in Table definition is not defined.");
<< " in Table definition is not defined." << endl;
abort();
} }
lookup_axis = axisElement->GetAttributeValue("lookup"); lookup_axis = axisElement->GetAttributeValue("lookup");
@ -177,6 +175,8 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
lookupProperty[eColumn] = node; lookupProperty[eColumn] = node;
} else if (lookup_axis == string("table")) { } else if (lookup_axis == string("table")) {
lookupProperty[eTable] = node; lookupProperty[eTable] = node;
} else if (!lookup_axis.empty()) {
throw("Lookup table axis specification not understood: " + lookup_axis);
} else { // assumed single dimension table; row lookup } else { // assumed single dimension table; row lookup
lookupProperty[eRow] = node; lookupProperty[eRow] = node;
} }

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TABLE "$Id$" #define ID_TABLE "$Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

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

View file

@ -52,7 +52,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.31 2009/11/28 14:30:11 andgi Exp $";
static const char *IdHdr = ID_AERODYNAMICS; static const char *IdHdr = ID_AERODYNAMICS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -52,7 +52,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AERODYNAMICS "$Id$" #define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.20 2009/11/12 13:08:11 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -109,7 +109,7 @@ CLASS DOCUMENTATION
Systems may NOT be combined, or a load error will occur. Systems may NOT be combined, or a load error will occur.
@author Jon S. Berndt, Tony Peden @author Jon S. Berndt, Tony Peden
@version $Revision$ @version $Revision: 1.20 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -214,7 +214,6 @@ private:
typedef std::map<std::string,int> AxisIndex; typedef std::map<std::string,int> AxisIndex;
AxisIndex AxisIdx; AxisIndex AxisIdx;
FGFunction* AeroRPShift; FGFunction* AeroRPShift;
std::vector <FGFunction*> variables;
typedef vector <FGFunction*> CoeffArray; typedef vector <FGFunction*> CoeffArray;
CoeffArray* Coeff; CoeffArray* Coeff;
FGColumnVector3 vFnative; FGColumnVector3 vFnative;

View file

@ -68,7 +68,7 @@ DEFINITIONS
GLOBAL DATA GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.26 2010/02/15 03:28:24 jberndt Exp $";
static const char *IdHdr = ID_AIRCRAFT; static const char *IdHdr = ID_AIRCRAFT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -123,6 +123,9 @@ bool FGAircraft::Run(void)
vForces += GroundReactions->GetForces(); vForces += GroundReactions->GetForces();
vForces += ExternalReactions->GetForces(); vForces += ExternalReactions->GetForces();
vForces += BuoyantForces->GetForces(); vForces += BuoyantForces->GetForces();
} else {
const FGMatrix33& mTl2b = Propagate->GetTl2b();
vForces = mTl2b * FGColumnVector3(0,0,-MassBalance->GetWeight());
} }
vMoments.InitMatrix(); vMoments.InitMatrix();

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AIRCRAFT "$Id$" #define ID_AIRCRAFT "$Id: FGAircraft.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -90,7 +90,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGAircraft.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $
@see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling @see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate
School, January 1994 School, January 1994

View file

@ -48,11 +48,11 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGState.h"
#include "FGFDMExec.h"
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGPropagate.h" #include "FGPropagate.h"
#include "FGInertial.h" #include "FGInertial.h"
#include "FGAuxiliary.h"
#include "FGFDMExec.h"
#include "input_output/FGPropertyManager.h" #include "input_output/FGPropertyManager.h"
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.33 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdHdr = ID_ATMOSPHERE; static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -383,7 +383,7 @@ void FGAtmosphere::SetWindPsi(double dir)
void FGAtmosphere::Turbulence(void) void FGAtmosphere::Turbulence(void)
{ {
double DeltaT = rate*State->Getdt(); double DeltaT = rate*FDMExec->GetDeltaT();
switch (turbType) { switch (turbType) {
case ttStandard: { case ttStandard: {

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ATMOSPHERE "$Id$" #define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -63,7 +63,7 @@ CLASS DOCUMENTATION
/** Models the 1976 Standard Atmosphere. /** Models the 1976 Standard Atmosphere.
@author Tony Peden, Jon Berndt @author Tony Peden, Jon Berndt
@version $Id$ @version $Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $
@see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill, @see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0 1989, ISBN 0-07-001641-0
*/ */

View file

@ -59,7 +59,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.39 2010/07/09 12:06:11 jberndt Exp $";
static const char *IdHdr = ID_AUXILIARY; static const char *IdHdr = ID_AUXILIARY;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -249,11 +249,12 @@ bool FGAuxiliary::Run()
vPilotAccel.InitMatrix(); vPilotAccel.InitMatrix();
if ( Vt > 1.0 ) { if ( Vt > 1.0 ) {
vAircraftAccel = Aerodynamics->GetForces() // Use the "+=" operator to avoid the creation of temporary objects.
+ Propulsion->GetForces() vAircraftAccel = Aerodynamics->GetForces();
+ GroundReactions->GetForces() vAircraftAccel += Propulsion->GetForces();
+ ExternalReactions->GetForces() vAircraftAccel += GroundReactions->GetForces();
+ BuoyantForces->GetForces(); vAircraftAccel += ExternalReactions->GetForces();
vAircraftAccel += BuoyantForces->GetForces();
vAircraftAccel /= MassBalance->GetMass(); vAircraftAccel /= MassBalance->GetMass();
// Nz is Acceleration in "g's", along normal axis (-Z body axis) // Nz is Acceleration in "g's", along normal axis (-Z body axis)
@ -276,7 +277,7 @@ bool FGAuxiliary::Run()
// VRP computation // VRP computation
const FGLocation& vLocation = Propagate->GetLocation(); const FGLocation& vLocation = Propagate->GetLocation();
FGColumnVector3 vrpStructural = Aircraft->GetXYZvrp(); FGColumnVector3& vrpStructural = Aircraft->GetXYZvrp();
FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural ); FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural );
FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody; FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody;
vLocationVRP = vLocation.LocalToLocation( vrpLocal ); vLocationVRP = vLocation.LocalToLocation( vrpLocal );

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AUXILIARY "$Id$" #define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -100,7 +100,7 @@ CLASS DOCUMENTATION
The radius R is calculated below in the vector vToEyePt. The radius R is calculated below in the vector vToEyePt.
@author Tony Peden, Jon Berndt @author Tony Peden, Jon Berndt
@version $Id$ @version $Id: FGAuxiliary.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -5,7 +5,7 @@
Date started: 01/21/08 Date started: 01/21/08
Purpose: Encapsulates the buoyant forces Purpose: Encapsulates the buoyant forces
------------- Copyright (C) 2008 - 2009 Anders Gidenstam ------------- ------------- Copyright (C) 2008 - 2010 Anders Gidenstam -------------
------------- Copyright (C) 2008 Jon S. Berndt (jon@jsbsim.org) ------------- ------------- Copyright (C) 2008 Jon S. Berndt (jon@jsbsim.org) -------------
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
@ -38,14 +38,14 @@ INCLUDES
#include "FGBuoyantForces.h" #include "FGBuoyantForces.h"
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "input_output/FGPropertyManager.h" // Need? #include "input_output/FGPropertyManager.h"
#include <iostream> #include <iostream>
using namespace std; using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.12 2010/05/07 18:59:55 andgi Exp $";
static const char *IdHdr = ID_BUOYANTFORCES; static const char *IdHdr = ID_BUOYANTFORCES;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -63,8 +63,6 @@ FGBuoyantForces::FGBuoyantForces(FGFDMExec* FDMExec) : FGModel(FDMExec)
gasCellJ.InitMatrix(); gasCellJ.InitMatrix();
bind();
Debug(0); Debug(0);
} }
@ -141,6 +139,10 @@ bool FGBuoyantForces::Load(Element *element)
FGModel::PostLoad(element); FGModel::PostLoad(element);
if (!NoneDefined) {
bind();
}
return true; return true;
} }
@ -258,6 +260,19 @@ string FGBuoyantForces::GetBuoyancyValues(string delimeter)
void FGBuoyantForces::bind(void) void FGBuoyantForces::bind(void)
{ {
typedef double (FGBuoyantForces::*PMF)(int) const;
PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL,
(PMF)&FGBuoyantForces::GetMoments);
PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM,
(PMF)&FGBuoyantForces::GetMoments);
PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN,
(PMF)&FGBuoyantForces::GetMoments);
PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX,
(PMF)&FGBuoyantForces::GetForces);
PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY,
(PMF)&FGBuoyantForces::GetForces);
PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ,
(PMF)&FGBuoyantForces::GetForces);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -4,7 +4,7 @@
Author: Anders Gidenstam, Jon S. Berndt Author: Anders Gidenstam, Jon S. Berndt
Date started: 01/21/08 Date started: 01/21/08
------------- Copyright (C) 2008 Anders Gidenstam ------------- ------------- Copyright (C) 2008 - 2010 Anders Gidenstam -------------
------------- Copyright (C) 2008 Jon S. Berndt (jon@jsbsim.org) ------------- ------------- Copyright (C) 2008 Jon S. Berndt (jon@jsbsim.org) -------------
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_BUOYANTFORCES "$Id$" #define ID_BUOYANTFORCES "$Id: FGBuoyantForces.h,v 1.11 2010/05/07 20:38:34 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -96,7 +96,7 @@ CLASS DOCUMENTATION
See FGGasCell for the full configuration file format for gas cells. See FGGasCell for the full configuration file format for gas cells.
@author Anders Gidenstam, Jon S. Berndt @author Anders Gidenstam, Jon S. Berndt
@version $Id$ @version $Id: FGBuoyantForces.h,v 1.11 2010/05/07 20:38:34 andgi Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -130,10 +130,18 @@ public:
@return a force vector. */ @return a force vector. */
const FGColumnVector3& GetForces(void) const {return vTotalForces;} const FGColumnVector3& GetForces(void) const {return vTotalForces;}
/** Gets a component of the total Buoyant force vector.
@return a component of the force vector. */
double GetForces(int idx) const {return vTotalForces(idx);}
/** Gets the total Buoyancy moment vector. /** Gets the total Buoyancy moment vector.
@return a moment vector. */ @return a moment vector. */
const FGColumnVector3& GetMoments(void) const {return vTotalMoments;} const FGColumnVector3& GetMoments(void) const {return vTotalMoments;}
/** Gets a component of the total Buoyancy moment vector.
@return a component of the moment vector. */
double GetMoments(int idx) const {return vTotalMoments(idx);}
/** Gets the total gas mass. The gas mass is part of the aircraft's /** Gets the total gas mass. The gas mass is part of the aircraft's
inertia. inertia.
@return mass in slugs. */ @return mass in slugs. */

View file

@ -60,7 +60,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGExternalForce.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_EXTERNALFORCE; static const char *IdHdr = ID_EXTERNALFORCE;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_EXTERNALFORCE "$Id$" #define ID_EXTERNALFORCE "$Id: FGExternalForce.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -53,7 +53,7 @@ DEFINITIONS
GLOBAL DATA GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.8 2009/11/12 13:08:11 jberndt Exp $";
static const char *IdHdr = ID_EXTERNALREACTIONS; static const char *IdHdr = ID_EXTERNALREACTIONS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_EXTERNALREACTIONS "$Id$" #define ID_EXTERNALREACTIONS "$Id: FGExternalReactions.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -63,7 +63,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGFCS.cpp,v 1.68 2010/03/18 13:21:24 jberndt Exp $";
static const char *IdHdr = ID_FCS; static const char *IdHdr = ID_FCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -533,19 +533,17 @@ bool FGFCS::Load(Element* el, SystemType systype)
Components=0; Components=0;
string separator = "/";
// ToDo: The handling of name and file attributes could be improved, here, // ToDo: The handling of name and file attributes could be improved, here,
// considering that a name can be in the external file, as well. // considering that a name can be in the external file, as well.
name = el->GetAttributeValue("name"); name = el->GetAttributeValue("name");
if (name.empty()) { if (name.empty() || !el->GetAttributeValue("file").empty()) {
fname = el->GetAttributeValue("file"); fname = el->GetAttributeValue("file");
if (systype == stSystem) { if (systype == stSystem) {
file = FindSystemFullPathname(fname); file = FindSystemFullPathname(fname);
} else { } else {
file = FDMExec->GetFullAircraftPath() + separator + fname + ".xml"; file = FDMExec->GetFullAircraftPath() + "/" + fname + ".xml";
} }
if (fname.empty()) { if (fname.empty()) {
cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl; cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl;
@ -692,49 +690,55 @@ double FGFCS::GetBrake(FGLGear::BrakeGroup bg)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGFCS::FindSystemFullPathname(const string& system_filename) string FGFCS::FindSystemFullPathname(const string& sysfilename)
{ {
string fullpath, localpath; string fullpath, localpath;
string system_filename = sysfilename;
string systemPath = FDMExec->GetSystemsPath(); string systemPath = FDMExec->GetSystemsPath();
string aircraftPath = FDMExec->GetFullAircraftPath(); string aircraftPath = FDMExec->GetFullAircraftPath();
ifstream system_file; ifstream system_file;
string separator = "/"; fullpath = systemPath + "/";
localpath = aircraftPath + "/Systems/";
fullpath = systemPath + separator; if (system_filename.length() <=4 || system_filename.substr(system_filename.length()-4, 4) != ".xml") {
localpath = aircraftPath + separator + "Systems" + separator; system_filename.append(".xml");
}
system_file.open(string(fullpath + system_filename + ".xml").c_str()); system_file.open(string(fullpath + system_filename).c_str());
if ( !system_file.is_open()) { if ( !system_file.is_open()) {
system_file.open(string(localpath + system_filename + ".xml").c_str()); system_file.open(string(localpath + system_filename).c_str());
if ( !system_file.is_open()) { if ( !system_file.is_open()) {
cerr << " Could not open system file: " << system_filename << " in path " cerr << " Could not open system file: " << system_filename << " in path "
<< fullpath << " or " << localpath << endl; << fullpath << " or " << localpath << endl;
return string(""); return string("");
} else { } else {
return string(localpath + system_filename + ".xml"); return string(localpath + system_filename);
} }
} }
return string(fullpath + system_filename + ".xml"); return string(fullpath + system_filename);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ifstream* FGFCS::FindSystemFile(const string& system_filename) ifstream* FGFCS::FindSystemFile(const string& sysfilename)
{ {
string fullpath, localpath; string fullpath, localpath;
string system_filename = sysfilename;
string systemPath = FDMExec->GetSystemsPath(); string systemPath = FDMExec->GetSystemsPath();
string aircraftPath = FDMExec->GetFullAircraftPath(); string aircraftPath = FDMExec->GetFullAircraftPath();
ifstream* system_file = new ifstream(); ifstream* system_file = new ifstream();
string separator = "/"; fullpath = systemPath + "/";
localpath = aircraftPath + "/Systems/";
fullpath = systemPath + separator; if (system_filename.substr(system_filename.length()-4, 4) != ".xml") {
localpath = aircraftPath + separator + "Systems" + separator; system_filename.append(".xml");
}
system_file->open(string(fullpath + system_filename + ".xml").c_str()); system_file->open(string(fullpath + system_filename).c_str());
if ( !system_file->is_open()) { if ( !system_file->is_open()) {
system_file->open(string(localpath + system_filename + ".xml").c_str()); system_file->open(string(localpath + system_filename).c_str());
if ( !system_file->is_open()) { if ( !system_file->is_open()) {
cerr << " Could not open system file: " << system_filename << " in path " cerr << " Could not open system file: " << system_filename << " in path "
<< fullpath << " or " << localpath << endl; << fullpath << " or " << localpath << endl;

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCS "$Id$" #define ID_FCS "$Id: FGFCS.h,v 1.28 2010/01/18 13:12:25 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -168,7 +168,7 @@ CLASS DOCUMENTATION
@property gear/tailhook-pos-norm @property gear/tailhook-pos-norm
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision$ @version $Revision: 1.28 $
@see FGActuator @see FGActuator
@see FGDeadBand @see FGDeadBand
@see FGFCSFunction @see FGFCSFunction
@ -407,12 +407,12 @@ public:
/** Sets the throttle command for the specified engine /** Sets the throttle command for the specified engine
@param engine engine ID number @param engine engine ID number
@param cmd throttle command in percent (0 - 100)*/ @param cmd normalized throttle command (0.0 - 1.0)*/
void SetThrottleCmd(int engine, double cmd); void SetThrottleCmd(int engine, double cmd);
/** Sets the mixture command for the specified engine /** Sets the mixture command for the specified engine
@param engine engine ID number @param engine engine ID number
@param cmd mixture command in percent (0 - 100)*/ @param cmd normalized mixture command (0.0 - 1.0)*/
void SetMixtureCmd(int engine, double cmd); void SetMixtureCmd(int engine, double cmd);
/** Set the gear extend/retract command, defaults to down /** Set the gear extend/retract command, defaults to down
@ -462,12 +462,12 @@ public:
/** Sets the actual throttle setting for the specified engine /** Sets the actual throttle setting for the specified engine
@param engine engine ID number @param engine engine ID number
@param cmd throttle setting in percent (0 - 100)*/ @param cmd normalized throttle setting (0.0 - 1.0)*/
void SetThrottlePos(int engine, double cmd); void SetThrottlePos(int engine, double cmd);
/** Sets the actual mixture setting for the specified engine /** Sets the actual mixture setting for the specified engine
@param engine engine ID number @param engine engine ID number
@param cmd mixture setting in percent (0 - 100)*/ @param cmd normalized mixture setting (0.0 - 1.0)*/
void SetMixturePos(int engine, double cmd); void SetMixturePos(int engine, double cmd);
/** Sets the steering position /** Sets the steering position

View file

@ -53,7 +53,7 @@ using std::max;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGGasCell.cpp,v 1.12 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_GASCELL; static const char *IdHdr = ID_GASCELL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_GASCELL "$Id$" #define ID_GASCELL "$Id: FGGasCell.h,v 1.10 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -46,7 +46,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.26 2009/11/12 13:08:11 jberndt Exp $";
static const char *IdHdr = ID_GROUNDREACTIONS; static const char *IdHdr = ID_GROUNDREACTIONS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -45,7 +45,7 @@ INCLUDES
#include "math/FGColumnVector3.h" #include "math/FGColumnVector3.h"
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#define ID_GROUNDREACTIONS "$Id$" #define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.15 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -38,7 +38,6 @@ INCLUDES
#include "FGInertial.h" #include "FGInertial.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGPropagate.h" #include "FGPropagate.h"
#include "FGState.h"
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include <iostream> #include <iostream>
@ -46,7 +45,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGInertial.cpp,v 1.18 2010/03/28 05:57:00 jberndt Exp $";
static const char *IdHdr = ID_INERTIAL; static const char *IdHdr = ID_INERTIAL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -119,7 +118,7 @@ bool FGInertial::Run(void)
// Gravitation accel // Gravitation accel
double r = Propagate->GetRadius(); double r = Propagate->GetRadius();
gAccel = GetGAccel(r); gAccel = GetGAccel(r);
earthPosAngle += State->Getdt()*RotationRate; earthPosAngle += FDMExec->GetDeltaT()*RotationRate;
RunPostFunctions(); RunPostFunctions();
@ -133,6 +132,34 @@ double FGInertial::GetGAccel(double r) const
return GM/(r*r); return GM/(r*r);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// Calculate the WGS84 gravitation value in ECEF frame. Pass in the ECEF position
// via the position parameter. The J2Gravity value returned is in ECEF frame,
// and therefore may need to be expressed (transformed) in another frame,
// depending on how it is used. See Stevens and Lewis eqn. 1.4-16.
FGColumnVector3 FGInertial::GetGravityJ2(FGColumnVector3 position) const
{
FGColumnVector3 J2Gravity;
// Gravitation accel
double r = position.Magnitude();
double lat = Propagate->GetLatitude();
double sinLat = sin(lat);
double preCommon = 1.5*J2*(a/r)*(a/r);
double xy = 1.0 - 5.0*(sinLat*sinLat);
double z = 3.0 - 5.0*(sinLat*sinLat);
double GMOverr2 = GM/(r*r);
J2Gravity(1) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eX)/r);
J2Gravity(2) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eY)/r);
J2Gravity(3) = -GMOverr2 * ((1.0 + (preCommon * z)) * position(eZ)/r);
return J2Gravity;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGInertial::bind(void) void FGInertial::bind(void)

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INERTIAL "$Id$" #define ID_INERTIAL "$Id: FGInertial.h,v 1.15 2010/01/27 04:01:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -82,10 +82,13 @@ public:
double GetEarthPositionAngle(void) const { return earthPosAngle; } double GetEarthPositionAngle(void) const { return earthPosAngle; }
double GetEarthPositionAngleDeg(void) const { return earthPosAngle*radtodeg;} double GetEarthPositionAngleDeg(void) const { return earthPosAngle*radtodeg;}
double GetGAccel(double r) const; double GetGAccel(double r) const;
FGColumnVector3 GetGravityJ2(FGColumnVector3 position) const;
double GetRefRadius(void) const {return RadiusReference;} double GetRefRadius(void) const {return RadiusReference;}
double GetSemimajor(void) const {return a;} double GetSemimajor(void) const {return a;}
double GetSemiminor(void) const {return b;} double GetSemiminor(void) const {return b;}
void SetEarthPositionAngle(double epa) {earthPosAngle = epa;}
private: private:
double gAccel; double gAccel;
double gAccelReference; double gAccelReference;

View file

@ -39,7 +39,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGInput.h" #include "FGInput.h"
#include "FGState.h" #include "FGAircraft.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "input_output/FGfdmSocket.h" #include "input_output/FGfdmSocket.h"
@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGInput.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdHdr = ID_INPUT; static const char *IdHdr = ID_INPUT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -192,7 +192,7 @@ bool FGInput::Run(void)
info << "JSBSim version: " << JSBSim_version << endl; info << "JSBSim version: " << JSBSim_version << endl;
info << "Config File version: " << needed_cfg_version << endl; info << "Config File version: " << needed_cfg_version << endl;
info << "Aircraft simulated: " << Aircraft->GetAircraftName() << endl; info << "Aircraft simulated: " << Aircraft->GetAircraftName() << endl;
info << "Simulation time: " << setw(8) << setprecision(3) << State->Getsim_time() << endl; info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl;
socket->Reply(info.str()); socket->Reply(info.str());
} else if (command == "help") { // HELP } else if (command == "help") { // HELP

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INPUT "$Id$" #define ID_INPUT "$Id: FGInput.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -41,7 +41,6 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGLGear.h" #include "FGLGear.h"
#include "FGState.h"
#include "FGGroundReactions.h" #include "FGGroundReactions.h"
#include "FGFCS.h" #include "FGFCS.h"
#include "FGAuxiliary.h" #include "FGAuxiliary.h"
@ -62,7 +61,7 @@ DEFINITIONS
GLOBAL DATA GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGLGear.cpp,v 1.74 2010/05/18 10:54:14 jberndt Exp $";
static const char *IdHdr = ID_LGEAR; static const char *IdHdr = ID_LGEAR;
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in // Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
@ -76,7 +75,8 @@ CLASS IMPLEMENTATION
FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) : FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
FGForce(fdmex), FGForce(fdmex),
GearNumber(number), GearNumber(number),
SteerAngle(0.0) SteerAngle(0.0),
Castered(false)
{ {
Element *force_table=0; Element *force_table=0;
Element *dampCoeff=0; Element *dampCoeff=0;
@ -202,7 +202,7 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
if (sSteerType == "STEERABLE") eSteerType = stSteer; if (sSteerType == "STEERABLE") eSteerType = stSteer;
else if (sSteerType == "FIXED" ) eSteerType = stFixed; else if (sSteerType == "FIXED" ) eSteerType = stFixed;
else if (sSteerType == "CASTERED" ) eSteerType = stCaster; else if (sSteerType == "CASTERED" ) {eSteerType = stCaster; Castered = true;}
else if (sSteerType.empty() ) {eSteerType = stFixed; else if (sSteerType.empty() ) {eSteerType = stFixed;
sSteerType = "FIXED (defaulted)";} sSteerType = "FIXED (defaulted)";}
else { else {
@ -223,15 +223,14 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
} }
} }
State = fdmex->GetState();
Aircraft = fdmex->GetAircraft(); Aircraft = fdmex->GetAircraft();
Propagate = fdmex->GetPropagate(); Propagate = fdmex->GetPropagate();
Auxiliary = fdmex->GetAuxiliary(); Auxiliary = fdmex->GetAuxiliary();
FCS = fdmex->GetFCS(); FCS = fdmex->GetFCS();
MassBalance = fdmex->GetMassBalance(); MassBalance = fdmex->GetMassBalance();
LongForceLagFilterCoeff = 1/State->Getdt(); // default longitudinal force filter coefficient LongForceLagFilterCoeff = 1/fdmex->GetDeltaT(); // default longitudinal force filter coefficient
LatForceLagFilterCoeff = 1/State->Getdt(); // default lateral force filter coefficient LatForceLagFilterCoeff = 1/fdmex->GetDeltaT(); // default lateral force filter coefficient
Element* force_lag_filter_elem = el->FindElement("force_lag_filter"); Element* force_lag_filter_elem = el->FindElement("force_lag_filter");
if (force_lag_filter_elem) { if (force_lag_filter_elem) {
@ -243,17 +242,17 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
} }
} }
LongForceFilter = Filter(LongForceLagFilterCoeff, State->Getdt()); LongForceFilter = Filter(LongForceLagFilterCoeff, fdmex->GetDeltaT());
LatForceFilter = Filter(LatForceLagFilterCoeff, State->Getdt()); LatForceFilter = Filter(LatForceLagFilterCoeff, fdmex->GetDeltaT());
WheelSlipLagFilterCoeff = 1/State->Getdt(); WheelSlipLagFilterCoeff = 1/fdmex->GetDeltaT();
Element *wheel_slip_angle_lag_elem = el->FindElement("wheel_slip_filter"); Element *wheel_slip_angle_lag_elem = el->FindElement("wheel_slip_filter");
if (wheel_slip_angle_lag_elem) { if (wheel_slip_angle_lag_elem) {
WheelSlipLagFilterCoeff = wheel_slip_angle_lag_elem->GetDataAsNumber(); WheelSlipLagFilterCoeff = wheel_slip_angle_lag_elem->GetDataAsNumber();
} }
WheelSlipFilter = Filter(WheelSlipLagFilterCoeff, State->Getdt()); WheelSlipFilter = Filter(WheelSlipLagFilterCoeff, fdmex->GetDeltaT());
GearUp = false; GearUp = false;
GearDown = true; GearDown = true;
@ -307,8 +306,8 @@ FGLGear::~FGLGear()
FGColumnVector3& FGLGear::GetBodyForces(void) FGColumnVector3& FGLGear::GetBodyForces(void)
{ {
double t = fdmex->GetState()->Getsim_time(); double t = fdmex->GetSimTime();
dT = State->Getdt()*fdmex->GetGroundReactions()->GetRate(); dT = fdmex->GetDeltaT()*fdmex->GetGroundReactions()->GetRate();
vFn.InitMatrix(); vFn.InitMatrix();
@ -324,7 +323,7 @@ FGColumnVector3& FGLGear::GetBodyForces(void)
// Compute the height of the theoretical location of the wheel (if strut is not compressed) with // Compute the height of the theoretical location of the wheel (if strut is not compressed) with
// respect to the ground level // respect to the ground level
double height = fdmex->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel); double height = fdmex->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel);
vGroundNormal = -1. * Propagate->GetTec2b() * normal; vGroundNormal = Propagate->GetTec2b() * normal;
// The height returned above is the AGL and is expressed in the Z direction of the local // The height returned above is the AGL and is expressed in the Z direction of the local
// coordinate frame. We now need to transform this height in actual compression of the strut (BOGEY) // coordinate frame. We now need to transform this height in actual compression of the strut (BOGEY)
@ -335,7 +334,7 @@ FGColumnVector3& FGLGear::GetBodyForces(void)
compressLength = verticalZProj > 0.0 ? -height / verticalZProj : 0.0; compressLength = verticalZProj > 0.0 ? -height / verticalZProj : 0.0;
break; break;
case ctSTRUCTURE: case ctSTRUCTURE:
verticalZProj = (Propagate->GetTec2l()*normal)(eZ); verticalZProj = -(Propagate->GetTec2l()*normal)(eZ);
compressLength = fabs(verticalZProj) > 0.0 ? -height / verticalZProj : 0.0; compressLength = fabs(verticalZProj) > 0.0 ? -height / verticalZProj : 0.0;
break; break;
} }
@ -516,7 +515,13 @@ void FGLGear::ComputeSteeringAngle(void)
SteerAngle = 0.0; SteerAngle = 0.0;
break; break;
case stCaster: case stCaster:
SteerAngle = atan2(vWhlVelVec(eY), fabs(vWhlVelVec(eX))); if (!Castered)
SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber);
else {
// Check that the speed is non-null otherwise use the current angle
if (vWhlVelVec.Magnitude(eX,eY) > 1E-3)
SteerAngle = atan2(vWhlVelVec(eY), fabs(vWhlVelVec(eX)));
}
break; break;
default: default:
cerr << "Improper steering type membership detected for this gear." << endl; cerr << "Improper steering type membership detected for this gear." << endl;
@ -571,7 +576,7 @@ void FGLGear::InitializeReporting(void)
void FGLGear::ReportTakeoffOrLanding(void) void FGLGear::ReportTakeoffOrLanding(void)
{ {
double deltaT = State->Getdt()*fdmex->GetGroundReactions()->GetRate(); double deltaT = fdmex->GetDeltaT()*fdmex->GetGroundReactions()->GetRate();
if (FirstContact) if (FirstContact)
LandingDistanceTraveled += Auxiliary->GetVground()*deltaT; LandingDistanceTraveled += Auxiliary->GetVground()*deltaT;
@ -608,10 +613,10 @@ void FGLGear::CrashDetect(void)
if ( (compressLength > 500.0 || if ( (compressLength > 500.0 ||
vFn.Magnitude() > 100000000.0 || vFn.Magnitude() > 100000000.0 ||
GetMoments().Magnitude() > 5000000000.0 || GetMoments().Magnitude() > 5000000000.0 ||
SinkRate > 1.4666*30 ) && !State->IntegrationSuspended()) SinkRate > 1.4666*30 ) && !fdmex->IntegrationSuspended())
{ {
PutMessage("Crash Detected: Simulation FREEZE."); PutMessage("Crash Detected: Simulation FREEZE.");
State->SuspendIntegration(); fdmex->SuspendIntegration();
} }
} }
@ -760,8 +765,10 @@ void FGLGear::bind(void)
fdmex->GetPropertyManager()->Tie( property_name.c_str(), &staticFCoeff ); fdmex->GetPropertyManager()->Tie( property_name.c_str(), &staticFCoeff );
if (eSteerType == stCaster) { if (eSteerType == stCaster) {
property_name = base_property_name + "/steering-angle-rad"; property_name = base_property_name + "/steering-angle-deg";
fdmex->GetPropertyManager()->Tie( property_name.c_str(), &SteerAngle ); fdmex->GetPropertyManager()->Tie( property_name.c_str(), this, &FGLGear::GetSteerAngleDeg );
property_name = base_property_name + "/castered";
fdmex->GetPropertyManager()->Tie( property_name.c_str(), &Castered);
} }
} }
@ -780,7 +787,7 @@ void FGLGear::Report(ReportType repType)
switch(repType) { switch(repType) {
case erLand: case erLand:
cout << endl << "Touchdown report for " << name << " (WOW at time: " cout << endl << "Touchdown report for " << name << " (WOW at time: "
<< fdmex->GetState()->Getsim_time() << " seconds)" << endl; << fdmex->GetSimTime() << " seconds)" << endl;
cout << " Sink rate at contact: " << SinkRate << " fps, " cout << " Sink rate at contact: " << SinkRate << " fps, "
<< SinkRate*0.3048 << " mps" << endl; << SinkRate*0.3048 << " mps" << endl;
cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, " cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, "
@ -795,7 +802,7 @@ void FGLGear::Report(ReportType repType)
break; break;
case erTakeoff: case erTakeoff:
cout << endl << "Takeoff report for " << name << " (Liftoff at time: " cout << endl << "Takeoff report for " << name << " (Liftoff at time: "
<< fdmex->GetState()->Getsim_time() << " seconds)" << endl; << fdmex->GetSimTime() << " seconds)" << endl;
cout << " Distance traveled: " << TakeoffDistanceTraveled cout << " Distance traveled: " << TakeoffDistanceTraveled
<< " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl; << " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl;
cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_LGEAR "$Id$" #define ID_LGEAR "$Id: FGLGear.h,v 1.38 2010/03/23 22:44:36 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -84,7 +84,6 @@ CLASS DOCUMENTATION
<h3>Operational Properties</h3> <h3>Operational Properties</h3>
<ol> <ol>
<li>Name</li> <li>Name</li>
<li>Steerability attribute {one of STEERABLE | FIXED | CASTERED}</li>
<li>Brake Group Membership {one of LEFT | CENTER | RIGHT | NOSE | TAIL | NONE}</li> <li>Brake Group Membership {one of LEFT | CENTER | RIGHT | NOSE | TAIL | NONE}</li>
<li>Max Steer Angle, in degrees</li> <li>Max Steer Angle, in degrees</li>
</ol></p> </ol></p>
@ -190,7 +189,7 @@ CLASS DOCUMENTATION
</contact> </contact>
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGLGear.h,v 1.38 2010/03/23 22:44:36 andgi Exp $
@see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at @see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
NASA-Ames", NASA CR-2497, January 1975 NASA-Ames", NASA CR-2497, January 1975
@see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics", @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
@ -289,6 +288,7 @@ public:
double GetWheelVel(int axis) const { return vWhlVelVec(axis);} double GetWheelVel(int axis) const { return vWhlVelVec(axis);}
bool IsBogey(void) const { return (eContactType == ctBOGEY);} bool IsBogey(void) const { return (eContactType == ctBOGEY);}
double GetGearUnitPos(void); double GetGearUnitPos(void);
double GetSteerAngleDeg(void) const { return radtodeg*SteerAngle; }
void bind(void); void bind(void);
@ -337,6 +337,7 @@ private:
bool isRetractable; bool isRetractable;
bool GearUp, GearDown; bool GearUp, GearDown;
bool Servicable; bool Servicable;
bool Castered;
std::string name; std::string name;
std::string sSteerType; std::string sSteerType;
std::string sBrakeGroup; std::string sBrakeGroup;

View file

@ -40,16 +40,18 @@ INCLUDES
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "FGPropulsion.h" #include "FGPropulsion.h"
#include "propulsion/FGTank.h"
#include "FGBuoyantForces.h" #include "FGBuoyantForces.h"
#include "input_output/FGPropertyManager.h" #include "input_output/FGPropertyManager.h"
#include <iostream> #include <iostream>
#include <iomanip>
#include <cstdlib> #include <cstdlib>
using namespace std; using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.31 2010/02/19 00:30:00 jberndt Exp $";
static const char *IdHdr = ID_MASSBALANCE; static const char *IdHdr = ID_MASSBALANCE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -124,7 +126,9 @@ bool FGMassBalance::Load(Element* el)
SetAircraftBaseInertias(FGMatrix33( bixx, -bixy, bixz, SetAircraftBaseInertias(FGMatrix33( bixx, -bixy, bixz,
-bixy, biyy, -biyz, -bixy, biyy, -biyz,
bixz, -biyz, bizz )); bixz, -biyz, bizz ));
EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS"); if (el->FindElement("emptywt")) {
EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS");
}
element = el->FindElement("location"); element = el->FindElement("location");
while (element) { while (element) {
@ -241,6 +245,7 @@ bool FGMassBalance::Run(void)
void FGMassBalance::AddPointMass(Element* el) void FGMassBalance::AddPointMass(Element* el)
{ {
double radius=0, length=0;
Element* loc_element = el->FindElement("location"); Element* loc_element = el->FindElement("location");
string pointmass_name = el->GetAttributeValue("name"); string pointmass_name = el->GetAttributeValue("name");
if (!loc_element) { if (!loc_element) {
@ -251,8 +256,36 @@ void FGMassBalance::AddPointMass(Element* el)
double w = el->FindElementValueAsNumberConvertTo("weight", "LBS"); double w = el->FindElementValueAsNumberConvertTo("weight", "LBS");
FGColumnVector3 vXYZ = loc_element->FindElementTripletConvertTo("IN"); FGColumnVector3 vXYZ = loc_element->FindElementTripletConvertTo("IN");
PointMasses.push_back(new PointMass(w, vXYZ)); PointMass *pm = new PointMass(w, vXYZ);
PointMasses.back()->bind(PropertyManager, PointMasses.size()-1); pm->SetName(pointmass_name);
Element* form_element = el->FindElement("form");
if (form_element) {
string shape = form_element->GetAttributeValue("shape");
Element* radius_element = form_element->FindElement("radius");
Element* length_element = form_element->FindElement("length");
if (radius_element) radius = form_element->FindElementValueAsNumberConvertTo("radius", "FT");
if (length_element) length = form_element->FindElementValueAsNumberConvertTo("length", "FT");
if (shape == "tube") {
pm->SetPointMassShapeType(PointMass::esTube);
pm->SetRadius(radius);
pm->SetLength(length);
pm->CalculateShapeInertia();
} else if (shape == "cylinder") {
pm->SetPointMassShapeType(PointMass::esCylinder);
pm->SetRadius(radius);
pm->SetLength(length);
pm->CalculateShapeInertia();
} else if (shape == "sphere") {
pm->SetPointMassShapeType(PointMass::esSphere);
pm->SetRadius(radius);
pm->CalculateShapeInertia();
} else {
}
}
pm->bind(PropertyManager, PointMasses.size());
PointMasses.push_back(pm);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -290,8 +323,10 @@ FGMatrix33& FGMassBalance::CalculatePMInertias(void)
pmJ = FGMatrix33(); pmJ = FGMatrix33();
for (unsigned int i=0; i<size; i++) for (unsigned int i=0; i<size; i++) {
pmJ += GetPointmassInertia( lbtoslug * PointMasses[i]->Weight, PointMasses[i]->Location ); pmJ += GetPointmassInertia( lbtoslug * PointMasses[i]->Weight, PointMasses[i]->Location );
pmJ += PointMasses[i]->GetPointMassInertia();
}
return pmJ; return pmJ;
} }
@ -339,7 +374,7 @@ void FGMassBalance::bind(void)
PropertyManager->Tie("inertia/weight-lbs", this, PropertyManager->Tie("inertia/weight-lbs", this,
&FGMassBalance::GetWeight); &FGMassBalance::GetWeight);
PropertyManager->Tie("inertia/empty-weight-lbs", this, PropertyManager->Tie("inertia/empty-weight-lbs", this,
&FGMassBalance::GetWeight, &FGMassBalance::SetEmptyWeight); &FGMassBalance::GetEmptyWeight);
PropertyManager->Tie("inertia/cg-x-in", this,1, PropertyManager->Tie("inertia/cg-x-in", this,1,
(PMF)&FGMassBalance::GetXYZcg); (PMF)&FGMassBalance::GetXYZcg);
PropertyManager->Tie("inertia/cg-y-in", this,2, PropertyManager->Tie("inertia/cg-y-in", this,2,
@ -349,7 +384,9 @@ void FGMassBalance::bind(void)
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// This function binds properties for each pointmass object created.
//
void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num) { void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num) {
string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num); string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num);
PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight, PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight,
@ -366,6 +403,63 @@ void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num)
&PointMass::SetPointMassLocation); &PointMass::SetPointMassLocation);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGMassBalance::GetMassPropertiesReport(void) const
{
cout << endl << fgblue << highint
<< " Mass Properties Report (English units: lbf, in, slug-ft^2)"
<< reset << endl;
cout << " " << underon << " Weight CG-X CG-Y"
<< " CG-Z Ixx Iyy Izz" << underoff << endl;
cout.precision(1);
cout << highint << setw(34) << left << " Base Vehicle " << normint
<< right << setw(10) << EmptyWeight << setw(8) << vbaseXYZcg(eX) << setw(8)
<< vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ) << setw(12) << baseJ(1,1)
<< setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3) << endl;
for (unsigned int i=0;i<PointMasses.size();i++) {
PointMass* pm = PointMasses[i];
double pmweight = pm->GetPointMassWeight();
cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint
<< right << setw(10) << pmweight << setw(8) << pm->GetLocation()(eX)
<< setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ)
<< setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2)
<< setw(12) << pm->GetPointMassMoI(3,3) << endl;
}
for (unsigned int i=0;i<Propulsion->GetNumTanks() ;i++) {
FGTank* tank = Propulsion->GetTank(i);
string tankname="";
if (tank->GetType() == FGTank::ttFUEL && tank->GetGrainType() != FGTank::gtUNKNOWN) {
tankname = "Solid Fuel";
} else if (tank->GetType() == FGTank::ttFUEL) {
tankname = "Fuel";
} else if (tank->GetType() == FGTank::ttOXIDIZER) {
tankname = "Oxidizer";
} else {
tankname = "(Unknown tank type)";
}
cout << highint << left << setw(4) << i << setw(30) << tankname << normint
<< right << setw(10) << tank->GetContents() << setw(8) << tank->GetXYZ(eX)
<< setw(8) << tank->GetXYZ(eY) << setw(8) << tank->GetXYZ(eZ)
<< setw(12) << "*" << setw(12) << "*"
<< setw(12) << "*" << endl;
}
cout << underon << setw(104) << " " << underoff << endl;
cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight
<< setw(8) << vXYZcg(eX)
<< setw(8) << vXYZcg(eY)
<< setw(8) << vXYZcg(eZ)
<< setw(12) << mJ(1,1)
<< setw(12) << mJ(2,2)
<< setw(12) << mJ(3,3)
<< normint << endl;
cout.setf(ios_base::fixed);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows: // The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print // unset: In this case (the default) JSBSim would only print
@ -398,7 +492,7 @@ void FGMassBalance::Debug(int from)
cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl; cout << " baseIxy: " << baseJ(1,2) << " slug-ft2" << endl;
cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl; cout << " baseIxz: " << baseJ(1,3) << " slug-ft2" << endl;
cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl; cout << " baseIyz: " << baseJ(2,3) << " slug-ft2" << endl;
cout << " EmptyWeight: " << EmptyWeight << " lbm" << endl; cout << " Empty Weight: " << EmptyWeight << " lbm" << endl;
cout << " CG (x, y, z): " << vbaseXYZcg << endl; cout << " CG (x, y, z): " << vbaseXYZcg << endl;
// ToDo: Need to add point mass outputs here // ToDo: Need to add point mass outputs here
for (unsigned int i=0; i<PointMasses.size(); i++) { for (unsigned int i=0; i<PointMasses.size(); i++) {

View file

@ -43,17 +43,20 @@ INCLUDES
#include "math/FGMatrix33.h" #include "math/FGMatrix33.h"
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#include <vector> #include <vector>
#include <string>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MASSBALANCE "$Id$" #define ID_MASSBALANCE "$Id: FGMassBalance.h,v 1.20 2010/02/04 13:09:26 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONSS FORWARD DECLARATIONSS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
using std::string;
namespace JSBSim { namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -109,9 +112,10 @@ public:
double GetMass(void) const {return Mass;} double GetMass(void) const {return Mass;}
double GetWeight(void) const {return Weight;} double GetWeight(void) const {return Weight;}
FGColumnVector3& GetXYZcg(void) {return vXYZcg;} double GetEmptyWeight(void) const {return EmptyWeight;}
const FGColumnVector3& GetXYZcg(void) const {return vXYZcg;}
double GetXYZcg(int axis) const {return vXYZcg(axis);} double GetXYZcg(int axis) const {return vXYZcg(axis);}
FGColumnVector3& GetDeltaXYZcg(void) {return vDeltaXYZcg;} const FGColumnVector3& GetDeltaXYZcg(void) const {return vDeltaXYZcg;}
double GetDeltaXYZcg(int axis) const {return vDeltaXYZcg(axis);} double GetDeltaXYZcg(int axis) const {return vDeltaXYZcg(axis);}
/** Computes the inertia contribution of a pointmass. /** Computes the inertia contribution of a pointmass.
@ -158,6 +162,7 @@ public:
FGMatrix33& GetJ(void) {return mJ;} FGMatrix33& GetJ(void) {return mJ;}
FGMatrix33& GetJinv(void) {return mJinv;} FGMatrix33& GetJinv(void) {return mJinv;}
void SetAircraftBaseInertias(FGMatrix33 BaseJ) {baseJ = BaseJ;} void SetAircraftBaseInertias(FGMatrix33 BaseJ) {baseJ = BaseJ;}
void GetMassPropertiesReport(void) const;
private: private:
double Weight; double Weight;
@ -177,17 +182,57 @@ private:
FGColumnVector3 PointMassCG; FGColumnVector3 PointMassCG;
FGMatrix33& CalculatePMInertias(void); FGMatrix33& CalculatePMInertias(void);
/** The PointMass structure encapsulates a point mass object, moments of inertia
mass, location, etc. */
struct PointMass { struct PointMass {
PointMass(double w, FGColumnVector3& vXYZ) { PointMass(double w, FGColumnVector3& vXYZ) {
Weight = w; Weight = w;
Location = vXYZ; Location = vXYZ;
mPMInertia.InitMatrix();
Radius = 0.0;
Length = 0.0;
} }
void CalculateShapeInertia(void) {
switch(eShapeType) {
case esTube:
mPMInertia(1,1) = (Weight/(32.16))*Radius*Radius; // mr^2
mPMInertia(2,2) = (Weight/(32.16*12))*(6*Radius*Radius + Length*Length);
mPMInertia(3,3) = mPMInertia(2,2);
break;
case esCylinder:
mPMInertia(1,1) = (Weight/(32.16*2))*Radius*Radius; // 0.5*mr^2
mPMInertia(2,2) = (Weight/(32.16*12))*(3*Radius*Radius + Length*Length);
mPMInertia(3,3) = mPMInertia(2,2);
break;
default:
break;
}
}
enum esShape {esUnspecified, esTube, esCylinder, esSphere} eShapeType;
FGColumnVector3 Location; FGColumnVector3 Location;
double Weight; double Weight; /// Weight in pounds.
double Radius; /// Radius in feet.
double Length; /// Length in feet.
string Name;
FGMatrix33 mPMInertia;
double GetPointMassLocation(int axis) const {return Location(axis);} double GetPointMassLocation(int axis) const {return Location(axis);}
double GetPointMassWeight(void) const {return Weight;}
esShape GetShapeType(void) {return eShapeType;}
FGColumnVector3 GetLocation(void) {return Location;}
FGMatrix33 GetPointMassInertia(void) {return mPMInertia;}
string GetName(void) {return Name;}
void SetPointMassLocation(int axis, double value) {Location(axis) = value;} void SetPointMassLocation(int axis, double value) {Location(axis) = value;}
void SetPointMassWeight(double wt) {Weight = wt;} void SetPointMassWeight(double wt) {Weight = wt;}
double GetPointMassWeight(void) const {return Weight;} void SetPointMassShapeType(esShape st) {eShapeType = st;}
void SetRadius(double r) {Radius = r;}
void SetLength(double l) {Length = l;}
void SetName(string name) {Name = name;}
double GetPointMassMoI(int r, int c) {return mPMInertia(r,c);}
void bind(FGPropertyManager* PropertyManager, int num); void bind(FGPropertyManager* PropertyManager, int num);
}; };

View file

@ -39,7 +39,6 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h" #include "FGModel.h"
#include "FGState.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGFCS.h" #include "FGFCS.h"
@ -58,7 +57,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGModel.cpp,v 1.14 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdHdr = ID_MODEL; static const char *IdHdr = ID_MODEL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -74,7 +73,6 @@ FGModel::FGModel(FGFDMExec* fdmex)
FDMExec = fdmex; FDMExec = fdmex;
NextModel = 0L; NextModel = 0L;
State = 0;
Atmosphere = 0; Atmosphere = 0;
FCS = 0; FCS = 0;
Propulsion = 0; Propulsion = 0;
@ -115,7 +113,6 @@ FGModel::~FGModel()
bool FGModel::InitModel(void) bool FGModel::InitModel(void)
{ {
State = FDMExec->GetState();
Atmosphere = FDMExec->GetAtmosphere(); Atmosphere = FDMExec->GetAtmosphere();
FCS = FDMExec->GetFCS(); FCS = FDMExec->GetFCS();
Propulsion = FDMExec->GetPropulsion(); Propulsion = FDMExec->GetPropulsion();
@ -129,8 +126,7 @@ bool FGModel::InitModel(void)
Propagate = FDMExec->GetPropagate(); Propagate = FDMExec->GetPropagate();
Auxiliary = FDMExec->GetAuxiliary(); Auxiliary = FDMExec->GetAuxiliary();
if (!State || if (!Atmosphere ||
!Atmosphere ||
!FCS || !FCS ||
!Propulsion || !Propulsion ||
!MassBalance || !MassBalance ||

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MODEL "$Id$" #define ID_MODEL "$Id: FGModel.h,v 1.14 2009/11/12 13:08:11 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS

View file

@ -40,7 +40,6 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGOutput.h" #include "FGOutput.h"
#include "FGState.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGAtmosphere.h" #include "FGAtmosphere.h"
#include "FGFCS.h" #include "FGFCS.h"
@ -53,6 +52,7 @@ INCLUDES
#include "FGPropagate.h" #include "FGPropagate.h"
#include "FGAuxiliary.h" #include "FGAuxiliary.h"
#include "FGInertial.h" #include "FGInertial.h"
#include "FGPropulsion.h"
#include "models/propulsion/FGEngine.h" #include "models/propulsion/FGEngine.h"
#include "models/propulsion/FGTank.h" #include "models/propulsion/FGTank.h"
#include "models/propulsion/FGPiston.h" #include "models/propulsion/FGPiston.h"
@ -77,7 +77,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGOutput.cpp,v 1.48 2010/04/12 12:25:19 jberndt Exp $";
static const char *IdHdr = ID_OUTPUT; static const char *IdHdr = ID_OUTPUT;
// (stolen from FGFS native_fdm.cxx) // (stolen from FGFS native_fdm.cxx)
@ -187,7 +187,7 @@ bool FGOutput::Run(void)
{ {
if (FGModel::Run()) return true; if (FGModel::Run()) return true;
if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) { if (enabled && !FDMExec->IntegrationSuspended()&& !FDMExec->Holding()) {
RunPreFunctions(); RunPreFunctions();
if (Type == otSocket) { if (Type == otSocket) {
SocketOutput(); SocketOutput();
@ -267,7 +267,8 @@ void FGOutput::DelimitedOutput(const string& fname)
if (SubSystems & ssRates) { if (SubSystems & ssRates) {
outstream << delimeter; outstream << delimeter;
outstream << "P (deg/s)" + delimeter + "Q (deg/s)" + delimeter + "R (deg/s)" + delimeter; outstream << "P (deg/s)" + delimeter + "Q (deg/s)" + delimeter + "R (deg/s)" + delimeter;
outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)"; outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)" + delimeter;
outstream << "P_{inertial} (deg/s)" + delimeter + "Q_{inertial} (deg/s)" + delimeter + "R_{inertial} (deg/s)";
} }
if (SubSystems & ssVelocities) { if (SubSystems & ssVelocities) {
outstream << delimeter; outstream << delimeter;
@ -277,6 +278,7 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << "V_{Inertial} (ft/s)" + delimeter; outstream << "V_{Inertial} (ft/s)" + delimeter;
outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter; outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter; outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter;
outstream << "V_{X_{inertial}} (ft/s)" + delimeter + "V_{Y_{inertial}} (ft/s)" + delimeter + "V_{Z_{inertial}} (ft/s)" + delimeter;
outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)"; outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)";
} }
if (SubSystems & ssForces) { if (SubSystems & ssForces) {
@ -334,8 +336,9 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << "Beta (deg)" + delimeter; outstream << "Beta (deg)" + delimeter;
outstream << "Latitude (deg)" + delimeter; outstream << "Latitude (deg)" + delimeter;
outstream << "Longitude (deg)" + delimeter; outstream << "Longitude (deg)" + delimeter;
outstream << "ECEF X (ft)" + delimeter + "ECEF Y (ft)" + delimeter + "ECEF Z (ft)" + delimeter; outstream << "X_{ECI} (ft)" + delimeter + "Y_{ECI} (ft)" + delimeter + "Z_{ECI} (ft)" + delimeter;
outstream << "EPA (deg)" + delimeter; outstream << "X_{ECEF} (ft)" + delimeter + "Y_{ECEF} (ft)" + delimeter + "Z_{ECEF} (ft)" + delimeter;
outstream << "Earth Position Angle (deg)" + delimeter;
outstream << "Distance AGL (ft)" + delimeter; outstream << "Distance AGL (ft)" + delimeter;
outstream << "Terrain Elevation (ft)"; outstream << "Terrain Elevation (ft)";
} }
@ -365,7 +368,7 @@ void FGOutput::DelimitedOutput(const string& fname)
dFirstPass = false; dFirstPass = false;
} }
outstream << State->Getsim_time(); outstream << FDMExec->GetSimTime();
if (SubSystems & ssSimulation) { if (SubSystems & ssSimulation) {
} }
if (SubSystems & ssAerosurfaces) { if (SubSystems & ssAerosurfaces) {
@ -383,7 +386,8 @@ void FGOutput::DelimitedOutput(const string& fname)
if (SubSystems & ssRates) { if (SubSystems & ssRates) {
outstream << delimeter; outstream << delimeter;
outstream << (radtodeg*Propagate->GetPQR()).Dump(delimeter) << delimeter; outstream << (radtodeg*Propagate->GetPQR()).Dump(delimeter) << delimeter;
outstream << (radtodeg*Propagate->GetPQRdot()).Dump(delimeter); outstream << (radtodeg*Propagate->GetPQRdot()).Dump(delimeter) << delimeter;
outstream << (radtodeg*Propagate->GetPQRi()).Dump(delimeter);
} }
if (SubSystems & ssVelocities) { if (SubSystems & ssVelocities) {
outstream << delimeter; outstream << delimeter;
@ -393,6 +397,7 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << Propagate->GetInertialVelocityMagnitude() << delimeter; outstream << Propagate->GetInertialVelocityMagnitude() << delimeter;
outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter; outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter; outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter;
outstream << Propagate->GetVel().Dump(delimeter); outstream << Propagate->GetVel().Dump(delimeter);
outstream.precision(10); outstream.precision(10);
} }
@ -445,6 +450,7 @@ void FGOutput::DelimitedOutput(const string& fname)
outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter; outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter;
outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter; outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter;
outstream.precision(18); outstream.precision(18);
outstream << ((FGColumnVector3)Propagate->GetInertialPosition()).Dump(delimeter) << delimeter;
outstream << ((FGColumnVector3)Propagate->GetLocation()).Dump(delimeter) << delimeter; outstream << ((FGColumnVector3)Propagate->GetLocation()).Dump(delimeter) << delimeter;
outstream.precision(14); outstream.precision(14);
outstream << Inertial->GetEarthPositionAngleDeg() << delimeter; outstream << Inertial->GetEarthPositionAngleDeg() << delimeter;
@ -817,7 +823,7 @@ void FGOutput::SocketOutput(void)
} }
socket->Clear(); socket->Clear();
socket->Append(State->Getsim_time()); socket->Append(FDMExec->GetSimTime());
if (SubSystems & ssAerosurfaces) { if (SubSystems & ssAerosurfaces) {
socket->Append(FCS->GetDaCmd()); socket->Append(FCS->GetDaCmd());
@ -952,13 +958,15 @@ bool FGOutput::Load(Element* element)
output_file_name = DirectivesFile; // one found in the config file. output_file_name = DirectivesFile; // one found in the config file.
document = LoadXMLDocument(output_file_name); document = LoadXMLDocument(output_file_name);
} else if (!element->GetAttributeValue("file").empty()) { } else if (!element->GetAttributeValue("file").empty()) {
output_file_name = element->GetAttributeValue("file"); output_file_name = FDMExec->GetRootDir() + element->GetAttributeValue("file");
document = LoadXMLDocument(output_file_name); document = LoadXMLDocument(output_file_name);
} else { } else {
document = element; document = element;
} }
name = document->GetAttributeValue("name"); if (!document) return false;
name = FDMExec->GetRootDir() + document->GetAttributeValue("name");
type = document->GetAttributeValue("type"); type = document->GetAttributeValue("type");
SetType(type); SetType(type);
if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) { if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) {
@ -1035,7 +1043,7 @@ void FGOutput::SetRate(int rtHz)
{ {
rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz); rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz);
if (rtHz > 0) { if (rtHz > 0) {
rate = (int)(0.5 + 1.0/(State->Getdt()*rtHz)); rate = (int)(0.5 + 1.0/(FDMExec->GetDeltaT()*rtHz));
Enable(); Enable();
} else { } else {
rate = 1; rate = 1;
@ -1085,7 +1093,7 @@ void FGOutput::Debug(int from)
} }
switch (Type) { switch (Type) {
case otCSV: case otCSV:
cout << scratch << " in CSV format output at rate " << 1/(State->Getdt()*rate) << " Hz" << endl; cout << scratch << " in CSV format output at rate " << 1/(FDMExec->GetDeltaT()*rate) << " Hz" << endl;
break; break;
case otNone: case otNone:
default: default:

View file

@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_OUTPUT "$Id$" #define ID_OUTPUT "$Id: FGOutput.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -123,7 +123,7 @@ CLASS DOCUMENTATION
propulsion ON|OFF propulsion ON|OFF
</pre> </pre>
NOTE that Time is always output with the data. NOTE that Time is always output with the data.
@version $Id$ @version $Id: FGOutput.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -56,10 +56,11 @@ INCLUDES
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <iomanip>
#include "FGPropagate.h" #include "FGPropagate.h"
#include "FGGroundReactions.h"
#include "FGFDMExec.h" #include "FGFDMExec.h"
#include "FGState.h"
#include "FGAircraft.h" #include "FGAircraft.h"
#include "FGMassBalance.h" #include "FGMassBalance.h"
#include "FGInertial.h" #include "FGInertial.h"
@ -69,7 +70,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.55 2010/07/09 04:11:45 jberndt Exp $";
static const char *IdHdr = ID_PROPAGATE; static const char *IdHdr = ID_PROPAGATE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -80,30 +81,23 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
{ {
Debug(0); Debug(0);
Name = "FGPropagate"; Name = "FGPropagate";
gravType = gtWGS84;
last2_vPQRdot.InitMatrix();
last_vPQRdot.InitMatrix();
vPQRdot.InitMatrix(); vPQRdot.InitMatrix();
last2_vQtrndot = FGQuaternion(0,0,0);
last_vQtrndot = FGQuaternion(0,0,0);
vQtrndot = FGQuaternion(0,0,0); vQtrndot = FGQuaternion(0,0,0);
last2_vUVWdot.InitMatrix();
last_vUVWdot.InitMatrix();
vUVWdot.InitMatrix(); vUVWdot.InitMatrix();
vInertialVelocity.InitMatrix();
last2_vLocationDot.InitMatrix();
last_vLocationDot.InitMatrix();
vLocationDot.InitMatrix();
vOmegaLocal.InitMatrix();
integrator_rotational_rate = eAdamsBashforth2; integrator_rotational_rate = eAdamsBashforth2;
integrator_translational_rate = eTrapezoidal; integrator_translational_rate = eTrapezoidal;
integrator_rotational_position = eAdamsBashforth2; integrator_rotational_position = eAdamsBashforth2;
integrator_translational_position = eTrapezoidal; integrator_translational_position = eTrapezoidal;
VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqQtrndot.resize(4, FGQuaternion(0.0,0.0,0.0));
bind(); bind();
Debug(0); Debug(0);
} }
@ -126,25 +120,17 @@ bool FGPropagate::InitModel(void)
VState.vLocation.SetRadius( LocalTerrainRadius + 4.0 ); VState.vLocation.SetRadius( LocalTerrainRadius + 4.0 );
VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor()); VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor());
vOmega = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector vOmegaEarth = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector
last2_vPQRdot.InitMatrix();
last_vPQRdot.InitMatrix();
vPQRdot.InitMatrix(); vPQRdot.InitMatrix();
last2_vQtrndot = FGQuaternion(0,0,0);
last_vQtrndot = FGQuaternion(0,0,0);
vQtrndot = FGQuaternion(0,0,0); vQtrndot = FGQuaternion(0,0,0);
last2_vUVWdot.InitMatrix();
last_vUVWdot.InitMatrix();
vUVWdot.InitMatrix(); vUVWdot.InitMatrix();
vInertialVelocity.InitMatrix();
last2_vLocationDot.InitMatrix();
last_vLocationDot.InitMatrix();
vLocationDot.InitMatrix();
vOmegaLocal.InitMatrix(); VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
integrator_rotational_rate = eAdamsBashforth2; integrator_rotational_rate = eAdamsBashforth2;
integrator_translational_rate = eTrapezoidal; integrator_translational_rate = eTrapezoidal;
@ -161,51 +147,92 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC()); SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC());
SetTerrainElevation(FGIC->GetTerrainElevationFtIC()); SetTerrainElevation(FGIC->GetTerrainElevationFtIC());
// Set the position lat/lon/radius
VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(),
FGIC->GetLatitudeRadIC(),
FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
VehicleRadius = GetRadius(); VehicleRadius = GetRadius();
radInv = 1.0/VehicleRadius; radInv = 1.0/VehicleRadius;
// Set the Orientation from the euler angles // Initialize the State Vector elements and the transformation matrices
VState.vQtrn = FGQuaternion( FGIC->GetPhiRadIC(),
FGIC->GetThetaRadIC(), // Set the position lat/lon/radius
FGIC->GetPsiRadIC() ); VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(),
FGIC->GetLatitudeRadIC(),
FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle());
Ti2ec = GetTi2ec(); // ECI to ECEF transform
Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
Tl2ec = GetTl2ec(); // local to ECEF transform
Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
Ti2l = GetTi2l();
Tl2i = Ti2l.Transposed();
// Set the orientation from the euler angles (is normalized within the
// constructor). The Euler angles represent the orientation of the body
// frame relative to the local frame.
VState.qAttitudeLocal = FGQuaternion( FGIC->GetPhiRadIC(),
FGIC->GetThetaRadIC(),
FGIC->GetPsiRadIC() );
VState.qAttitudeECI = Ti2l.GetQuaternion()*VState.qAttitudeLocal;
Ti2b = GetTi2b(); // ECI to body frame transform
Tb2i = Ti2b.Transposed(); // body to ECI frame transform
Tl2b = VState.qAttitudeLocal; // local to body frame transform
Tb2l = Tl2b.Transposed(); // body to local frame transform
Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
// Set the velocities in the instantaneus body frame // Set the velocities in the instantaneus body frame
VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(), VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(),
FGIC->GetVBodyFpsIC(), FGIC->GetVBodyFpsIC(),
FGIC->GetWBodyFpsIC() ); FGIC->GetWBodyFpsIC() );
// Set the angular velocities in the instantaneus body frame. VState.vInertialPosition = Tec2i * VState.vLocation;
VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
FGIC->GetQRadpsIC(),
FGIC->GetRRadpsIC() );
// Compute the local frame ECEF velocity // Compute the local frame ECEF velocity
vVel = GetTb2l()*VState.vUVW; vVel = Tb2l * VState.vUVW;
// Finally, make sure that the quaternion stays normalized. // Refer to Stevens and Lewis, 1.5-14a, pg. 49.
VState.vQtrn.Normalize(); // This is the rotation rate of the "Local" frame, expressed in the local frame.
FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vVel(eEast),
-radInv*vVel(eNorth),
-radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
// Set the angular velocities of the body frame relative to the ECEF frame,
// expressed in the body frame. Effectively, this is:
// w_b/e = w_b/l + w_l/e
VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
FGIC->GetQRadpsIC(),
FGIC->GetRRadpsIC() ) + Tl2b*vOmegaLocal;
VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
// Make an initial run and set past values
CalculatePQRdot(); // Angular rate derivative
CalculateUVWdot(); // Translational rate derivative
CalculateQuatdot(); // Angular orientation derivative
CalculateInertialVelocity(); // Translational position derivative
// Initialize past values deques
VState.dqPQRdot.clear();
VState.dqUVWdot.clear();
VState.dqInertialVelocity.clear();
VState.dqQtrndot.clear();
for (int i=0; i<4; i++) {
VState.dqPQRdot.push_front(vPQRdot);
VState.dqUVWdot.push_front(vUVWdot);
VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
VState.dqQtrndot.push_front(vQtrndot);
}
// Recompute the LocalTerrainRadius. // Recompute the LocalTerrainRadius.
RecomputeLocalTerrainRadius(); RecomputeLocalTerrainRadius();
// These local copies of the transformation matrices are for use for
// initial conditions only.
Tl2b = GetTl2b(); // local to body frame transform
Tb2l = Tl2b.Transposed(); // body to local frame transform
Tl2ec = GetTl2ec(); // local to ECEF transform
Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
Ti2ec = GetTi2ec(); // ECI to ECEF transform
Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
Ti2b = Tec2b*Ti2ec; // ECI to body frame transform
Tb2i = Ti2b.Transposed(); // body to ECI frame transform
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -230,123 +257,65 @@ Inertial.
bool FGPropagate::Run(void) bool FGPropagate::Run(void)
{ {
static int ctr;
if (FGModel::Run()) return true; // Fast return if we have nothing to do ... if (FGModel::Run()) return true; // Fast return if we have nothing to do ...
if (FDMExec->Holding()) return false; if (FDMExec->Holding()) return false;
double dt = FDMExec->GetDeltaT()*rate; // The 'stepsize'
RunPreFunctions(); RunPreFunctions();
// Calculate state derivatives
CalculatePQRdot(); // Angular rate derivative
CalculateUVWdot(); // Translational rate derivative
CalculateQuatdot(); // Angular orientation derivative
CalculateInertialVelocity(); // Translational position derivative
// Propagate rotational / translational velocity, angular /translational position, respectively.
Integrate(VState.vPQRi, vPQRdot, VState.dqPQRdot, dt, integrator_rotational_rate);
Integrate(VState.vUVW, vUVWdot, VState.dqUVWdot, dt, integrator_translational_rate);
Integrate(VState.qAttitudeECI, vQtrndot, VState.dqQtrndot, dt, integrator_rotational_position);
Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position);
VState.qAttitudeECI.Normalize(); // Normalize the ECI Attitude quaternion
VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); // Update the Earth position angle (EPA)
// Update the "Location-based" transformation matrices from the vLocation vector.
Ti2ec = GetTi2ec(); // ECI to ECEF transform
Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
Tl2ec = GetTl2ec(); // local to ECEF transform
Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
Ti2l = GetTi2l();
Tl2i = Ti2l.Transposed();
// Update the "Orientation-based" transformation matrices from the orientation quaternion
Ti2b = GetTi2b(); // ECI to body frame transform
Tb2i = Ti2b.Transposed(); // body to ECI frame transform
Tl2b = Ti2b*Tl2i; // local to body frame transform
Tb2l = Tl2b.Transposed(); // body to local frame transform
Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
// Set auxililary state variables
VState.vLocation = Ti2ec*VState.vInertialPosition;
RecomputeLocalTerrainRadius(); RecomputeLocalTerrainRadius();
// Calculate current aircraft radius from center of planet // Calculate current aircraft radius from center of planet
VehicleRadius = VState.vInertialPosition.Magnitude();
VehicleRadius = GetRadius();
radInv = 1.0/VehicleRadius; radInv = 1.0/VehicleRadius;
// These local copies of the transformation matrices are for use this VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
// pass through Run() only.
Tl2b = GetTl2b(); // local to body frame transform VState.qAttitudeLocal = Tl2b.GetQuaternion();
Tb2l = Tl2b.Transposed(); // body to local frame transform
Tl2ec = GetTl2ec(); // local to ECEF transform
Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
Ti2ec = GetTi2ec(); // ECI to ECEF transform
Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
Ti2b = Tec2b*Ti2ec; // ECI to body frame transform
Tb2i = Ti2b.Transposed(); // body to ECI frame transform
// Compute vehicle velocity wrt ECEF frame, expressed in Local horizontal frame. // Compute vehicle velocity wrt ECEF frame, expressed in Local horizontal frame.
vVel = Tb2l * VState.vUVW; vVel = Tb2l * VState.vUVW;
// Inertial angular velocity measured in the body frame. RunPostFunctions();
vPQRi = VState.vPQR + Tec2b*vOmega;
// Calculate state derivatives
CalculatePQRdot(); // Angular rate derivative
CalculateUVWdot(); // Translational rate derivative
CalculateQuatdot(); // Angular orientation derivative
CalculateLocationdot(); // Translational position derivative
// Integrate to propagate the state
double dt = State->Getdt()*rate; // The 'stepsize'
// Propagate rotational velocity
switch(integrator_rotational_rate) {
case eRectEuler: VState.vPQR += dt*vPQRdot;
break;
case eTrapezoidal: VState.vPQR += 0.5*dt*(vPQRdot + last_vPQRdot);
break;
case eAdamsBashforth2: VState.vPQR += dt*(1.5*vPQRdot - 0.5*last_vPQRdot);
break;
case eAdamsBashforth3: VState.vPQR += (1/12.0)*dt*(23.0*vPQRdot - 16.0*last_vPQRdot + 5.0*last2_vPQRdot);
break;
case eNone: // do nothing, freeze angular rate
break;
}
// Propagate translational velocity
switch(integrator_translational_rate) {
case eRectEuler: VState.vUVW += dt*vUVWdot;
break;
case eTrapezoidal: VState.vUVW += 0.5*dt*(vUVWdot + last_vUVWdot);
break;
case eAdamsBashforth2: VState.vUVW += dt*(1.5*vUVWdot - 0.5*last_vUVWdot);
break;
case eAdamsBashforth3: VState.vUVW += (1/12.0)*dt*(23.0*vUVWdot - 16.0*last_vUVWdot + 5.0*last2_vUVWdot);
break;
case eNone: // do nothing, freeze translational rate
break;
}
// Propagate angular position
switch(integrator_rotational_position) {
case eRectEuler: VState.vQtrn += dt*vQtrndot;
break;
case eTrapezoidal: VState.vQtrn += 0.5*dt*(vQtrndot + last_vQtrndot);
break;
case eAdamsBashforth2: VState.vQtrn += dt*(1.5*vQtrndot - 0.5*last_vQtrndot);
break;
case eAdamsBashforth3: VState.vQtrn += (1/12.0)*dt*(23.0*vQtrndot - 16.0*last_vQtrndot + 5.0*last2_vQtrndot);
break;
case eNone: // do nothing, freeze angular position
break;
}
// Propagate translational position
switch(integrator_translational_position) {
case eRectEuler: VState.vLocation += dt*vLocationDot;
break;
case eTrapezoidal: VState.vLocation += 0.5*dt*(vLocationDot + last_vLocationDot);
break;
case eAdamsBashforth2: VState.vLocation += dt*(1.5*vLocationDot - 0.5*last_vLocationDot);
break;
case eAdamsBashforth3: VState.vLocation += (1/12.0)*dt*(23.0*vLocationDot - 16.0*last_vLocationDot + 5.0*last2_vLocationDot);
break;
case eNone: // do nothing, freeze translational position
break;
}
// Set past values
last2_vPQRdot = last_vPQRdot;
last_vPQRdot = vPQRdot;
last2_vUVWdot = last_vUVWdot;
last_vUVWdot = vUVWdot;
last2_vQtrndot = last_vQtrndot;
last_vQtrndot = vQtrndot;
last2_vLocationDot = last_vLocationDot;
last_vLocationDot = vLocationDot;
RunPreFunctions();
Debug(2); Debug(2);
return false; return false;
@ -361,7 +330,7 @@ bool FGPropagate::Run(void)
// J is the inertia matrix // J is the inertia matrix
// Jinv is the inverse inertia matrix // Jinv is the inverse inertia matrix
// vMoments is the moment vector in the body frame // vMoments is the moment vector in the body frame
// vPQRi is the total inertial angular velocity of the vehicle // VState.vPQRi is the total inertial angular velocity of the vehicle
// expressed in the body frame. // expressed in the body frame.
// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", // Reference: See Stevens and Lewis, "Aircraft Control and Simulation",
// Second edition (2004), eqn 1.5-16e (page 50) // Second edition (2004), eqn 1.5-16e (page 50)
@ -376,7 +345,7 @@ void FGPropagate::CalculatePQRdot(void)
// moments and the total inertial angular velocity expressed in the body // moments and the total inertial angular velocity expressed in the body
// frame. // frame.
vPQRdot = Jinv*(vMoments - vPQRi*(J*vPQRi)); vPQRdot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi));
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -388,72 +357,140 @@ void FGPropagate::CalculatePQRdot(void)
void FGPropagate::CalculateQuatdot(void) void FGPropagate::CalculateQuatdot(void)
{ {
vOmegaLocal.InitMatrix( radInv*vVel(eEast),
-radInv*vVel(eNorth),
-radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
// Compute quaternion orientation derivative on current body rates // Compute quaternion orientation derivative on current body rates
vQtrndot = VState.vQtrn.GetQDot( VState.vPQR - Tl2b*vOmegaLocal); vQtrndot = VState.qAttitudeECI.GetQDot( VState.vPQRi);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This set of calculations results in the body frame accelerations being // This set of calculations results in the body frame accelerations being
// computed. // computed.
// Compute body frame accelerations based on the current body forces.
// Include centripetal and coriolis accelerations.
// vOmegaEarth is the Earth angular rate - expressed in the inertial frame -
// so it has to be transformed to the body frame. More completely,
// vOmegaEarth is the rate of the ECEF frame relative to the Inertial
// frame (ECI), expressed in the Inertial frame.
// vForces is the total force on the vehicle in the body frame.
// VState.vPQR is the vehicle body rate relative to the ECEF frame, expressed
// in the body frame.
// VState.vUVW is the vehicle velocity relative to the ECEF frame, expressed
// in the body frame.
// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", // Reference: See Stevens and Lewis, "Aircraft Control and Simulation",
// Second edition (2004), eqn 1.5-16d (page 50) // Second edition (2004), eqns 1.5-13 (pg 48) and 1.5-16d (page 50)
void FGPropagate::CalculateUVWdot(void) void FGPropagate::CalculateUVWdot(void)
{ {
double mass = MassBalance->GetMass(); // mass double mass = MassBalance->GetMass(); // mass
const FGColumnVector3& vForces = Aircraft->GetForces(); // current forces const FGColumnVector3& vForces = Aircraft->GetForces(); // current forces
const FGColumnVector3 vGravAccel( 0.0, 0.0, Inertial->GetGAccel(VehicleRadius) ); vUVWdot = vForces/mass - (VState.vPQR + 2.0*(Ti2b *vOmegaEarth)) * VState.vUVW;
// Begin to compute body frame accelerations based on the current body forces // Include Centripetal acceleration.
vUVWdot = vForces/mass - VState.vPQR * VState.vUVW; if (!GroundReactions->GetWOW() && Aircraft->GetHoldDown() == 0) {
vUVWdot -= Ti2b * (vOmegaEarth*(vOmegaEarth*VState.vInertialPosition));
// Include Coriolis acceleration.
vUVWdot -= 2.0 * (Ti2b *vOmega) * VState.vUVW;
// Include Centrifugal acceleration.
if (!GroundReactions->GetWOW()) {
vUVWdot -= Ti2b*(vOmega*(vOmega*(Tec2i*VState.vLocation)));
} }
// Include Gravitation accel // Include Gravitation accel
FGColumnVector3 gravAccel = Tl2b*vGravAccel; switch (gravType) {
vUVWdot += gravAccel; case gtStandard:
vGravAccel = Tl2b * FGColumnVector3( 0.0, 0.0, Inertial->GetGAccel(VehicleRadius) );
break;
case gtWGS84:
vGravAccel = Tec2b * Inertial->GetGravityJ2(VState.vLocation);
break;
}
vUVWdot += vGravAccel;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Transform the velocity vector of the body relative to the origin (Earth
// center) to be expressed in the inertial frame, and add the vehicle velocity
// contribution due to the rotation of the planet.
// Reference: See Stevens and Lewis, "Aircraft Control and Simulation",
// Second edition (2004), eqn 1.5-16c (page 50)
void FGPropagate::CalculateInertialVelocity(void)
{
VState.vInertialVelocity = Tb2i * VState.vUVW + (vOmegaEarth * VState.vInertialPosition);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::CalculateLocationdot(void) void FGPropagate::Integrate( FGColumnVector3& Integrand,
FGColumnVector3& Val,
deque <FGColumnVector3>& ValDot,
double dt,
eIntegrateType integration_type)
{ {
// Transform the vehicle velocity relative to the ECEF frame, expressed ValDot.push_front(Val);
// in the body frame, to be expressed in the ECEF frame. ValDot.pop_back();
vLocationDot = Tb2ec * VState.vUVW;
// Now, transform the velocity vector of the body relative to the origin (Earth switch(integration_type) {
// center) to be expressed in the inertial frame, and add the vehicle velocity case eRectEuler: Integrand += dt*ValDot[0];
// contribution due to the rotation of the planet. The above velocity is only break;
// relative to the rotating ECEF frame. case eTrapezoidal: Integrand += 0.5*dt*(ValDot[0] + ValDot[1]);
// Reference: See Stevens and Lewis, "Aircraft Control and Simulation", break;
// Second edition (2004), eqn 1.5-16c (page 50) case eAdamsBashforth2: Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]);
break;
case eAdamsBashforth3: Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]);
break;
case eAdamsBashforth4: Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]);
break;
case eNone: // do nothing, freeze translational rate
break;
}
}
vInertialVelocity = Tec2i * vLocationDot + (vOmega * (Tec2i * VState.vLocation)); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::Integrate( FGQuaternion& Integrand,
FGQuaternion& Val,
deque <FGQuaternion>& ValDot,
double dt,
eIntegrateType integration_type)
{
ValDot.push_front(Val);
ValDot.pop_back();
switch(integration_type) {
case eRectEuler: Integrand += dt*ValDot[0];
break;
case eTrapezoidal: Integrand += 0.5*dt*(ValDot[0] + ValDot[1]);
break;
case eAdamsBashforth2: Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]);
break;
case eAdamsBashforth3: Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]);
break;
case eAdamsBashforth4: Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]);
break;
case eNone: // do nothing, freeze translational rate
break;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::SetInertialOrientation(FGQuaternion Qi) {
VState.qAttitudeECI = Qi;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) {
VState.vInertialVelocity = Vi;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::RecomputeLocalTerrainRadius(void) void FGPropagate::RecomputeLocalTerrainRadius(void)
{ {
double t = State->Getsim_time(); double t = FDMExec->GetSimTime();
// Get the LocalTerrain radius. // Get the LocalTerrain radius.
FGLocation contactloc; // FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
FGColumnVector3 dv; // LocalTerrainRadius = contactloc.GetRadius();
FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv); LocalTerrainRadius = FDMExec->GetGroundCallback()->GetTerrainGeoCentRadius();
LocalTerrainRadius = contactloc.GetRadius();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -472,17 +509,19 @@ double FGPropagate::GetTerrainElevation(void) const
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//Todo: when should this be called - when should the new EPA be used to
// calculate the transformation matrix, so that the matrix is not a step
// ahead of the sim and the associated calculations?
const FGMatrix33& FGPropagate::GetTi2ec(void) const FGMatrix33& FGPropagate::GetTi2ec(void)
{ {
return VState.vLocation.GetTi2ec(Inertial->GetEarthPositionAngle()); return VState.vLocation.GetTi2ec();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
const FGMatrix33& FGPropagate::GetTec2i(void) const FGMatrix33& FGPropagate::GetTec2i(void)
{ {
return VState.vLocation.GetTec2i(Inertial->GetEarthPositionAngle()); return VState.vLocation.GetTec2i();
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -518,7 +557,7 @@ void FGPropagate::SetDistanceAGL(double tt)
void FGPropagate::bind(void) void FGPropagate::bind(void)
{ {
typedef double (FGPropagate::*PMF)(int) const; typedef double (FGPropagate::*PMF)(int) const;
// typedef double (FGPropagate::*dPMF)() const;
PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot); PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot);
PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel); PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel);
@ -572,10 +611,11 @@ void FGPropagate::bind(void)
PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (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); PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
PropertyManager->Tie("simulation/integrator/rate/rotational", &integrator_rotational_rate); PropertyManager->Tie("simulation/integrator/rate/rotational", (int*)&integrator_rotational_rate);
PropertyManager->Tie("simulation/integrator/rate/translational", &integrator_translational_rate); PropertyManager->Tie("simulation/integrator/rate/translational", (int*)&integrator_translational_rate);
PropertyManager->Tie("simulation/integrator/position/rotational", &integrator_rotational_position); PropertyManager->Tie("simulation/integrator/position/rotational", (int*)&integrator_rotational_position);
PropertyManager->Tie("simulation/integrator/position/translational", &integrator_translational_position); PropertyManager->Tie("simulation/integrator/position/translational", (int*)&integrator_translational_position);
PropertyManager->Tie("simulation/gravity-model", &gravType);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -612,7 +652,96 @@ void FGPropagate::Debug(int from)
} }
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
} }
if (debug_lvl & 8 ) { // Runtime state variables if (debug_lvl & 8 && from == 2) { // Runtime state variables
cout << endl << fgblue << highint << left
<< " Propagation Report (English units: ft, degrees) at simulation time " << FDMExec->GetSimTime() << " seconds"
<< reset << endl;
cout << endl;
cout << highint << " Earth Position Angle (deg): " << setw(8) << setprecision(3) << reset
<< Inertial->GetEarthPositionAngleDeg() << endl;
cout << endl;
cout << highint << " Body velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vUVW << endl;
cout << highint << " Local velocity (ft/sec): " << setw(8) << setprecision(3) << reset << vVel << endl;
cout << highint << " Inertial velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vInertialVelocity << endl;
cout << highint << " Inertial Position (ft): " << setw(10) << setprecision(3) << reset << VState.vInertialPosition << endl;
cout << highint << " Latitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLatitudeDeg() << endl;
cout << highint << " Longitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLongitudeDeg() << endl;
cout << highint << " Altitude ASL (ft): " << setw(8) << setprecision(3) << reset << GetAltitudeASL() << endl;
cout << highint << " Acceleration (NED, ft/sec^2): " << setw(8) << setprecision(3) << reset << Tb2l*GetUVWdot() << endl;
cout << endl;
cout << highint << " Matrix ECEF to Body (Orientation of Body with respect to ECEF): "
<< reset << endl << Tec2b.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tec2b.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Body to ECEF (Orientation of ECEF with respect to Body):"
<< reset << endl << Tb2ec.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tb2ec.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Local to Body (Orientation of Body with respect to Local):"
<< reset << endl << Tl2b.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tl2b.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Body to Local (Orientation of Local with respect to Body):"
<< reset << endl << Tb2l.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tb2l.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Local to ECEF (Orientation of ECEF with respect to Local):"
<< reset << endl << Tl2ec.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tl2ec.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix ECEF to Local (Orientation of Local with respect to ECEF):"
<< reset << endl << Tec2l.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tec2l.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix ECEF to Inertial (Orientation of Inertial with respect to ECEF):"
<< reset << endl << Tec2i.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tec2i.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Inertial to ECEF (Orientation of ECEF with respect to Inertial):"
<< reset << endl << Ti2ec.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Ti2ec.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Inertial to Body (Orientation of Body with respect to Inertial):"
<< reset << endl << Ti2b.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Ti2b.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Body to Inertial (Orientation of Inertial with respect to Body):"
<< reset << endl << Tb2i.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tb2i.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Inertial to Local (Orientation of Local with respect to Inertial):"
<< reset << endl << Ti2l.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Ti2l.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << highint << " Matrix Local to Inertial (Orientation of Inertial with respect to Local):"
<< reset << endl << Tl2i.Dump("\t", " ") << endl;
cout << highint << " Associated Euler angles (deg): " << setw(8)
<< setprecision(3) << reset << (Tl2i.GetQuaternion().GetEuler()*radtodeg)
<< endl << endl;
cout << setprecision(6); // reset the output stream
} }
if (debug_lvl & 16) { // Sanity checking if (debug_lvl & 16) { // Sanity checking
if (from == 2) { // State sanity checking if (from == 2) { // State sanity checking

View file

@ -43,12 +43,13 @@ INCLUDES
#include "math/FGLocation.h" #include "math/FGLocation.h"
#include "math/FGQuaternion.h" #include "math/FGQuaternion.h"
#include "math/FGMatrix33.h" #include "math/FGMatrix33.h"
#include <deque>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPAGATE "$Id$" #define ID_PROPAGATE "$Id: FGPropagate.h,v 1.41 2010/07/09 04:11:45 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -56,6 +57,7 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
using std::deque;
class FGInitialCondition; class FGInitialCondition;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -66,6 +68,16 @@ CLASS DOCUMENTATION
The Equations of Motion (EOM) for JSBSim are integrated to propagate the The Equations of Motion (EOM) for JSBSim are integrated to propagate the
state of the vehicle given the forces and moments that act on it. The state of the vehicle given the forces and moments that act on it. The
integration accounts for a rotating Earth. integration accounts for a rotating Earth.
The general execution of this model follows this process:
-Calculate the angular accelerations
-Calculate the translational accelerations
-Calculate the angular rate
-Calculate the translational velocity
-Integrate accelerations and rates
Integration of rotational and translation position and rate can be Integration of rotational and translation position and rate can be
customized as needed or frozen by the selection of no integrator. The customized as needed or frozen by the selection of no integrator. The
selection of which integrator to use is done through the setting of selection of which integrator to use is done through the setting of
@ -86,10 +98,11 @@ CLASS DOCUMENTATION
2: Trapezoidal 2: Trapezoidal
3: Adams Bashforth 2 3: Adams Bashforth 2
4: Adams Bashforth 3 4: Adams Bashforth 3
5: Adams Bashforth 4
@endcode @endcode
@author Jon S. Berndt, Mathias Froehlich @author Jon S. Berndt, Mathias Froehlich
@version $Id$ @version $Id: FGPropagate.h,v 1.41 2010/07/09 04:11:45 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -106,17 +119,38 @@ public:
fixed (ECEF) frame. fixed (ECEF) frame.
units ft */ units ft */
FGLocation vLocation; FGLocation vLocation;
/** The velocity vector of the vehicle with respect to the ECEF frame, /** The velocity vector of the vehicle with respect to the ECEF frame,
expressed in the body system. expressed in the body system.
units ft/sec */ units ft/sec */
FGColumnVector3 vUVW; FGColumnVector3 vUVW;
/** The angular velocity vector for the vehicle relative to the ECEF frame, /** The angular velocity vector for the vehicle relative to the ECEF frame,
expressed in the body frame. expressed in the body frame.
units rad/sec */ units rad/sec */
FGColumnVector3 vPQR; FGColumnVector3 vPQR;
/** The angular velocity vector for the vehicle body frame relative to the
ECI frame, expressed in the body frame.
units rad/sec */
FGColumnVector3 vPQRi;
/** The current orientation of the vehicle, that is, the orientation of the /** The current orientation of the vehicle, that is, the orientation of the
body frame relative to the local, vehilce-carried, NED frame. */ body frame relative to the local, NED frame. */
FGQuaternion vQtrn; FGQuaternion qAttitudeLocal;
/** The current orientation of the vehicle, that is, the orientation of the
body frame relative to the inertial (ECI) frame. */
FGQuaternion qAttitudeECI;
FGColumnVector3 vInertialVelocity;
FGColumnVector3 vInertialPosition;
deque <FGColumnVector3> dqPQRdot;
deque <FGColumnVector3> dqUVWdot;
deque <FGColumnVector3> dqInertialVelocity;
deque <FGQuaternion> dqQtrndot;
}; };
/** Constructor. /** Constructor.
@ -133,7 +167,10 @@ public:
~FGPropagate(); ~FGPropagate();
/// These define the indices use to select the various integrators. /// These define the indices use to select the various integrators.
enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3}; enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3, eAdamsBashforth4};
/// These define the indices use to select the gravitation models.
enum eGravType {gtStandard, gtWGS84};
/** Initializes the FGPropagate class after instantiation and prior to first execution. /** Initializes the FGPropagate class after instantiation and prior to first execution.
The base class FGModel::InitModel is called first, initializing pointers to the The base class FGModel::InitModel is called first, initializing pointers to the
@ -144,6 +181,12 @@ public:
@return false if no error */ @return false if no error */
bool Run(void); bool Run(void);
void CalculatePQRdot(void);
void CalculateQuatdot(void);
void CalculateInertialVelocity(void);
void CalculateUVWdot(void);
const FGQuaternion& GetQuaterniondot(void) const {return vQtrndot;}
/** Retrieves the velocity vector. /** Retrieves the velocity vector.
The vector returned is represented by an FGColumnVector reference. The vector The vector returned is represented by an FGColumnVector reference. The vector
for the velocity in Local frame is organized (Vnorth, Veast, Vdown). The vector for the velocity in Local frame is organized (Vnorth, Veast, Vdown). The vector
@ -207,9 +250,9 @@ public:
in FGJSBBase. The relevant enumerators for the vector returned by this call are, in FGJSBBase. The relevant enumerators for the vector returned by this call are,
eP=1, eQ=2, eR=3. eP=1, eQ=2, eR=3.
units rad/sec units rad/sec
@return The body frame angular rates in rad/sec. @return The body frame inertial angular rates in rad/sec.
*/ */
const FGColumnVector3& GetPQRi(void) const {return vPQRi;} const FGColumnVector3& GetPQRi(void) const {return VState.vPQRi;}
/** Retrieves the body axis angular acceleration vector. /** Retrieves the body axis angular acceleration vector.
Retrieves the body axis angular acceleration vector in rad/sec^2. The Retrieves the body axis angular acceleration vector in rad/sec^2. The
@ -241,7 +284,7 @@ public:
angle about the Y axis, and the third item is the angle angle about the Y axis, and the third item is the angle
about the Z axis (Phi, Theta, Psi). about the Z axis (Phi, Theta, Psi).
*/ */
const FGColumnVector3& GetEuler(void) const { return VState.vQtrn.GetEuler(); } const FGColumnVector3& GetEuler(void) const { return VState.qAttitudeLocal.GetEuler(); }
/** Retrieves a body frame velocity component. /** Retrieves a body frame velocity component.
Retrieves a body frame velocity component. The velocity returned is Retrieves a body frame velocity component. The velocity returned is
@ -284,7 +327,15 @@ public:
/** Retrieves the total inertial velocity in ft/sec. /** Retrieves the total inertial velocity in ft/sec.
*/ */
double GetInertialVelocityMagnitude(void) const { return vInertialVelocity.Magnitude(); } double GetInertialVelocityMagnitude(void) const { return VState.vInertialVelocity.Magnitude(); }
/** Retrieves the inertial velocity vector in ft/sec.
*/
const FGColumnVector3& GetInertialVelocity(void) const { return VState.vInertialVelocity; }
/** Retrieves the inertial position vector.
*/
const FGColumnVector3& GetInertialPosition(void) const { return VState.vInertialPosition; }
/** Returns the current altitude above sea level. /** Returns the current altitude above sea level.
This function returns the altitude above sea level. This function returns the altitude above sea level.
@ -324,7 +375,7 @@ public:
@param axis the index of the angular velocity component desired (1-based). @param axis the index of the angular velocity component desired (1-based).
@return The body frame angular velocity component. @return The body frame angular velocity component.
*/ */
double GetPQRi(int axis) const {return vPQRi(axis);} double GetPQRi(int axis) const {return VState.vPQRi(axis);}
/** Retrieves a body frame angular acceleration component. /** Retrieves a body frame angular acceleration component.
Retrieves a body frame angular acceleration component. The angular Retrieves a body frame angular acceleration component. The angular
@ -350,7 +401,7 @@ public:
units radians units radians
@return An Euler angle. @return An Euler angle.
*/ */
double GetEuler(int axis) const { return VState.vQtrn.GetEuler(axis); } double GetEuler(int axis) const { return VState.qAttitudeLocal.GetEuler(axis); }
/** Retrieves the cosine of a vehicle Euler angle component. /** Retrieves the cosine of a vehicle Euler angle component.
Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the
@ -362,7 +413,7 @@ public:
units none units none
@return The cosine of an Euler angle. @return The cosine of an Euler angle.
*/ */
double GetCosEuler(int idx) const { return VState.vQtrn.GetCosEuler(idx); } double GetCosEuler(int idx) const { return VState.qAttitudeLocal.GetCosEuler(idx); }
/** Retrieves the sine of a vehicle Euler angle component. /** Retrieves the sine of a vehicle Euler angle component.
Retrieves the sine of an Euler angle (Phi, Theta, or Psi) from the Retrieves the sine of an Euler angle (Phi, Theta, or Psi) from the
@ -374,7 +425,7 @@ public:
units none units none
@return The sine of an Euler angle. @return The sine of an Euler angle.
*/ */
double GetSinEuler(int idx) const { return VState.vQtrn.GetSinEuler(idx); } double GetSinEuler(int idx) const { return VState.qAttitudeLocal.GetSinEuler(idx); }
/** Returns the current altitude rate. /** Returns the current altitude rate.
Returns the current altitude rate (rate of climb). Returns the current altitude rate (rate of climb).
@ -414,13 +465,13 @@ public:
The quaternion class, being the means by which the orientation of the The quaternion class, being the means by which the orientation of the
vehicle is stored, manages the local-to-body transformation matrix. vehicle is stored, manages the local-to-body transformation matrix.
@return a reference to 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(); } const FGMatrix33& GetTl2b(void) const { return VState.qAttitudeLocal.GetT(); }
/** Retrieves the body-to-local transformation matrix. /** Retrieves the body-to-local transformation matrix.
The quaternion class, being the means by which the orientation of the The quaternion class, being the means by which the orientation of the
vehicle is stored, manages the body-to-local transformation matrix. vehicle is stored, manages the body-to-local transformation matrix.
@return a reference to the body-to-local matrix. */ @return a reference to the body-to-local matrix. */
const FGMatrix33& GetTb2l(void) const { return VState.vQtrn.GetTInv(); } const FGMatrix33& GetTb2l(void) const { return VState.qAttitudeLocal.GetTInv(); }
/** Retrieves the ECEF-to-body transformation matrix. /** Retrieves the ECEF-to-body transformation matrix.
@return a reference to the ECEF-to-body transformation matrix. */ @return a reference to the ECEF-to-body transformation matrix. */
@ -430,6 +481,14 @@ public:
@return a reference to the body-to-ECEF matrix. */ @return a reference to the body-to-ECEF matrix. */
const FGMatrix33& GetTb2ec(void) const { return Tb2ec; } const FGMatrix33& GetTb2ec(void) const { return Tb2ec; }
/** Retrieves the ECI-to-body transformation matrix.
@return a reference to the ECI-to-body transformation matrix. */
const FGMatrix33& GetTi2b(void) const { return VState.qAttitudeECI.GetT(); }
/** Retrieves the body-to-ECI transformation matrix.
@return a reference to the body-to-ECI matrix. */
const FGMatrix33& GetTb2i(void) const { return VState.qAttitudeECI.GetTInv(); }
/** Retrieves the ECEF-to-ECI transformation matrix. /** Retrieves the ECEF-to-ECI transformation matrix.
@return a reference to the ECEF-to-ECI transformation matrix. */ @return a reference to the ECEF-to-ECI transformation matrix. */
const FGMatrix33& GetTec2i(void); const FGMatrix33& GetTec2i(void);
@ -450,16 +509,33 @@ public:
@return a reference to the local-to-ECEF matrix. */ @return a reference to the local-to-ECEF matrix. */
const FGMatrix33& GetTl2ec(void) const { return VState.vLocation.GetTl2ec(); } const FGMatrix33& GetTl2ec(void) const { return VState.vLocation.GetTl2ec(); }
/** Retrieves the local-to-inertial transformation matrix.
@return a reference to the local-to-inertial transformation matrix. */
const FGMatrix33& GetTl2i(void) { return VState.vLocation.GetTl2i(); }
/** Retrieves the inertial-to-local transformation matrix.
@return a reference to the inertial-to-local matrix. */
const FGMatrix33& GetTi2l(void) { return VState.vLocation.GetTi2l(); }
VehicleState* GetVState(void) { return &VState; } VehicleState* GetVState(void) { return &VState; }
void SetVState(VehicleState* vstate) { void SetVState(VehicleState* vstate) {
VState.vLocation = vstate->vLocation; VState.vLocation = vstate->vLocation;
VState.vUVW = vstate->vUVW; VState.vUVW = vstate->vUVW;
VState.vPQR = vstate->vPQR; VState.vPQR = vstate->vPQR;
VState.vQtrn = vstate->vQtrn; // ... mmh VState.qAttitudeLocal = vstate->qAttitudeLocal;
VState.qAttitudeECI = vstate->qAttitudeECI;
VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
} }
const FGQuaternion GetQuaternion(void) const { return VState.vQtrn; } void SetInertialOrientation(FGQuaternion Qi);
void SetInertialVelocity(FGColumnVector3 Vi);
const FGQuaternion GetQuaternion(void) const { return VState.qAttitudeLocal; }
void SetPQR(unsigned int i, double val) { void SetPQR(unsigned int i, double val) {
if ((i>=1) && (i<=3) ) if ((i>=1) && (i<=3) )
@ -492,11 +568,6 @@ public:
VState.vLocation -= vDeltaXYZEC; VState.vLocation -= vDeltaXYZEC;
} }
void CalculatePQRdot(void);
void CalculateQuatdot(void);
void CalculateLocationdot(void);
void CalculateUVWdot(void);
private: private:
// state vector // state vector
@ -504,16 +575,14 @@ private:
struct VehicleState VState; struct VehicleState VState;
FGColumnVector3 vVel; FGColumnVector3 vVel;
FGColumnVector3 vPQRdot;
FGColumnVector3 vUVWdot;
FGColumnVector3 vInertialVelocity; FGColumnVector3 vInertialVelocity;
FGColumnVector3 vPQRdot, last_vPQRdot, last2_vPQRdot;
FGColumnVector3 vUVWdot, last_vUVWdot, last2_vUVWdot;
FGColumnVector3 vLocationDot, last_vLocationDot, last2_vLocationDot;
FGColumnVector3 vLocation; FGColumnVector3 vLocation;
FGColumnVector3 vDeltaXYZEC; FGColumnVector3 vDeltaXYZEC;
FGColumnVector3 vPQRi; // Inertial frame angular velocity FGColumnVector3 vGravAccel;
FGColumnVector3 vOmega; // The Earth angular velocity vector FGColumnVector3 vOmegaEarth; // The Earth angular velocity vector
FGColumnVector3 vOmegaLocal; // The local frame angular velocity vector FGQuaternion vQtrndot;
FGQuaternion vQtrndot, last_vQtrndot, last2_vQtrndot;
FGMatrix33 Tec2b; FGMatrix33 Tec2b;
FGMatrix33 Tb2ec; FGMatrix33 Tb2ec;
FGMatrix33 Tl2b; // local to body frame matrix copy for immediate local use FGMatrix33 Tl2b; // local to body frame matrix copy for immediate local use
@ -524,13 +593,30 @@ private:
FGMatrix33 Ti2ec; // ECI to ECEF frame matrix copy for immediate local use FGMatrix33 Ti2ec; // ECI to ECEF frame matrix copy for immediate local use
FGMatrix33 Ti2b; // ECI to body frame rotation matrix FGMatrix33 Ti2b; // ECI to body frame rotation matrix
FGMatrix33 Tb2i; // body to ECI frame rotation matrix FGMatrix33 Tb2i; // body to ECI frame rotation matrix
FGMatrix33 Ti2l;
FGMatrix33 Tl2i;
FGLocation contactloc;
FGColumnVector3 dv;
double LocalTerrainRadius, SeaLevelRadius, VehicleRadius; double LocalTerrainRadius, SeaLevelRadius, VehicleRadius;
double radInv; double radInv;
int integrator_rotational_rate; eIntegrateType integrator_rotational_rate;
int integrator_translational_rate; eIntegrateType integrator_translational_rate;
int integrator_rotational_position; eIntegrateType integrator_rotational_position;
int integrator_translational_position; eIntegrateType integrator_translational_position;
int gravType;
void Integrate( FGColumnVector3& Integrand,
FGColumnVector3& Val,
deque <FGColumnVector3>& ValDot,
double dt,
eIntegrateType integration_type);
void Integrate( FGQuaternion& Integrand,
FGQuaternion& Val,
deque <FGQuaternion>& ValDot,
double dt,
eIntegrateType integration_type);
void bind(void); void bind(void);
void Debug(int from); void Debug(int from);

View file

@ -45,7 +45,6 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGPropulsion.h" #include "FGPropulsion.h"
#include "FGState.h"
#include "models/FGFCS.h" #include "models/FGFCS.h"
#include "models/FGMassBalance.h" #include "models/FGMassBalance.h"
#include "models/propulsion/FGThruster.h" #include "models/propulsion/FGThruster.h"
@ -66,7 +65,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.39 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdHdr = ID_PROPULSION; static const char *IdHdr = ID_PROPULSION;
extern short debug_lvl; extern short debug_lvl;
@ -149,7 +148,7 @@ bool FGPropulsion::Run(void)
RunPreFunctions(); RunPreFunctions();
double dt = State->Getdt(); double dt = FDMExec->GetDeltaT();
vForces.InitMatrix(); vForces.InitMatrix();
vMoments.InitMatrix(); vMoments.InitMatrix();

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPULSION "$Id$" #define ID_PROPULSION "$Id: FGPropulsion.h,v 1.25 2010/01/02 17:58:01 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -91,7 +91,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGPropulsion.h,v 1.25 2010/01/02 17:58:01 andgi Exp $
@see @see
FGEngine FGEngine
FGTank FGTank
@ -132,8 +132,8 @@ public:
@return the address of the specific engine, or zero if no such engine is @return the address of the specific engine, or zero if no such engine is
available */ available */
inline FGEngine* GetEngine(unsigned int index) { inline FGEngine* GetEngine(unsigned int index) {
if (index <= Engines.size()-1) return Engines[index]; if (index < Engines.size()) return Engines[index];
else return 0L; } else return 0L; }
/// Retrieves the number of tanks defined for the aircraft. /// Retrieves the number of tanks defined for the aircraft.
inline unsigned int GetNumTanks(void) const {return (unsigned int)Tanks.size();} inline unsigned int GetNumTanks(void) const {return (unsigned int)Tanks.size();}
@ -143,8 +143,8 @@ public:
@return the address of the specific tank, or zero if no such tank is @return the address of the specific tank, or zero if no such tank is
available */ available */
inline FGTank* GetTank(unsigned int index) { inline FGTank* GetTank(unsigned int index) {
if (index <= Tanks.size()-1) return Tanks[index]; if (index < Tanks.size()) return Tanks[index];
else return 0L; } else return 0L; }
/** Returns the number of fuel tanks currently actively supplying fuel */ /** Returns the number of fuel tanks currently actively supplying fuel */
inline int GetnumSelectedFuelTanks(void) const {return numSelectedFuelTanks;} inline int GetnumSelectedFuelTanks(void) const {return numSelectedFuelTanks;}

View file

@ -58,7 +58,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGMSIS.h" #include "FGMSIS.h"
#include "FGState.h" #include "models/FGAuxiliary.h"
#include <cmath> /* maths functions */ #include <cmath> /* maths functions */
#include <iostream> // for cout, endl #include <iostream> // for cout, endl
@ -66,7 +66,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGMSIS.cpp,v 1.13 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdHdr = ID_MSIS; static const char *IdHdr = ID_MSIS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -41,12 +41,13 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "models/FGAtmosphere.h" #include "models/FGAtmosphere.h"
#include "FGFDMExec.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MSIS "$Id$" #define ID_MSIS "$Id: FGMSIS.h,v 1.7 2010/02/25 05:21:36 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -74,7 +75,7 @@ CLASS DOCUMENTATION
and check http://www.brodo.de/english/pub/nrlmsise/index.html for and check http://www.brodo.de/english/pub/nrlmsise/index.html for
updated releases of this package. updated releases of this package.
@author David Culp @author David Culp
@version $Id$ @version $Id: FGMSIS.h,v 1.7 2010/02/25 05:21:36 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -42,14 +42,13 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGMars.h" #include "FGMars.h"
#include "FGState.h"
#include <iostream> #include <iostream>
using namespace std; using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGMars.cpp,v 1.10 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdHdr = ID_MARS; static const char *IdHdr = ID_MARS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MARS "$Id$" #define ID_MARS "$Id: FGMars.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -58,7 +58,7 @@ CLASS DOCUMENTATION
/** Models the Martian atmosphere. /** Models the Martian atmosphere.
@author Jon Berndt @author Jon Berndt
@version $Id$ @version $Id: FGMars.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGAccelerometer.cpp,v 1.8 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_ACCELEROMETER; static const char *IdHdr = ID_ACCELEROMETER;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ACCELEROMETER "$Id$" #define ID_ACCELEROMETER "$Id: FGAccelerometer.h,v 1.4 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -110,7 +110,7 @@ even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the del
time. time.
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision$ @version $Revision: 1.4 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

2
src/FDM/JSBSim/models/flight_control/FGActuator.cpp Executable file → Normal file
View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGActuator.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_ACTUATOR; static const char *IdHdr = ID_ACTUATOR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

4
src/FDM/JSBSim/models/flight_control/FGActuator.h Executable file → Normal file
View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ACTUATOR "$Id$" #define ID_ACTUATOR "$Id: FGActuator.h,v 1.11 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -111,7 +111,7 @@ Example:
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision$ @version $Revision: 1.11 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -46,7 +46,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGDeadBand.cpp,v 1.9 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_DEADBAND; static const char *IdHdr = ID_DEADBAND;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -43,7 +43,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_DEADBAND "$Id$" #define ID_DEADBAND "$Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -80,7 +80,7 @@ CLASS DOCUMENTATION
produce no output. For example, say that the width value is 2.0. If the 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. input is between -1.0 and +1.0, the output will be zero.
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.27 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_FCSCOMPONENT; static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSCOMPONENT "$Id$" #define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -80,7 +80,7 @@ CLASS DOCUMENTATION
- FGActuator - FGActuator
@author Jon S. Berndt @author Jon S. Berndt
@version $Id$ @version $Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $
@see Documentation for the FGFCS class, and for the configuration file class @see Documentation for the FGFCS class, and for the configuration file class
*/ */

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim { namespace JSBSim {
static const char *IdSrc = "$Id$"; static const char *IdSrc = "$Id: FGFCSFunction.cpp,v 1.9 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdHdr = ID_FCSFUNCTION; static const char *IdHdr = ID_FCSFUNCTION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSFUNCTION "$Id$" #define ID_FCSFUNCTION "$Id: FGFCSFunction.h,v 1.7 2009/10/02 10:30:09 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
@ -105,7 +105,7 @@ a function (from an aero specification):
</function> </function>
@endcode @endcode
@version $Id$ @version $Id: FGFCSFunction.h,v 1.7 2009/10/02 10:30:09 jberndt Exp $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

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