%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGAuxiliary.h"
+#include "FGAerodynamics.h"
#include "FGTranslation.h"
#include "FGRotation.h"
#include "FGAtmosphere.h"
vPilotAccelN.InitMatrix();
+ bind();
+
Debug(0);
}
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include <stdio.h>
+
#include "FGCoefficient.h"
#include "FGState.h"
#include "FGFDMExec.h"
double FGCoefficient::Value(double Val)
{
double Value;
-
+
SD = Value = gain*Table->GetValue(Val) + bias;
for (unsigned int midx=0; midx < multipliers.size(); midx++)
cerr << "Unknown FCS mode" << endl;
break;
}
+ return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cerr << "Unknown FCS mode" << endl;
break;
}
+ return string("");
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void Debug(int from);
};
-#include "FGState.h"
#endif
Position = 0;
Auxiliary = 0;
Output = 0;
+ IC = 0;
+ Trim = 0;
terminate = false;
frozen = false;
Error+=4096;}
if (Error > 0) result = false;
+
+ IC = new FGInitialCondition(this);
+ //Trim is allocated as needed by GetTrim()
+
// Schedule a model. The second arg (the integer) is the pass number. For
// instance, the atmosphere model gets executed every fifth pass it is called
// by the executive. Everything else here gets executed each pass.
Schedule(Position, 1);
Schedule(Auxiliary, 1);
Schedule(Output, 1);
+ //IC and Trim are *not* scheduled objects
+
+
modelLoaded = false;
bool FGFDMExec::DeAllocate(void) {
- if ( Atmosphere != 0 ) delete Atmosphere;
- if ( FCS != 0 ) delete FCS;
- if ( Propulsion != 0) delete Propulsion;
- if ( MassBalance != 0) delete MassBalance;
- if ( Aerodynamics != 0) delete Aerodynamics;
- if ( Inertial != 0) delete Inertial;
- if ( GroundReactions != 0) delete GroundReactions;
- if ( Aircraft != 0 ) delete Aircraft;
- if ( Translation != 0 ) delete Translation;
- if ( Rotation != 0 ) delete Rotation;
- if ( Position != 0 ) delete Position;
- if ( Auxiliary != 0 ) delete Auxiliary;
- if ( Output != 0 ) delete Output;
- if ( State != 0 ) delete State;
+ delete Atmosphere;
+ delete FCS;
+ delete Propulsion;
+ delete MassBalance;
+ delete Aerodynamics;
+ delete Inertial;
+ delete GroundReactions;
+ delete Aircraft;
+ delete Translation;
+ delete Rotation;
+ delete Position;
+ delete Auxiliary;
+ delete Output;
+ delete State;
+
+ delete IC;
+ delete Trim;
FirstModel = 0L;
Error = 0;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGFDMExec::RunIC(FGInitialCondition *fgic)
+bool FGFDMExec::RunIC(void)
{
State->Suspend();
- State->Initialize(fgic);
+ State->Initialize(IC);
Run();
State->Resume();
return true;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGFDMExec::LoadModel(string APath, string EPath, string model)
+bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model) {
+ FGFDMExec::AircraftPath=AircraftPath;
+ FGFDMExec::EnginePath=EnginePath;
+ return LoadModel(model);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGFDMExec::LoadModel(string model)
{
bool result = true;
string token;
string aircraftCfgFileName;
- AircraftPath = APath;
- EnginePath = EPath;
-
+ if( AircraftPath.empty() || EnginePath.empty() ) {
+ cerr << "Error: attempted to load aircraft with undefined ";
+ cerr << "aircraft and engine paths" << endl;
+ return false;
+ }
+
# ifndef macintosh
aircraftCfgFileName = AircraftPath + "/" + model + "/" + model + ".xml";
# else
FGConfigFile AC_cfg(aircraftCfgFileName);
if (!AC_cfg.IsOpen()) return false;
-
+
+ modelName = model;
+
if (modelLoaded) {
DeAllocate();
Allocate();
string AircraftName = AC_cfg->GetValue("FILE");
debug_lvl = 0; // turn off debug output for slave vehicle
- SlaveFDMList.back()->exec->LoadModel("aircraft", "engine", AircraftName);
+
+ SlaveFDMList.back()->exec->SetAircraftPath( AircraftPath );
+ SlaveFDMList.back()->exec->SetEnginePath( EnginePath );
+ SlaveFDMList.back()->exec->LoadModel(AircraftName);
debug_lvl = saved_debug_lvl; // turn debug output back on for master vehicle
AC_cfg->GetNextConfigLine();
return instance;
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTrim* FGFDMExec::GetTrim(void) {
+ delete Trim;
+ Trim = new FGTrim(this,tNone);
+ return Trim;
+}
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGModel.h"
+#include "FGTrim.h"
#include "FGInitialCondition.h"
#include "FGJSBBase.h"
#include "FGPropertyManager.h"
+
#include <vector>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGInitialCondition;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@return true if successful, false if sim should be ended */
bool Run(void);
- /** Initializes the sim with a set of initial conditions.
- @param fgic A pointer to a filled out initial conditions class which
- describes the desired initial conditions.
+ /** Initializes the sim from the initial condition object and executes
+ each scheduled model without integrating i.e. dt=0.
@return true if successful
*/
- bool RunIC(FGInitialCondition *fgic);
+ bool RunIC(void);
/// Freezes the sim
void Freeze(void) {frozen = true;}
/// Resumes the sim
void Resume(void) {frozen = false;}
-
- /** Loads an aircraft model.
+
+ /** Loads an aircraft model.
@param AircraftPath path to the aircraft directory. For instance:
"aircraft". Under aircraft, then, would be directories for various
modeled aircraft such as C172/, x15/, etc.
instance: "aircraft/x15/x15.xml"
@return true if successful*/
bool LoadModel(string AircraftPath, string EnginePath, string model);
+
+
+ /** Loads an aircraft model. The paths to the aircraft and engine
+ config file directories must be set prior to calling this. See
+ below.
+ @param model the name of the aircraft model itself. This file will
+ be looked for in the directory specified in the AircraftPath variable,
+ and in turn under the directory with the same name as the model. For
+ instance: "aircraft/x15/x15.xml"
+ @return true if successful*/
+ bool LoadModel(string model);
+
- bool SetEnginePath(string path) {EnginePath = path; return true;}
- bool SetAircraftPath(string path) {AircraftPath = path; return true;}
+ /** Sets the path to the engine config file directories.
+ @param EnginePath path to the directory under which engine config
+ files are kept, for instance "engine"
+ */
+ bool SetEnginePath(string path) { EnginePath = path; return true; }
+ /** Sets the path to the aircraft config file directories.
+ @param AircraftPath path to the aircraft directory. For instance:
+ "aircraft". Under aircraft, then, would be directories for various
+ modeled aircraft such as C172/, x15/, etc.
+ */
+ bool SetAircraftPath(string path) { AircraftPath = path; return true; }
+
+ /** Sets the path to the autopilot config file directories.
+ @param ControlPath path to the control directory. For instance:
+ "control".
+ */
+ bool SetControlPath(string path) { ControlPath = path; return true; }
+
+
/// @name Top-level executive State and Model retrieval mechanism
//@{
/// Returns the FGState pointer.
inline FGAuxiliary* GetAuxiliary(void) {return Auxiliary;}
/// Returns the FGOutput pointer.
inline FGOutput* GetOutput(void) {return Output;}
+ // Returns a pointer to the FGInitialCondition object
+ inline FGInitialCondition* GetIC(void) {return IC;}
+ // Returns a pointer to the FGTrim object
+ FGTrim* GetTrim(void);
//@}
-
+
/// Retrieves the engine path.
inline string GetEnginePath(void) {return EnginePath;}
/// Retrieves the aircraft path.
inline string GetAircraftPath(void) {return AircraftPath;}
+ /// Retrieves the control path.
+ inline string GetControlPath(void) {return ControlPath;}
+
+ string GetModelName(void) { return modelName; }
FGPropertyManager* GetPropertyManager(void);
vector <string> EnumerateFDMs(void);
unsigned int IdFDM;
static unsigned int FDMctr;
bool modelLoaded;
+ string modelName;
bool IsSlave;
static FGPropertyManager *master;
FGPropertyManager *instance;
string AircraftPath;
string EnginePath;
+ string ControlPath;
+
string CFGVersion;
FGState* State;
FGPosition* Position;
FGAuxiliary* Auxiliary;
FGOutput* Output;
+
+ FGInitialCondition* IC;
+ FGTrim *Trim;
vector <slaveData*> SlaveFDMList;
#include "FGFDMExec.h"
#include "FGState.h"
#include "FGAtmosphere.h"
+#include "FGAerodynamics.h"
#include "FGFCS.h"
#include "FGAircraft.h"
#include "FGTranslation.h"
//******************************************************************************
-bool FGInitialCondition::Load(string acpath, string acname, string rstfile)
+bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
{
string resetDef;
string token="";
double temp;
-
-# ifndef macintosh
- resetDef = acpath + "/" + acname + "/" + rstfile + ".xml";
-# else
- resetDef = acpath + ";" + acname + ";" + rstfile + ".xml";
-# endif
-
+ # ifndef macintosh
+ string sep = "/";
+ # else
+ string sep = ";";
+ #endif
+
+ if( useStoredPath ) {
+ string acpath = fdmex->GetAircraftPath() + sep + fdmex->GetModelName();
+ resetDef = acpath + sep + rstfile + ".xml";
+ } else {
+ resetDef = rstfile;
+ }
+
FGConfigFile resetfile(resetDef);
if (!resetfile.IsOpen()) {
cerr << "Failed to open reset file: " << resetDef << endl;
resetfile >> token;
}
- fdmex->RunIC(this);
+ fdmex->RunIC();
return true;
}
inline speedset GetSpeedSet(void) { return lastSpeedSet; }
inline windset GetWindSet(void) { return lastWindSet; }
- bool Load(string acpath, string acname, string rstname);
+ bool Load(string rstname, bool useStoredPath = true );
void bind(void);
void unbind(void);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+void FGJSBBase::disableHighLighting(void) {
+ highint[0]='\0';
+ halfint[0]='\0';
+ normint[0]='\0';
+ reset[0]='\0';
+ underon[0]='\0';
+ underoff[0]='\0';
+ fgblue[0]='\0';
+ fgcyan[0]='\0';
+ fgred[0]='\0';
+ fggreen[0]='\0';
+ fgdef[0]='\0';
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
Message* ProcessMessage(void);
//@}
string GetVersion(void) {return JSBSim_version;}
+
+ void disableHighLighting(void);
protected:
static Message localMsg;
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include <string>
#include <simgear/misc/props.hxx>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGPropertyManager:public SGPropertyNode {
+class FGPropertyManager : public SGPropertyNode {
public:
/// Constructor
- FGPropertyManager(void) {
-
- }
+ FGPropertyManager(void) {}
/// Destructor
- ~FGPropertyManager(void) {
-
- }
+ ~FGPropertyManager(void) {}
+
+ /** Property-ify a name
+ * replaces spaces with '-' and, optionally, makes name all lower case
+ * @param name string to change
+ * @param lowercase true to change all upper case chars to lower
+ * NOTE: this function changes its argument and thus relies
+ * on pass by value
+ */
+ string mkPropertyName(string name, bool lowercase);
+
/**
* Get a property node.
*
* @param create true to create the node if it doesn't exist.
* @return The node, or 0 if none exists and none was created.
*/
- inline FGPropertyManager*
- GetNode (const string &path, bool create = false)
- {
- SGPropertyNode* node=this->getNode(path.c_str(), create);
- if(node == 0)
- cout << "FGPropertyManager::GetNode() No node found for "
- << path << endl;
- return (FGPropertyManager*)node;
- }
+ FGPropertyManager*
+ GetNode (const string &path, bool create = false);
- inline FGPropertyManager*
- GetNode (const string &relpath, int index, bool create = false)
- {
- return (FGPropertyManager*)getNode(relpath.c_str(),index,create);
- }
-
+ FGPropertyManager*
+ GetNode (const string &relpath, int index, bool create = false);
/**
* Test whether a given node exists.
* @param path The path of the node, relative to root.
* @return true if the node exists, false otherwise.
*/
- inline bool
- HasNode (const string &path)
- {
- return (GetNode(path, false) != 0);
- }
+ bool HasNode (const string &path);
/**
* Get the name of a node
*/
- inline string
- GetName( void ) {
- return string( getName() );
- }
+ string GetName( void );
/**
* Get a bool value for a property.
* does not exist.
* @return The property's value as a bool, or the default value provided.
*/
- inline bool GetBool (const string &name, bool defaultValue = false)
- {
- return getBoolValue(name.c_str(), defaultValue);
- }
+ bool GetBool (const string &name, bool defaultValue = false);
/**
* does not exist.
* @return The property's value as an int, or the default value provided.
*/
- inline int GetInt (const string &name, int defaultValue = 0)
- {
- return getIntValue(name.c_str(), defaultValue);
- }
+ int GetInt (const string &name, int defaultValue = 0);
/**
* does not exist.
* @return The property's value as a long, or the default value provided.
*/
- inline int GetLong (const string &name, long defaultValue = 0L)
- {
- return getLongValue(name.c_str(), defaultValue);
- }
+ int GetLong (const string &name, long defaultValue = 0L);
/**
* does not exist.
* @return The property's value as a float, or the default value provided.
*/
- inline float GetFloat (const string &name, float defaultValue = 0.0)
- {
- return getFloatValue(name.c_str(), defaultValue);
- }
+ float GetFloat (const string &name, float defaultValue = 0.0);
/**
* does not exist.
* @return The property's value as a double, or the default value provided.
*/
- inline double GetDouble (const string &name, double defaultValue = 0.0)
- {
- return getDoubleValue(name.c_str(), defaultValue);
- }
+ double GetDouble (const string &name, double defaultValue = 0.0);
/**
* does not exist.
* @return The property's value as a string, or the default value provided.
*/
- inline string GetString (const string &name, string defaultValue = "")
- {
- return string(getStringValue(name.c_str(), defaultValue.c_str()));
- }
+ string GetString (const string &name, string defaultValue = "");
/**
* @param val The new value for the property.
* @return true if the assignment succeeded, false otherwise.
*/
- inline bool SetBool (const string &name, bool val)
- {
- return setBoolValue(name.c_str(), val);
- }
+ bool SetBool (const string &name, bool val);
/**
* @param val The new value for the property.
* @return true if the assignment succeeded, false otherwise.
*/
- inline bool SetInt (const string &name, int val)
- {
- return setIntValue(name.c_str(), val);
- }
+ bool SetInt (const string &name, int val);
/**
* @param val The new value for the property.
* @return true if the assignment succeeded, false otherwise.
*/
- inline bool SetLong (const string &name, long val)
- {
- return setLongValue(name.c_str(), val);
- }
+ bool SetLong (const string &name, long val);
/**
* @param val The new value for the property.
* @return true if the assignment succeeded, false otherwise.
*/
- inline bool SetFloat (const string &name, float val)
- {
- return setFloatValue(name.c_str(), val);
- }
+ bool SetFloat (const string &name, float val);
/**
* @param val The new value for the property.
* @return true if the assignment succeeded, false otherwise.
*/
- inline bool SetDouble (const string &name, double val)
- {
- return setDoubleValue(name.c_str(), val);
- }
+ bool SetDouble (const string &name, double val);
/**
* @param val The new value for the property.
* @return true if the assignment succeeded, false otherwise.
*/
- inline bool SetString (const string &name, const string &val)
- {
- return setStringValue(name.c_str(), val.c_str());
- }
+ bool SetString (const string &name, const string &val);
////////////////////////////////////////////////////////////////////////
* @param name The property name.
* @param state The state of the archive attribute (defaults to true).
*/
- inline void
- SetArchivable (const string &name, bool state = true)
- {
- SGPropertyNode * node = getNode(name.c_str());
- if (node == 0)
- cout <<
- "Attempt to set archive flag for non-existant property "
- << name << endl;
- else
- node->setAttribute(SGPropertyNode::ARCHIVE, state);
- }
+ void SetArchivable (const string &name, bool state = true);
/**
* @param name The property name.
* @param state The state of the read attribute (defaults to true).
*/
- inline void
- SetReadable (const string &name, bool state = true)
- {
- SGPropertyNode * node = getNode(name.c_str());
- if (node == 0)
- cout <<
- "Attempt to set read flag for non-existant property "
- << name << endl;
- else
- node->setAttribute(SGPropertyNode::READ, state);
- }
+ void SetReadable (const string &name, bool state = true);
/**
* @param name The property name.
* @param state The state of the write attribute (defaults to true).
*/
- inline void
- SetWritable (const string &name, bool state = true)
- {
- SGPropertyNode * node = getNode(name.c_str());
- if (node == 0)
- cout <<
- "Attempt to set write flag for non-existant property "
- << name << endl;
- else
- node->setAttribute(SGPropertyNode::WRITE, state);
- }
+ void SetWritable (const string &name, bool state = true);
////////////////////////////////////////////////////////////////////////
* Classes should use this function to release control of any
* properties they are managing.
*/
- inline void
- Untie (const string &name)
- {
- if (!untie(name.c_str()))
- cout << "Failed to untie property " << name << endl;
- }
+ void Untie (const string &name);
// Templates cause ambiguity here
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
- inline void
- Tie (const string &name, bool *pointer, bool useDefault = true)
- {
- if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer),
- useDefault))
- cout <<
- "Failed to tie property " << name << " to a pointer" << endl;
- }
+ void
+ Tie (const string &name, bool *pointer, bool useDefault = true);
/**
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
- inline void
- Tie (const string &name, int *pointer, bool useDefault = true)
- {
- if (!tie(name.c_str(), SGRawValuePointer<int>(pointer),
- useDefault))
- cout <<
- "Failed to tie property " << name << " to a pointer" << endl;
- }
+ void
+ Tie (const string &name, int *pointer, bool useDefault = true);
/**
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
- inline void
- Tie (const string &name, long *pointer, bool useDefault = true)
- {
- if (!tie(name.c_str(), SGRawValuePointer<long>(pointer),
- useDefault))
- cout <<
- "Failed to tie property " << name << " to a pointer" << endl;
- }
+ void
+ Tie (const string &name, long *pointer, bool useDefault = true);
/**
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
- inline void
- Tie (const string &name, float *pointer, bool useDefault = true)
- {
- if (!tie(name.c_str(), SGRawValuePointer<float>(pointer),
- useDefault))
- cout <<
- "Failed to tie property " << name << " to a pointer" << endl;
- }
-
+ void
+ Tie (const string &name, float *pointer, bool useDefault = true);
/**
* Tie a property to an external double variable.
* copied to the variable; false if the variable should not
* be modified; defaults to true.
*/
- inline void
- Tie (const string &name, double *pointer, bool useDefault = true)
- {
- if (!tie(name.c_str(), SGRawValuePointer<double>(pointer),
- useDefault))
- cout <<
- "Failed to tie property " << name << " to a pointer" << endl;
- }
-
+ void
+ Tie (const string &name, double *pointer, bool useDefault = true);
+
+//============================================================================
+//
+// All of the following functions *must* be inlined, otherwise linker
+// errors will result
+//
+//============================================================================
+
/* template <class V> void
Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
bool useDefault = true);
V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
bool useDefault = true); */
-/**
+ /**
* Tie a property to a pair of simple functions.
*
* Every time the property value is queried, the getter (if any) will
* property value should be; false if the old value should be
* discarded; defaults to true.
*/
- template <class V>
- inline void
+
+ template <class V> inline void
Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
- bool useDefault = true)
+ bool useDefault = true)
{
if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter),
useDefault))
* property value should be; false if the old value should be
* discarded; defaults to true.
*/
- template <class V>
- inline void
- Tie (const string &name, int index, V (*getter)(int),
+ template <class V> inline void Tie (const string &name,
+ int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(),
* property value should be; false if the old value should be
* discarded; defaults to true.
*/
- template <class T, class V>
- inline void
+ template <class T, class V> inline void
Tie (const string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true)
{
if (!tie(name.c_str(),
- SGRawValueMethods<T,V>(*obj, getter, setter),
- useDefault))
+ SGRawValueMethods<T,V>(*obj, getter, setter),
+ useDefault))
cout <<
- "Failed to tie property " << name << " to object methods" << endl;
+ "Failed to tie property " << name << " to object methods" << endl;
}
-
-
+
/**
* Tie a property to a pair of indexed object methods.
*
* property value should be; false if the old value should be
* discarded; defaults to true.
*/
- template <class T, class V>
- inline void
+ template <class T, class V> inline void
Tie (const string &name, T * obj, int index,
V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
- bool useDefault = true)
+ bool useDefault = true)
{
if (!tie(name.c_str(),
- SGRawValueMethodsIndexed<T,V>(*obj,
- index,
- getter,
- setter),
- useDefault))
+ SGRawValueMethodsIndexed<T,V>(*obj,
+ index,
+ getter,
+ setter),
+ useDefault))
cout <<
- "Failed to tie property " << name << " to indexed object methods" << endl;
- }
-
-};
+ "Failed to tie property " << name << " to indexed object methods" << endl;
+ }
+};
#endif // FGPROPERTYMANAGER_H
} else {
steady_count=0;
}
- j++;
+ j++;
}
vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
vForces.InitMatrix();
vMoments.InitMatrix();
-
+
for (unsigned int i=0; i<numEngines; i++) {
Engines[i]->SetTrimMode(true);
Thrusters[i]->SetdeltaT(dt*rate);
while (!Engines[i]->GetRunning() && j < 2000) {
PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
Thrusters[i]->Calculate(PowerAvailable);
- j++;
+ j++;
}
vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
if (Eng_cfg.IsOpen()) {
Eng_cfg.GetNextConfigLine();
engType = Eng_cfg.GetValue();
+ cout << engType << endl;
FCS->AddThrottle();
ThrottleAdded = true;
if (thrType == "FG_PROPELLER") {
Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
} else if (thrType == "FG_NOZZLE") {
- Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg));
- }
+ Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg ));
+ } else if (thrType == "FG_DIRECT") {
+ Thrusters.push_back(new FGThruster( FDMExec, &Thruster_cfg) );
+ }
AC_cfg->GetNextConfigLine();
while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
default:
PropulsionStrings += "INVALID THRUSTER TYPE";
break;
- }
+ }
}
return PropulsionStrings;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGScript::LoadScript(string script)
+bool FGScript::LoadScript( string script )
{
FGConfigFile Script(script);
string token="";
if (token == "use") {
if ((token = Script.GetValue("aircraft")) != string("")) {
aircraft = token;
- result = FDMExec->LoadModel("aircraft", "engine", aircraft);
+ result = FDMExec->LoadModel(aircraft);
if (!result) {
cerr << "Aircraft file " << aircraft << " was not found" << endl;
exit(-1);
Debug(4);
- FGInitialCondition IC(FDMExec);
- if ( ! IC.Load("aircraft", aircraft, initialize)) {
+ FGInitialCondition *IC=FDMExec->GetIC();
+ if ( ! IC->Load( initialize )) {
cerr << "Initialization unsuccessful" << endl;
exit(-1);
}
The language is the Simple Script Directives for JSBSim (SSDJ).
@param script the filename (including path name, if any) for the script.
@return true if successful */
- bool LoadScript(string script);
+ bool LoadScript( string script );
/** This function is called each pass through the executive Run() method IF
scripting is enabled.
Debug(1);
}
-//***************************************************************************
-//
-// Reset: Assume all angles READ FROM FILE IN DEGREES !!
-//
-
-bool FGState::Reset(string path, string acname, string fname)
-{
- string resetDef;
- string token="";
-
- double U, V, W;
- double phi, tht, psi;
- double latitude, longitude, h;
- double wdir, wmag, wnorth, weast;
-
-# ifndef macintosh
- resetDef = path + "/" + acname + "/" + fname + ".xml";
-# else
- resetDef = path + ";" + acname + ";" + fname + ".xml";
-# endif
-
- FGConfigFile resetfile(resetDef);
- if (!resetfile.IsOpen()) return false;
-
- resetfile.GetNextConfigLine();
- token = resetfile.GetValue();
- if (token != string("initialize")) {
- cerr << "The reset file " << resetDef
- << " does not appear to be a reset file" << endl;
- return false;
- } else {
- resetfile.GetNextConfigLine();
- resetfile >> token;
- cout << "Resetting using: " << token << endl << endl;
- }
-
- while (token != string("/initialize") && token != string("EOF")) {
- if (token == "UBODY") resetfile >> U;
- if (token == "VBODY") resetfile >> V;
- if (token == "WBODY") resetfile >> W;
- if (token == "LATITUDE") resetfile >> latitude;
- if (token == "LONGITUDE") resetfile >> longitude;
- if (token == "PHI") resetfile >> phi;
- if (token == "THETA") resetfile >> tht;
- if (token == "PSI") resetfile >> psi;
- if (token == "ALTITUDE") resetfile >> h;
- if (token == "WINDDIR") resetfile >> wdir;
- if (token == "VWIND") resetfile >> wmag;
-
- resetfile >> token;
- }
-
- Position->SetLatitude(latitude*degtorad);
- Position->SetLongitude(longitude*degtorad);
- Position->Seth(h);
-
- wnorth = wmag*ktstofps*cos(wdir*degtorad);
- weast = wmag*ktstofps*sin(wdir*degtorad);
-
- Initialize(U, V, W, phi*degtorad, tht*degtorad, psi*degtorad,
- latitude*degtorad, longitude*degtorad, h, wnorth, weast, 0.0);
-
- return true;
-}
-
//***************************************************************************
//
// Initialize: Assume all angles GIVEN IN RADIANS !!
#include "FGColumnVector3.h"
#include "FGColumnVector4.h"
+#include "FGFDMExec.h"
+#include "FGAtmosphere.h"
+#include "FGFCS.h"
+#include "FGTranslation.h"
+#include "FGRotation.h"
+#include "FGPosition.h"
+#include "FGAerodynamics.h"
+#include "FGOutput.h"
+#include "FGAircraft.h"
+#include "FGGroundReactions.h"
+#include "FGPropulsion.h"
+
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGAircraft;
-class FGTranslation;
-class FGRotation;
-class FGAtmosphere;
-class FGOutput;
-class FGPosition;
-class FGFDMExec;
-class FGGroundReactions;
-class FGPropulsion;
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/// Destructor
~FGState();
- /** Specifies the Reset file to use.
- The reset file normally resides in the same directory as an aircraft config file.
- it includes the following information:
- <ul>
- <li>U, the body X-Axis velocity</li>
- <li>V, the body Y-Axis velocity</li>
- <li>W, the body Z-Axis velocity</li>
- <li>Latitude measured in radians from the equator, negative values are south.</li>
- <li>Longitude, measured in radians from the Greenwich meridian, negative values are west.</li>
- <li>Phi, the roll angle in radians.</li>
- <li>Theta, the pitch attitude in radians.</li>
- <li>Psi, the heading angle in radians.</li>
- <li>H, the altitude in feet</li>
- <li>Wind Direction, the direction the wind is coming <u>from</u>.</li>
- <li>Wind magnitude, the wind speed in fps.</li>
- </ul>
- @param path the path string leading to the specific aircraft file, i.e. "aircraft".
- @param aircraft the name of the aircraft, i.e. "c172".
- @param filename the name of the reset file without an extension, i.e. "reset00".
- @return true if successful, false if the file could not be opened.
- */
- bool Reset(string path, string aircraft, string filename);
-
- /** Initializes the simulation state based on the passed-in parameters.
+ /** Initializes the simulation state based on the passed-in parameters.
@param U the body X-Axis velocity in fps.
@param V the body Y-Axis velocity in fps.
@param W the body Z-Axis velocity in fps.
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#include "FGFDMExec.h"
-#include "FGAtmosphere.h"
-#include "FGFCS.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGPosition.h"
-#include "FGAerodynamics.h"
-#include "FGOutput.h"
-#include "FGAircraft.h"
-#include "FGGroundReactions.h"
-#include "FGPropulsion.h"
#endif
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FGThruster::FGThruster(FGFDMExec *FDMExec,
+ FGConfigFile *Eng_cfg ): FGForce(FDMExec) {
+ ThrusterNumber=0;
+ SetTransformType(FGForce::tCustom);
+ Name=Eng_cfg->GetValue();
+ Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
FGThruster::~FGThruster()
{
Debug(1);
public:
/// Constructor
FGThruster(FGFDMExec *FDMExec);
+ FGThruster(FGFDMExec *FDMExec, FGConfigFile *Eng_cfg );
/// Destructor
virtual ~FGThruster();
enum eType {ttNozzle, ttRotor, ttPropeller};
- virtual double Calculate(double) {return 0.0;}
+ virtual double Calculate(double Thrust) { vFn(1)=Thrust; return 0.0; }
void SetName(string name) {Name = name;}
void SetThrusterNumber(int nn) {ThrusterNumber = nn;}
virtual void SetRPM(double rpm) {};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGTrim::FGTrim(FGFDMExec *FDMExec,FGInitialCondition *FGIC, TrimMode tt ) {
+FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) {
N=Nsub=0;
max_iterations=60;
Debug=0;DebugLevel=0;
fdmex=FDMExec;
- fgic=FGIC;
+ fgic=fdmex->GetIC();
total_its=0;
trimudot=true;
gamma_fallback=true;
xlo=xhi=alo=ahi=0.0;
targetNlf=1.0;
debug_axis=tAll;
- switch(mode) {
- case tFull:
- cout << " Full Trim" << endl;
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
- break;
- case tLongitudinal:
- cout << " Longitudinal Trim" << endl;
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
- break;
- case tGround:
- cout << " Ground Trim" << endl;
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta ));
- //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi ));
- break;
- case tPullup:
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
- break;
- case tTurn:
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
- TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
- break;
- case tCustom:
- case tNone:
- break;
-}
- //cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
- sub_iterations=new double[TrimAxes.size()];
- successful=new double[TrimAxes.size()];
- solution=new bool[TrimAxes.size()];
- current_axis=0;
-
+ SetMode(tt);
if (debug_lvl & 2) cout << "Instantiated: FGTrim" << endl;
}
return solutionExists;
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
void FGTrim::setupPullup() {
float g,q,cgamma;
FGColumnVector3 vPQR;
cout << "setPitchRateInPullup() complete" << endl;
}
-
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
void FGTrim::setupTurn(void){
double g,phi;
phi = fgic->GetRollAngleRadIC();
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
void FGTrim::updateRates(void){
if( mode == tTurn ) {
double phi = fgic->GetRollAngleRadIC();
}
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
void FGTrim::setDebug(void) {
if(debug_axis == tAll ||
TrimAxes[current_axis]->GetStateType() == debug_axis ) {
return;
}
}
-
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::SetMode(TrimMode tt) {
+ ClearStates();
+ switch(tt) {
+ case tFull:
+ cout << " Full Trim" << endl;
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+ break;
+ case tLongitudinal:
+ cout << " Longitudinal Trim" << endl;
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+ break;
+ case tGround:
+ cout << " Ground Trim" << endl;
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta ));
+ //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi ));
+ break;
+ case tPullup:
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+ break;
+ case tTurn:
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
+ TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+ break;
+ case tCustom:
+ case tNone:
+ break;
+ }
+ //cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
+ sub_iterations=new double[TrimAxes.size()];
+ successful=new double[TrimAxes.size()];
+ solution=new bool[TrimAxes.size()];
+ current_axis=0;
+}
//YOU WERE WARNED, BUT YOU DID IT ANYWAY.
#include "FGFDMExec.h"
#include "FGJSBBase.h"
-#include "FGRotation.h"
-#include "FGAtmosphere.h"
-#include "FGState.h"
-#include "FGFCS.h"
-#include "FGAircraft.h"
-#include "FGTranslation.h"
-#include "FGPosition.h"
-#include "FGAuxiliary.h"
-#include "FGOutput.h"
-#include "FGTrim.h"
#include "FGTrimAxis.h"
#include <vector>
/** Initializes the trimming class
@param FDMExec pointer to a JSBSim executive object.
@param FGIC pointer to a FGInitialCondition object
- @param TrimMode the set of axes to trim. Can be:
- tLongitudinal, tFull, tGround, tCustom, or tNone
*/
- FGTrim(FGFDMExec *FDMExec, FGInitialCondition *FGIC, TrimMode tt);
+ FGTrim(FGFDMExec *FDMExec, TrimMode tt=tGround );
~FGTrim(void);
/** Iteration statistics
*/
void TrimStats();
+
+ /** Clear all state-control pairs and set a predefined trim mode
+ @param TrimMode the set of axes to trim. Can be:
+ tLongitudinal, tFull, tGround, tCustom, or tNone
+ */
+ void SetMode(TrimMode tt);
/** Clear all state-control pairs from the current configuration.
The trimming routine must have at least one state-control pair
#include "FGTrimAxis.h"
#include "FGAircraft.h"
#include "FGPropulsion.h"
+#include "FGAerodynamics.h"
+
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TRIMAXIS;
while(!level && (i < 100)) {
theta+=2.0*zDiff;
fgic->SetPitchAngleDegIC(theta);
- fdmex->RunIC(fgic);
+ fdmex->RunIC();
zAft=fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear(3);
zForward=fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear(3);
zDiff = zForward - zAft;
while(!stable) {
i++;
last_state_value=state_value;
- fdmex->RunIC(fgic);
+ fdmex->RunIC();
getState();
if(i > 1) {
if((fabs(last_state_value - state_value) < tolerance) || (i >= 100) )
//cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value;
fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin));
//cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl;
- fdmex->RunIC(fgic); //apply throttle change
+ fdmex->RunIC(); //apply throttle change
fdmex->GetPropulsion()->GetSteadyState();
}
}
#include "FGFDMExec.h"
#include "FGJSBBase.h"
-#include "FGRotation.h"
-#include "FGAtmosphere.h"
-#include "FGState.h"
-#include "FGFCS.h"
-#include "FGAircraft.h"
-#include "FGTranslation.h"
-#include "FGPosition.h"
-#include "FGAuxiliary.h"
-#include "FGOutput.h"
+#include "FGInitialCondition.h"
#define ID_TRIMAXIS "$Id$"
"Heading"
};
+class FGInitialCondition;
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGTrimAxis : public FGJSBBase
{
public:
- FGTrimAxis(FGFDMExec* fdmex, FGInitialCondition *ic, State st,
+ FGTrimAxis(FGFDMExec* fdmex,
+ FGInitialCondition *ic,
+ State st,
Control ctrl );
~FGTrimAxis();
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include <vector>
#include "FGTurbine.h"
+
static const char *IdSrc = "$Id$";
static const char *IdHdr = ID_TURBINE;
FGTurbine::FGTurbine(FGFDMExec* exec, FGConfigFile* cfg) : FGEngine(exec)
{
+ Load(cfg);
+ PowerCommand=0;
Debug(0);
}
double FGTurbine::Calculate(double dummy)
{
+ double idle,mil,aug;
+ double throttle=FCS->GetThrottlePos(EngineNumber);
+ double dt=State->Getdt();
+ if( dt > 0 ) {
+ PowerCommand+=dt*PowerLag( PowerCommand,
+ ThrottleToPowerCommand(throttle) );
+ if(PowerCommand > 100 )
+ PowerCommand=100;
+ else if(PowerCommand < 0 )
+ PowerCommand=0;
+
+ } else {
+ PowerCommand=ThrottleToPowerCommand(throttle);
+ }
+
+ mil=MaxMilThrust*ThrustTables[1]->TotalValue();
+
+ if( PowerCommand <= 50 ) {
+ idle=MaxMilThrust*ThrustTables[0]->TotalValue();
+ Thrust = idle + (mil-idle)*PowerCommand*0.02;
+ } else {
+ aug=MaxAugThrust*ThrustTables[2]->TotalValue();
+ Thrust = mil + (aug-mil)*(PowerCommand-50)*0.02;
+ }
+
ConsumeFuel();
- return 0.0;
+
+ return Thrust;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+double FGTurbine::ThrottleToPowerCommand(double throttle) {
+ if( throttle <= 0.77 )
+ return 64.94*throttle;
+ else
+ return 217.38*throttle - 117.38;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurbine::PowerLag(double actual_power, double power_command) {
+ double t, p2;
+ if( power_command >= 50 ) {
+ if( actual_power >= 50 ) {
+ t=5;
+ p2=power_command;
+ } else {
+ p2=60;
+ t=rtau(p2-actual_power);
+ }
+ } else {
+ if( actual_power >= 50 ) {
+ t=5;
+ p2=40;
+ } else {
+ p2=power_command;
+ t=rtau(p2-actual_power);
+ }
+ }
+ return t*(p2-actual_power);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurbine::rtau(double delta_power) {
+ if( delta_power <= 25 )
+ return 1.0;
+ else if ( delta_power >= 50)
+ return 0.1;
+ else
+ return 1.9-0.036*delta_power;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
void FGTurbine::doInlet(void)
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGTurbine::Load(FGConfigFile *AC_cfg)
+bool FGTurbine::Load(FGConfigFile *Eng_cfg)
{
+ int i;
+ string token;
+ Name = Eng_cfg->GetValue("NAME");
+ cout << Name << endl;
+ Eng_cfg->GetNextConfigLine();
+ *Eng_cfg >> token >> MaxMilThrust;
+ *Eng_cfg >> token >> MaxAugThrust;
+ i=0;
+ while( Eng_cfg->GetValue() != "/FG_TURBINE" && i < 10){
+ ThrustTables.push_back( new FGCoefficient(FDMExec) );
+ ThrustTables.back()->Load(Eng_cfg);
+ i++;
+ }
+
return true;
}
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+#include <vector>
#include "FGEngine.h"
#include "FGConfigFile.h"
+#include "FGCoefficient.h"
#define ID_TURBINE "$Id$"
~FGTurbine();
double Calculate(double);
-
+
private:
+ typedef vector<FGCoefficient*> CoeffArray;
+ CoeffArray ThrustTables;
+
+ string name;
+ double MaxMilThrust;
+ double MaxAugThrust;
+
+ double PowerCommand;
+
+ double ThrottleToPowerCommand(double throttle);
+ double PowerLag(double actual_power, double power_command);
+ double rtau(double delta_power);
+
void doInlet(void);
void doCompressor(void);
void doBleedDuct(void);
void doTransition(void);
- bool Load(FGConfigFile *AC_cfg);
+ bool Load(FGConfigFile *ENG_cfg);
void Debug(int from);
};
Aerodynamics = fdmex->GetAerodynamics();
GroundReactions = fdmex->GetGroundReactions();
- fgic=new FGInitialCondition(fdmex);
+ fgic=fdmex->GetIC();
needTrim=true;
SGPath aircraft_path( globals->get_fg_root() );
copy_to_JSBsim();
- fdmex->RunIC(fgic); //loop JSBSim once w/o integrating
+ fdmex->RunIC(); //loop JSBSim once w/o integrating
copy_from_JSBsim(); //update the bus
SG_LOG( SG_FLIGHT, SG_INFO, " Initialized JSBSim with:" );
fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() );
do_trim();
} else {
- fdmex->RunIC(fgic); //apply any changes made through the set_ functions
+ fdmex->RunIC(); //apply any changes made through the set_ functions
}
needTrim = false;
}
FGTrim *fgtrim;
if( fgGetBool("/sim/startup/onground") ) {
fgic->SetVcalibratedKtsIC(0.0);
- fgtrim=new FGTrim(fdmex,fgic,tGround);
+ fgtrim=new FGTrim(fdmex,tGround);
} else {
- fgtrim=new FGTrim(fdmex,fgic,tLongitudinal);
+ fgtrim=new FGTrim(fdmex,tLongitudinal);
}
if( !fgtrim->DoTrim() ) {
fgtrim->Report();
FGTank.cpp FGTank.h \
FGfdmSocket.cpp FGfdmSocket.h \
FGTurbine.cpp FGTurbine.h \
- FGPropertyManager.h \
+ FGPropertyManager.cpp FGPropertyManager.h \
JSBSim.cxx JSBSim.hxx