1
0
Fork 0

Upgrade to JSBSim 1.0-prerelease

This commit is contained in:
ehofman 2009-06-01 08:52:34 +00:00 committed by Tim Moore
parent 5917e80bf0
commit 4aff7b279d
23 changed files with 354 additions and 223 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
@ -296,6 +296,8 @@ void PutMessage(const string& text, double dVal);
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);

View file

@ -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() );

View file

@ -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,

View file

@ -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;

View file

@ -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 << ")";

View file

@ -36,6 +36,7 @@ HISTORY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <FGFDMExec.h>
#include "FGAerodynamics.h"
#include "FGPropagate.h"
#include "FGAircraft.h"

View file

@ -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);

View file

@ -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; }

View file

@ -36,6 +36,7 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGInertial.h"
#include <FGFDMExec.h>
#include "FGPropagate.h"
#include "FGState.h"
#include "FGMassBalance.h"

View file

@ -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;
}

View file

@ -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;

View file

@ -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));

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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();

View file

@ -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;

View file

@ -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)