Upgrade to JSBSim 1.0-prerelease
This commit is contained in:
parent
5917e80bf0
commit
4aff7b279d
23 changed files with 354 additions and 223 deletions
|
@ -90,7 +90,6 @@ void checkTied ( FGPropertyManager *node )
|
|||
|
||||
for (int i=0; i<N; i++) {
|
||||
if (node->getChild(i)->nChildren() ) {
|
||||
// cout << "Untieing " << node->getChild(i)->getName() << " property branch." << endl;
|
||||
checkTied( (FGPropertyManager*)node->getChild(i) );
|
||||
} else if ( node->getChild(i)->isTied() ) {
|
||||
name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName();
|
||||
|
@ -128,19 +127,12 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
|
|||
Script = 0;
|
||||
|
||||
modelLoaded = false;
|
||||
IsSlave = false;
|
||||
IsChild = false;
|
||||
holding = false;
|
||||
Terminate = false;
|
||||
|
||||
// Multiple FDM's are stopped for now. We need to ensure that
|
||||
// the "user" instance always gets the zeroeth instance number,
|
||||
// because there may be instruments or scripts tied to properties
|
||||
// in the jsbsim[0] node.
|
||||
// ToDo: it could be that when JSBSim is reset and a new FDM is wanted, that
|
||||
// process might try setting FDMctr = 0. Then the line below would not need
|
||||
// to be commented out.
|
||||
IdFDM = FDMctr;
|
||||
//FDMctr++;
|
||||
IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth"
|
||||
FDMctr++; // instance. "child" instances are loaded last.
|
||||
|
||||
try {
|
||||
char* num = getenv("JSBSIM_DEBUG");
|
||||
|
@ -189,10 +181,10 @@ FGFDMExec::~FGFDMExec()
|
|||
cout << "Caught error: " << msg << endl;
|
||||
}
|
||||
|
||||
for (unsigned int i=1; i<SlaveFDMList.size(); i++) delete SlaveFDMList[i]->exec;
|
||||
SlaveFDMList.clear();
|
||||
for (unsigned int i=1; i<ChildFDMList.size(); i++) delete ChildFDMList[i]->exec;
|
||||
ChildFDMList.clear();
|
||||
|
||||
//ToDo remove property catalog.
|
||||
PropertyCatalog.clear();
|
||||
|
||||
Debug(1);
|
||||
}
|
||||
|
@ -355,9 +347,9 @@ bool FGFDMExec::Run(void)
|
|||
|
||||
Debug(2);
|
||||
|
||||
for (unsigned int i=1; i<SlaveFDMList.size(); i++) {
|
||||
// SlaveFDMList[i]->exec->State->Initialize(); // Transfer state to the slave FDM
|
||||
// SlaveFDMList[i]->exec->Run();
|
||||
for (unsigned int i=1; i<ChildFDMList.size(); i++) {
|
||||
ChildFDMList[i]->AssignState(Propagate); // Transfer state to the child FDM
|
||||
ChildFDMList[i]->Run();
|
||||
}
|
||||
|
||||
// returns true if success
|
||||
|
@ -453,8 +445,8 @@ vector <string> FGFDMExec::EnumerateFDMs(void)
|
|||
|
||||
FDMList.push_back(Aircraft->GetAircraftName());
|
||||
|
||||
for (unsigned int i=1; i<SlaveFDMList.size(); i++) {
|
||||
FDMList.push_back(SlaveFDMList[i]->exec->GetAircraft()->GetAircraftName());
|
||||
for (unsigned int i=1; i<ChildFDMList.size(); i++) {
|
||||
FDMList.push_back(ChildFDMList[i]->exec->GetAircraft()->GetAircraftName());
|
||||
}
|
||||
|
||||
return FDMList;
|
||||
|
@ -511,10 +503,16 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
|
|||
Allocate();
|
||||
}
|
||||
|
||||
int saved_debug_lvl = debug_lvl;
|
||||
|
||||
document = LoadXMLDocument(aircraftCfgFileName); // "document" is a class member
|
||||
if (document) {
|
||||
if (IsChild) debug_lvl = 0;
|
||||
|
||||
ReadPrologue(document);
|
||||
|
||||
if (IsChild) debug_lvl = saved_debug_lvl;
|
||||
|
||||
// Process the fileheader element in the aircraft config file. This element is OPTIONAL.
|
||||
element = document->FindElement("fileheader");
|
||||
if (element) {
|
||||
|
@ -525,6 +523,8 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
|
|||
}
|
||||
}
|
||||
|
||||
if (IsChild) debug_lvl = 0;
|
||||
|
||||
// Process the metrics element. This element is REQUIRED.
|
||||
element = document->FindElement("metrics");
|
||||
if (element) {
|
||||
|
@ -662,18 +662,27 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
|
|||
element = document->FindNextElement("output");
|
||||
}
|
||||
|
||||
// Lastly, process the slave element. This element is OPTIONAL - and NOT YET SUPPORTED.
|
||||
element = document->FindElement("slave");
|
||||
// Lastly, process the child element. This element is OPTIONAL - and NOT YET SUPPORTED.
|
||||
element = document->FindElement("child");
|
||||
if (element) {
|
||||
result = ReadSlave(element);
|
||||
result = ReadChild(element);
|
||||
if (!result) {
|
||||
cerr << endl << "Aircraft slave element has problems in file " << aircraftCfgFileName << endl;
|
||||
cerr << endl << "Aircraft child element has problems in file " << aircraftCfgFileName << endl;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
modelLoaded = true;
|
||||
|
||||
if (debug_lvl > 0) {
|
||||
cout << endl << fgblue << highint
|
||||
<< "End of vehicle configuration loading." << endl
|
||||
<< "-------------------------------------------------------------------------------"
|
||||
<< reset << endl;
|
||||
}
|
||||
|
||||
if (IsChild) debug_lvl = saved_debug_lvl;
|
||||
|
||||
} else {
|
||||
cerr << fgred
|
||||
<< " JSBSim failed to open the configuration file: " << aircraftCfgFileName
|
||||
|
@ -745,16 +754,20 @@ bool FGFDMExec::ReadFileHeader(Element* el)
|
|||
{
|
||||
bool result = true; // true for success
|
||||
|
||||
if (debug_lvl & ~1) return result;
|
||||
if (debug_lvl == 0) return result;
|
||||
|
||||
if (IsChild) {
|
||||
cout << endl <<highint << fgblue << "Reading child model: " << IdFDM << reset << endl << endl;
|
||||
}
|
||||
|
||||
if (el->FindElement("description"))
|
||||
cout << " Description: " << el->FindElement("description")->GetDataLine() << endl;
|
||||
if (el->FindElement("author"))
|
||||
cout << " Model Author: " << el->FindElement("author")->GetDataLine() << endl;
|
||||
if (el->FindElement("filecreationdate"))
|
||||
cout << " Creation Date: " << el->FindElement("filecreationdate")->GetDataLine() << endl;
|
||||
if (el->FindElement("version"))
|
||||
cout << " Version: " << el->FindElement("version")->GetDataLine() << endl;
|
||||
if (el->FindElement("description"))
|
||||
cout << " Description: " << el->FindElement("description")->GetDataLine() << endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -821,54 +834,51 @@ bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
bool FGFDMExec::ReadSlave(Element* el)
|
||||
bool FGFDMExec::ReadChild(Element* el)
|
||||
{
|
||||
// Add a new slaveData object to the slave FDM list
|
||||
// Populate that slaveData element with a new FDMExec object
|
||||
// Set the IsSlave flag for that FDMExec object
|
||||
// Add a new childData object to the child FDM list
|
||||
// Populate that childData element with a new FDMExec object
|
||||
// Set the IsChild flag for that FDMExec object
|
||||
// Get the aircraft name
|
||||
// set debug level to print out no additional data for slave objects
|
||||
// set debug level to print out no additional data for child objects
|
||||
// Load the model given the aircraft name
|
||||
// reset debug level to prior setting
|
||||
|
||||
int saved_debug_lvl = debug_lvl;
|
||||
string token;
|
||||
|
||||
SlaveFDMList.push_back(new slaveData);
|
||||
SlaveFDMList.back()->exec = new FGFDMExec();
|
||||
SlaveFDMList.back()->exec->SetSlave(true);
|
||||
/*
|
||||
string AircraftName = AC_cfg->GetValue("file");
|
||||
struct childData* child = new childData;
|
||||
|
||||
debug_lvl = 0; // turn off debug output for slave vehicle
|
||||
child->exec = new FGFDMExec();
|
||||
child->exec->SetChild(true);
|
||||
|
||||
SlaveFDMList.back()->exec->SetAircraftPath( AircraftPath );
|
||||
SlaveFDMList.back()->exec->SetEnginePath( EnginePath );
|
||||
SlaveFDMList.back()->exec->SetSystemsPath( SystemsPath );
|
||||
SlaveFDMList.back()->exec->LoadModel(AircraftName);
|
||||
debug_lvl = saved_debug_lvl; // turn debug output back on for master vehicle
|
||||
string childAircraft = el->GetAttributeValue("name");
|
||||
string sMated = el->GetAttributeValue("mated");
|
||||
if (sMated == "false") child->mated = false; // child objects are mated by default.
|
||||
string sInternal = el->GetAttributeValue("internal");
|
||||
if (sInternal == "true") child->internal = true; // child objects are external by default.
|
||||
|
||||
AC_cfg->GetNextConfigLine();
|
||||
while ((token = AC_cfg->GetValue()) != string("/SLAVE")) {
|
||||
*AC_cfg >> token;
|
||||
if (token == "xloc") { *AC_cfg >> SlaveFDMList.back()->x; }
|
||||
else if (token == "yloc") { *AC_cfg >> SlaveFDMList.back()->y; }
|
||||
else if (token == "zloc") { *AC_cfg >> SlaveFDMList.back()->z; }
|
||||
else if (token == "pitch") { *AC_cfg >> SlaveFDMList.back()->pitch;}
|
||||
else if (token == "yaw") { *AC_cfg >> SlaveFDMList.back()->yaw; }
|
||||
else if (token == "roll") { *AC_cfg >> SlaveFDMList.back()->roll; }
|
||||
else cerr << "Unknown identifier: " << token << " in slave vehicle definition" << endl;
|
||||
child->exec->SetAircraftPath( AircraftPath );
|
||||
child->exec->SetEnginePath( EnginePath );
|
||||
child->exec->SetSystemsPath( SystemsPath );
|
||||
child->exec->LoadModel(childAircraft);
|
||||
|
||||
Element* location = el->FindElement("location");
|
||||
if (location) {
|
||||
child->Loc = location->FindElementTripletConvertTo("IN");
|
||||
} else {
|
||||
cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl;
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
if (debug_lvl > 0) {
|
||||
cout << " X = " << SlaveFDMList.back()->x << endl;
|
||||
cout << " Y = " << SlaveFDMList.back()->y << endl;
|
||||
cout << " Z = " << SlaveFDMList.back()->z << endl;
|
||||
cout << " Pitch = " << SlaveFDMList.back()->pitch << endl;
|
||||
cout << " Yaw = " << SlaveFDMList.back()->yaw << endl;
|
||||
cout << " Roll = " << SlaveFDMList.back()->roll << endl;
|
||||
|
||||
Element* orientation = el->FindElement("orient");
|
||||
if (orientation) {
|
||||
child->Orient = orientation->FindElementTripletConvertTo("RAD");
|
||||
} else if (debug_lvl > 0) {
|
||||
cerr << endl << highint << " No orientation was found for this child object! Assuming 0,0,0." << reset << endl;
|
||||
}
|
||||
|
||||
ChildFDMList.push_back(child);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ INCLUDES
|
|||
#include <input_output/FGGroundCallback.h>
|
||||
#include <input_output/FGXMLFileRead.h>
|
||||
#include <models/FGPropagate.h>
|
||||
#include <math/FGColumnVector3.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -177,6 +178,32 @@ CLASS DECLARATION
|
|||
|
||||
class FGFDMExec : public FGJSBBase, public FGXMLFileRead
|
||||
{
|
||||
struct childData {
|
||||
FGFDMExec* exec;
|
||||
string info;
|
||||
FGColumnVector3 Loc;
|
||||
FGColumnVector3 Orient;
|
||||
bool mated;
|
||||
bool internal;
|
||||
|
||||
childData(void) {
|
||||
info = "";
|
||||
Loc = FGColumnVector3(0,0,0);
|
||||
Orient = FGColumnVector3(0,0,0);
|
||||
mated = true;
|
||||
internal = false;
|
||||
}
|
||||
|
||||
void Run(void) {exec->Run();}
|
||||
void AssignState(FGPropagate* source_prop) {
|
||||
exec->GetPropagate()->SetVState(source_prop->GetVState());
|
||||
}
|
||||
|
||||
~childData(void) {
|
||||
delete exec;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Default constructor
|
||||
|
@ -335,8 +362,12 @@ public:
|
|||
FGPropertyManager* GetPropertyManager(void);
|
||||
/// Returns a vector of strings representing the names of all loaded models (future)
|
||||
vector <string> EnumerateFDMs(void);
|
||||
/// Marks this instance of the Exec object as a "slave" object.
|
||||
void SetSlave(bool s) {IsSlave = s;}
|
||||
/// Gets the number of child FDMs.
|
||||
int GetFDMCount(void) {return ChildFDMList.size();}
|
||||
/// Gets a particular child FDM.
|
||||
childData* GetChildFDM(int i) {return ChildFDMList[i];}
|
||||
/// Marks this instance of the Exec object as a "child" object.
|
||||
void SetChild(bool ch) {IsChild = ch;}
|
||||
|
||||
/** Sets the output (logging) mechanism for this run.
|
||||
Calling this function passes the name of an output directives file to
|
||||
|
@ -443,7 +474,7 @@ private:
|
|||
bool holding;
|
||||
bool Constructing;
|
||||
bool modelLoaded;
|
||||
bool IsSlave;
|
||||
bool IsChild;
|
||||
string modelName;
|
||||
string AircraftPath;
|
||||
string FullAircraftPath;
|
||||
|
@ -455,26 +486,6 @@ private:
|
|||
bool trim_status;
|
||||
int ta_mode;
|
||||
|
||||
|
||||
struct slaveData {
|
||||
FGFDMExec* exec;
|
||||
string info;
|
||||
double x, y, z;
|
||||
double roll, pitch, yaw;
|
||||
bool mated;
|
||||
|
||||
slaveData(void) {
|
||||
info = "";
|
||||
x = y = z = 0.0;
|
||||
roll = pitch = yaw = 0.0;
|
||||
mated = true;
|
||||
}
|
||||
|
||||
~slaveData(void) {
|
||||
delete exec;
|
||||
}
|
||||
};
|
||||
|
||||
static FGPropertyManager *master;
|
||||
|
||||
FGModel* FirstModel;
|
||||
|
@ -502,10 +513,10 @@ private:
|
|||
|
||||
vector <string> PropertyCatalog;
|
||||
vector <FGOutput*> Outputs;
|
||||
vector <slaveData*> SlaveFDMList;
|
||||
vector <childData*> ChildFDMList;
|
||||
|
||||
bool ReadFileHeader(Element*);
|
||||
bool ReadSlave(Element*);
|
||||
bool ReadChild(Element*);
|
||||
bool ReadPrologue(Element*);
|
||||
void ResetToInitialConditions(int mode);
|
||||
bool Allocate(void);
|
||||
|
|
|
@ -156,7 +156,7 @@ public:
|
|||
/** Places a Message structure on the Message queue.
|
||||
@param msg pointer to a Message structure
|
||||
@return pointer to a Message structure */
|
||||
void PutMessage(const Message& msg);
|
||||
void PutMessage(const Message& msg);
|
||||
/** Creates a message with the given text and places it on the queue.
|
||||
@param text message text
|
||||
@return pointer to a Message structure */
|
||||
|
@ -165,17 +165,17 @@ void PutMessage(const Message& msg);
|
|||
@param text message text
|
||||
@param bVal boolean value associated with the message
|
||||
@return pointer to a Message structure */
|
||||
void PutMessage(const string& text, bool bVal);
|
||||
void PutMessage(const string& text, bool bVal);
|
||||
/** Creates a message with the given text and integer value and places it on the queue.
|
||||
@param text message text
|
||||
@param iVal integer value associated with the message
|
||||
@return pointer to a Message structure */
|
||||
void PutMessage(const string& text, int iVal);
|
||||
void PutMessage(const string& text, int iVal);
|
||||
/** Creates a message with the given text and double value and places it on the queue.
|
||||
@param text message text
|
||||
@param dVal double value associated with the message
|
||||
@return pointer to a Message structure */
|
||||
void PutMessage(const string& text, double dVal);
|
||||
void PutMessage(const string& text, double dVal);
|
||||
/** Reads the message on the queue (but does not delete it).
|
||||
@return 1 if some messages */
|
||||
int SomeMessages(void);
|
||||
|
@ -295,6 +295,8 @@ void PutMessage(const string& text, double dVal);
|
|||
static double Constrain(double min, double value, double max) {
|
||||
return value<min?(min):(value>max?(max):(value));
|
||||
}
|
||||
|
||||
static double sign(double num) {return num>=0.0?1.0:-1.0;}
|
||||
|
||||
protected:
|
||||
static Message localMsg;
|
||||
|
@ -341,6 +343,8 @@ protected:
|
|||
static int phase = 0;
|
||||
double X;
|
||||
|
||||
V1 = V2 = S = X = 0.0;
|
||||
|
||||
if (phase == 0) {
|
||||
do {
|
||||
double U1 = (double)rand() / RAND_MAX;
|
||||
|
@ -351,7 +355,7 @@ protected:
|
|||
S = V1 * V1 + V2 * V2;
|
||||
} while(S >= 1 || S == 0);
|
||||
|
||||
X = V1 * sqrt(-2 * log(S) / S);
|
||||
X = V1 * sqrt(-2 * log(S) / S);
|
||||
} else
|
||||
X = V2 * sqrt(-2 * log(S) / S);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
FGFSGroundCallback(FGJSBsim* ifc) : mInterface(ifc) {}
|
||||
virtual ~FGFSGroundCallback() {}
|
||||
|
||||
/** Get the altitude above sea level depenent on the location. */
|
||||
/** Get the altitude above sea level dependent on the location. */
|
||||
virtual double GetAltitude(const FGLocation& l) const {
|
||||
double pt[3] = { SG_FEET_TO_METER*l(eX),
|
||||
SG_FEET_TO_METER*l(eY),
|
||||
|
@ -145,13 +145,6 @@ FGJSBsim::FGJSBsim( double dt )
|
|||
|
||||
fdmex = new FGFDMExec( (FGPropertyManager*)globals->get_props() );
|
||||
|
||||
// begin ugly hack
|
||||
// Untie the write-state-file property to avoid creating an initfile.xml
|
||||
// file on each FlightGear reset.
|
||||
fgGetNode("/fdm/jsbsim/simulation/write-state-file")->untie();
|
||||
fgGetNode("/fdm/jsbsim/simulation")->removeChild("write-state-file", false);
|
||||
// end ugly hack
|
||||
|
||||
// Register ground callback.
|
||||
fdmex->SetGroundCallback( new FGFSGroundCallback(this) );
|
||||
|
||||
|
@ -391,7 +384,7 @@ void FGJSBsim::init()
|
|||
SG_LOG( SG_FLIGHT, SG_INFO, " Longitude: "
|
||||
<< Propagate->GetLocation().GetLongitudeDeg() << " deg" );
|
||||
SG_LOG( SG_FLIGHT, SG_INFO, " Altitude: "
|
||||
<< Propagate->Geth() << " feet" );
|
||||
<< Propagate->GetAltitudeASL() << " feet" );
|
||||
SG_LOG( SG_FLIGHT, SG_INFO, " loaded initial conditions" );
|
||||
|
||||
SG_LOG( SG_FLIGHT, SG_INFO, " set dt" );
|
||||
|
@ -438,7 +431,7 @@ void FGJSBsim::update( double dt )
|
|||
double alt, slr, lat, lon;
|
||||
FGColumnVector3 cart = Auxiliary->GetLocationVRP();
|
||||
if ( needTrim && startup_trim->getBoolValue() ) {
|
||||
alt = fgic->GetAltitudeFtIC();
|
||||
alt = fgic->GetAltitudeASLFtIC();
|
||||
slr = fgic->GetSeaLevelRadiusFtIC();
|
||||
lat = fgic->GetLatitudeDegIC() * SGD_DEGREES_TO_RADIANS;
|
||||
lon = fgic->GetLongitudeDegIC() * SGD_DEGREES_TO_RADIANS;
|
||||
|
@ -452,7 +445,7 @@ void FGJSBsim::update( double dt )
|
|||
SG_LOG(SG_FLIGHT, SG_WARN,
|
||||
"FGInterface is being called without scenery below the aircraft!");
|
||||
|
||||
alt = fgic->GetAltitudeFtIC();
|
||||
alt = fgic->GetAltitudeASLFtIC();
|
||||
SG_LOG(SG_FLIGHT, SG_WARN, "altitude = " << alt);
|
||||
|
||||
slr = fgic->GetSeaLevelRadiusFtIC();
|
||||
|
@ -479,10 +472,10 @@ void FGJSBsim::update( double dt )
|
|||
+ contact[2]*contact[2]) - fgic->GetSeaLevelRadiusFtIC();
|
||||
|
||||
SG_LOG(SG_FLIGHT, SG_INFO,
|
||||
"Ready to trim, terrain altitude is: "
|
||||
"Ready to trim, terrain elevation is: "
|
||||
<< terrain_alt * SG_METER_TO_FEET );
|
||||
|
||||
fgic->SetTerrainAltitudeFtIC( terrain_alt );
|
||||
fgic->SetTerrainElevationFtIC( terrain_alt );
|
||||
do_trim();
|
||||
} else {
|
||||
fdmex->RunIC(); //apply any changes made through the set_ functions
|
||||
|
@ -638,7 +631,7 @@ bool FGJSBsim::copy_to_JSBsim()
|
|||
}
|
||||
|
||||
Propulsion->SetFuelFreeze((fgGetNode("/sim/freeze/fuel",true))->getBoolValue());
|
||||
fdmex->SetSlave(slaved->getBoolValue());
|
||||
fdmex->SetChild(slaved->getBoolValue());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -963,6 +956,7 @@ void FGJSBsim::set_Longitude(double lon)
|
|||
needTrim=true;
|
||||
}
|
||||
|
||||
// Sets the altitude above sea level.
|
||||
void FGJSBsim::set_Altitude(double alt)
|
||||
{
|
||||
static SGConstPropertyNode_ptr latitude = fgGetNode("/position/latitude-deg");
|
||||
|
@ -981,9 +975,9 @@ void FGJSBsim::set_Altitude(double alt)
|
|||
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
|
||||
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET );
|
||||
SG_LOG(SG_FLIGHT, SG_INFO,
|
||||
"Terrain altitude: " << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET );
|
||||
"Terrain elevation: " << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET );
|
||||
fgic->SetLatitudeRadIC( lat_geoc );
|
||||
fgic->SetAltitudeFtIC(alt);
|
||||
fgic->SetAltitudeASLFtIC(alt);
|
||||
needTrim=true;
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1163,7 @@ void FGJSBsim::update_ic(void)
|
|||
if ( !needTrim ) {
|
||||
fgic->SetLatitudeRadIC(get_Lat_geocentric() );
|
||||
fgic->SetLongitudeRadIC( get_Longitude() );
|
||||
fgic->SetAltitudeFtIC( get_Altitude() );
|
||||
fgic->SetAltitudeASLFtIC( get_Altitude() );
|
||||
fgic->SetVcalibratedKtsIC( get_V_calibrated_kts() );
|
||||
fgic->SetThetaRadIC( get_Theta() );
|
||||
fgic->SetPhiRadIC( get_Phi() );
|
||||
|
|
|
@ -66,7 +66,7 @@ FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec) : fdmex(FDMExec)
|
|||
InitializeIC();
|
||||
|
||||
if(FDMExec != NULL ) {
|
||||
fdmex->GetPropagate()->Seth(altitude);
|
||||
fdmex->GetPropagate()->SetAltitudeASL(altitudeASL);
|
||||
fdmex->GetAtmosphere()->Run();
|
||||
PropertyManager=fdmex->GetPropertyManager();
|
||||
Constructing = true;
|
||||
|
@ -120,7 +120,7 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0,
|
|||
FGColumnVector3 _vUVW_BODY(u,v,w);
|
||||
FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY;
|
||||
FGColumnVector3 _vWIND_NED(wnorth,weast,wdown);
|
||||
FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED );
|
||||
// FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED );
|
||||
|
||||
uw=_vWIND_NED(1); vw=_vWIND_NED(2); ww=_vWIND_NED(3);
|
||||
|
||||
|
@ -134,7 +134,7 @@ void FGInitialCondition::InitializeIC(void)
|
|||
mach=0;
|
||||
alpha=beta=gamma=0;
|
||||
theta=phi=psi=0;
|
||||
altitude=hdot=0;
|
||||
altitudeASL=hdot=0;
|
||||
latitude=longitude=0;
|
||||
u=v=w=0;
|
||||
p=q=r=0;
|
||||
|
@ -146,7 +146,7 @@ void FGInitialCondition::InitializeIC(void)
|
|||
lastSpeedSet=setvt;
|
||||
lastWindSet=setwned;
|
||||
radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius();
|
||||
terrain_altitude = 0;
|
||||
terrain_elevation = 0;
|
||||
|
||||
targetNlfIC = 1.0;
|
||||
|
||||
|
@ -181,7 +181,7 @@ void FGInitialCondition::WriteStateFile(int num)
|
|||
outfile << " <psi unit=\"DEG\"> " << Propagate->GetEuler(ePsi) << " </psi>" << endl;
|
||||
outfile << " <longitude unit=\"DEG\"> " << Propagate->GetLongitudeDeg() << " </longitude>" << endl;
|
||||
outfile << " <latitude unit=\"DEG\"> " << Propagate->GetLatitudeDeg() << " </latitude>" << endl;
|
||||
outfile << " <altitude unit=\"FT\"> " << Propagate->Geth() << " </altitude>" << endl;
|
||||
outfile << " <altitude unit=\"FT\"> " << Propagate->GetAltitudeASL() << " </altitude>" << endl;
|
||||
outfile << "</initialize>" << endl;
|
||||
outfile.close();
|
||||
} else {
|
||||
|
@ -538,9 +538,10 @@ void FGInitialCondition::calcWindUVW(void) {
|
|||
|
||||
//******************************************************************************
|
||||
|
||||
void FGInitialCondition::SetAltitudeFtIC(double tt) {
|
||||
altitude=tt;
|
||||
fdmex->GetPropagate()->Seth(altitude);
|
||||
void FGInitialCondition::SetAltitudeASLFtIC(double tt)
|
||||
{
|
||||
altitudeASL=tt;
|
||||
fdmex->GetPropagate()->SetAltitudeASL(altitudeASL);
|
||||
fdmex->GetAtmosphere()->Run();
|
||||
//lets try to make sure the user gets what they intended
|
||||
|
||||
|
@ -567,25 +568,29 @@ void FGInitialCondition::SetAltitudeFtIC(double tt) {
|
|||
|
||||
//******************************************************************************
|
||||
|
||||
void FGInitialCondition::SetAltitudeAGLFtIC(double tt) {
|
||||
SetAltitudeFtIC(terrain_altitude + tt);
|
||||
void FGInitialCondition::SetAltitudeAGLFtIC(double tt)
|
||||
{
|
||||
SetAltitudeASLFtIC(terrain_elevation + tt);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) {
|
||||
void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt)
|
||||
{
|
||||
sea_level_radius = tt;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) {
|
||||
terrain_altitude=tt;
|
||||
void FGInitialCondition::SetTerrainElevationFtIC(double tt)
|
||||
{
|
||||
terrain_elevation=tt;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
void FGInitialCondition::calcUVWfromNED(void) {
|
||||
void FGInitialCondition::calcUVWfromNED(void)
|
||||
{
|
||||
u=vnorth*ctheta*cpsi +
|
||||
veast*ctheta*spsi -
|
||||
vdown*stheta;
|
||||
|
@ -858,8 +863,10 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
|
|||
SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
|
||||
if (document->FindElement("longitude"))
|
||||
SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
|
||||
if (document->FindElement("altitude"))
|
||||
SetAltitudeFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
|
||||
if (document->FindElement("elevation"))
|
||||
SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT"));
|
||||
if (document->FindElement("altitude")) // This is feet above ground level
|
||||
SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
|
||||
if (document->FindElement("ubody"))
|
||||
SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
|
||||
if (document->FindElement("vbody"))
|
||||
|
@ -979,8 +986,8 @@ void FGInitialCondition::bind(void){
|
|||
&FGInitialCondition::SetLongitudeDegIC,
|
||||
true);
|
||||
PropertyManager->Tie("ic/h-sl-ft", this,
|
||||
&FGInitialCondition::GetAltitudeFtIC,
|
||||
&FGInitialCondition::SetAltitudeFtIC,
|
||||
&FGInitialCondition::GetAltitudeASLFtIC,
|
||||
&FGInitialCondition::SetAltitudeASLFtIC,
|
||||
true);
|
||||
PropertyManager->Tie("ic/h-agl-ft", this,
|
||||
&FGInitialCondition::GetAltitudeAGLFtIC,
|
||||
|
@ -990,9 +997,9 @@ void FGInitialCondition::bind(void){
|
|||
&FGInitialCondition::GetSeaLevelRadiusFtIC,
|
||||
&FGInitialCondition::SetSeaLevelRadiusFtIC,
|
||||
true);
|
||||
PropertyManager->Tie("ic/terrain-altitude-ft", this,
|
||||
&FGInitialCondition::GetTerrainAltitudeFtIC,
|
||||
&FGInitialCondition::SetTerrainAltitudeFtIC,
|
||||
PropertyManager->Tie("ic/terrain-elevation-ft", this,
|
||||
&FGInitialCondition::GetTerrainElevationFtIC,
|
||||
&FGInitialCondition::SetTerrainElevationFtIC,
|
||||
true);
|
||||
PropertyManager->Tie("ic/vg-fps", this,
|
||||
&FGInitialCondition::GetVgroundFpsIC,
|
||||
|
|
|
@ -85,7 +85,7 @@ CLASS DOCUMENTATION
|
|||
@code
|
||||
FGInitialCondition fgic=new FGInitialCondition(FDMExec);
|
||||
fgic->SetVcalibratedKtsIC()
|
||||
fgic->SetAltitudeFtIC();
|
||||
fgic->SetAltitudeAGLFtIC();
|
||||
|
||||
// directly into Run
|
||||
FDMExec->GetState()->Initialize(fgic)
|
||||
|
@ -140,7 +140,7 @@ CLASS DOCUMENTATION
|
|||
- beta (angle, degrees)
|
||||
- gamma (angle, degrees)
|
||||
- roc (vertical velocity, ft/sec)
|
||||
- altitude (altitude, ft)
|
||||
- altitude (altitude AGL, ft)
|
||||
- winddir (wind from-angle, degrees)
|
||||
- vwind (magnitude wind speed, ft/sec)
|
||||
- hwind (headwind speed, knots)
|
||||
|
@ -168,7 +168,7 @@ CLASS DOCUMENTATION
|
|||
@property ic/h-sl-ft (read/write) Height above sea level initial condition in feet
|
||||
@property ic/h-agl-ft (read/write) Height above ground level initial condition in feet
|
||||
@property ic/sea-level-radius-ft (read/write) Radius of planet at sea level in feet
|
||||
@property ic/terrain-altitude-ft (read/write) Terrain elevation above sea level in feet
|
||||
@property ic/terrain-elevation-ft (read/write) Terrain elevation above sea level in feet
|
||||
@property ic/vg-fps (read/write) Ground speed initial condition in feet/second
|
||||
@property ic/vt-fps (read/write) True airspeed initial condition in feet/second
|
||||
@property ic/vw-bx-fps (read/write) Wind velocity initial condition in Body X frame in feet/second
|
||||
|
@ -269,9 +269,9 @@ public:
|
|||
@param gamma Flight path angle in degrees */
|
||||
inline void SetFlightPathAngleDegIC(double gamma) { SetFlightPathAngleRadIC(gamma*degtorad); }
|
||||
|
||||
/** Sets the altitude initial condition in feet.
|
||||
@param alt Altitude in feet */
|
||||
void SetAltitudeFtIC(double alt);
|
||||
/** Sets the altitude above sea level initial condition in feet.
|
||||
@param altitudeASL Altitude above sea level in feet */
|
||||
void SetAltitudeASLFtIC(double altitudeASL);
|
||||
|
||||
/** Sets the initial Altitude above ground level.
|
||||
@param agl Altitude above ground level in feet */
|
||||
|
@ -283,7 +283,7 @@ public:
|
|||
|
||||
/** Sets the initial terrain elevation.
|
||||
@param elev Initial terrain elevation in feet */
|
||||
void SetTerrainAltitudeFtIC(double elev);
|
||||
void SetTerrainElevationFtIC(double elev);
|
||||
|
||||
/** Sets the initial latitude.
|
||||
@param lat Initial latitude in degrees */
|
||||
|
@ -349,13 +349,13 @@ public:
|
|||
@return Initial longitude in degrees */
|
||||
inline double GetLongitudeDegIC(void) const { return longitude*radtodeg; }
|
||||
|
||||
/** Gets the initial altitude.
|
||||
/** Gets the initial altitude above sea level.
|
||||
@return Initial altitude in feet. */
|
||||
inline double GetAltitudeFtIC(void) const { return altitude; }
|
||||
inline double GetAltitudeASLFtIC(void) const { return altitudeASL; }
|
||||
|
||||
/** Gets the initial altitude above ground level.
|
||||
@return Initial altitude AGL in feet */
|
||||
inline double GetAltitudeAGLFtIC(void) const { return altitude - terrain_altitude; }
|
||||
inline double GetAltitudeAGLFtIC(void) const { return altitudeASL - terrain_elevation; }
|
||||
|
||||
/** Gets the initial sea level radius.
|
||||
@return Initial sea level radius */
|
||||
|
@ -363,7 +363,7 @@ public:
|
|||
|
||||
/** Gets the initial terrain elevation.
|
||||
@return Initial terrain elevation in feet */
|
||||
inline double GetTerrainAltitudeFtIC(void) const { return terrain_altitude; }
|
||||
inline double GetTerrainElevationFtIC(void) const { return terrain_elevation; }
|
||||
|
||||
/** Sets the initial ground speed.
|
||||
@param vg Initial ground speed in feet/second */
|
||||
|
@ -616,7 +616,7 @@ public:
|
|||
private:
|
||||
double vt,vc,ve,vg;
|
||||
double mach;
|
||||
double altitude,hdot;
|
||||
double altitudeASL,hdot;
|
||||
double latitude,longitude;
|
||||
double u,v,w;
|
||||
double p,q,r;
|
||||
|
@ -625,7 +625,7 @@ private:
|
|||
double wnorth,weast,wdown;
|
||||
double whead, wcross, wdir, wmag;
|
||||
double sea_level_radius;
|
||||
double terrain_altitude;
|
||||
double terrain_elevation;
|
||||
double radius_to_vehicle;
|
||||
double targetNlfIC;
|
||||
|
||||
|
|
|
@ -181,14 +181,20 @@ bool FGScript::LoadScript( string script )
|
|||
while (property_element) {
|
||||
|
||||
double value=0.0;
|
||||
string title="";
|
||||
|
||||
title = property_element->GetDataLine();
|
||||
if ( ! property_element->GetAttributeValue("value").empty())
|
||||
value = property_element->GetAttributeValueAsNumber("value");
|
||||
|
||||
LocalProps *localProp = new LocalProps(value);
|
||||
localProp->title = property_element->GetDataLine();
|
||||
localProp->title = title;
|
||||
local_properties.push_back(localProp);
|
||||
|
||||
PropertyManager->Tie(localProp->title, (local_properties.back())->value);
|
||||
if (PropertyManager->HasNode(title)) {
|
||||
PropertyManager->GetNode(title)->setDoubleValue(value);
|
||||
} else {
|
||||
PropertyManager->Tie(localProp->title, localProp->value);
|
||||
}
|
||||
property_element = run_element->FindNextElement("property");
|
||||
}
|
||||
|
||||
|
@ -447,6 +453,14 @@ void FGScript::Debug(int from)
|
|||
<< " seconds with dt = " << State->Getdt() << endl;
|
||||
cout << endl;
|
||||
|
||||
for (unsigned int i=0; i<local_properties.size(); i++) {
|
||||
cout << "Local property: " << local_properties[i]->title
|
||||
<< " = " << PropertyManager->GetNode(local_properties[i]->title)->getDoubleValue()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (local_properties.size() > 0) cout << endl;
|
||||
|
||||
for (unsigned i=0; i<Events.size(); i++) {
|
||||
cout << "Event " << i;
|
||||
if (!Events[i].Name.empty()) cout << " (" << Events[i].Name << ")";
|
||||
|
|
|
@ -36,6 +36,7 @@ HISTORY
|
|||
INCLUDES
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#include <FGFDMExec.h>
|
||||
#include "FGAerodynamics.h"
|
||||
#include "FGPropagate.h"
|
||||
#include "FGAircraft.h"
|
||||
|
|
|
@ -136,7 +136,7 @@ bool FGAtmosphere::Run(void)
|
|||
if (FDMExec->Holding()) return false;
|
||||
|
||||
T_dev = 0.0;
|
||||
h = Propagate->Geth();
|
||||
h = Propagate->GetAltitudeASL();
|
||||
|
||||
if (!useExternal) {
|
||||
Calculate(h);
|
||||
|
|
|
@ -40,6 +40,7 @@ INCLUDES
|
|||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#include "FGModel.h"
|
||||
#include <FGFDMExec.h>
|
||||
#include <math/FGColumnVector3.h>
|
||||
#include <math/FGLocation.h>
|
||||
#include "FGPropagate.h"
|
||||
|
@ -185,10 +186,23 @@ public:
|
|||
double GetqbarUW (void) const { return qbarUW; }
|
||||
double GetqbarUV (void) const { return qbarUV; }
|
||||
double GetReynoldsNumber(void) const { return Re; }
|
||||
|
||||
/** Gets the magnitude of total vehicle velocity including wind effects in feet per second. */
|
||||
double GetVt (void) const { return Vt; }
|
||||
|
||||
/** Gets the ground speed in feet per second.
|
||||
The magnitude is the square root of the sum of the squares (RSS) of the
|
||||
vehicle north and east velocity components.
|
||||
@return The magnitude of the vehicle velocity in the horizontal plane. */
|
||||
double GetVground (void) const { return Vground; }
|
||||
|
||||
/** Gets the Mach number. */
|
||||
double GetMach (void) const { return Mach; }
|
||||
|
||||
/** The mach number calculated using the vehicle X axis velocity. */
|
||||
double GetMachU (void) const { return MachU; }
|
||||
|
||||
/** The vertical acceleration in g's of the aircraft center of gravity. */
|
||||
double GetNz (void) const { return Nz; }
|
||||
|
||||
double GetHOverBCG(void) const { return hoverbcg; }
|
||||
|
|
|
@ -36,6 +36,7 @@ INCLUDES
|
|||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
||||
|
||||
#include "FGInertial.h"
|
||||
#include <FGFDMExec.h>
|
||||
#include "FGPropagate.h"
|
||||
#include "FGState.h"
|
||||
#include "FGMassBalance.h"
|
||||
|
|
|
@ -663,7 +663,8 @@ void FGLGear::Report(ReportType repType)
|
|||
|
||||
switch(repType) {
|
||||
case erLand:
|
||||
cout << endl << "Touchdown report for " << name << endl;
|
||||
cout << endl << "Touchdown report for " << name << " (WOW at time: "
|
||||
<< Exec->GetState()->Getsim_time() << " seconds)" << endl;
|
||||
cout << " Sink rate at contact: " << SinkRate << " fps, "
|
||||
<< SinkRate*0.3048 << " mps" << endl;
|
||||
cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, "
|
||||
|
@ -677,11 +678,17 @@ void FGLGear::Report(ReportType repType)
|
|||
LandingReported = true;
|
||||
break;
|
||||
case erTakeoff:
|
||||
cout << endl << "Takeoff report for " << name << endl;
|
||||
cout << endl << "Takeoff report for " << name << " (Liftoff at time: "
|
||||
<< Exec->GetState()->Getsim_time() << " seconds)" << endl;
|
||||
cout << " Distance traveled: " << TakeoffDistanceTraveled
|
||||
<< " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl;
|
||||
cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft
|
||||
<< " ft, " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl;
|
||||
cout << " [Altitude (ASL): " << Exec->GetPropagate()->GetAltitudeASL() << " ft. / "
|
||||
<< Exec->GetPropagate()->GetAltitudeASLmeters() << " m | Temperature: "
|
||||
<< Exec->GetAtmosphere()->GetTemperature() - 459.67 << " F / "
|
||||
<< RankineToCelsius(Exec->GetAtmosphere()->GetTemperature()) << " C]" << endl;
|
||||
cout << " [Velocity (KCAS): " << Exec->GetAuxiliary()->GetVcalibratedKTS() << "]" << endl;
|
||||
TakeoffReported = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -130,8 +130,13 @@ bool FGMassBalance::Load(Element* el)
|
|||
element = el->FindNextElement("pointmass");
|
||||
}
|
||||
|
||||
double ChildFDMWeight = 0.0;
|
||||
for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
|
||||
if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
|
||||
}
|
||||
|
||||
Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight()
|
||||
+ BuoyantForces->GetGasMass()*slugtolb;
|
||||
+ BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight;
|
||||
|
||||
Mass = lbtoslug*Weight;
|
||||
|
||||
|
@ -149,8 +154,13 @@ bool FGMassBalance::Run(void)
|
|||
if (FGModel::Run()) return true;
|
||||
if (FDMExec->Holding()) return false;
|
||||
|
||||
double ChildFDMWeight = 0.0;
|
||||
for (int fdm=0; fdm<FDMExec->GetFDMCount(); fdm++) {
|
||||
if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight();
|
||||
}
|
||||
|
||||
Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight()
|
||||
+ BuoyantForces->GetGasMass()*slugtolb;
|
||||
+ BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight;
|
||||
|
||||
Mass = lbtoslug*Weight;
|
||||
|
||||
|
|
|
@ -323,7 +323,8 @@ void FGOutput::DelimitedOutput(string fname)
|
|||
}
|
||||
if (SubSystems & ssPropagate) {
|
||||
outstream << delimeter;
|
||||
outstream << "Altitude (ft)" + delimeter;
|
||||
outstream << "Altitude ASL (ft)" + delimeter;
|
||||
outstream << "Altitude AGL (ft)" + delimeter;
|
||||
outstream << "Phi (deg)" + delimeter + "Theta (deg)" + delimeter + "Psi (deg)" + delimeter;
|
||||
outstream << "Alpha (deg)" + delimeter;
|
||||
outstream << "Beta (deg)" + delimeter;
|
||||
|
@ -332,7 +333,7 @@ void FGOutput::DelimitedOutput(string fname)
|
|||
outstream << "ECEF X (ft)" + delimeter + "ECEF Y (ft)" + delimeter + "ECEF Z (ft)" + delimeter;
|
||||
outstream << "EPA (deg)" + delimeter;
|
||||
outstream << "Distance AGL (ft)" + delimeter;
|
||||
outstream << "Runway Radius (ft)";
|
||||
outstream << "Terrain Radius (ft)";
|
||||
}
|
||||
if (SubSystems & ssCoefficients) {
|
||||
scratch = Aerodynamics->GetCoefficientStrings(delimeter);
|
||||
|
@ -432,7 +433,8 @@ void FGOutput::DelimitedOutput(string fname)
|
|||
if (SubSystems & ssPropagate) {
|
||||
outstream.precision(14);
|
||||
outstream << delimeter;
|
||||
outstream << Propagate->Geth() << delimeter;
|
||||
outstream << Propagate->GetAltitudeASL() << delimeter;
|
||||
outstream << Propagate->GetDistanceAGL() << delimeter;
|
||||
outstream << (radtodeg*Propagate->GetEuler()).Dump(delimeter) << delimeter;
|
||||
outstream << Auxiliary->Getalpha(inDegrees) << delimeter;
|
||||
outstream << Auxiliary->Getbeta(inDegrees) << delimeter;
|
||||
|
@ -443,7 +445,7 @@ void FGOutput::DelimitedOutput(string fname)
|
|||
outstream.precision(14);
|
||||
outstream << Inertial->GetEarthPositionAngleDeg() << delimeter;
|
||||
outstream << Propagate->GetDistanceAGL() << delimeter;
|
||||
outstream << Propagate->GetRunwayRadius();
|
||||
outstream << Propagate->GetLocalTerrainRadius();
|
||||
outstream.precision(10);
|
||||
}
|
||||
if (SubSystems & ssCoefficients) {
|
||||
|
@ -483,7 +485,7 @@ void FGOutput::SocketDataFill(FGNetFDM* net)
|
|||
// Positions
|
||||
net->longitude = Propagate->GetLocation().GetLongitude(); // geodetic (radians)
|
||||
net->latitude = Propagate->GetLocation().GetLatitude(); // geodetic (radians)
|
||||
net->altitude = Propagate->Geth()*0.3048; // altitude, above sea level (meters)
|
||||
net->altitude = Propagate->GetAltitudeASL()*0.3048; // altitude, above sea level (meters)
|
||||
net->agl = (float)(Propagate->GetDistanceAGL()*0.3048); // altitude, above ground level (meters)
|
||||
|
||||
net->phi = (float)(Propagate->GetEuler(ePhi)); // roll (radians)
|
||||
|
@ -881,7 +883,7 @@ void FGOutput::SocketOutput(void)
|
|||
socket->Append(MassBalance->GetXYZcg()(eZ));
|
||||
}
|
||||
if (SubSystems & ssPropagate) {
|
||||
socket->Append(Propagate->Geth());
|
||||
socket->Append(Propagate->GetAltitudeASL());
|
||||
socket->Append(radtodeg*Propagate->GetEuler(ePhi));
|
||||
socket->Append(radtodeg*Propagate->GetEuler(eTht));
|
||||
socket->Append(radtodeg*Propagate->GetEuler(ePsi));
|
||||
|
|
|
@ -118,10 +118,10 @@ bool FGPropagate::InitModel(void)
|
|||
{
|
||||
if (!FGModel::InitModel()) return false;
|
||||
|
||||
SeaLevelRadius = Inertial->GetRefRadius(); // For initialization ONLY
|
||||
RunwayRadius = SeaLevelRadius;
|
||||
// For initialization ONLY:
|
||||
SeaLevelRadius = LocalTerrainRadius = Inertial->GetRefRadius();
|
||||
|
||||
VState.vLocation.SetRadius( SeaLevelRadius + 4.0 ); // Todo Add terrain elevation?
|
||||
VState.vLocation.SetRadius( LocalTerrainRadius + 4.0 );
|
||||
VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor());
|
||||
vOmega = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector
|
||||
|
||||
|
@ -155,13 +155,13 @@ bool FGPropagate::InitModel(void)
|
|||
|
||||
void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
|
||||
{
|
||||
SeaLevelRadius = FGIC->GetSeaLevelRadiusFtIC();
|
||||
RunwayRadius = SeaLevelRadius;
|
||||
SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC());
|
||||
SetTerrainElevation(FGIC->GetTerrainElevationFtIC());
|
||||
|
||||
// Set the position lat/lon/radius
|
||||
VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(),
|
||||
FGIC->GetLatitudeRadIC(),
|
||||
FGIC->GetAltitudeFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
|
||||
FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
|
||||
|
||||
VehicleRadius = GetRadius();
|
||||
radInv = 1.0/VehicleRadius;
|
||||
|
@ -187,8 +187,8 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
|
|||
// Finally, make sure that the quaternion stays normalized.
|
||||
VState.vQtrn.Normalize();
|
||||
|
||||
// Recompute the RunwayRadius level.
|
||||
RecomputeRunwayRadius();
|
||||
// Recompute the LocalTerrainRadius.
|
||||
RecomputeLocalTerrainRadius();
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -216,7 +216,7 @@ bool FGPropagate::Run(void)
|
|||
if (FGModel::Run()) return true; // Fast return if we have nothing to do ...
|
||||
if (FDMExec->Holding()) return false;
|
||||
|
||||
RecomputeRunwayRadius();
|
||||
RecomputeLocalTerrainRadius();
|
||||
|
||||
// Calculate current aircraft radius from center of planet
|
||||
|
||||
|
@ -424,27 +424,28 @@ void FGPropagate::CalculateLocationdot(void)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropagate::RecomputeRunwayRadius(void)
|
||||
void FGPropagate::RecomputeLocalTerrainRadius(void)
|
||||
{
|
||||
// Get the runway radius.
|
||||
double t = State->Getsim_time();
|
||||
|
||||
// Get the LocalTerrain radius.
|
||||
FGLocation contactloc;
|
||||
FGColumnVector3 dv;
|
||||
FGGroundCallback* gcb = FDMExec->GetGroundCallback();
|
||||
double t = State->Getsim_time();
|
||||
gcb->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
|
||||
RunwayRadius = contactloc.GetRadius();
|
||||
FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
|
||||
LocalTerrainRadius = contactloc.GetRadius();
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropagate::SetTerrainElevationASL(double tt)
|
||||
void FGPropagate::SetTerrainElevation(double terrainElev)
|
||||
{
|
||||
FDMExec->GetGroundCallback()->SetTerrainGeoCentRadius(tt+SeaLevelRadius);
|
||||
LocalTerrainRadius = terrainElev + SeaLevelRadius;
|
||||
FDMExec->GetGroundCallback()->SetTerrainGeoCentRadius(LocalTerrainRadius);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
double FGPropagate::GetTerrainElevationASL(void) const
|
||||
double FGPropagate::GetTerrainElevation(void) const
|
||||
{
|
||||
return FDMExec->GetGroundCallback()->GetTerrainGeoCentRadius()-SeaLevelRadius;
|
||||
}
|
||||
|
@ -465,30 +466,30 @@ const FGMatrix33& FGPropagate::GetTec2i(void)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropagate::Seth(double tt)
|
||||
void FGPropagate::SetAltitudeASL(double altASL)
|
||||
{
|
||||
VState.vLocation.SetRadius( tt + SeaLevelRadius );
|
||||
VState.vLocation.SetRadius( altASL + SeaLevelRadius );
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
double FGPropagate::GetRunwayRadius(void) const
|
||||
double FGPropagate::GetLocalTerrainRadius(void) const
|
||||
{
|
||||
return RunwayRadius;
|
||||
return LocalTerrainRadius;
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
double FGPropagate::GetDistanceAGL(void) const
|
||||
{
|
||||
return VState.vLocation.GetRadius() - RunwayRadius;
|
||||
return VState.vLocation.GetRadius() - LocalTerrainRadius;
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGPropagate::SetDistanceAGL(double tt)
|
||||
{
|
||||
VState.vLocation.SetRadius( tt + RunwayRadius );
|
||||
VState.vLocation.SetRadius( tt + LocalTerrainRadius );
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -525,8 +526,8 @@ void FGPropagate::bind(void)
|
|||
PropertyManager->Tie("accelerations/vdot-ft_sec2", this, eV, (PMF)&FGPropagate::GetUVWdot);
|
||||
PropertyManager->Tie("accelerations/wdot-ft_sec2", this, eW, (PMF)&FGPropagate::GetUVWdot);
|
||||
|
||||
PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::Geth, &FGPropagate::Seth, true);
|
||||
PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::Gethmeters, &FGPropagate::Sethmeters, true);
|
||||
PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::GetAltitudeASL, &FGPropagate::SetAltitudeASL, true);
|
||||
PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::GetAltitudeASLmeters, &FGPropagate::SetAltitudeASLmeters, true);
|
||||
PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude);
|
||||
PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude);
|
||||
PropertyManager->Tie("position/lat-gc-deg", this, &FGPropagate::GetLatitudeDeg, &FGPropagate::SetLatitudeDeg);
|
||||
|
@ -537,10 +538,10 @@ void FGPropagate::bind(void)
|
|||
PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL);
|
||||
PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius);
|
||||
PropertyManager->Tie("position/terrain-elevation-asl-ft", this,
|
||||
&FGPropagate::GetTerrainElevationASL,
|
||||
&FGPropagate::SetTerrainElevationASL, false);
|
||||
&FGPropagate::GetTerrainElevation,
|
||||
&FGPropagate::SetTerrainElevation, false);
|
||||
|
||||
PropertyManager->Tie("metrics/runway-radius", this, &FGPropagate::GetRunwayRadius);
|
||||
PropertyManager->Tie("metrics/terrain-radius", this, &FGPropagate::GetLocalTerrainRadius);
|
||||
|
||||
PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
|
||||
PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
|
||||
|
|
|
@ -286,21 +286,19 @@ public:
|
|||
*/
|
||||
double GetInertialVelocityMagnitude(void) const { return vInertialVelocity.Magnitude(); }
|
||||
|
||||
/** Returns the current altitude.
|
||||
Returns the current altitude. Specifically, this function returns the
|
||||
difference between the distance to the center of the Earth, and sea level.
|
||||
/** Returns the current altitude above sea level.
|
||||
This function returns the altitude above sea level.
|
||||
units ft
|
||||
@return The current altitude above sea level in feet.
|
||||
*/
|
||||
double Geth(void) const { return VState.vLocation.GetRadius() - SeaLevelRadius; }
|
||||
double GetAltitudeASL(void) const { return VState.vLocation.GetRadius() - SeaLevelRadius; }
|
||||
|
||||
/** Returns the current altitude.
|
||||
Returns the curren altitude. Specifically, this function returns the
|
||||
difference between the distance to the center of the Earth, and sea level.
|
||||
/** Returns the current altitude above sea level.
|
||||
This function returns the altitude above sea level.
|
||||
units meters
|
||||
@return The current altitude above sea level in meters.
|
||||
*/
|
||||
double Gethmeters(void) const { return Geth()*fttom;}
|
||||
double GetAltitudeASLmeters(void) const { return GetAltitudeASL()*fttom;}
|
||||
|
||||
/** Retrieves a body frame angular velocity component relative to the ECEF frame.
|
||||
Retrieves a body frame angular velocity component. The angular velocity
|
||||
|
@ -385,16 +383,16 @@ public:
|
|||
*/
|
||||
double Gethdot(void) const { return -vVel(eDown); }
|
||||
|
||||
/** Returns the "constant" RunwayRadius.
|
||||
The RunwayRadius parameter is set by the calling application or set to
|
||||
sea level if JSBSim is running in standalone mode.
|
||||
/** Returns the "constant" LocalTerrainRadius.
|
||||
The LocalTerrainRadius parameter is set by the calling application or set to
|
||||
sea level + terrain elevation if JSBSim is running in standalone mode.
|
||||
units feet
|
||||
@return distance of the runway from the center of the earth.
|
||||
@return distance of the local terrain from the center of the earth.
|
||||
*/
|
||||
double GetRunwayRadius(void) const;
|
||||
double GetLocalTerrainRadius(void) const;
|
||||
|
||||
double GetSeaLevelRadius(void) const { return SeaLevelRadius; }
|
||||
double GetTerrainElevationASL(void) const;
|
||||
double GetTerrainElevation(void) const;
|
||||
double GetDistanceAGL(void) const;
|
||||
double GetRadius(void) const {
|
||||
if (VState.vLocation.GetRadius() == 0) return 1.0;
|
||||
|
@ -481,13 +479,13 @@ public:
|
|||
void SetLatitudeDeg(double lat) {SetLatitude(lat*degtorad);}
|
||||
void SetRadius(double r) { VState.vLocation.SetRadius(r); }
|
||||
void SetLocation(const FGLocation& l) { VState.vLocation = l; }
|
||||
void Seth(double tt);
|
||||
void Sethmeters(double tt) {Seth(tt/fttom);}
|
||||
void SetAltitudeASL(double altASL);
|
||||
void SetAltitudeASLmeters(double altASL) {SetAltitudeASL(altASL/fttom);}
|
||||
void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
|
||||
void SetTerrainElevationASL(double tt);
|
||||
void SetTerrainElevation(double tt);
|
||||
void SetDistanceAGL(double tt);
|
||||
void SetInitialState(const FGInitialCondition *);
|
||||
void RecomputeRunwayRadius(void);
|
||||
void RecomputeLocalTerrainRadius(void);
|
||||
|
||||
void CalculatePQRdot(void);
|
||||
void CalculateQuatdot(void);
|
||||
|
@ -521,7 +519,7 @@ private:
|
|||
FGMatrix33 Ti2b; // ECI to body frame rotation matrix
|
||||
FGMatrix33 Tb2i; // body to ECI frame rotation matrix
|
||||
|
||||
double RunwayRadius, SeaLevelRadius, VehicleRadius;
|
||||
double LocalTerrainRadius, SeaLevelRadius, VehicleRadius;
|
||||
double radInv;
|
||||
int integrator_rotational_rate;
|
||||
int integrator_translational_rate;
|
||||
|
|
|
@ -168,7 +168,7 @@ bool MSIS::Run(void)
|
|||
// get at-altitude values
|
||||
Calculate(Auxiliary->GetDayOfYear(),
|
||||
Auxiliary->GetSecondsInDay(),
|
||||
Propagate->Geth(),
|
||||
Propagate->GetAltitudeASL(),
|
||||
Propagate->GetLocation().GetLatitudeDeg(),
|
||||
Propagate->GetLocation().GetLongitudeDeg());
|
||||
intTemperature = output.t[1] * 1.8;
|
||||
|
|
|
@ -106,7 +106,7 @@ bool FGActuator::Run(void )
|
|||
Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
|
||||
|
||||
if (fail_zero) Input = 0;
|
||||
if (fail_hardover) Input = clipmax*fabs(Input)/Input;
|
||||
if (fail_hardover) Input = clipmax*sign(Input);
|
||||
|
||||
Output = Input; // Perfect actuator. At this point, if no failures are present
|
||||
// and no subsequent lag, limiting, etc. is done, the output
|
||||
|
|
|
@ -56,7 +56,7 @@ FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
|
|||
|
||||
// inputs are read from the base class constructor
|
||||
|
||||
bits = quantized = divisions = 0;
|
||||
bits = quantized = divisions = index = delay = 0;
|
||||
PreviousInput = PreviousOutput = 0.0;
|
||||
min = max = bias = noise_variance = lag = drift_rate = drift = span = 0.0;
|
||||
granularity = 0.0;
|
||||
|
@ -103,6 +103,21 @@ FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
|
|||
cerr << "Unknown noise type in sensor: " << Name << endl;
|
||||
cerr << " defaulting to PERCENT." << endl;
|
||||
}
|
||||
string distribution = element->FindElement("noise")->GetAttributeValue("distribution");
|
||||
if (distribution == "UNIFORM") {
|
||||
DistributionType = eUniform;
|
||||
} else if (distribution == "GAUSSIAN") {
|
||||
DistributionType = eGaussian;
|
||||
} else {
|
||||
DistributionType = eUniform;
|
||||
cerr << "Unknown random distribution type in sensor: " << Name << endl;
|
||||
cerr << " defaulting to UNIFORM." << endl;
|
||||
}
|
||||
}
|
||||
if ( element->FindElement("delay") ) {
|
||||
delay = (unsigned int)element->FindElementValueAsNumber("delay");
|
||||
output_array.resize(delay);
|
||||
for (unsigned int i=0; i<delay; i++) output_array[i] = 0.0;
|
||||
}
|
||||
|
||||
FGFCSComponent::bind();
|
||||
|
@ -133,16 +148,17 @@ bool FGSensor::Run(void )
|
|||
return true;
|
||||
}
|
||||
|
||||
if (lag != 0.0) Lag(); // models sensor lag
|
||||
if (lag != 0.0) Lag(); // models sensor lag and filter
|
||||
if (noise_variance != 0.0) Noise(); // models noise
|
||||
if (drift_rate != 0.0) Drift(); // models drift over time
|
||||
if (bias != 0.0) Bias(); // models a finite bias
|
||||
|
||||
if (delay != 0.0) Delay(); // models system signal transport latencies
|
||||
|
||||
if (fail_low) Output = -HUGE_VAL;
|
||||
if (fail_high) Output = HUGE_VAL;
|
||||
|
||||
if (bits != 0) Quantize(); // models quantization degradation
|
||||
// if (delay != 0.0) Delay(); // models system signal transport latencies
|
||||
|
||||
Clip(); // Is it right to clip a sensor?
|
||||
return true;
|
||||
|
@ -152,7 +168,13 @@ bool FGSensor::Run(void )
|
|||
|
||||
void FGSensor::Noise(void)
|
||||
{
|
||||
double random_value = ((double)rand()/(double)RAND_MAX) - 0.5;
|
||||
double random_value=0.0;
|
||||
|
||||
if (DistributionType == eUniform) {
|
||||
random_value = ((double)rand()/(double)RAND_MAX) - 0.5;
|
||||
} else {
|
||||
random_value = GaussianRandomNumber();
|
||||
}
|
||||
|
||||
switch( NoiseType ) {
|
||||
case ePercent:
|
||||
|
@ -195,7 +217,7 @@ void FGSensor::Quantize(void)
|
|||
|
||||
void FGSensor::Lag(void)
|
||||
{
|
||||
// "Output" on the right side of the "=" is the current frame input
|
||||
// "Output" on the right side of the "=" is the current input
|
||||
Output = ca * (Output + PreviousInput) + PreviousOutput * cb;
|
||||
|
||||
PreviousOutput = Output;
|
||||
|
@ -204,6 +226,16 @@ void FGSensor::Lag(void)
|
|||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGSensor::Delay(void)
|
||||
{
|
||||
output_array[index] = Output;
|
||||
if (index == delay-1) index = 0;
|
||||
else index++;
|
||||
Output = output_array[index];
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void FGSensor::bind(void)
|
||||
{
|
||||
string tmp = Name;
|
||||
|
@ -258,7 +290,8 @@ void FGSensor::Debug(int from)
|
|||
else
|
||||
cout << " INPUT: " << InputNodes[0]->getName() << endl;
|
||||
}
|
||||
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
|
||||
if (delay > 0) cout <<" Frame delay: " << delay
|
||||
<< " frames (" << delay*dt << " sec)" << endl;
|
||||
if (bits != 0) {
|
||||
if (quant_property.empty())
|
||||
cout << " Quantized output" << endl;
|
||||
|
@ -281,7 +314,13 @@ void FGSensor::Debug(int from)
|
|||
} else {
|
||||
cout << " Noise variance type is invalid" << endl;
|
||||
}
|
||||
if (DistributionType == eUniform) {
|
||||
cout << " Random noise is uniformly distributed." << endl;
|
||||
} else if (DistributionType == eGaussian) {
|
||||
cout << " Random noise is gaussian distributed." << endl;
|
||||
}
|
||||
}
|
||||
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
|
||||
}
|
||||
}
|
||||
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
|
||||
|
|
|
@ -39,6 +39,7 @@ INCLUDES
|
|||
|
||||
#include "FGFCSComponent.h"
|
||||
#include <input_output/FGXMLElement.h>
|
||||
#include <vector>
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
DEFINITIONS
|
||||
|
@ -52,6 +53,7 @@ FORWARD DECLARATIONS
|
|||
|
||||
namespace JSBSim {
|
||||
|
||||
using std::vector;
|
||||
class FGFCS;
|
||||
|
||||
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -74,6 +76,7 @@ Syntax:
|
|||
</quantization>
|
||||
<drift_rate> number </drift_rate>
|
||||
<bias> number </bias>
|
||||
<delay> number < /delay>
|
||||
</sensor>
|
||||
@endcode
|
||||
|
||||
|
@ -101,7 +104,8 @@ percentage variance. That is, if the number given is 0.05, the the variance is
|
|||
understood to be +/-0.05 percent maximum variance. So, the actual value for the sensor
|
||||
will be *anywhere* from 0.95 to 1.05 of the actual "perfect" value at any time -
|
||||
even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the delta
|
||||
time.
|
||||
time. The delay element can specify a frame delay. The integer number provided is
|
||||
the number of frames to delay the output signal.
|
||||
|
||||
@author Jon S. Berndt
|
||||
@version $Revision$
|
||||
|
@ -130,6 +134,7 @@ public:
|
|||
|
||||
protected:
|
||||
enum eNoiseType {ePercent=0, eAbsolute} NoiseType;
|
||||
enum eDistributionType {eUniform=0, eGaussian} DistributionType;
|
||||
double dt;
|
||||
double min, max;
|
||||
double span;
|
||||
|
@ -147,16 +152,20 @@ protected:
|
|||
int bits;
|
||||
int quantized;
|
||||
int divisions;
|
||||
int delay;
|
||||
int index;
|
||||
bool fail_low;
|
||||
bool fail_high;
|
||||
bool fail_stuck;
|
||||
string quant_property;
|
||||
vector <double> output_array;
|
||||
|
||||
void Noise(void);
|
||||
void Bias(void);
|
||||
void Drift(void);
|
||||
void Quantize(void);
|
||||
void Lag(void);
|
||||
void Delay(void);
|
||||
|
||||
void bind(void);
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ void FGPiston::doMAP(void)
|
|||
}
|
||||
}
|
||||
// Boost the manifold pressure.
|
||||
double boost_factor = BoostMul[BoostSpeed] * map_coefficient * RPM/RatedRPM[BoostSpeed];
|
||||
double boost_factor = BoostMul[BoostSpeed] * RPM/RatedRPM[BoostSpeed];
|
||||
if (boost_factor < 1.0) boost_factor = 1.0; // boost will never reduce the MAP
|
||||
MAP = TMAP * boost_factor;
|
||||
// Now clip the manifold pressure to BCV or Wastegate setting.
|
||||
|
@ -713,7 +713,7 @@ void FGPiston::doEGT(void)
|
|||
* Calculate the cylinder head temperature.
|
||||
*
|
||||
* Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel,
|
||||
* combustion_efficiency, RPM, MaxRPM
|
||||
* combustion_efficiency, RPM, MaxRPM, Displacement
|
||||
*
|
||||
* Outputs: CylinderHeadTemp_degK
|
||||
*/
|
||||
|
@ -813,7 +813,7 @@ string FGPiston::GetEngineLabels(string delimeter)
|
|||
buf << Name << " Power Available (engine " << EngineNumber << " in HP)" << delimeter
|
||||
<< Name << " HP (engine " << EngineNumber << ")" << delimeter
|
||||
<< Name << " equivalent ratio (engine " << EngineNumber << ")" << delimeter
|
||||
<< Name << " MAP (engine " << EngineNumber << ")" << delimeter
|
||||
<< Name << " MAP (engine " << EngineNumber << " in inHg)" << delimeter
|
||||
<< Thruster->GetThrusterLabels(EngineNumber, delimeter);
|
||||
|
||||
return buf.str();
|
||||
|
@ -826,7 +826,7 @@ string FGPiston::GetEngineValues(string delimeter)
|
|||
std::ostringstream buf;
|
||||
|
||||
buf << PowerAvailable << delimeter << HP << delimeter
|
||||
<< equivalence_ratio << delimeter << MAP << delimeter
|
||||
<< equivalence_ratio << delimeter << ManifoldPressure_inHg << delimeter
|
||||
<< Thruster->GetThrusterValues(EngineNumber, delimeter);
|
||||
|
||||
return buf.str();
|
||||
|
|
|
@ -92,6 +92,7 @@ FGTurbine::~FGTurbine()
|
|||
void FGTurbine::ResetToIC(void)
|
||||
{
|
||||
N1 = N2 = 0.0;
|
||||
N2norm = 0.0;
|
||||
correctedTSFC = TSFC;
|
||||
ThrottlePos = AugmentCmd = 0.0;
|
||||
InletPosition = NozzlePosition = 1.0;
|
||||
|
@ -186,7 +187,9 @@ double FGTurbine::Off(void)
|
|||
double FGTurbine::Run()
|
||||
{
|
||||
double idlethrust, milthrust, thrust;
|
||||
double N2norm; // 0.0 = idle N2, 1.0 = maximum N2
|
||||
double spoolup; // acceleration in pct/sec
|
||||
double sigma = Atmosphere->GetDensityRatio();
|
||||
double T = Atmosphere->GetTemperature();
|
||||
|
||||
idlethrust = MilThrust * IdleThrustLookup->GetValue();
|
||||
milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
|
||||
|
@ -194,8 +197,13 @@ double FGTurbine::Run()
|
|||
Running = true;
|
||||
Starter = false;
|
||||
|
||||
N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, delay, delay * 3.0);
|
||||
N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, delay, delay * 2.4);
|
||||
// adjust acceleration for N2 and atmospheric density
|
||||
double n = N2norm + 0.1;
|
||||
if (n > 1) n = 1;
|
||||
spoolup = delay / (1 + 3 * (1-n)*(1-n)*(1-n) + (1 - sigma));
|
||||
|
||||
N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, spoolup, spoolup * 3.0);
|
||||
N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, spoolup, spoolup * 2.4);
|
||||
N2norm = (N2 - IdleN2) / N2_factor;
|
||||
thrust = idlethrust + (milthrust * N2norm * N2norm);
|
||||
EGT_degC = TAT + 363.1 + ThrottlePos * 357.1;
|
||||
|
@ -203,7 +211,7 @@ double FGTurbine::Run()
|
|||
OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1);
|
||||
|
||||
if (!Augmentation) {
|
||||
correctedTSFC = TSFC * (0.84 + (1-N2norm)*(1-N2norm));
|
||||
correctedTSFC = TSFC * sqrt(T/389.7) * (0.84 + (1-N2norm)*(1-N2norm));
|
||||
FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 100000);
|
||||
if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
|
||||
NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
|
||||
|
@ -329,7 +337,7 @@ double FGTurbine::Seize(void)
|
|||
|
||||
double FGTurbine::Trim()
|
||||
{
|
||||
double idlethrust, milthrust, thrust, tdiff, N2norm;
|
||||
double idlethrust, milthrust, thrust, tdiff;
|
||||
idlethrust = MilThrust * IdleThrustLookup->GetValue();
|
||||
milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
|
||||
N2 = IdleN2 + ThrottlePos * N2_factor;
|
||||
|
@ -457,7 +465,7 @@ bool FGTurbine::Load(FGFDMExec* exec, Element *el)
|
|||
|
||||
// Pre-calculations and initializations
|
||||
|
||||
delay = 60.0 / (BypassRatio + 3.0);
|
||||
delay = 90.0 / (BypassRatio + 3.0);
|
||||
N1_factor = MaxN1 - IdleN1;
|
||||
N2_factor = MaxN2 - IdleN2;
|
||||
OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
|
||||
|
|
|
@ -224,6 +224,7 @@ private:
|
|||
double IdleN2; ///< Idle N2
|
||||
double N1; ///< N1
|
||||
double N2; ///< N2
|
||||
double N2norm; ///< N2 normalized (0=idle, 1=max)
|
||||
double MaxN1; ///< N1 at 100% throttle
|
||||
double MaxN2; ///< N2 at 100% throttle
|
||||
double IdleFF; ///< Idle Fuel Flow (lbm/hr)
|
||||
|
|
Loading…
Reference in a new issue