#include "models/FGInput.h"
#include "models/FGOutput.h"
#include "initialization/FGInitialCondition.h"
+#include "initialization/FGTrim.h"
#include "initialization/FGSimplexTrim.h"
#include "initialization/FGLinearization.h"
#include "input_output/FGPropertyManager.h"
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGFDMExec.cpp,v 1.154 2014/01/13 10:45:59 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGFDMExec.cpp,v 1.161 2014/05/17 15:35:53 jberndt Exp $");
IDENT(IdHdr,ID_FDMEXEC);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{
Frame = 0;
Error = 0;
- SetGroundCallback(new FGDefaultGroundCallback());
+ //SetGroundCallback(new FGDefaultGroundCallback());
IC = 0;
Trim = 0;
Script = 0;
+ disperse = 0;
RootDir = "";
FGPropertyNode* instanceRoot = Root->GetNode("/fdm/jsbsim",IdFDM,true);
instance = new FGPropertyManager(instanceRoot);
+
+ try {
+ char* num = getenv("JSBSIM_DISPERSE");
+ if (num) {
+ if (atoi(num) != 0) disperse = 1; // set dispersions on
+ }
+ } catch (...) { // if error set to false
+ disperse = 0;
+ std::cerr << "Could not process JSBSIM_DISPERSIONS environment variable: Assumed NO dispersions." << endl;
+ }
+
Debug(0);
// this is to catch errors in binding member functions to the property tree.
try {
Constructing = true;
typedef int (FGFDMExec::*iPMF)(void) const;
-// typedef double (FGFDMExec::*dPMF)(void) const;
-// typedef unsigned int (FGFDMExec::*uiPMF)(void) const;
// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
instance->Tie("simulation/do_simplex_trim", this, (iPMF)0, &FGFDMExec::DoSimplexTrim);
instance->Tie("simulation/do_linearization", this, (iPMF)0, &FGFDMExec::DoLinearization);
- instance->Tie("simulation/reset", (int*)&ResetMode);
+ instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
+ instance->Tie("simulation/disperse", this, &FGFDMExec::GetDisperse);
instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false);
instance->Tie("simulation/terminate", (int *)&Terminate);
instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
// Initialize planet (environment) constants
LoadPlanetConstants();
- GetGroundCallback()->SetSeaLevelRadius(Inertial->GetRefRadius());
+ //GetGroundCallback()->SetSeaLevelRadius(Inertial->GetRefRadius());
+ SetGroundCallback(new FGDefaultGroundCallback(Inertial->GetRefRadius()));
// Initialize models
for (unsigned int i = 0; i < Models.size(); i++) {
}
IC = new FGInitialCondition(this);
+ IC->bind(instance);
modelLoaded = false;
}
if (ResetMode) {
- if (ResetMode == 1) Output->SetStartNewOutput();
+ unsigned int mode = ResetMode;
ResetMode = 0;
- ResetToInitialConditions();
+ ResetToInitialConditions(mode);
}
if (Terminate) success = false;
{
FGPropulsion* propulsion = (FGPropulsion*)Models[ePropulsion];
- if (!trim_status)
- Models[eOutput]->InitModel();
+ Models[eOutput]->InitModel();
SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0.
Initialize(IC);
Run();
ResumeIntegration(); // Restores the integration rate to what it was.
- for (unsigned int i=0; i<IC->GetNumEnginesRunning(); i++)
- propulsion->InitRunning(IC->GetEngineRunning(i));
+ for (unsigned int n=0; n < propulsion->GetNumEngines(); ++n) {
+ if (IC->IsEngineRunning(n)) {
+ try {
+ propulsion->InitRunning(n);
+ } catch (string str) {
+ cerr << str << endl;
+ return false;
+ }
+ }
+ }
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGFDMExec::ResetToInitialConditions(void)
+void FGFDMExec::ResetToInitialConditions(int mode)
{
if (Constructing) return;
+ if (mode == 1) Output->SetStartNewOutput();
+
for (unsigned int i = 0; i < Models.size(); i++) {
// The Output model will be initialized during the RunIC() execution
if (i == eOutput) continue;
Models[ePropulsion]->Run(false); // Update propulsion properties for the report.
LoadInputs(eMassBalance); // Update all (one more time) input mass properties for the report.
Models[eMassBalance]->Run(false); // Update all (one more time) mass properties for the report.
- ((FGMassBalance*)Models[eMassBalance])->GetMassPropertiesReport();
+ ((FGMassBalance*)Models[eMassBalance])->GetMassPropertiesReport(0);
cout << endl << fgblue << highint
<< "End of vehicle configuration loading." << endl
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+void FGFDMExec::PrintSimulationConfiguration(void) const
+{
+ cout << endl << "Simulation Configuration" << endl << "------------------------" << endl;
+ cout << MassBalance->Name << endl;
+ cout << GroundReactions->Name << endl;
+ cout << Aerodynamics->Name << endl;
+ cout << Propulsion->Name << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
bool FGFDMExec::ReadFileHeader(Element* el)
{
bool result = true; // true for success
<< "JSBSim Flight Dynamics Model v" << JSBSim_version << endl;
cout << " [JSBSim-ML v" << needed_cfg_version << "]\n\n";
cout << "JSBSim startup beginning ...\n\n";
+ if (disperse == 1) cout << "Dispersions are ON." << endl << endl;
} else if (from == 3) {
cout << "\n\nJSBSim startup complete\n\n";
}
#include <vector>
#include <string>
-#include "initialization/FGTrim.h"
#include "FGJSBBase.h"
#include "input_output/FGPropertyManager.h"
#include "models/FGPropagate.h"
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.86 2014/01/02 21:37:14 bcoconni Exp $"
+#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.91 2014/05/17 15:35:53 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
class FGInput;
class FGPropulsion;
class FGMassBalance;
+class FGTrim;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
property actually maps toa function call of DoTrim().
@author Jon S. Berndt
- @version $Revision: 1.86 $
+ @version $Revision: 1.91 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/// Returns the model name.
const std::string& GetModelName(void) const { return modelName; }
-/*
- /// Returns the current time.
- double GetSimTime(void);
- /// Returns the current frame time (delta T).
- double GetDeltaT(void);
-*/
/// Returns a pointer to the property manager object.
FGPropertyManager* GetPropertyManager(void);
/// Returns a vector of strings representing the names of all loaded models (future)
void SetLoggingRate(double rate) { Output->SetRate(rate); }
/** Sets (or overrides) the output filename
+ @param n index of file
@param fname the name of the file to output data to
@return true if successful, false if there is no output specified for the flight model */
bool SetOutputFileName(const int n, const std::string& fname) { return Output->SetOutputName(n, fname); }
void Resume(void) {holding = false;}
/// Returns true if the simulation is Holding (i.e. simulation time is not moving).
bool Holding(void) {return holding;}
- /// Resets the initial conditions object and prepares the simulation to run again.
- void ResetToInitialConditions(void);
+ /** Resets the initial conditions object and prepares the simulation to run
+ again. If mode is set to 1 the output instances will take special actions
+ such as closing the current output file and open a new one with a
+ different name.
+ @param mode Sets the reset mode.*/
+ void ResetToInitialConditions(int mode);
/// Sets the debug level.
void SetDebugLevel(int level) {debug_lvl = level;}
// Print the contents of the property catalog for the loaded aircraft.
void PrintPropertyCatalog(void);
+ // Print the simulation configuration
+ void PrintSimulationConfiguration(void) const;
+
std::vector<std::string>& GetPropertyCatalog(void) {return PropertyCatalog;}
void SetTrimStatus(bool status){ trim_status = status; }
int Error;
unsigned int Frame;
unsigned int IdFDM;
+ int disperse;
unsigned short Terminate;
double dT;
double saved_dT;
void LoadModelConstants(void);
bool Allocate(void);
bool DeAllocate(void);
+ int GetDisperse(void) const {return disperse;}
void Debug(int from);
};
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGInitialCondition.cpp,v 1.93 2014/01/13 10:46:00 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGInitialCondition.cpp,v 1.95 2014/05/01 18:32:54 bcoconni Exp $");
IDENT(IdHdr,ID_INITIALCONDITION);
//******************************************************************************
InitializeIC();
if(FDMExec != NULL ) {
- PropertyManager=fdmex->GetPropertyManager();
Atmosphere=fdmex->GetAtmosphere();
- bind();
} else {
cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
}
lastSpeedSet = setvt;
lastAltitudeSet = setasl;
- enginesRunning.clear();
+ enginesRunning = 0;
}
//******************************************************************************
// Check to see if any engines are specified to be initialized in a running state
Element* running_elements = document->FindElement("running");
while (running_elements) {
- enginesRunning.push_back(int(running_elements->GetDataAsNumber()));
+ enginesRunning &= 1 << int(running_elements->GetDataAsNumber());
running_elements = document->FindNextElement("running");
}
//******************************************************************************
-void FGInitialCondition::bind(void)
+void FGInitialCondition::bind(FGPropertyManager* PropertyManager)
{
PropertyManager->Tie("ic/vc-kts", this,
&FGInitialCondition::GetVcalibratedKtsIC,
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.39 2013/11/24 11:40:55 bcoconni Exp $"
+#define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.41 2014/05/01 18:32:54 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@property ic/r-rad_sec (read/write) Yaw rate initial condition in radians/second
@author Tony Peden
- @version "$Id: FGInitialCondition.h,v 1.39 2013/11/24 11:40:55 bcoconni Exp $"
+ @version "$Id: FGInitialCondition.h,v 1.41 2014/05/01 18:32:54 bcoconni Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@return true if successful */
bool Load(std::string rstname, bool useStoredPath = true );
- /** Get the number of engines running
- */
- unsigned int GetNumEnginesRunning(void) const
- { return (unsigned int)enginesRunning.size(); }
+ /** Is an engine running ?
+ @param index of the engine to be checked
+ @return true if the engine is running. */
+ bool IsEngineRunning(unsigned int n) const { return (enginesRunning & (1 << n)); }
- /** Gets the running engine identification
- @param engine index of running engine instance
- @return the identification of running engine instance requested */
- int GetEngineRunning(unsigned int engine) const { return enginesRunning[engine]; }
+ void bind(FGPropertyManager* pm);
private:
FGColumnVector3 vUVW_NED;
speedset lastSpeedSet;
altitudeset lastAltitudeSet;
- std::vector<int> enginesRunning;
+ unsigned int enginesRunning;
FGFDMExec *fdmex;
- FGPropertyManager *PropertyManager;
FGAtmosphere* Atmosphere;
bool Load_v1(Element* document);
double GetBodyVelFpsIC(int idx) const;
void calcAeroAngles(const FGColumnVector3& _vt_BODY);
void calcThetaBeta(double alfa, const FGColumnVector3& _vt_NED);
- void bind(void);
void Debug(int from);
};
}
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "FGInitialCondition.h"
#include "FGLinearization.h"
#include <ctime>
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "FGTrim.h"
#include "FGSimplexTrim.h"
#include <ctime>
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGTrim.cpp,v 1.22 2014/01/13 10:46:00 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGTrim.cpp,v 1.23 2014/05/01 18:32:54 bcoconni Exp $");
IDENT(IdHdr,ID_TRIM);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) {
+FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt)
+ : fgic(FDMExec)
+{
- N=Nsub=0;
+ Nsub=0;
max_iterations=60;
max_sub_iterations=100;
Tolerance=1E-3;
Debug=0;DebugLevel=0;
fdmex=FDMExec;
- fgic=fdmex->GetIC();
total_its=0;
- trimudot=true;
gamma_fallback=false;
- axis_count=0;
mode=tt;
xlo=xhi=alo=ahi=0.0;
targetNlf=1.0;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTrim::~FGTrim(void) {
- for(current_axis=0; current_axis<TrimAxes.size(); current_axis++) {
- delete TrimAxes[current_axis];
- }
- delete[] sub_iterations;
- delete[] successful;
- delete[] solution;
if (debug_lvl & 2) cout << "Destroyed: FGTrim" << endl;
}
cout << " Total Iterations: " << total_its << endl;
if( total_its > 0) {
cout << " Sub-iterations:" << endl;
- for (current_axis=0; current_axis<TrimAxes.size(); current_axis++) {
- run_sum += TrimAxes[current_axis]->GetRunCount();
- cout << " " << setw(5) << TrimAxes[current_axis]->GetStateName().c_str()
+ for (unsigned int current_axis=0; current_axis<TrimAxes.size(); current_axis++) {
+ run_sum += TrimAxes[current_axis].GetRunCount();
+ cout << " " << setw(5) << TrimAxes[current_axis].GetStateName().c_str()
<< ": " << setprecision(3) << sub_iterations[current_axis]
<< " average: " << setprecision(5) << sub_iterations[current_axis]/double(total_its)
<< " successful: " << setprecision(3) << successful[current_axis]
- << " stability: " << setprecision(5) << TrimAxes[current_axis]->GetAvgStability()
+ << " stability: " << setprecision(5) << TrimAxes[current_axis].GetAvgStability()
<< endl;
}
cout << " Run Count: " << run_sum << endl;
void FGTrim::Report(void) {
cout << " Trim Results: " << endl;
- for(current_axis=0; current_axis<TrimAxes.size(); current_axis++)
- TrimAxes[current_axis]->AxisReport();
+ for(unsigned int current_axis=0; current_axis<TrimAxes.size(); current_axis++)
+ TrimAxes[current_axis].AxisReport();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGTrim::ClearStates(void) {
- FGTrimAxis* ta;
-
mode=tCustom;
- vector<FGTrimAxis*>::iterator iAxes;
- iAxes = TrimAxes.begin();
- while (iAxes != TrimAxes.end()) {
- ta=*iAxes;
- delete ta;
- iAxes++;
- }
TrimAxes.clear();
//cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGTrim::AddState( State state, Control control ) {
- FGTrimAxis* ta;
- bool result=true;
-
mode = tCustom;
- vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
- while (iAxes != TrimAxes.end()) {
- ta=*iAxes;
- if( ta->GetStateType() == state )
- result=false;
- iAxes++;
+ vector <FGTrimAxis>::iterator iAxes = TrimAxes.begin();
+ for (; iAxes != TrimAxes.end(); ++iAxes) {
+ if (iAxes->GetStateType() == state)
+ return false;
}
- if(result) {
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,state,control));
- delete[] sub_iterations;
- delete[] successful;
- delete[] solution;
- sub_iterations=new double[TrimAxes.size()];
- successful=new double[TrimAxes.size()];
- solution=new bool[TrimAxes.size()];
- }
- return result;
+
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,state,control));
+ sub_iterations.resize(TrimAxes.size());
+ successful.resize(TrimAxes.size());
+ solution.resize(TrimAxes.size());
+
+ return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGTrim::RemoveState( State state ) {
- FGTrimAxis* ta;
bool result=false;
mode = tCustom;
- vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
+ vector <FGTrimAxis>::iterator iAxes = TrimAxes.begin();
while (iAxes != TrimAxes.end()) {
- ta=*iAxes;
- if( ta->GetStateType() == state ) {
- delete ta;
+ if( iAxes->GetStateType() == state ) {
iAxes = TrimAxes.erase(iAxes);
result=true;
continue;
}
- iAxes++;
+ ++iAxes;
}
if(result) {
- delete[] sub_iterations;
- delete[] successful;
- delete[] solution;
- sub_iterations=new double[TrimAxes.size()];
- successful=new double[TrimAxes.size()];
- solution=new bool[TrimAxes.size()];
+ sub_iterations.resize(TrimAxes.size());
+ successful.resize(TrimAxes.size());
+ solution.resize(TrimAxes.size());
}
return result;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGTrim::EditState( State state, Control new_control ){
- FGTrimAxis* ta;
- bool result=false;
-
mode = tCustom;
- vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
+ vector <FGTrimAxis>::iterator iAxes = TrimAxes.begin();
while (iAxes != TrimAxes.end()) {
- ta=*iAxes;
- if( ta->GetStateType() == state ) {
- TrimAxes.insert(iAxes,1,new FGTrimAxis(fdmex,fgic,state,new_control));
- delete ta;
- TrimAxes.erase(iAxes+1);
- result=true;
- break;
+ if( iAxes->GetStateType() == state ) {
+ *iAxes = FGTrimAxis(fdmex,&fgic,state,new_control);
+ return true;
}
- iAxes++;
+ ++iAxes;
}
- return result;
+ return false;
}
-
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGTrim::DoTrim(void) {
-
- trim_failed=false;
- int i;
+ bool trim_failed=false;
+ unsigned int N = 0;
+ unsigned int axis_count = 0;
FGFCS *FCS = fdmex->GetFCS();
vector<double> throttle0 = FCS->GetThrottleCmd();
double elevator0 = FCS->GetDeCmd();
double aileron0 = FCS->GetDaCmd();
double rudder0 = FCS->GetDrCmd();
double PitchTrim0 = FCS->GetPitchTrimCmd();
- FGInitialCondition fgic0 = *fgic;
+ fgic = *fdmex->GetIC();
- for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
+ for(int i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false);
}
fdmex->DisableOutput();
fdmex->SetTrimStatus(true);
- fdmex->RunIC();
fdmex->SuspendIntegration();
- fgic->SetPRadpsIC(0.0);
- fgic->SetQRadpsIC(0.0);
- fgic->SetRRadpsIC(0.0);
+ fgic.SetPRadpsIC(0.0);
+ fgic.SetQRadpsIC(0.0);
+ fgic.SetRRadpsIC(0.0);
if (mode == tGround) {
trimOnGround();
- double theta = fgic->GetThetaRadIC();
- double phi = fgic->GetPhiRadIC();
+ double theta = fgic.GetThetaRadIC();
+ double phi = fgic.GetPhiRadIC();
// Take opportunity of the first approx. found by trimOnGround() to
// refine the control limits.
- TrimAxes[0]->SetControlLimits(0., fgic->GetAltitudeAGLFtIC());
- TrimAxes[1]->SetControlLimits(theta - 5.0 * degtorad, theta + 5.0 * degtorad);
- TrimAxes[2]->SetControlLimits(phi - 30.0 * degtorad, phi + 30.0 * degtorad);
+ TrimAxes[0].SetControlLimits(0., fgic.GetAltitudeAGLFtIC());
+ TrimAxes[1].SetControlLimits(theta - 5.0 * degtorad, theta + 5.0 * degtorad);
+ TrimAxes[2].SetControlLimits(phi - 30.0 * degtorad, phi + 30.0 * degtorad);
}
//clear the sub iterations counts & zero out the controls
- for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
+ for(unsigned int current_axis=0;current_axis<TrimAxes.size();current_axis++) {
//cout << current_axis << " " << TrimAxes[current_axis]->GetStateName()
//<< " " << TrimAxes[current_axis]->GetControlName()<< endl;
- xlo=TrimAxes[current_axis]->GetControlMin();
- xhi=TrimAxes[current_axis]->GetControlMax();
- TrimAxes[current_axis]->SetControl((xlo+xhi)/2);
- TrimAxes[current_axis]->Run();
- //TrimAxes[current_axis]->AxisReport();
+ xlo=TrimAxes[current_axis].GetControlMin();
+ xhi=TrimAxes[current_axis].GetControlMax();
+ TrimAxes[current_axis].SetControl((xlo+xhi)/2);
+ TrimAxes[current_axis].Run();
+ //TrimAxes[current_axis].AxisReport();
sub_iterations[current_axis]=0;
successful[current_axis]=0;
solution[current_axis]=false;
cout << "Setting pitch rate and nlf... " << endl;
setupPullup();
cout << "pitch rate done ... " << endl;
- TrimAxes[0]->SetStateTarget(targetNlf);
+ TrimAxes[0].SetStateTarget(targetNlf);
cout << "nlf done" << endl;
} else if (mode == tTurn) {
setupTurn();
- //TrimAxes[0]->SetStateTarget(targetNlf);
+ //TrimAxes[0].SetStateTarget(targetNlf);
}
do {
axis_count=0;
- for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
- setDebug();
+ for(unsigned int current_axis=0;current_axis<TrimAxes.size();current_axis++) {
+ setDebug(TrimAxes[current_axis]);
updateRates();
Nsub=0;
if(!solution[current_axis]) {
- if(checkLimits()) {
+ if(checkLimits(TrimAxes[current_axis])) {
solution[current_axis]=true;
- solve();
+ solve(TrimAxes[current_axis]);
}
- } else if(findInterval()) {
- solve();
+ } else if(findInterval(TrimAxes[current_axis])) {
+ solve(TrimAxes[current_axis]);
} else {
solution[current_axis]=false;
}
sub_iterations[current_axis]+=Nsub;
}
- for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
+ for(unsigned int current_axis=0;current_axis<TrimAxes.size();current_axis++) {
//these checks need to be done after all the axes have run
- if(Debug > 0) TrimAxes[current_axis]->AxisReport();
- if(TrimAxes[current_axis]->InTolerance()) {
+ if(Debug > 0) TrimAxes[current_axis].AxisReport();
+ if(TrimAxes[current_axis].InTolerance()) {
axis_count++;
successful[current_axis]++;
}
//is, keep going until success or max iteration count
//Oh, well: two out of three ain't bad
- for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
+ for(unsigned int current_axis=0;current_axis<TrimAxes.size();current_axis++) {
//these checks need to be done after all the axes have run
- if(!TrimAxes[current_axis]->InTolerance()) {
- if(!checkLimits()) {
+ if(!TrimAxes[current_axis].InTolerance()) {
+ if(!checkLimits(TrimAxes[current_axis])) {
// special case this for now -- if other cases arise proper
// support can be added to FGTrimAxis
if( (gamma_fallback) &&
- (TrimAxes[current_axis]->GetStateType() == tUdot) &&
- (TrimAxes[current_axis]->GetControlType() == tThrottle)) {
+ (TrimAxes[current_axis].GetStateType() == tUdot) &&
+ (TrimAxes[current_axis].GetControlType() == tThrottle)) {
cout << " Can't trim udot with throttle, trying flight"
<< " path angle. (" << N << ")" << endl;
- if(TrimAxes[current_axis]->GetState() > 0)
- TrimAxes[current_axis]->SetControlToMin();
+ if(TrimAxes[current_axis].GetState() > 0)
+ TrimAxes[current_axis].SetControlToMin();
else
- TrimAxes[current_axis]->SetControlToMax();
- TrimAxes[current_axis]->Run();
- delete TrimAxes[current_axis];
- TrimAxes[current_axis]=new FGTrimAxis(fdmex,fgic,tUdot,
- tGamma );
+ TrimAxes[current_axis].SetControlToMax();
+ TrimAxes[current_axis].Run();
+ TrimAxes[current_axis]=FGTrimAxis(fdmex,&fgic,tUdot,tGamma);
} else {
- cout << " Sorry, " << TrimAxes[current_axis]->GetStateName()
+ cout << " Sorry, " << TrimAxes[current_axis].GetStateName()
<< " doesn't appear to be trimmable" << endl;
//total_its=k;
trim_failed=true; //force the trim to fail
total_its=N;
// Restore the aircraft parameters to their initial values
- *fgic = fgic0;
+ fgic = *fdmex->GetIC();
FCS->SetDeCmd(elevator0);
FCS->SetDaCmd(aileron0);
FCS->SetDrCmd(rudder0);
for (unsigned int i=0; i < throttle0.size(); i++)
FCS->SetThrottleCmd(i, throttle0[i]);
+ fdmex->Initialize(&fgic);
+ fdmex->Run();
+
// If WOW is true we must make sure there are no gears into the ground.
- if (fdmex->GetGroundReactions()->GetWOW()) {
- fdmex->Initialize(fgic);
- fdmex->Run();
+ if (fdmex->GetGroundReactions()->GetWOW())
trimOnGround();
- }
if (debug_lvl > 0)
cout << endl << " Trim failed" << endl;
}
fdmex->ResumeIntegration();
- fdmex->RunIC();
fdmex->SetTrimStatus(false);
fdmex->EnableOutput();
- for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
+ for(int i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
}
// Update the initial conditions: this should remove the forces generated
// by overcompressed landing gears
- fgic->SetAltitudeASLFtIC(fgic->GetAltitudeASLFtIC() - hmin);
- fdmex->Initialize(fgic);
+ fgic.SetAltitudeASLFtIC(fgic.GetAltitudeASLFtIC() - hmin);
+ fdmex->Initialize(&fgic);
fdmex->Run();
// Compute the rotation axis: it is obtained from the direction of the
FGQuaternion q1(rParam.angleMin, rotationAxis);
// Update the aircraft orientation
- FGColumnVector3 euler = (q0 * q1 * fgic->GetOrientation()).GetEuler();
+ FGColumnVector3 euler = (q0 * q1 * fgic.GetOrientation()).GetEuler();
- fgic->SetPhiRadIC(euler(1));
- fgic->SetThetaRadIC(euler(2));
- fgic->SetPsiRadIC(euler(3));
+ fgic.SetPhiRadIC(euler(1));
+ fgic.SetThetaRadIC(euler(2));
+ fgic.SetPsiRadIC(euler(3));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGTrim::solve(void) {
+bool FGTrim::solve(FGTrimAxis& axis) {
double x1,x2,x3,f1,f2,f3,d,d0;
const double relax =0.9;
- double eps=TrimAxes[current_axis]->GetSolverEps();
+ double eps=axis.GetSolverEps();
x1=x2=x3=0;
d=1;
} */
d0=fabs(x3-x1);
//iterations
- //max_sub_iterations=TrimAxes[current_axis]->GetIterationLimit();
- while ( (TrimAxes[current_axis]->InTolerance() == false )
+ //max_sub_iterations=axis.GetIterationLimit();
+ while ( (axis.InTolerance() == false )
&& (fabs(d) > eps) && (Nsub < max_sub_iterations)) {
Nsub++;
d=(x3-x1)/d0;
x2=x1-d*d0*f1/(f3-f1);
- TrimAxes[current_axis]->SetControl(x2);
- TrimAxes[current_axis]->Run();
- f2=TrimAxes[current_axis]->GetState();
+ axis.SetControl(x2);
+ axis.Run();
+ f2=axis.GetState();
if(Debug > 1) {
cout << "FGTrim::solve Nsub,x1,x2,x3: " << Nsub << ", " << x1
<< ", " << x2 << ", " << x3 << endl;
no assumptions about the state of the sim after this function has run
can be made.
*/
-bool FGTrim::findInterval(void) {
+bool FGTrim::findInterval(FGTrimAxis& axis) {
bool found=false;
double step;
- double current_control=TrimAxes[current_axis]->GetControl();
- double current_accel=TrimAxes[current_axis]->GetState();;
- double xmin=TrimAxes[current_axis]->GetControlMin();
- double xmax=TrimAxes[current_axis]->GetControlMax();
+ double current_control=axis.GetControl();
+ double current_accel=axis.GetState();;
+ double xmin=axis.GetControlMin();
+ double xmax=axis.GetControlMax();
double lastxlo,lastxhi,lastalo,lastahi;
step=0.025*fabs(xmax);
if(xlo < xmin) xlo=xmin;
xhi+=step;
if(xhi > xmax) xhi=xmax;
- TrimAxes[current_axis]->SetControl(xlo);
- TrimAxes[current_axis]->Run();
- alo=TrimAxes[current_axis]->GetState();
- TrimAxes[current_axis]->SetControl(xhi);
- TrimAxes[current_axis]->Run();
- ahi=TrimAxes[current_axis]->GetState();
- if(fabs(ahi-alo) <= TrimAxes[current_axis]->GetTolerance()) continue;
+ axis.SetControl(xlo);
+ axis.Run();
+ alo=axis.GetState();
+ axis.SetControl(xhi);
+ axis.Run();
+ ahi=axis.GetState();
+ if(fabs(ahi-alo) <= axis.GetTolerance()) continue;
if(alo*ahi <=0) { //found interval with root
found=true;
if(alo*current_accel <= 0) { //narrow interval down a bit
//xhi=xmax and ahi=accel(xmax)
//in all cases the sim is left such that the control=xmax and accel=ahi
-bool FGTrim::checkLimits(void) {
+bool FGTrim::checkLimits(FGTrimAxis& axis)
+{
bool solutionExists;
- double current_control=TrimAxes[current_axis]->GetControl();
- double current_accel=TrimAxes[current_axis]->GetState();
- xlo=TrimAxes[current_axis]->GetControlMin();
- xhi=TrimAxes[current_axis]->GetControlMax();
-
- TrimAxes[current_axis]->SetControl(xlo);
- TrimAxes[current_axis]->Run();
- alo=TrimAxes[current_axis]->GetState();
- TrimAxes[current_axis]->SetControl(xhi);
- TrimAxes[current_axis]->Run();
- ahi=TrimAxes[current_axis]->GetState();
+ double current_control=axis.GetControl();
+ double current_accel=axis.GetState();
+ xlo=axis.GetControlMin();
+ xhi=axis.GetControlMax();
+
+ axis.SetControl(xlo);
+ axis.Run();
+ alo=axis.GetState();
+ axis.SetControl(xhi);
+ axis.Run();
+ ahi=axis.GetState();
if(Debug > 1)
cout << "checkLimits() xlo,xhi,alo,ahi: " << xlo << ", " << xhi << ", "
<< alo << ", " << ahi << endl;
solutionDomain=0;
solutionExists=false;
- if(fabs(ahi-alo) > TrimAxes[current_axis]->GetTolerance()) {
+ if(fabs(ahi-alo) > axis.GetTolerance()) {
if(alo*current_accel <= 0) {
solutionExists=true;
solutionDomain=-1;
alo=current_accel;
}
}
- TrimAxes[current_axis]->SetControl(current_control);
- TrimAxes[current_axis]->Run();
+ axis.SetControl(current_control);
+ axis.Run();
return solutionExists;
}
void FGTrim::setupPullup() {
double g,q,cgamma;
g=fdmex->GetInertial()->gravity();
- cgamma=cos(fgic->GetFlightPathAngleRadIC());
+ cgamma=cos(fgic.GetFlightPathAngleRadIC());
cout << "setPitchRateInPullup(): " << g << ", " << cgamma << ", "
- << fgic->GetVtrueFpsIC() << endl;
- q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
+ << fgic.GetVtrueFpsIC() << endl;
+ q=g*(targetNlf-cgamma)/fgic.GetVtrueFpsIC();
cout << targetNlf << ", " << q << endl;
- fgic->SetQRadpsIC(q);
+ fgic.SetQRadpsIC(q);
cout << "setPitchRateInPullup() complete" << endl;
}
void FGTrim::setupTurn(void){
double g,phi;
- phi = fgic->GetPhiRadIC();
+ phi = fgic.GetPhiRadIC();
if( fabs(phi) > 0.001 && fabs(phi) < 1.56 ) {
targetNlf = 1 / cos(phi);
g = fdmex->GetInertial()->gravity();
- psidot = g*tan(phi) / fgic->GetUBodyFpsIC();
+ psidot = g*tan(phi) / fgic.GetUBodyFpsIC();
cout << targetNlf << ", " << psidot << endl;
}
void FGTrim::updateRates(void){
if( mode == tTurn ) {
- double phi = fgic->GetPhiRadIC();
+ double phi = fgic.GetPhiRadIC();
double g = fdmex->GetInertial()->gravity();
double p,q,r,theta;
if(fabs(phi) > 0.001 && fabs(phi) < 1.56 ) {
- theta=fgic->GetThetaRadIC();
- phi=fgic->GetPhiRadIC();
- psidot = g*tan(phi) / fgic->GetUBodyFpsIC();
+ theta=fgic.GetThetaRadIC();
+ phi=fgic.GetPhiRadIC();
+ psidot = g*tan(phi) / fgic.GetUBodyFpsIC();
p=-psidot*sin(theta);
q=psidot*cos(theta)*sin(phi);
r=psidot*cos(theta)*cos(phi);
} else {
p=q=r=0;
}
- fgic->SetPRadpsIC(p);
- fgic->SetQRadpsIC(q);
- fgic->SetRRadpsIC(r);
+ fgic.SetPRadpsIC(p);
+ fgic.SetQRadpsIC(q);
+ fgic.SetRRadpsIC(r);
} else if( mode == tPullup && fabs(targetNlf-1) > 0.01) {
double g,q,cgamma;
g=fdmex->GetInertial()->gravity();
- cgamma=cos(fgic->GetFlightPathAngleRadIC());
- q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
- fgic->SetQRadpsIC(q);
+ cgamma=cos(fgic.GetFlightPathAngleRadIC());
+ q=g*(targetNlf-cgamma)/fgic.GetVtrueFpsIC();
+ fgic.SetQRadpsIC(q);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGTrim::setDebug(void) {
+void FGTrim::setDebug(FGTrimAxis& axis) {
if(debug_axis == tAll ||
- TrimAxes[current_axis]->GetStateType() == debug_axis ) {
+ axis.GetStateType() == debug_axis ) {
Debug=DebugLevel;
return;
} else {
case tFull:
if (debug_lvl > 0)
cout << " Full Trim" << endl;
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
- //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tWdot,tAlpha));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tQdot,tPitchTrim ));
+ //TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tHmgt,tBeta ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tVdot,tPhi ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tPdot,tAileron ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tRdot,tRudder ));
break;
case tLongitudinal:
if (debug_lvl > 0)
cout << " Longitudinal Trim" << endl;
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tWdot,tAlpha ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tQdot,tPitchTrim ));
break;
case tGround:
if (debug_lvl > 0)
cout << " Ground Trim" << endl;
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tWdot,tAltAGL ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tQdot,tTheta ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tPdot,tPhi ));
break;
case tPullup:
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tNlf,tAlpha ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tQdot,tPitchTrim ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tHmgt,tBeta ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tVdot,tPhi ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tPdot,tAileron ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tRdot,tRudder ));
break;
case tTurn:
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tWdot,tAlpha ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tQdot,tPitchTrim ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tVdot,tBeta ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tPdot,tAileron ));
+ TrimAxes.push_back(FGTrimAxis(fdmex,&fgic,tRdot,tRudder ));
break;
case tCustom:
case tNone:
break;
}
//cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
- sub_iterations=new double[TrimAxes.size()];
- successful=new double[TrimAxes.size()];
- solution=new bool[TrimAxes.size()];
- current_axis=0;
+ sub_iterations.resize(TrimAxes.size());
+ successful.resize(TrimAxes.size());
+ solution.resize(TrimAxes.size());
}
//YOU WERE WARNED, BUT YOU DID IT ANYWAY.
}
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_TRIM "$Id: FGTrim.h,v 1.10 2013/11/24 16:53:15 bcoconni Exp $"
+#define ID_TRIM "$Id: FGTrim.h,v 1.11 2014/05/01 18:32:54 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@endcode
@author Tony Peden
- @version "$Id: FGTrim.h,v 1.10 2013/11/24 16:53:15 bcoconni Exp $"
+ @version "$Id: FGTrim.h,v 1.11 2014/05/01 18:32:54 bcoconni Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{
private:
- std::vector<FGTrimAxis*> TrimAxes;
- unsigned int current_axis;
- int N, Nsub;
+ std::vector<FGTrimAxis> TrimAxes;
+ unsigned int Nsub;
TrimMode mode;
int DebugLevel, Debug;
double Tolerance, A_Tolerance;
- double wdot,udot,qdot;
- double dth;
- double *sub_iterations;
- double *successful;
- bool *solution;
- int max_sub_iterations;
- int max_iterations;
- int total_its;
- bool trimudot;
+ std::vector<double> sub_iterations, successful;
+ std::vector<bool> solution;
+ unsigned int max_sub_iterations;
+ unsigned int max_iterations;
+ unsigned int total_its;
bool gamma_fallback;
- bool trim_failed;
- unsigned int axis_count;
int solutionDomain;
double xlo,xhi,alo,ahi;
double targetNlf;
int debug_axis;
- double psidot,thetadot;
+ double psidot;
FGFDMExec* fdmex;
- FGInitialCondition* fgic;
+ FGInitialCondition fgic;
- bool solve(void);
+ bool solve(FGTrimAxis& axis);
/** @return false if there is no change in the current axis accel
between accel(control_min) and accel(control_max). If there is a
-1 if sign change between accel(control_min) and accel(0)
1 if sign between accel(0) and accel(control_max)
*/
- bool findInterval(void);
+ bool findInterval(FGTrimAxis& axis);
- bool checkLimits(void);
+ bool checkLimits(FGTrimAxis& axis);
void setupPullup(void);
void setupTurn(void);
void updateRates(void);
- void setDebug(void);
+ void setDebug(FGTrimAxis& axis);
struct ContactPoints {
FGColumnVector3 location;
#include <cstdlib>
#include <stdexcept>
#include "simgear/misc/stdint.hxx"
+#include "FGInitialCondition.h"
namespace JSBSim
{
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.16 2013/02/02 13:23:40 bcoconni Exp $"
+#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.17 2014/05/17 15:35:54 jberndt Exp $"
namespace JSBSim {
ball formed earth with an adjustable terrain elevation.
@author Mathias Froehlich
- @version $Id: FGGroundCallback.h,v 1.16 2013/02/02 13:23:40 bcoconni Exp $
+ @version $Id: FGGroundCallback.h,v 1.17 2014/05/17 15:35:54 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{
public:
- FGDefaultGroundCallback(double referenceRadius = 20925650.0);
+ // This should not be hardcoded, but retrieved from FGInertial
+ FGDefaultGroundCallback(double referenceRadius);
double GetAltitude(const FGLocation& l) const;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGOutputFG.cpp,v 1.8 2014/01/13 10:46:00 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGOutputFG.cpp,v 1.9 2014/02/17 05:01:55 jberndt Exp $");
IDENT(IdHdr,ID_OUTPUTFG);
// (stolen from FGFS native_fdm.cxx)
net->version = FG_NET_FDM_VERSION;
// Positions
- net->longitude = Propagate->GetLocation().GetLongitude(); // geodetic (radians)
- net->latitude = Propagate->GetLocation().GetLatitude(); // geodetic (radians)
+ net->longitude = Propagate->GetLocation().GetLongitude(); //
+ net->latitude = Propagate->GetLocation().GetGeodLatitudeRad(); // geodetic (radians)
net->altitude = Propagate->GetAltitudeASL()*0.3048; // altitude, above sea level (meters)
net->agl = (float)(Propagate->GetDistanceAGL()*0.3048); // altitude, above ground level (meters)
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGOutputFile.cpp,v 1.6 2014/01/13 10:46:00 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGOutputFile.cpp,v 1.9 2014/05/04 17:00:27 bcoconni Exp $");
IDENT(IdHdr,ID_OUTPUTFILE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGOutputFile::FGOutputFile(FGFDMExec* fdmex) :
FGOutputType(fdmex),
- runID_postfix(0)
+ runID_postfix(-1)
{
}
bool FGOutputFile::InitModel(void)
{
- if (FGOutputType::InitModel())
+ if (FGOutputType::InitModel()) {
+ if (Filename.empty()) {
+ Filename = Name;
+ runID_postfix = 0;
+ }
return OpenFile();
+ }
return false;
}
void FGOutputFile::SetStartNewOutput(void)
{
- if (Filename.size() > 0) {
+ if (runID_postfix >= 0) {
ostringstream buf;
string::size_type dot = Name.find_last_of('.');
if (dot != string::npos) {
buf << Name << '_' << runID_postfix++;
}
Filename = buf.str();
- CloseFile();
}
+
+ CloseFile();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_OUTPUTFILE "$Id: FGOutputFile.h,v 1.3 2012/12/15 16:13:57 bcoconni Exp $"
+#define ID_OUTPUTFILE "$Id: FGOutputFile.h,v 1.6 2014/05/04 17:00:27 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
the next call to SetStartNewOutput().
@param name new name */
void SetOutputName(const std::string& fname) {
- Name = Filename = FDMExec->GetRootDir() + fname;
- runID_postfix = 0;
+ Name = FDMExec->GetRootDir() + fname;
+ runID_postfix = -1;
+ Filename = std::string();
}
/** Generate the output. This is a pure method so it must be implemented by
the classes that inherits from FGOutputFile.
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGOutputSocket.cpp,v 1.8 2014/01/13 10:46:00 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGOutputSocket.cpp,v 1.9 2014/02/17 05:01:22 jberndt Exp $");
IDENT(IdHdr,ID_OUTPUTSOCKET);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
socket->Append("SL pressure");
socket->Append("Ambient pressure");
socket->Append("Turbulence Magnitude");
- socket->Append("Turbulence Direction X");
- socket->Append("Turbulence Direction Y");
- socket->Append("Turbulence Direction Z");
+ socket->Append("Turbulence Direction");
socket->Append("NWind");
socket->Append("EWind");
socket->Append("DWind");
socket->Append(Atmosphere->GetPressureSL());
socket->Append(Atmosphere->GetPressure());
socket->Append(Winds->GetTurbMagnitude());
- socket->Append(Winds->GetTurbDirection().Dump(","));
+ socket->Append(Winds->GetTurbDirection());
socket->Append(Winds->GetTotalWindNED().Dump(","));
}
if (SubSystems & ssMassProps) {
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGOutputTextFile.cpp,v 1.10 2014/01/13 10:46:00 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGOutputTextFile.cpp,v 1.11 2014/02/17 05:02:38 jberndt Exp $");
IDENT(IdHdr,ID_OUTPUTTEXTFILE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
outstream << "P_{SL} (psf)" + delimeter;
outstream << "P_{Ambient} (psf)" + delimeter;
outstream << "Turbulence Magnitude (ft/sec)" + delimeter;
- outstream << "Turbulence X Direction (rad)" + delimeter + "Turbulence Y Direction (rad)" + delimeter + "Turbulence Z Direction (rad)" + delimeter;
- outstream << "Wind V_{North} (ft/s)" + delimeter + "Wind V_{East} (ft/s)" + delimeter + "Wind V_{Down} (ft/s)";
+ outstream << "Turbulence X Direction (deg)" + delimeter;
+ outstream << "Wind V_{North} (ft/s)" + delimeter + "Wind V_{East} (ft/s)" + delimeter + "Wind V_{Down} (ft/s)" + delimeter;
+ outstream << "Roll Turbulence (deg/sec)" + delimeter + "Pitch Turbulence (deg/sec)" + delimeter + "Yaw Turbulence (deg/sec)";
}
if (SubSystems & ssMassProps) {
outstream << delimeter;
outstream << "I_{zy}" + delimeter;
outstream << "I_{zz}" + delimeter;
outstream << "Mass" + delimeter;
+ outstream << "Weight" + delimeter;
outstream << "X_{cg}" + delimeter + "Y_{cg}" + delimeter + "Z_{cg}";
}
if (SubSystems & ssPropagate) {
outstream << Atmosphere->GetPressureSL() << delimeter;
outstream << Atmosphere->GetPressure() << delimeter;
outstream << Winds->GetTurbMagnitude() << delimeter;
- outstream << Winds->GetTurbDirection().Dump(delimeter) << delimeter;
- outstream << Winds->GetTotalWindNED().Dump(delimeter);
+ outstream << Winds->GetTurbDirection() << delimeter;
+ outstream << Winds->GetTotalWindNED().Dump(delimeter) << delimeter;
+ outstream << (Winds->GetTurbPQR()*radtodeg).Dump(delimeter);
}
if (SubSystems & ssMassProps) {
outstream << delimeter;
outstream << MassBalance->GetJ().Dump(delimeter) << delimeter;
outstream << MassBalance->GetMass() << delimeter;
+ outstream << MassBalance->GetWeight() << delimeter;
outstream << MassBalance->GetXYZcg().Dump(delimeter);
}
if (SubSystems & ssPropagate) {
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGScript.cpp,v 1.56 2014/01/13 10:46:01 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGScript.cpp,v 1.57 2014/05/17 15:33:08 jberndt Exp $");
IDENT(IdHdr,ID_FGSCRIPT);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Set sim timing
- StartTime = run_element->GetAttributeValueAsNumber("start");
+ if (run_element->HasAttribute("start")) StartTime = run_element->GetAttributeValueAsNumber("start");
FDMExec->Setsim_time(StartTime);
- EndTime = run_element->GetAttributeValueAsNumber("end");
+ if (run_element->HasAttribute("end")) {
+ EndTime = run_element->GetAttributeValueAsNumber("end");
+ } else {
+ cerr << "An end time (duration) for the script must be specified in the script <run> element." << endl;
+ return false;
+ }
+
// Make sure that the desired time is reached and executed.
EndTime += 0.99*FDMExec->GetDeltaT();
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGXMLElement.cpp,v 1.45 2014/01/13 10:46:02 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGXMLElement.cpp,v 1.48 2014/05/17 15:31:17 jberndt Exp $");
IDENT(IdHdr,ID_XMLELEMENT);
bool Element::converterIsInitialized = false;
convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
// Mass flow
convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
+ convert ["N/SEC"]["LBS/SEC"] = 0.224808943;
+ convert ["LBS/SEC"]["N/SEC"] = 1.0/convert ["N/SEC"]["LBS/SEC"];
// Fuel Consumption
convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083;
convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"];
convert["LBS/SEC"]["LBS/SEC"] = 1.00;
convert["KG/MIN"]["KG/MIN"] = 1.0;
convert["LBS/MIN"]["LBS/MIN"] = 1.0;
+ convert["N/SEC"]["N/SEC"] = 1.0;
// Fuel Consumption
convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0;
convert["KG/KW*HR"]["KG/KW*HR"] = 1.0;
{
double value=val;
double disp=0.0;
- if (e->HasAttribute("dispersion")) {
+
+ bool disperse = false;
+ try {
+ char* num = getenv("JSBSIM_DISPERSE");
+ if (num) {
+ disperse = (atoi(num) == 1); // set dispersions
+ }
+ } catch (...) { // if error set to false
+ disperse = false;
+ std::cerr << "Could not process JSBSIM_DISPERSE environment variable: Assumed NO dispersions." << endl;
+ }
+
+ if (e->HasAttribute("dispersion") && disperse) {
disp = e->GetAttributeValueAsNumber("dispersion");
if (!supplied_units.empty()) disp *= convert[supplied_units][target_units];
string attType = e->GetAttributeValue("type");
- if (attType == "gaussian") {
+ if (attType == "gaussian" || attType == "gaussiansigned") {
double grn = GaussianRandomNumber();
+ if (attType == "gaussian") {
value = val + disp*grn;
-/* std::cout << "DISPERSION GAUSSIAN: Initial: " << val
- << " Dispersion: " << disp
- << " Gaussian Rand Num: " << grn
- << " Total Dispersed Value: " << value << endl; */
- } else if (attType == "uniform") {
+ } else { // Assume gaussiansigned
+ value = (val + disp*grn)*(fabs(grn)/grn);
+ }
+ } else if (attType == "uniform" || attType == "uniformsigned") {
double urn = ((((double)rand()/RAND_MAX)-0.5)*2.0);
+ if (attType == "uniform") {
value = val + disp * urn;
-/* std::cout << "DISPERSION UNIFORM: Initial: " << val
- << " Dispersion: " << disp
- << " Uniform Rand Num: " << urn
- << " Total Dispersed Value: " << value << endl; */
+ } else { // Assume uniformsigned
+ value = (val + disp * urn)*(fabs(urn)/urn);
+ }
} else {
cerr << ReadFrom() << "Unknown dispersion type" << attType << endl;
exit(-1);
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.18 2014/01/13 10:46:03 ehofman Exp $"
+#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.19 2014/01/29 13:30:11 ehofman Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
extern bool is_number(const std::string& str);
std::vector <std::string> split(std::string str, char d);
-// libc++ has these as built-ins for all C++ language versions
+ // libc++ has these as built-ins for all C++ language versions
#if !defined(_LIBCPP_VERSION)
extern std::string to_string(int);
extern std::string to_string(double);
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "initialization/FGInitialCondition.h"
#include "FGStateSpace.h"
#include <limits>
#include <iomanip>
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGAerodynamics.cpp,v 1.52 2014/01/13 10:46:04 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGAerodynamics.cpp,v 1.53 2014/05/17 15:30:35 jberndt Exp $");
IDENT(IdHdr,ID_AERODYNAMICS);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
document = element;
}
+ Name = "Aerodynamics Model: " + document->GetAttributeValue("name");
+
FGModel::Load(document); // Perform base class Pre-Load
DetermineAxisSystem(document); // Detemine if Lift/Side/Drag, etc. is used.
{
typedef double (FGAerodynamics::*PMF)(int) const;
- PropertyManager->Tie("forces/fbx-aero-lbs", this,1,
- (PMF)&FGAerodynamics::GetForces);
- PropertyManager->Tie("forces/fby-aero-lbs", this,2,
- (PMF)&FGAerodynamics::GetForces);
- PropertyManager->Tie("forces/fbz-aero-lbs", this,3,
- (PMF)&FGAerodynamics::GetForces);
- PropertyManager->Tie("moments/l-aero-lbsft", this,1,
- (PMF)&FGAerodynamics::GetMoments);
- PropertyManager->Tie("moments/m-aero-lbsft", this,2,
- (PMF)&FGAerodynamics::GetMoments);
- PropertyManager->Tie("moments/n-aero-lbsft", this,3,
- (PMF)&FGAerodynamics::GetMoments);
- PropertyManager->Tie("forces/fwx-aero-lbs", this,1,
- (PMF)&FGAerodynamics::GetvFw);
- PropertyManager->Tie("forces/fwy-aero-lbs", this,2,
- (PMF)&FGAerodynamics::GetvFw);
- PropertyManager->Tie("forces/fwz-aero-lbs", this,3,
- (PMF)&FGAerodynamics::GetvFw);
- PropertyManager->Tie("forces/lod-norm", this,
- &FGAerodynamics::GetLoD);
- PropertyManager->Tie("aero/cl-squared", this,
- &FGAerodynamics::GetClSquared);
+ PropertyManager->Tie("forces/fbx-aero-lbs", this, 1, (PMF)&FGAerodynamics::GetForces);
+ PropertyManager->Tie("forces/fby-aero-lbs", this, 2, (PMF)&FGAerodynamics::GetForces);
+ PropertyManager->Tie("forces/fbz-aero-lbs", this, 3, (PMF)&FGAerodynamics::GetForces);
+ PropertyManager->Tie("moments/l-aero-lbsft", this, 1, (PMF)&FGAerodynamics::GetMoments);
+ PropertyManager->Tie("moments/m-aero-lbsft", this, 2, (PMF)&FGAerodynamics::GetMoments);
+ PropertyManager->Tie("moments/n-aero-lbsft", this, 3, (PMF)&FGAerodynamics::GetMoments);
+ PropertyManager->Tie("forces/fwx-aero-lbs", this, 1, (PMF)&FGAerodynamics::GetvFw);
+ PropertyManager->Tie("forces/fwy-aero-lbs", this, 2, (PMF)&FGAerodynamics::GetvFw);
+ PropertyManager->Tie("forces/fwz-aero-lbs", this, 3, (PMF)&FGAerodynamics::GetvFw);
+ PropertyManager->Tie("forces/lod-norm", this, &FGAerodynamics::GetLoD);
+ PropertyManager->Tie("aero/cl-squared", this, &FGAerodynamics::GetClSquared);
PropertyManager->Tie("aero/qbar-area", &qbar_area);
- PropertyManager->Tie("aero/alpha-max-rad", this,
- &FGAerodynamics::GetAlphaCLMax,
- &FGAerodynamics::SetAlphaCLMax,
- true);
- PropertyManager->Tie("aero/alpha-min-rad", this,
- &FGAerodynamics::GetAlphaCLMin,
- &FGAerodynamics::SetAlphaCLMin,
- true);
- PropertyManager->Tie("aero/bi2vel", this,
- &FGAerodynamics::GetBI2Vel);
- PropertyManager->Tie("aero/ci2vel", this,
- &FGAerodynamics::GetCI2Vel);
- PropertyManager->Tie("aero/alpha-wing-rad", this,
- &FGAerodynamics::GetAlphaW);
- PropertyManager->Tie("systems/stall-warn-norm", this,
- &FGAerodynamics::GetStallWarn);
- PropertyManager->Tie("aero/stall-hyst-norm", this,
- &FGAerodynamics::GetHysteresisParm);
+ PropertyManager->Tie("aero/alpha-max-rad", this, &FGAerodynamics::GetAlphaCLMax, &FGAerodynamics::SetAlphaCLMax, true);
+ PropertyManager->Tie("aero/alpha-min-rad", this, &FGAerodynamics::GetAlphaCLMin, &FGAerodynamics::SetAlphaCLMin, true);
+ PropertyManager->Tie("aero/bi2vel", this, &FGAerodynamics::GetBI2Vel);
+ PropertyManager->Tie("aero/ci2vel", this, &FGAerodynamics::GetCI2Vel);
+ PropertyManager->Tie("aero/alpha-wing-rad", this, &FGAerodynamics::GetAlphaW);
+ PropertyManager->Tie("systems/stall-warn-norm", this, &FGAerodynamics::GetStallWarn);
+ PropertyManager->Tie("aero/stall-hyst-norm", this, &FGAerodynamics::GetHysteresisParm);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-IDENT(IdSrc,"$Id: FGAircraft.cpp,v 1.39 2014/01/13 10:46:04 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGAircraft.cpp,v 1.40 2014/05/17 15:29:30 jberndt Exp $");
IDENT(IdHdr,ID_AIRCRAFT);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
PropertyManager->Tie("metrics/lv-norm", this, &FGAircraft::Getlbarv);
PropertyManager->Tie("metrics/vbarh-norm", this, &FGAircraft::Getvbarh);
PropertyManager->Tie("metrics/vbarv-norm", this, &FGAircraft::Getvbarv);
- PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp);
- PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp);
- PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp);
+ PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp, &FGAircraft::SetXYZrp);
+ PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp, &FGAircraft::SetXYZrp);
+ PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp, &FGAircraft::SetXYZrp);
PropertyManager->Tie("metrics/eyepoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZep);
PropertyManager->Tie("metrics/eyepoint-y-in", this, eY,(PMF)&FGAircraft::GetXYZep);
PropertyManager->Tie("metrics/eyepoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZep);
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGAtmosphere.cpp,v 1.58 2014/01/13 10:46:04 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGAtmosphere.cpp,v 1.59 2014/05/07 19:51:43 bcoconni Exp $");
IDENT(IdHdr,ID_ATMOSPHERE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGAtmosphere::bind(void)
{
- typedef double (FGAtmosphere::*PMFi)(int) const;
- typedef void (FGAtmosphere::*PMF)(int, double);
+// typedef double (FGAtmosphere::*PMFi)(int) const;
+// typedef void (FGAtmosphere::*PMF)(int, double);
PropertyManager->Tie("atmosphere/T-R", this, &FGAtmosphere::GetTemperature);
PropertyManager->Tie("atmosphere/rho-slugs_ft3", this, &FGAtmosphere::GetDensity);
PropertyManager->Tie("atmosphere/P-psf", this, &FGAtmosphere::GetPressure);
#include <iostream>
#include "FGAuxiliary.h"
+#include "initialization/FGInitialCondition.h"
#include "FGFDMExec.h"
#include "input_output/FGPropertyManager.h"
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGAuxiliary.cpp,v 1.65 2014/01/13 10:46:06 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGAuxiliary.cpp,v 1.67 2014/05/17 15:28:51 jberndt Exp $");
IDENT(IdHdr,ID_AUXILIARY);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double Vt2 = Vt*Vt;
- if ( Vt > 1.0 ) {
+ if ( Vt > 0.001 ) {
if (vAeroUVW(eW) != 0.0)
alpha = AeroU2 > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
if (vAeroUVW(eV) != 0.0)
//double signU=1;
//if (vAeroUVW(eU) < 0.0) signU=-1;
- if ( mUW >= 1.0 ) {
+ if ( mUW >= 0.001 ) {
adot = (vAeroUVW(eU)*in.vUVWdot(eW) - vAeroUVW(eW)*in.vUVWdot(eU))/mUW;
// bdot = (signU*mUW*in.vUVWdot(eV)
// - vAeroUVW(eV)*(vAeroUVW(eU)*in.vUVWdot(eU) + vAeroUVW(eW)*in.vUVWdot(eW)))/(Vt2*sqrt(mUW));
if (abs(MachU) > 0.0) {
vcas = sqrt(7 * in.PressureSL / in.DensitySL * (A-1));
veas = sqrt(2 * qbar / in.DensitySL);
- vtrue = 1116.43559 * MachU * sqrt(in.Temperature / 518.67);
+ vtrue = 1116.43559 * Mach * sqrt(in.Temperature / 518.67);
} else {
vcas = veas = vtrue = 0.0;
}
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGFCS.cpp,v 1.87 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGFCS.cpp,v 1.88 2014/05/17 15:27:16 jberndt Exp $");
IDENT(IdHdr,ID_FCS);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
document = el;
}
+ Name = "Flight Control Systems Model: " + document->GetAttributeValue("name");
+
if (document->GetName() == "autopilot") {
Name = "Autopilot: " + document->GetAttributeValue("name");
} else if (document->GetName() == "flight_control") {
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGGroundReactions.cpp,v 1.49 2014/01/28 09:42:21 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGGroundReactions.cpp,v 1.50 2014/05/17 15:25:20 jberndt Exp $");
IDENT(IdHdr,ID_GROUNDREACTIONS);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
document = elem;
}
+ Name = "Ground Reactions Model: " + document->GetAttributeValue("name");
+
Debug(2);
unsigned int numContacts = document->GetNumElements("contact");
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGInertial.cpp,v 1.29 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGInertial.cpp,v 1.31 2014/05/17 15:24:37 jberndt Exp $");
IDENT(IdHdr,ID_INERTIAL);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Earth defaults
RotationRate = 0.00007292115;
- GM = 14.07644180E15; // WGS84 value
- RadiusReference = 20925650.00; // Equatorial radius (WGS84)
+// RotationRate = 0.000072921151467;
+ GM = 14.0764417572E15; // WGS84 value
C2_0 = -4.84165371736E-04; // WGS84 value for the C2,0 coefficient
- J2 = 1.0826266836E-03; // WGS84 value for J2
- a = 20925646.3255; // WGS84 semimajor axis length in feet
+ J2 = 1.08262982E-03; // WGS84 value for J2
+ a = 20925646.32546; // WGS84 semimajor axis length in feet
+// a = 20902254.5305; // Effective Earth radius for a sphere
b = 20855486.5951; // WGS84 semiminor axis length in feet
+ RadiusReference = a;
// Lunar defaults
/*
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.114 2014/01/28 09:42:21 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.116 2014/05/17 15:26:39 jberndt Exp $");
IDENT(IdHdr,ID_LGEAR);
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
SinkRate > 1.4666*30 ) && !fdmex->IntegrationSuspended())
{
PutMessage("Crash Detected: Simulation FREEZE.");
- fdmex->SuspendIntegration();
+ // fdmex->SuspendIntegration();
}
}
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGMassBalance.cpp,v 1.47 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGMassBalance.cpp,v 1.49 2014/05/17 15:17:13 jberndt Exp $");
IDENT(IdHdr,ID_MASSBALANCE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
document = elem;
}
+ Name = "Mass Properties Model: " + document->GetAttributeValue("name");
+
FGModel::Load(document); // Perform base class Load.
bixx = biyy = bizz = bixy = bixz = biyz = 0.0;
(PMF)&FGMassBalance::GetXYZcg);
PropertyManager->Tie("inertia/cg-z-in", this,3,
(PMF)&FGMassBalance::GetXYZcg);
+ typedef int (FGMassBalance::*iOPV)() const;
+ PropertyManager->Tie("inertia/print-mass-properties", this, (iOPV)0, &FGMassBalance::GetMassPropertiesReport);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGMassBalance::GetMassPropertiesReport(void) const
+void FGMassBalance::GetMassPropertiesReport(int i)
{
cout << endl << fgblue << highint
<< " Mass Properties Report (English units: lbf, in, slug-ft^2)"
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_MASSBALANCE "$Id: FGMassBalance.h,v 1.29 2013/11/24 11:40:56 bcoconni Exp $"
+#define ID_MASSBALANCE "$Id: FGMassBalance.h,v 1.31 2014/05/17 15:17:13 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONSS
const FGMatrix33& GetJ(void) const {return mJ;}
const FGMatrix33& GetJinv(void) const {return mJinv;}
void SetAircraftBaseInertias(const FGMatrix33& BaseJ) {baseJ = BaseJ;}
- void GetMassPropertiesReport(void) const;
+ void GetMassPropertiesReport(int i);
struct Inputs {
double GasMass;
const string& GetName(void) {return Name;}
void SetPointMassLocation(int axis, double value) {Location(axis) = value;}
- void SetPointMassWeight(double wt) {Weight = wt;}
+ void SetPointMassWeight(double wt) {
+ Weight = wt;
+ CalculateShapeInertia();
+ }
void SetPointMassShapeType(esShape st) {eShapeType = st;}
void SetRadius(double r) {Radius = r;}
void SetLength(double l) {Length = l;}
#include <iomanip>
#include <fstream>
+#include "initialization/FGInitialCondition.h"
#include "FGPropagate.h"
#include "FGGroundReactions.h"
#include "FGFDMExec.h"
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGPropagate.cpp,v 1.123 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGPropagate.cpp,v 1.125 2014/05/17 15:15:53 jberndt Exp $");
IDENT(IdHdr,ID_PROPAGATE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
integrator_rotational_position = eRectEuler;
integrator_translational_position = eAdamsBashforth3;
- VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
- VState.dqUVWidot.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));
+ VState.dqPQRidot.resize(5, FGColumnVector3(0.0,0.0,0.0));
+ VState.dqUVWidot.resize(5, FGColumnVector3(0.0,0.0,0.0));
+ VState.dqInertialVelocity.resize(5, FGColumnVector3(0.0,0.0,0.0));
+ VState.dqQtrndot.resize(5, FGQuaternion(0.0,0.0,0.0));
bind();
Debug(0);
VState.vLocation.SetEllipse(in.SemiMajor, in.SemiMinor);
VState.vLocation.SetAltitudeAGL(4.0, FDMExec->GetSimTime());
- VState.dqPQRidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
- VState.dqUVWidot.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));
+ VState.dqPQRidot.resize(5, FGColumnVector3(0.0,0.0,0.0));
+ VState.dqUVWidot.resize(5, FGColumnVector3(0.0,0.0,0.0));
+ VState.dqInertialVelocity.resize(5, FGColumnVector3(0.0,0.0,0.0));
+ VState.dqQtrndot.resize(5, FGColumnVector3(0.0,0.0,0.0));
integrator_rotational_rate = eRectEuler;
integrator_translational_rate = eAdamsBashforth2;
void FGPropagate::InitializeDerivatives()
{
- for (int i=0; i<4; i++) {
+ for (int i=0; i<5; i++) {
VState.dqPQRidot[i] = in.vPQRidot;
VState.dqUVWidot[i] = in.vUVWidot;
VState.dqInertialVelocity[i] = VState.vInertialVelocity;
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 eAdamsBashforth5: Integrand += dt*((1901./720.)*ValDot[0] - (1387./360.)*ValDot[1] + (109./30.)*ValDot[2] - (637./360.)*ValDot[3] + (251./720.)*ValDot[4]);
+ break;
case eNone: // do nothing, freeze translational rate
break;
+ case eBuss1:
+ case eBuss2:
+ case eLocalLinearization:
+ throw("Can only use Buss (1 & 2) or local linearization integration methods in for rotational position!");
default:
break;
}
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 eAdamsBashforth5: Integrand += dt*((1901./720.)*ValDot[0] - (1387./360.)*ValDot[1] + (109./30.)*ValDot[2] - (637./360.)*ValDot[3] + (251./720.)*ValDot[4]);
+ break;
case eBuss1:
{
// This is the first order method as described in Samuel R. Buss paper[6].
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.80 2013/12/22 17:08:59 jberndt Exp $"
+#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.81 2014/05/17 15:15:53 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@endcode
@author Jon S. Berndt, Mathias Froehlich, Bertrand Coconnier
- @version $Id: FGPropagate.h,v 1.80 2013/12/22 17:08:59 jberndt Exp $
+ @version $Id: FGPropagate.h,v 1.81 2014/05/17 15:15:53 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/// These define the indices use to select the various integrators.
enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2,
- eAdamsBashforth3, eAdamsBashforth4, eBuss1, eBuss2, eLocalLinearization};
+ eAdamsBashforth3, eAdamsBashforth4, eBuss1, eBuss2, eLocalLinearization, eAdamsBashforth5};
/** Initializes the FGPropagate class after instantiation and prior to first execution.
The base class FGModel::InitModel is called first, initializing pointers to the
*/
FGColumnVector3 GetECEFVelocity(void) const {return Tb2ec * VState.vUVW; }
+ /** Calculates and retrieves the velocity vector relative to the earth centered earth fixed (ECEF) frame
+ for a particular axis.
+ */
+ double GetECEFVelocity(int idx) const {return (Tb2ec * VState.vUVW)(idx); }
+
/** Returns the current altitude above sea level.
This function returns the altitude above sea level.
units ft
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGPropulsion.cpp,v 1.76 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGPropulsion.cpp,v 1.78 2014/05/17 15:13:56 jberndt Exp $");
IDENT(IdHdr,ID_PROPULSION);
extern short debug_lvl;
{
Name = "FGPropulsion";
- InitializedEngines = 0;
numSelectedFuelTanks = numSelectedOxiTanks = 0;
numTanks = numEngines = 0;
numOxiTanks = numFuelTanks = 0;
HaveRocketEngine =
HaveTurboPropEngine =
HaveElectricEngine = false;
- HasInitializedEngines = false;
Debug(0);
}
for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
- for (unsigned int i=0; i<numEngines; i++) {
- switch (Engines[i]->GetType()) {
- case FGEngine::etPiston:
- Engines[i]->ResetToIC();
- try {
- if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
- } catch (string str) {
- cerr << str << endl;
- result = false;
- }
- break;
- case FGEngine::etTurbine:
- Engines[i]->ResetToIC();
- try {
- if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
- } catch (string str) {
- cerr << str << endl;
- result = false;
- }
- break;
- default:
- break;
- }
- }
+ for (unsigned int i=0; i<numEngines; i++)
+ Engines[i]->ResetToIC();
return result;
}
if (engine->GetType() == FGEngine::etRocket) {
double OxidizerToBurn = engine->CalcOxidizerNeed(); // How much fuel does this engine need?
- double OxidizerNeededPerTank = OxidizerToBurn / TanksWithOxidizer; // Determine fuel needed per tank.
+ double OxidizerNeededPerTank = 0;
+ if (TanksWithOxidizer > 0) OxidizerNeededPerTank = OxidizerToBurn / TanksWithOxidizer; // Determine fuel needed per tank.
for (unsigned int i=0; i<FeedListOxi.size(); i++) {
Tanks[FeedListOxi[i]]->Drain(OxidizerNeededPerTank);
}
GetEngine(n)->InitRunning();
GetSteadyState();
- InitializedEngines = 1 << n;
- HasInitializedEngines = true;
-
} else if (n < 0) { // -1 refers to "All Engines"
for (unsigned int i=0; i<GetNumEngines(); i++) {
}
GetSteadyState();
- InitializedEngines = -1;
- HasInitializedEngines = true;
}
}
el = elem;
}
+ Name = "Propulsion Model: " + el->GetAttributeValue("name");
+
FGModel::Load(el); // Perform base class Load.
// Process tank definitions first to establish the number of fuel tanks
&FGPropulsion::SetRefuel, true);
PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
&FGPropulsion::SetFuelDump, true);
- PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
- (PMF)&FGPropulsion::GetForces);
- PropertyManager->Tie("forces/fby-prop-lbs", this,2,
- (PMF)&FGPropulsion::GetForces);
- PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
- (PMF)&FGPropulsion::GetForces);
- PropertyManager->Tie("moments/l-prop-lbsft", this,1,
- (PMF)&FGPropulsion::GetMoments);
- PropertyManager->Tie("moments/m-prop-lbsft", this,2,
- (PMF)&FGPropulsion::GetMoments);
- PropertyManager->Tie("moments/n-prop-lbsft", this,3,
- (PMF)&FGPropulsion::GetMoments);
-
+ PropertyManager->Tie("forces/fbx-prop-lbs", this, eX, (PMF)&FGPropulsion::GetForces);
+ PropertyManager->Tie("forces/fby-prop-lbs", this, eY, (PMF)&FGPropulsion::GetForces);
+ PropertyManager->Tie("forces/fbz-prop-lbs", this, eZ, (PMF)&FGPropulsion::GetForces);
+ PropertyManager->Tie("moments/l-prop-lbsft", this, eX, (PMF)&FGPropulsion::GetMoments);
+ PropertyManager->Tie("moments/m-prop-lbsft", this, eY, (PMF)&FGPropulsion::GetMoments);
+ PropertyManager->Tie("moments/n-prop-lbsft", this, eZ, (PMF)&FGPropulsion::GetMoments);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.32 2013/11/24 11:40:56 bcoconni Exp $"
+#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.33 2014/04/13 11:19:15 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@endcode
@author Jon S. Berndt
- @version $Id: FGPropulsion.h,v 1.32 2013/11/24 11:40:56 bcoconni Exp $
+ @version $Id: FGPropulsion.h,v 1.33 2014/04/13 11:19:15 bcoconni Exp $
@see
FGEngine
FGTank
bool HaveElectricEngine;
void ConsumeFuel(FGEngine* engine);
- int InitializedEngines;
- bool HasInitializedEngines;
-
void bind();
void Debug(int from);
};
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGStandardAtmosphere.cpp,v 1.23 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGStandardAtmosphere.cpp,v 1.24 2014/05/17 15:07:48 jberndt Exp $");
IDENT(IdHdr,ID_STANDARDATMOSPHERE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// GeoMet Alt Temp GeoPot Alt GeoMet Alt
// (ft) (deg R) (km) (km)
// -------- -------- ---------- ----------
- *StdAtmosTemperatureTable << 0.0 << 518.67 // 0.000 0.000
- << 36151.6 << 390.0 // 11.000 11.019
- << 65823.5 << 390.0 // 20.000 20.063
- << 105518.4 << 411.6 // 32.000 32.162
- << 155347.8 << 487.2 // 47.000 47.350
- << 168677.8 << 487.2 // 51.000 51.413
- << 235570.9 << 386.4 // 71.000 71.802
- << 282152.2 << 336.5 // 84.852 86.000
- << 298556.4 << 336.5; // 91.000 - First layer in high altitude regime
+ //*StdAtmosTemperatureTable << 0.00 << 518.67 // 0.000 0.000
+ // << 36151.80 << 389.97 // 11.000 11.019
+ // << 65823.90 << 389.97 // 20.000 20.063
+ // << 105518.06 << 411.60 // 32.000 32.162
+ // << 155348.07 << 487.20 // 47.000 47.350
+ // << 168676.12 << 487.20 // 51.000 51.413
+ // << 235570.77 << 386.40 // 71.000 71.802
+ // << 282152.08 << 336.50 // 84.852 86.000
+ // << 298556.40 << 336.50; // 91.000 - First layer in high altitude regime
+
+ // GeoPot Alt Temp GeoPot Alt GeoMet Alt
+ // (ft) (deg R) (km) (km)
+ // ----------- -------- ---------- ----------
+ *StdAtmosTemperatureTable << 0.0000 << 518.67 // 0.000 0.000
+ << 36089.2388 << 389.97 // 11.000 11.019
+ << 65616.7979 << 389.97 // 20.000 20.063
+ << 104986.8766 << 411.57 // 32.000 32.162
+ << 154199.4751 << 487.17 // 47.000 47.350
+ << 167322.8346 << 487.17 // 51.000 51.413
+ << 232939.6325 << 386.37 // 71.000 71.802
+ << 278385.8268 << 336.50 // 84.852 86.000
+ << 298556.40 << 336.50; // 91.000 - First layer in high altitude regime
LapseRateVector.resize(StdAtmosTemperatureTable->GetNumRows()-1);
PressureBreakpointVector.resize(StdAtmosTemperatureTable->GetNumRows());
// Iterate through the altitudes to find the current Base Altitude
// in the table. That is, if the current altitude (the argument passed in)
// is 20000 ft, then the base altitude from the table is 0.0. If the
- // passed-in altitude is 40000 ft, the base altitude is 36151.6 ft (and
+ // passed-in altitude is 40000 ft, the base altitude is 36089.2388 ft (and
// the index "b" is 2 - the second entry in the table).
double testAlt = (*StdAtmosTemperatureTable)(b+1,0);
- while ((altitude >= testAlt) && (b <= numRows-2)) {
+ double GeoPotAlt = (altitude*20855531.5)/(20855531.5+altitude);
+ while ((GeoPotAlt >= testAlt) && (b <= numRows-2)) {
b++;
testAlt = (*StdAtmosTemperatureTable)(b+1,0);
}
double BaseAlt = (*StdAtmosTemperatureTable)(b+1,0);
Tmb = GetTemperature(BaseAlt);
- deltaH = altitude - BaseAlt;
+ deltaH = GeoPotAlt - BaseAlt;
if (LapseRateVector[b] != 0.00) {
Lmb = LapseRateVector[b];
double FGStandardAtmosphere::GetTemperature(double altitude) const
{
- double T = StdAtmosTemperatureTable->GetValue(altitude) + TemperatureBias;
+ double GeoPotAlt = (altitude*20855531.5)/(20855531.5+altitude);
+
+ double T = StdAtmosTemperatureTable->GetValue(GeoPotAlt) + TemperatureBias;
if (altitude <= GradientFadeoutAltitude)
T += TemperatureDeltaGradient * (GradientFadeoutAltitude - altitude);
if (altitude < 298556.4) { // 91 km - station 8
- temp = StdAtmosTemperatureTable->GetValue(altitude);
+ double GeoPotAlt = (altitude*20855531.5)/(20855531.5+altitude);
+ temp = StdAtmosTemperatureTable->GetValue(GeoPotAlt);
} else if (altitude < 360892.4) { // 110 km - station 9
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGWinds.cpp,v 1.11 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGWinds.cpp,v 1.12 2014/02/17 05:02:38 jberndt Exp $");
IDENT(IdHdr,ID_WINDS);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{
Name = "FGWinds";
- MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
+ MagnitudedAccelDt = MagnitudeAccel = Magnitude = TurbDirection = 0.0;
SetTurbType( ttMilspec );
TurbGain = 1.0;
TurbRate = 10.0;
// max vertical wind speed in fps, corresponds to TurbGain = 1.0
double max_vs = 40;
- vTurbulenceNED(1) = vTurbulenceNED(2) = vTurbulenceNED(3) = 0.0;
+ vTurbulenceNED.InitMatrix();
double delta = strength * max_vs * TurbGain * (1-Rhythmicity) * spike;
// Vertical component of turbulence.
- vTurbulenceNED(3) = sinewave * max_vs * TurbGain * Rhythmicity;
- vTurbulenceNED(3)+= delta;
+ vTurbulenceNED(eDown) = sinewave * max_vs * TurbGain * Rhythmicity;
+ vTurbulenceNED(eDown)+= delta;
if (in.DistanceAGL/in.wingspan < 3.0)
- vTurbulenceNED(3) *= in.DistanceAGL/in.wingspan * 0.3333;
+ vTurbulenceNED(eDown) *= in.DistanceAGL/in.wingspan * 0.3333;
// Yaw component of turbulence.
- vTurbulenceNED(1) = sin( delta * 3.0 );
- vTurbulenceNED(2) = cos( delta * 3.0 );
+ vTurbulenceNED(eNorth) = sin( delta * 3.0 );
+ vTurbulenceNED(eEast) = cos( delta * 3.0 );
// Roll component of turbulence. Clockwise vortex causes left roll.
vTurbPQR(eP) += delta * 0.04;
// an index of zero means turbulence is disabled
// airspeed occurs as divisor in the code below
if (probability_of_exceedence_index == 0 || in.V == 0) {
- vTurbulenceNED(1) = vTurbulenceNED(2) = vTurbulenceNED(3) = 0.0;
- vTurbPQR(1) = vTurbPQR(2) = vTurbPQR(3) = 0.0;
+ vTurbulenceNED(eNorth) = vTurbulenceNED(eEast) = vTurbulenceNED(eDown) = 0.0;
+ vTurbPQR(eP) = vTurbPQR(eQ) = vTurbPQR(eR) = 0.0;
return;
}
// rotate by wind azimuth and assign the velocities
double cospsi = cos(psiw), sinpsi = sin(psiw);
- vTurbulenceNED(1) = cospsi*xi_u + sinpsi*xi_v;
- vTurbulenceNED(2) = -sinpsi*xi_u + cospsi*xi_v;
- vTurbulenceNED(3) = xi_w;
+ vTurbulenceNED(eNorth) = cospsi*xi_u + sinpsi*xi_v;
+ vTurbulenceNED(eEast) = -sinpsi*xi_u + cospsi*xi_v;
+ vTurbulenceNED(eDown) = xi_w;
- vTurbPQR(1) = cospsi*xi_p + sinpsi*xi_q;
- vTurbPQR(2) = -sinpsi*xi_p + cospsi*xi_q;
- vTurbPQR(3) = xi_r;
+ vTurbPQR(eP) = cospsi*xi_p + sinpsi*xi_q;
+ vTurbPQR(eQ) = -sinpsi*xi_p + cospsi*xi_q;
+ vTurbPQR(eR) = xi_r;
// vTurbPQR is in the body fixed frame, not NED
vTurbPQR = in.Tl2b*vTurbPQR;
default:
break;
}
+
+ TurbDirection = atan2( vTurbulenceNED(eEast), vTurbulenceNED(eNorth))*radtodeg;
+
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_WINDS "$Id: FGWinds.h,v 1.9 2011/11/19 14:14:57 bcoconni Exp $"
+#define ID_WINDS "$Id: FGWinds.h,v 1.10 2014/02/17 05:02:38 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
virtual double GetRhythmicity() const {return Rhythmicity;}
virtual double GetTurbPQR(int idx) const {return vTurbPQR(idx);}
- virtual double GetTurbMagnitude(void) const {return Magnitude;}
- virtual const FGColumnVector3& GetTurbDirection(void) const {return vDirection;}
+ virtual double GetTurbMagnitude(void) const {return vTurbulenceNED.Magnitude();}
+ virtual double GetTurbDirection(void) const {return TurbDirection;}
virtual const FGColumnVector3& GetTurbPQR(void) const {return vTurbPQR;}
virtual void SetWindspeed20ft(double ws) { windspeed_at_20ft = ws;}
private:
- double MagnitudedAccelDt, MagnitudeAccel, Magnitude;
+ double MagnitudedAccelDt, MagnitudeAccel, Magnitude, TurbDirection;
double h;
double TurbGain;
double TurbRate;
double Rhythmicity;
double wind_from_clockwise;
double spike, target_time, strength;
- FGColumnVector3 vDirectiondAccelDt;
- FGColumnVector3 vDirectionAccel;
- FGColumnVector3 vDirection;
FGColumnVector3 vTurbulenceGrad;
FGColumnVector3 vBodyTurbGrad;
FGColumnVector3 vTurbPQR;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGActuator.cpp,v 1.32 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGActuator.cpp,v 1.33 2014/05/17 15:05:27 jberndt Exp $");
IDENT(IdHdr,ID_ACTUATOR);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (deadband_width != 0.0) Deadband();
if (hysteresis_width != 0.0) Hysteresis();
if (bias != 0.0) Bias(); // models a finite bias
+ if (delay != 0) Delay(); // Model transport latency
}
PreviousOutput = Output; // previous value needed for "stuck" malfunction
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGDistributor.cpp,v 1.5 2014/01/13 10:46:08 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGDistributor.cpp,v 1.6 2014/02/17 05:33:25 jberndt Exp $");
IDENT(IdHdr,ID_DISTRIBUTOR);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
-
+ for (unsigned int ctr=0; ctr < Cases.size(); ctr++) {
+ std::cout << " Case: " << ctr << endl;
+ if (Cases[ctr]->GetTest() != 0) {
+ Cases[ctr]->GetTest()->PrintCondition(" ");
+ } else {
+ std::cout << " Set these properties by default: " << std::endl;
+ }
+ std::cout << std::endl;
+ for (unsigned int propCtr=0; propCtr < Cases[ctr]->GetNumPropValPairs(); propCtr++) {
+ std::cout << " Set property " << Cases[ctr]->GetPropValPair(propCtr)->GetPropName();
+ if (Cases[ctr]->GetPropValPair(propCtr)->GetPropNode() == 0) std::cout << " (late bound)";
+ std::cout << " to " << Cases[ctr]->GetPropValPair(propCtr)->GetValString();
+ if (Cases[ctr]->GetPropValPair(propCtr)->GetLateBoundValue()) std::cout << " (late bound)";
+ std::cout << std::endl;
+ }
+ }
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_DISTRIBUTOR "$Id: FGDistributor.h,v 1.5 2013/11/24 11:40:57 bcoconni Exp $"
+#define ID_DISTRIBUTOR "$Id: FGDistributor.h,v 1.6 2014/02/17 05:33:25 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
Note: In the "logic" attribute, "AND" is the default logic, if none is supplied.
@author Jon S. Berndt
-@version $Id: FGDistributor.h,v 1.5 2013/11/24 11:40:57 bcoconni Exp $
+@version $Id: FGDistributor.h,v 1.6 2014/02/17 05:33:25 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class PropValPair {
public:
PropValPair(std::string prop, std::string val, FGPropertyManager* propMan) {
+ // Process property to be set
PropMan = propMan;
sign = 1;
- Val = 0;
- ValString = val;
FGPropertyNode *node = propMan->GetNode(prop, false);
if (node) PropNode = node;
else PropNode = 0;
PropName = prop;
+
+ // Process set value
+ LateBoundValue = false;
+ Val = 0;
+ ValString = val;
if (is_number(ValString)) {
Val = new FGRealValue(atof(ValString.c_str()));
} else {
sign = -1;
ValString.erase(0,1);
}
- node = propMan->GetNode(ValString, false);
+ node = propMan->GetNode(ValString, false); // Reuse the node variable
if (node) Val = new FGPropertyValue(node);
+ else {
+ Val = new FGPropertyValue(ValString, propMan);
+ LateBoundValue = true;
+ }
}
}
throw(PropName+" in distributor component is not known");
}
}
- if (Val == 0) {
- if (PropMan->HasNode(ValString)) {
- FGPropertyNode* node = PropMan->GetNode(ValString, false);
- if (node) Val = new FGPropertyValue(node);
- } else {
- throw(ValString+" in distributor component is not known. Check spelling.");
- }
- }
PropNode->setDoubleValue(Val->GetValue()*sign);
}
+ std::string GetPropName() {return PropName;}
+ std::string GetValString() {return ValString;}
+ FGPropertyNode* GetPropNode() {return PropNode;}
+ bool GetLateBoundValue() {return LateBoundValue;}
private:
std::string PropName;
FGPropertyNode* PropNode;
FGPropertyManager* PropMan;
FGParameter* Val;
std::string ValString;
+ bool LateBoundValue;
int sign;
};
}
void SetTest(FGCondition* test) {Test = test;}
+ FGCondition* GetTest(void) {return Test;}
void AddPropValPair(PropValPair* pvPair) {PropValPairs.push_back(pvPair);}
void SetPropValPairs() {
for (unsigned int i=0; i<PropValPairs.size(); i++) PropValPairs[i]->SetPropToValue();
}
+ PropValPair* GetPropValPair(unsigned int idx) { return PropValPairs[idx]; }
+ unsigned int GetNumPropValPairs(void) {return PropValPairs.size();}
bool HasTest() {return (Test != 0);}
bool GetTestResult() { return Test->Evaluate(); }
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.25 2014/01/02 21:58:42 bcoconni Exp $"
+#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.26 2014/02/17 05:33:25 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
- FGAccelerometer
- FGGyro
- FGActuator
- - FGWaypoint
+ - FGWwaypoint
- FGAngle
@author Jon S. Berndt
- @version $Id: FGFCSComponent.h,v 1.25 2014/01/02 21:58:42 bcoconni Exp $
+ @version $Id: FGFCSComponent.h,v 1.26 2014/02/17 05:33:25 jberndt Exp $
@see Documentation for the FGFCS class, and for the configuration file class
*/
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGRocket.cpp,v 1.33 2014/01/13 10:46:10 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGRocket.cpp,v 1.35 2014/05/17 15:04:14 jberndt Exp $");
IDENT(IdHdr,ID_ROCKET);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
buf << Name << " Total Impulse (engine " << EngineNumber << " in lbf)" << delimiter
<< Name << " Total Vacuum Impulse (engine " << EngineNumber << " in lbf)" << delimiter
+ << Name << " Roll Moment (engine " << EngineNumber << " in ft-lbf)" << delimiter
+ << Name << " Pitch Moment (engine " << EngineNumber << " in ft-lbf)" << delimiter
+ << Name << " Yaw Moment (engine " << EngineNumber << " in ft-lbf)" << delimiter
+ << Name << " X Force (engine " << EngineNumber << " in lbf)" << delimiter
+ << Name << " Y Force (engine " << EngineNumber << " in lbf)" << delimiter
+ << Name << " Z Force (engine " << EngineNumber << " in lbf)" << delimiter
<< Thruster->GetThrusterLabels(EngineNumber, delimiter);
return buf.str();
buf << It << delimiter
<< ItVac << delimiter
+ << GetMoments().Dump(delimiter) << delimiter
+ << Thruster->GetBodyForces().Dump(delimiter) << delimiter
<< Thruster->GetThrusterValues(EngineNumber, delimiter);
return buf.str();
property_name = base_property_name + "/total-impulse";
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse);
+ property_name = base_property_name + "/total-vac-impulse";
+ PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacTotalImpulse);
property_name = base_property_name + "/vacuum-thrust_lbs";
PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust);
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include <cstdlib>
+#include <iostream>
#include "FGTank.h"
#include "FGFDMExec.h"
#include "input_output/FGXMLElement.h"
#include "input_output/FGPropertyManager.h"
-#include <iostream>
-#include <cstdlib>
+#include "input_output/string_utilities.h"
using namespace std;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGTank.cpp,v 1.39 2014/01/13 10:46:10 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGTank.cpp,v 1.40 2014/05/17 15:09:42 jberndt Exp $");
IDENT(IdHdr,ID_TANK);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
PropertyManager = Exec->GetPropertyManager();
vXYZ.InitMatrix();
vXYZ_drain.InitMatrix();
+ ixx_unit = iyy_unit = izz_unit = 1.0;
type = el->GetAttributeValue("type");
if (type == "FUEL") Type = ttFUEL;
PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
+ string property_name, base_property_name;
+ base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
+ property_name = base_property_name + "/contents-lbs";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
+ &FGTank::SetContents );
+ property_name = base_property_name + "/pct-full";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);
+
+ property_name = base_property_name + "/priority";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
+ &FGTank::SetPriority );
+ property_name = base_property_name + "/external-flow-rate-pps";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
+ &FGTank::SetExternalFlow );
+ property_name = base_property_name + "/local-ixx-slug_ft2";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIxx);
+ property_name = base_property_name + "/local-iyy-slug_ft2";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIyy);
+ property_name = base_property_name + "/local-izz-slug_ft2";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIzz);
+
// Check whether this is a solid propellant "tank". Initialize it if true.
grainType = gtUNKNOWN; // This is the default
strGType = element_Grain->GetAttributeValue("type");
if (strGType == "CYLINDRICAL") grainType = gtCYLINDRICAL;
else if (strGType == "ENDBURNING") grainType = gtENDBURNING;
+ else if (strGType == "FUNCTION") {
+ grainType = gtFUNCTION;
+ if (element_Grain->FindElement("ixx") != 0) {
+ Element* element_ixx = element_Grain->FindElement("ixx");
+ if (element_ixx->GetAttributeValue("unit") == "KG*M2") ixx_unit = 1.0/1.35594;
+ if (element_ixx->FindElement("function") != 0) {
+ function_ixx = new FGFunction(PropertyManager, element_ixx->FindElement("function"));
+ }
+ } else {
+ throw("For tank "+to_string(TankNumber)+" and when grain_config is specified an ixx must be specified when the FUNCTION grain type is specified.");
+ }
+
+ if (element_Grain->FindElement("iyy")) {
+ Element* element_iyy = element_Grain->FindElement("iyy");
+ if (element_iyy->GetAttributeValue("unit") == "KG*M2") iyy_unit = 1.0/1.35594;
+ if (element_iyy->FindElement("function") != 0) {
+ function_iyy = new FGFunction(PropertyManager, element_iyy->FindElement("function"));
+ }
+ } else {
+ throw("For tank "+to_string(TankNumber)+" and when grain_config is specified an iyy must be specified when the FUNCTION grain type is specified.");
+ }
+
+ if (element_Grain->FindElement("izz")) {
+ Element* element_izz = element_Grain->FindElement("izz");
+ if (element_izz->GetAttributeValue("unit") == "KG*M2") izz_unit = 1.0/1.35594;
+ if (element_izz->FindElement("function") != 0) {
+ function_izz = new FGFunction(PropertyManager, element_izz->FindElement("function"));
+ }
+ } else {
+ throw("For tank "+to_string(TankNumber)+" and when grain_config is specified an izz must be specified when the FUNCTION grain type is specified.");
+ }
+ }
else cerr << "Unknown propellant grain type specified" << endl;
if (element_Grain->FindElement("length"))
case gtENDBURNING:
Volume = M_PI * Length * Radius * Radius; // cubic inches
break;
+ case gtFUNCTION:
+ Volume = 1; // Volume is irrelevant for the FUNCTION type, but it can't be zero!
+ break;
case gtUNKNOWN:
cerr << "Unknown grain type found in this rocket engine definition." << endl;
exit(-1);
CalculateInertias();
- string property_name, base_property_name;
- base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
- property_name = base_property_name + "/contents-lbs";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
- &FGTank::SetContents );
- property_name = base_property_name + "/pct-full";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);
-
- property_name = base_property_name + "/priority";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
- &FGTank::SetPriority );
- property_name = base_property_name + "/external-flow-rate-pps";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
- &FGTank::SetExternalFlow );
-
if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
Area = 40.0 * pow(Capacity/1975, 0.666666667);
RadSumSqr = (Rad2 + InnerRadius*InnerRadius)/144.0;
Ixx = 0.5*Mass*RadSumSqr;
Iyy = Mass*(3.0*RadSumSqr + Length*Length/144.0)/12.0;
+ Izz = Iyy;
break;
case gtENDBURNING:
Length = Volume/(M_PI*Rad2);
Ixx = 0.5*Mass*Rad2/144.0;
Iyy = Mass*(3.0*Rad2 + Length*Length)/(144.0*12.0);
+ Izz = Iyy;
break;
+ case gtFUNCTION:
+ Ixx = function_ixx->GetValue()*ixx_unit;
+ Iyy = function_iyy->GetValue()*iyy_unit;
+ Izz = function_izz->GetValue()*izz_unit;
+ break;
case gtUNKNOWN:
cerr << "Unknown grain type found." << endl;
exit(-1);
break;
}
- Izz = Iyy;
- } else { // assume liquid propellant
+ } else { // assume liquid propellant: shrinking snowball
if (Radius > 0.0) Ixx = Iyy = Izz = Mass * InertiaFactor * 0.4 * Radius * Radius / 144.0;
#include "FGJSBBase.h"
#include "math/FGColumnVector3.h"
+#include "math/FGFunction.h"
#include <string>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_TANK "$Id: FGTank.h,v 1.27 2012/08/11 14:57:38 jberndt Exp $"
+#define ID_TANK "$Id: FGTank.h,v 1.28 2014/05/17 15:09:42 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@code
<tank type="{FUEL | OXIDIZER}">
- <grain_config type="{CYLINDRICAL | ENDBURNING}">
- <length unit="{IN | FT | M}"> {number} </radius>
+ <grain_config type="{CYLINDRICAL | ENDBURNING | FUNCTION}">
+ <length unit="{IN | FT | M}"> {number} </length>
+ <bore_diameter unit="{IN | FT | M}"> {number} </bore_diameter>
+ [<ixx unit="{IN | FT | M}"> {function} </ixx>
+ <iyy unit="{IN | FT | M}"> {function} </iyy>
+ <izz unit="{IN | FT | M}"> {function} </izz>]
</grain_config>
<location unit="{FT | M | IN}">
<x> {number} </x>
~FGTank();
enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER};
- enum GrainType {gtUNKNOWN, gtCYLINDRICAL, gtENDBURNING};
+ enum GrainType {gtUNKNOWN, gtCYLINDRICAL, gtENDBURNING, gtFUNCTION};
/** Removes fuel from the tank.
This function removes fuel from a tank. If the tank empties, it is
int TankNumber;
std::string type;
std::string strGType;
+ double ixx_unit;
+ double iyy_unit;
+ double izz_unit;
FGColumnVector3 vXYZ;
FGColumnVector3 vXYZ_drain;
+ FGFunction* function_ixx;
+ FGFunction* function_iyy;
+ FGFunction* function_izz;
double Capacity;
double Radius;
double InnerRadius;