1
0
Fork 0

Sync. with JSBSim CVS

This commit is contained in:
Erik Hofman 2010-09-19 11:16:29 +02:00
parent cf4d0fb0e3
commit 4b8fde057b
46 changed files with 729 additions and 385 deletions

View file

@ -71,7 +71,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.79 2010/07/25 13:52:20 jberndt Exp $";
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.80 2010/08/21 22:56:10 jberndt Exp $";
static const char *IdHdr = ID_FDMEXEC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -683,11 +683,21 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
<< fgdef << endl;
}
struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = "";
masterPCS.node = (FGPropertyManager*)Root;
// Late bind previously undefined FCS inputs.
try {
FCS->LateBind();
} catch (string prop) {
cerr << endl << fgred << " Could not late bind property " << prop
<< ". Aborting." << endl;
result = false;
}
BuildPropertyCatalog(&masterPCS);
if (result) {
struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = "";
masterPCS.node = (FGPropertyManager*)Root;
BuildPropertyCatalog(&masterPCS);
}
return result;
}

View file

@ -62,7 +62,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.40 2010/06/02 04:05:13 jberndt Exp $";
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.44 2010/09/18 22:48:12 jberndt Exp $";
static const char *IdHdr = ID_INITIALCONDITION;
//******************************************************************************
@ -966,10 +966,19 @@ bool FGInitialCondition::Load_v2(void)
bool result = true;
FGInertial* Inertial = fdmex->GetInertial();
FGPropagate* Propagate = fdmex->GetPropagate();
FGColumnVector3 vOmegaEarth = FGColumnVector3(0.0, 0.0, Inertial->omega());
if (document->FindElement("earth_position_angle")) {
double epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD");
Inertial->SetEarthPositionAngle(epa);
Propagate->GetVState()->vLocation.SetEarthPositionAngle(epa);
}
Propagate->SetSeaLevelRadius(GetSeaLevelRadiusFtIC());
if (document->FindElement("elevation")) {
SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT"));
Propagate->SetTerrainElevation(terrain_elevation);
}
// Initialize vehicle position
@ -983,25 +992,28 @@ bool FGInitialCondition::Load_v2(void)
vLoc = position->FindElementTripletConvertTo("FT");
string frame = position->GetAttributeValue("frame");
frame = to_lower(frame);
if (frame == "eci") {
// Need to transform vLoc to ECEF for storage and use in FGLocation.
if (frame == "eci") { // Need to transform vLoc to ECEF for storage and use in FGLocation.
vLoc = Propagate->GetTi2ec()*vLoc;
Propagate->SetLocation(vLoc);
} else if (frame == "ecef") {
// Move vLoc query until after lat/lon/alt query to eliminate spurious warning msgs.
double AltitudeASL = 0.0;
if (vLoc.Magnitude() == 0.0) {
Propagate->SetLatitudeDeg(position->FindElementValueAsNumberConvertTo("latitude", "DEG"));
Propagate->SetLongitudeDeg(position->FindElementValueAsNumberConvertTo("longitude", "DEG"));
if (position->FindElement("radius")) {
radius_to_vehicle = position->FindElementValueAsNumberConvertTo("radius", "FT");
SetAltitudeASLFtIC(radius_to_vehicle - sea_level_radius);
AltitudeASL = position->FindElementValueAsNumberConvertTo("radius", "FT") - sea_level_radius;
} else if (position->FindElement("altitudeAGL")) {
SetAltitudeAGLFtIC(position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
AltitudeASL = terrain_elevation + position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT");
} else if (position->FindElement("altitudeMSL")) {
SetAltitudeASLFtIC(position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
AltitudeASL = position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT");
} else {
cerr << endl << " No altitude or radius initial condition is given." << endl;
result = false;
}
Propagate->SetPosition(
position->FindElementValueAsNumberConvertTo("longitude", "RAD"),
position->FindElementValueAsNumberConvertTo("latitude", "RAD"),
AltitudeASL + GetSeaLevelRadiusFtIC());
} else {
Propagate->SetLocation(vLoc);
}
} else {
cerr << endl << " Neither ECI nor ECEF frame is specified for initial position." << endl;
@ -1038,11 +1050,11 @@ bool FGInitialCondition::Load_v2(void)
// ToDo: Do we need to deal with normalization of the quaternions here?
Element* orientation_el = document->FindElement("orientation");
FGQuaternion QuatI2Body;
if (orientation_el) {
string frame = orientation_el->GetAttributeValue("frame");
frame = to_lower(frame);
vOrient = orientation_el->FindElementTripletConvertTo("RAD");
FGQuaternion QuatI2Body;
if (frame == "eci") {
QuatI2Body = FGQuaternion(vOrient);
@ -1088,10 +1100,10 @@ bool FGInitialCondition::Load_v2(void)
result = false;
}
Propagate->SetInertialOrientation(QuatI2Body);
}
Propagate->SetInertialOrientation(QuatI2Body);
// Initialize vehicle velocity
// Allowable frames
// - ECI (Earth Centered Inertial)
@ -1103,23 +1115,23 @@ bool FGInitialCondition::Load_v2(void)
Element* velocity_el = document->FindElement("velocity");
FGColumnVector3 vInertialVelocity;
FGColumnVector3 vInitVelocity = FGColumnVector3(0.0, 0.0, 0.0);
FGColumnVector3 omega_cross_r = vOmegaEarth * Propagate->GetInertialPosition();
FGMatrix33 mTl2i = Propagate->GetTl2i();
FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e
FGMatrix33 mTb2i = Propagate->GetTb2i();
if (velocity_el) {
string frame = velocity_el->GetAttributeValue("frame");
frame = to_lower(frame);
FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo("FT/SEC");
FGColumnVector3 omega_cross_r = Inertial->omega() * Propagate->GetInertialPosition();
if (frame == "eci") {
vInertialVelocity = vInitVelocity;
} else if (frame == "ecef") {
FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e
vInertialVelocity = mTec2i * vInitVelocity + omega_cross_r;
} else if (frame == "local") {
FGMatrix33 mTl2i = Propagate->GetTl2i();
vInertialVelocity = mTl2i * vInitVelocity + omega_cross_r;
} else if (frame == "body") {
FGMatrix33 mTb2i = Propagate->GetTb2i();
vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r;
} else {
@ -1131,13 +1143,13 @@ bool FGInitialCondition::Load_v2(void)
} else {
FGMatrix33 mTb2i = Propagate->GetTb2i();
vInertialVelocity = mTb2i * vInitVelocity + (Inertial->omega() * Propagate->GetInertialPosition());
vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r;
}
Propagate->SetInertialVelocity(vInertialVelocity);
// Initialize vehicle body rates
// Allowable frames
// - ECI (Earth Centered Inertial)
// - ECEF (Earth Centered, Earth Fixed)
@ -1145,6 +1157,13 @@ bool FGInitialCondition::Load_v2(void)
FGColumnVector3 vInertialRate;
Element* attrate_el = document->FindElement("attitude_rate");
double radInv = 1.0/Propagate->GetRadius();
FGColumnVector3 vVel = Propagate->GetVel();
FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vVel(eEast),
-radInv*vVel(eNorth),
-radInv*vVel(eEast)*Propagate->GetLocation().GetTanLatitude() );
if (attrate_el) {
string frame = attrate_el->GetAttributeValue("frame");
@ -1154,11 +1173,9 @@ bool FGInitialCondition::Load_v2(void)
if (frame == "eci") {
vInertialRate = vAttRate;
} else if (frame == "ecef") {
// vInertialRate = vAttRate + Inertial->omega();
} else if (frame == "body") {
//Todo: determine local frame rate
FGMatrix33 mTb2l = Propagate->GetTb2l();
// vInertialRate = mTb2l*vAttRate + Inertial->omega();
vInertialRate = vAttRate + vOmegaEarth;
} else if (frame == "local") {
vInertialRate = vOmegaEarth + Propagate->GetTl2i() * vOmegaLocal + Propagate->GetTb2i() * vAttRate;
} else if (!frame.empty()) { // misspelling of frame
cerr << endl << fgred << " Attitude rate frame type: \"" << frame
@ -1170,21 +1187,10 @@ bool FGInitialCondition::Load_v2(void)
}
} else { // Body frame attitude rate assumed 0 relative to local.
/*
//Todo: determine local frame rate
FGMatrix33 mTi2l = Propagate->GetTi2l();
vVel = mTi2l * vInertialVelocity;
// Compute the local frame ECEF velocity
vVel = Tb2l * VState.vUVW;
FGColumnVector3 vOmegaLocal = FGColumnVector3(
radInv*vVel(eEast),
-radInv*vVel(eNorth),
-radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
*/
vInertialRate = vOmegaEarth + Propagate->GetTl2i() * vOmegaLocal;
}
Propagate->SetInertialRates(vInertialRate);
Propagate->InitializeDerivatives();
// Check to see if any engines are specified to be initialized in a running state
FGPropulsion* propulsion = fdmex->GetPropulsion();

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.4 2006/10/01 22:47:47 jberndt Exp $"
#define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.5 2010/09/07 18:36:29 andgi Exp $"
#define DEFAULT_TOLERANCE 0.001
@ -58,10 +58,10 @@ FORWARD DECLARATIONS
namespace JSBSim {
const string StateNames[10]= { "all","udot","vdot","wdot","qdot","pdot","rdot",
const string StateNames[] = { "all","udot","vdot","wdot","qdot","pdot","rdot",
"hmgt","nlf"
};
const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack",
const string ControlNames[] = { "Throttle","Sideslip","Angle of Attack",
"Elevator","Ailerons","Rudder",
"Altitude AGL", "Pitch Angle",
"Roll Angle", "Flight Path Angle",

View file

@ -42,7 +42,7 @@ FORWARD DECLARATIONS
namespace JSBSim {
static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.29 2010/03/18 13:18:31 jberndt Exp $";
static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.30 2010/09/04 14:15:15 jberndt Exp $";
static const char *IdHdr = ID_XMLELEMENT;
bool Element::converterIsInitialized = false;
@ -95,6 +95,9 @@ Element::Element(const string& nm)
// Angles
convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
// Angular rates
convert["RAD/SEC"]["DEG/SEC"] = 360.0/(2.0*3.1415926);
convert["DEG/SEC"]["RAD/SEC"] = 1.0/convert["RAD/SEC"]["DEG/SEC"];
// Spring force
convert["LBS/FT"]["N/M"] = 14.5939;
convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
@ -170,6 +173,9 @@ Element::Element(const string& nm)
// Angles
convert["DEG"]["DEG"] = 1.00;
convert["RAD"]["RAD"] = 1.00;
// Angular rates
convert["DEG/SEC"]["DEG/SEC"] = 1.00;
convert["RAD/SEC"]["RAD/SEC"] = 1.00;
// Spring force
convert["LBS/FT"]["LBS/FT"] = 1.00;
convert["N/M"]["N/M"] = 1.00;

View file

@ -40,12 +40,13 @@ INCLUDES
#include <string>
#include <vector>
#include <stdio.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.13 2010/07/07 11:59:48 jberndt Exp $"
#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.14 2010/08/21 17:13:47 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -69,6 +70,8 @@ CLASS DECLARATION
extern std::string& to_lower(std::string& str);
extern bool is_number(const std::string& str);
std::vector <std::string> split(std::string str, char d);
extern std::string to_string(int);
extern std::string replace(std::string str, const std::string& old, const std::string& newstr);
#else
#include <cctype>
@ -148,6 +151,24 @@ CLASS DECLARATION
return str_array;
}
string to_string(int i)
{
char buffer[32];
sprintf(buffer, "%d", i);
return string(buffer);
}
string replace(string str, const string& oldstr, const string& newstr)
{
int old_idx;
string temp;
old_idx = str.find(oldstr);
if (old_idx >= 0) {
temp = str.replace(old_idx, 1, newstr);
}
return temp;
}
#endif
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFunction.cpp,v 1.32 2010/03/18 13:21:24 jberndt Exp $";
static const char *IdSrc = "$Id: FGFunction.cpp,v 1.35 2010/08/28 12:41:56 jberndt Exp $";
static const char *IdHdr = ID_FUNCTION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -167,12 +167,19 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
// data types
if (operation == property_string || operation == p_string) {
property_name = element->GetDataLine();
FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
if (newNode == 0) {
cerr << "The property " << property_name << " is undefined." << endl;
abort();
} else {
if (property_name.find("#") != string::npos) {
if (is_number(Prefix)) {
property_name = replace(property_name,"#",Prefix);
}
}
FGPropertyManager* newNode = 0L;
if (PropertyManager->HasNode(property_name)) {
newNode = PropertyManager->GetNode(property_name);
Parameters.push_back(new FGPropertyValue( newNode ));
} else {
cerr << fgcyan << "The property " + property_name + " is initially undefined."
<< reset << endl;
Parameters.push_back(new FGPropertyValue( property_name ));
}
} else if (operation == value_string || operation == v_string) {
Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
@ -204,7 +211,7 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
operation == random_string ||
operation == avg_string )
{
Parameters.push_back(new FGFunction(PropertyManager, element));
Parameters.push_back(new FGFunction(PropertyManager, element, Prefix));
} else if (operation != description_string) {
cerr << "Bad operation " << operation << " detected in configuration file" << endl;
}
@ -241,10 +248,20 @@ double FGFunction::GetValue(void) const
{
unsigned int i;
double scratch;
double temp=0;
if (cached) return cachedValue;
double temp = Parameters[0]->GetValue();
try {
temp = Parameters[0]->GetValue();
} catch (string prop) {
if (PropertyManager->HasNode(prop)) {
((FGPropertyValue*)Parameters[0])->SetNode(PropertyManager->GetNode(prop));
temp = Parameters[0]->GetValue();
} else {
throw("Property " + prop + " was not defined anywhere.");
}
}
switch (Type) {
case eTopLevel:
@ -366,9 +383,21 @@ void FGFunction::bind(void)
if ( !Name.empty() ) {
string tmp;
if (Prefix.empty())
tmp = PropertyManager->mkPropertyName(Name, false); // Allow upper case
else
tmp = PropertyManager->mkPropertyName(Prefix + "/" + Name, false); // Allow upper case
tmp = PropertyManager->mkPropertyName(Name, false);
else {
if (is_number(Prefix)) {
if (Name.find("#") != string::npos) { // if "#" is found
Name = replace(Name,"#",Prefix);
tmp = PropertyManager->mkPropertyName(Name, false);
} else {
cerr << "Malformed function name with number: " << Prefix
<< " and property name: " << Name
<< " but no \"#\" sign for substitution." << endl;
}
} else {
tmp = PropertyManager->mkPropertyName(Prefix + "/" + Name, false);
}
}
PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
}

View file

@ -45,9 +45,10 @@ INCLUDES
namespace JSBSim {
static const char *IdSrc = "$Id: FGLocation.cpp,v 1.21 2010/07/02 01:48:12 jberndt Exp $";
static const char *IdSrc = "$Id: FGLocation.cpp,v 1.22 2010/09/18 22:47:17 jberndt Exp $";
static const char *IdHdr = ID_LOCATION;
using std::cerr;
using std::endl;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -103,10 +104,6 @@ FGLocation::FGLocation(double lon, double lat, double radius)
radius*cosLat*sinLon,
radius*sinLat );
mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
// initial_longitude = 0.0
ComputeDerived();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -182,7 +179,6 @@ void FGLocation::SetPosition(double lon, double lat, double radius)
mECLoc = FGColumnVector3( radius*cosLat*cosLon,
radius*cosLat*sinLon,
radius*sinLat );
ComputeDerived();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -202,7 +198,6 @@ void FGLocation::SetPositionGeodetic(double lon, double lat, double height)
mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon);
mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon);
mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -228,6 +223,7 @@ void FGLocation::SetEllipse(double semimajor, double semiminor)
const FGMatrix33& FGLocation::GetTec2i(void)
{
ComputeDerived();
return mTec2i;
}
@ -240,6 +236,7 @@ const FGMatrix33& FGLocation::GetTec2i(void)
const FGMatrix33& FGLocation::GetTi2ec(void)
{
ComputeDerived();
return mTi2ec;
}
@ -331,7 +328,8 @@ void FGLocation::ComputeDerivedUnconditional(void) const
if (q>0)
{
u = p/sqrt_q;
u2 = p2/q;
// u2 = p2/q;
u2 = u*u;
v = b2*u2/q;
P = 27.0*v*s/q;
Q0 = sqrt(P+1) + sqrt(P);
@ -340,7 +338,11 @@ void FGLocation::ComputeDerivedUnconditional(void) const
c = sqrt(u2 - 1 + 2.0*t);
w = (c - u)/2.0;
signz0 = mECLoc(eZ)>=0?1.0:-1.0;
z = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
if ((sqrt(t*t+v)-u*w-0.5*t-0.25) < 0.0) {
z = 0.0;
} else {
z = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
}
Ne = a*sqrt(1+eps2*z*z/b2);
mGeodLat = asin((eps2+1.0)*(z/Ne));
r0 = rxy;

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_LOCATION "$Id: FGLocation.h,v 1.23 2010/08/04 07:28:21 ehofman Exp $"
#define ID_LOCATION "$Id: FGLocation.h,v 1.25 2010/09/18 22:47:24 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -142,7 +142,7 @@ CLASS DOCUMENTATION
@see W. C. Durham "Aircraft Dynamics & Control", section 2.2
@author Mathias Froehlich
@version $Id: FGLocation.h,v 1.23 2010/08/04 07:28:21 ehofman Exp $
@version $Id: FGLocation.h,v 1.25 2010/09/18 22:47:24 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -259,7 +259,7 @@ public:
Inertial frame.
@param EPA Earth fixed frame (ECEF) rotation offset about the axis with
respect to the Inertial (ECI) frame in radians. */
void SetEarthPositionAngle(double EPA) {epa = EPA; mCacheValid = false; ComputeDerived();}
void SetEarthPositionAngle(double EPA) {epa = EPA; mCacheValid = false;}
/** Get the longitude.
@return the longitude in rad of the location represented with this
@ -304,7 +304,7 @@ public:
double GetGeodLatitudeDeg(void) const { ComputeDerived(); return radtodeg*mGeodLat; }
/** Gets the geodetic altitude in feet. */
double GetGeodAltitude(void) const { return GeodeticAltitude;}
double GetGeodAltitude(void) const {ComputeDerived(); return GeodeticAltitude;}
/** Get the sine of Latitude. */
double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); }
@ -349,9 +349,9 @@ public:
the earth centered frame to the inertial frame (ECEF to ECI). */
const FGMatrix33& GetTec2i(void);
const FGMatrix33& GetTi2l(void) const {return mTi2l;}
const FGMatrix33& GetTi2l(void) const {ComputeDerived(); return mTi2l;}
const FGMatrix33& GetTl2i(void) const {return mTl2i;}
const FGMatrix33& GetTl2i(void) const {ComputeDerived(); return mTl2i;}
/** Conversion from Local frame coordinates to a location in the
earth centered and fixed frame.
@ -450,6 +450,8 @@ public:
f = l.f;
initial_longitude = l.initial_longitude;
mGeodLat = l.mGeodLat;
GeodeticAltitude = l.GeodeticAltitude;
return *this;
}

View file

@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.11 2010/06/30 03:13:40 jberndt Exp $"
#define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.12 2010/08/21 17:13:47 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -111,7 +111,8 @@ public:
Create copy of the matrix given in the argument.
*/
FGMatrix33(const FGMatrix33& M) {
FGMatrix33(const FGMatrix33& M)
{
data[0] = M.data[0];
data[1] = M.data[1];
data[2] = M.data[2];
@ -122,7 +123,7 @@ public:
data[7] = M.data[7];
data[8] = M.data[8];
// Debug(0);
// Debug(0);
}
/** Initialization by given values.

View file

@ -32,7 +32,7 @@ INCLUDES
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.4 2009/08/30 03:51:28 jberndt Exp $";
static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.6 2010/08/24 10:30:14 jberndt Exp $";
static const char *IdHdr = ID_PROPERTYVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -45,9 +45,23 @@ FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode) : PropertyManager(
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyValue::FGPropertyValue(std::string propName) : PropertyManager(0L)
{
PropertyName = propName;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGPropertyValue::GetValue(void) const
{
return PropertyManager->getDoubleValue();
double val;
try {
val = PropertyManager->getDoubleValue();
} catch (...) {
throw(PropertyName);
}
return val;
}
}

View file

@ -41,7 +41,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.6 2009/10/02 10:30:09 jberndt Exp $"
#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.8 2010/08/24 10:30:14 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -66,12 +66,15 @@ class FGPropertyValue : public FGParameter
public:
FGPropertyValue(FGPropertyManager* propNode);
FGPropertyValue(std::string propName);
~FGPropertyValue() {};
double GetValue(void) const;
void SetNode(FGPropertyManager* node) {PropertyManager = node;}
private:
FGPropertyManager* PropertyManager;
std::string PropertyName;
};
} // namespace JSBSim

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTable.cpp,v 1.21 2010/04/07 03:08:37 jberndt Exp $";
static const char *IdSrc = "$Id: FGTable.cpp,v 1.23 2010/09/16 11:01:24 jberndt Exp $";
static const char *IdHdr = ID_TABLE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -68,6 +68,20 @@ FGTable::FGTable(int NRows) : nRows(NRows), nCols(1), PropertyManager(0)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols), PropertyManager(0)
{
Type = tt2D;
colCounter = 1;
rowCounter = 0;
nTables = 0;
Data = Allocate();
Debug(0);
lastRowIndex=lastColumnIndex=2;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGTable::FGTable(const FGTable& t) : PropertyManager(t.PropertyManager)
{
Type = t.Type;
@ -165,7 +179,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
node = PropertyManager->GetNode(property_string);
if (node == 0) {
throw("IndependenVar property, " + property_string + " in Table definition is not defined.");
throw("IndependentVar property, " + property_string + " in Table definition is not defined.");
}
lookup_axis = axisElement->GetAttributeValue("lookup");

View file

@ -47,7 +47,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TABLE "$Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $"
#define ID_TABLE "$Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
@endcode
@author Jon S. Berndt
@version $Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $
@version $Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -253,6 +253,7 @@ public:
/// The constructor for a table
FGTable (FGPropertyManager* propMan, Element* el);
FGTable (int );
FGTable (int, int);
double GetValue(void) const;
double GetValue(double key) const;
double GetValue(double rowKey, double colKey) const;

View file

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

View file

@ -52,7 +52,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.31 2009/11/28 14:30:11 andgi Exp $";
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.32 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_AERODYNAMICS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -356,7 +356,7 @@ bool FGAerodynamics::Load(Element *element)
axis_element = document->FindNextElement("axis");
}
FGModel::PostLoad(document); // Perform base class Post-Load
PostLoad(document, PropertyManager); // Perform base class Post-Load
return true;
}

View file

@ -68,7 +68,7 @@ DEFINITIONS
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.27 2010/07/27 23:18:19 jberndt Exp $";
static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.28 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_AIRCRAFT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -206,7 +206,7 @@ bool FGAircraft::Load(Element* el)
}
}
FGModel::PostLoad(el);
PostLoad(el, PropertyManager);
Debug(2);

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.35 2010/08/11 11:51:33 jberndt Exp $";
static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.38 2010/09/16 11:01:24 jberndt Exp $";
static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -100,6 +100,22 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
vGustNED.InitMatrix();
vTurbulenceNED.InitMatrix();
// Milspec turbulence model
windspeed_at_20ft = 0.;
probability_of_exceedence_index = 0;
POE_Table = new FGTable(7,12);
// this is Figure 7 from p. 49 of MIL-F-8785C
// rows: probability of exceedance curve index, cols: altitude in ft
*POE_Table
<< 500.0 << 1750.0 << 3750.0 << 7500.0 << 15000.0 << 25000.0 << 35000.0 << 45000.0 << 55000.0 << 65000.0 << 75000.0 << 80000.0
<< 1 << 3.2 << 2.2 << 1.5 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0
<< 2 << 4.2 << 3.6 << 3.3 << 1.6 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0
<< 3 << 6.6 << 6.9 << 7.4 << 6.7 << 4.6 << 2.7 << 0.4 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0
<< 4 << 8.6 << 9.6 << 10.6 << 10.1 << 8.0 << 6.6 << 5.0 << 4.2 << 2.7 << 0.0 << 0.0 << 0.0
<< 5 << 11.8 << 13.0 << 16.0 << 15.1 << 11.6 << 9.7 << 8.1 << 8.2 << 7.9 << 4.9 << 3.2 << 2.1
<< 6 << 15.6 << 17.6 << 23.0 << 23.6 << 22.1 << 20.0 << 16.0 << 15.1 << 12.1 << 7.9 << 6.2 << 5.1
<< 7 << 18.7 << 21.5 << 28.4 << 30.2 << 30.7 << 31.0 << 25.2 << 23.1 << 17.5 << 10.7 << 8.4 << 7.2;
bind();
Debug(0);
}
@ -279,7 +295,7 @@ void FGAtmosphere::CalculateDerived(void)
T_dev = (*temperature) - GetTemperature(h);
if (T_dev == 0.0) density_altitude = h;
else density_altitude = 518.4/0.00357 * (1.0 - pow(GetDensityRatio(),0.235));
else density_altitude = 518.67/0.00356616 * (1.0 - pow(GetDensityRatio(),0.235));
if (turbType != ttNone) Turbulence();
@ -347,6 +363,9 @@ static inline double square_signed (double value)
return value * value;
}
/// simply square a value
static inline double sqr(double x) { return x*x; }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// psi is the angle that the wind is blowing *towards*
@ -549,6 +568,134 @@ void FGAtmosphere::Turbulence(void)
spike = spike * 0.9;
break;
}
case ttMilspec:
case ttTustin: {
// an index of zero means turbulence is disabled
if (probability_of_exceedence_index == 0) {
vTurbulenceNED(1) = vTurbulenceNED(2) = vTurbulenceNED(3) = 0.0;
vTurbPQR(1) = vTurbPQR(2) = vTurbPQR(3) = 0.0;
return;
}
// Turbulence model according to MIL-F-8785C (Flying Qualities of Piloted Aircraft)
double
h = Propagate->GetDistanceAGL(),
V = Auxiliary->GetVt(), // true airspeed in ft/s
b_w = Aircraft->GetWingSpan(),
L_u, L_w, sig_u, sig_w;
// clip height functions at 10 ft
if (h <= 10.) h = 10;
// Scale lengths L and amplitudes sigma as function of height
if (h <= 1000) {
L_u = h/pow(0.177 + 0.000823*h, 1.2); // MIL-F-8785c, Fig. 10, p. 55
L_w = h;
sig_w = 0.1*windspeed_at_20ft;
sig_u = sig_w/pow(0.177 + 0.000823*h, 0.4); // MIL-F-8785c, Fig. 11, p. 56
} else if (h <= 2000) {
// linear interpolation between low altitude and high altitude models
L_u = L_w = 1000 + (h-1000.)/1000.*750.;
sig_u = sig_w = 0.1*windspeed_at_20ft
+ (h-1000.)/1000.*(POE_Table->GetValue(probability_of_exceedence_index, h) - 0.1*windspeed_at_20ft);
} else {
L_u = L_w = 1750.; // MIL-F-8785c, Sec. 3.7.2.1, p. 48
sig_u = sig_w = POE_Table->GetValue(probability_of_exceedence_index, h);
}
// keep values from last timesteps
// TODO maybe use deque?
static double
xi_u_km1 = 0, nu_u_km1 = 0,
xi_v_km1 = 0, xi_v_km2 = 0, nu_v_km1 = 0, nu_v_km2 = 0,
xi_w_km1 = 0, xi_w_km2 = 0, nu_w_km1 = 0, nu_w_km2 = 0,
xi_p_km1 = 0, nu_p_km1 = 0,
xi_q_km1 = 0, xi_r_km1 = 0;
double
T_V = DeltaT, // for compatibility of nomenclature
sig_p = 1.9/sqrt(L_w*b_w)*sig_w, // Yeager1998, eq. (8)
sig_q = sqrt(M_PI/2/L_w/b_w), // eq. (14)
sig_r = sqrt(2*M_PI/3/L_w/b_w), // eq. (17)
L_p = sqrt(L_w*b_w)/2.6, // eq. (10)
tau_u = L_u/V, // eq. (6)
tau_w = L_w/V, // eq. (3)
tau_p = L_p/V, // eq. (9)
tau_q = 4*b_w/M_PI/V, // eq. (13)
tau_r =3*b_w/M_PI/V, // eq. (17)
nu_u = GaussianRandomNumber(),
nu_v = GaussianRandomNumber(),
nu_w = GaussianRandomNumber(),
nu_p = GaussianRandomNumber(),
xi_u, xi_v, xi_w, xi_p, xi_q, xi_r;
// values of turbulence NED velocities
if (turbType == ttTustin) {
// the following is the Tustin formulation of Yeager's report
double
omega_w = V/L_w, // hidden in nomenclature p. 3
omega_v = V/L_u, // this is defined nowhere
C_BL = 1/tau_u/tan(T_V/2/tau_u), // eq. (19)
C_BLp = 1/tau_p/tan(T_V/2/tau_p), // eq. (22)
C_BLq = 1/tau_q/tan(T_V/2/tau_q), // eq. (24)
C_BLr = 1/tau_r/tan(T_V/2/tau_r); // eq. (26)
xi_u = -(1 - C_BL*tau_u)/(1 + C_BL*tau_u)*xi_u_km1
+ sig_u*sqrt(2*tau_u/T_V)/(1 + C_BL*tau_u)*(nu_u + nu_u_km1); // eq. (18)
xi_v = -2*(sqr(omega_v) - sqr(C_BL))/sqr(omega_v + C_BL)*xi_v_km1
- sqr(omega_v - C_BL)/sqr(omega_v + C_BL) * xi_v_km2
+ sig_u*sqrt(3*omega_v/T_V)/sqr(omega_v + C_BL)*(
(C_BL + omega_v/sqrt(3.))*nu_v
+ 2/sqrt(3.)*omega_v*nu_v_km1
+ (omega_v/sqrt(3.) - C_BL)*nu_v_km2); // eq. (20) for v
xi_w = -2*(sqr(omega_w) - sqr(C_BL))/sqr(omega_w + C_BL)*xi_w_km1
- sqr(omega_w - C_BL)/sqr(omega_w + C_BL) * xi_w_km2
+ sig_w*sqrt(3*omega_w/T_V)/sqr(omega_w + C_BL)*(
(C_BL + omega_w/sqrt(3.))*nu_w
+ 2/sqrt(3.)*omega_w*nu_w_km1
+ (omega_w/sqrt(3.) - C_BL)*nu_w_km2); // eq. (20) for w
xi_p = -(1 - C_BLp*tau_p)/(1 + C_BLp*tau_p)*xi_p_km1
+ sig_p*sqrt(2*tau_p/T_V)/(1 + C_BLp*tau_p) * (nu_p + nu_p_km1); // eq. (21)
xi_q = -(1 - 4*b_w*C_BLq/M_PI/V)/(1 + 4*b_w*C_BLq/M_PI/V) * xi_q_km1
+ C_BLq/V/(1 + 4*b_w*C_BLq/M_PI/V) * (xi_w - xi_w_km1); // eq. (23)
xi_r = - (1 - 3*b_w*C_BLr/M_PI/V)/(1 + 3*b_w*C_BLr/M_PI/V) * xi_r_km1
+ C_BLr/V/(1 + 3*b_w*C_BLr/M_PI/V) * (xi_v - xi_v_km1); // eq. (25)
} else if (turbType == ttMilspec) {
// the following is the MIL-STD-1797A formulation
// as cited in Yeager's report
xi_u = (1 - T_V/tau_u) *xi_u_km1 + sig_u*sqrt(2*T_V/tau_u)*nu_u; // eq. (30)
xi_v = (1 - 2*T_V/tau_u)*xi_v_km1 + sig_u*sqrt(4*T_V/tau_u)*nu_v; // eq. (31)
xi_w = (1 - 2*T_V/tau_w)*xi_w_km1 + sig_w*sqrt(4*T_V/tau_w)*nu_w; // eq. (32)
xi_p = (1 - T_V/tau_p) *xi_p_km1 + sig_p*sqrt(2*T_V/tau_p)*nu_p; // eq. (33)
xi_q = (1 - T_V/tau_q) *xi_q_km1 + M_PI/4/b_w*(xi_w - xi_w_km1); // eq. (34)
xi_r = (1 - T_V/tau_r) *xi_r_km1 + M_PI/3/b_w*(xi_v - xi_v_km1); // eq. (35)
}
// rotate by wind azimuth and assign the velocities
double cospsi = cos(psiw), sinpsi = sin(psiw);
vTurbulenceNED(1) = cospsi*xi_u + sinpsi*xi_v;
vTurbulenceNED(2) = -sinpsi*xi_u + cospsi*xi_v;
vTurbulenceNED(3) = xi_w;
vTurbPQR(1) = cospsi*xi_p + sinpsi*xi_q;
vTurbPQR(2) = -sinpsi*xi_p + cospsi*xi_q;
vTurbPQR(3) = xi_r;
// vTurbPQR is in the body fixed frame, not NED
vTurbPQR = Propagate->GetTl2b()*vTurbPQR;
// hand on the values for the next timestep
xi_u_km1 = xi_u; nu_u_km1 = nu_u;
xi_v_km2 = xi_v_km1; xi_v_km1 = xi_v; nu_v_km2 = nu_v_km1; nu_v_km1 = nu_v;
xi_w_km2 = xi_w_km1; xi_w_km1 = xi_w; nu_w_km2 = nu_w_km1; nu_w_km1 = nu_w;
xi_p_km1 = xi_p; nu_p_km1 = nu_p;
xi_q_km1 = xi_q;
xi_r_km1 = xi_r;
}
default:
break;
}
@ -634,6 +781,14 @@ void FGAtmosphere::bind(void)
PropertyManager->Tie("atmosphere/turb-gain", this, &FGAtmosphere::GetTurbGain, &FGAtmosphere::SetTurbGain);
PropertyManager->Tie("atmosphere/turb-rhythmicity", this, &FGAtmosphere::GetRhythmicity,
&FGAtmosphere::SetRhythmicity);
PropertyManager->Tie("atmosphere/turbulence/milspec/windspeed_at_20ft_AGL-fps",
this, &FGAtmosphere::GetWindspeed20ft,
&FGAtmosphere::SetWindspeed20ft);
PropertyManager->Tie("atmosphere/turbulence/milspec/severity",
this, &FGAtmosphere::GetProbabilityOfExceedence,
&FGAtmosphere::SetProbabilityOfExceedence);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -44,12 +44,13 @@ INCLUDES
#include "FGModel.h"
#include "math/FGColumnVector3.h"
#include "math/FGTable.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $"
#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.23 2010/09/16 11:01:24 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -63,9 +64,60 @@ CLASS DOCUMENTATION
/** Models the 1976 Standard Atmosphere.
@author Tony Peden, Jon Berndt
@version $Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $
@version $Id: FGAtmosphere.h,v 1.23 2010/09/16 11:01:24 jberndt Exp $
@see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
1989, ISBN 0-07-001641-0
Additionally, various turbulence models are available. They are specified
via the property <tt>atmosphere/turb-type</tt>. The following models are
available:
- 0: ttNone (turbulence disabled)
- 1: ttStandard
- 2: ttBerndt
- 3: ttCulp
- 4: ttMilspec (Dryden spectrum)
- 5: ttTustin (Dryden spectrum)
The Milspec and Tustin models are described in the Yeager report cited below.
They both use a Dryden spectrum model whose parameters (scale lengths and intensities)
are modelled according to MIL-F-8785C. Parameters are modelled differently
for altitudes below 1000ft and above 2000ft, for altitudes in between they
are interpolated linearly.
The two models differ in the implementation of the transfer functions
described in the milspec.
To use one of these two models, set <tt>atmosphere/turb-type</tt> to 4 resp. 5,
and specify values for <tt>atmosphere/turbulence/milspec/windspeed_at_20ft_AGL-fps<tt>
and <tt>atmosphere/turbulence/milspec/severity<tt> (the latter corresponds to
the probability of exceedence curves from Fig.&nbsp;7 of the milspec, allowable
range is 0 (disabled) to 7). <tt>atmosphere/psiw-rad</tt> is respected as well;
note that you have to specify a positive wind magnitude to prevent psiw from
being reset to zero.
Reference values (cf. figures 7 and 9 from the milspec):
<table>
<tr><td><b>Intensity</b></td>
<td><b><tt>windspeed_at_20ft_AGL-fps</tt></b></td>
<td><b><tt>severity</tt></b></td></tr>
<tr><td>light</td>
<td>25 (15 knots)</td>
<td>3</td></tr>
<tr><td>moderate</td>
<td>50 (30 knots)</td>
<td>4</td></tr>
<tr><td>severe</td>
<td>75 (45 knots)</td>
<td>6</td></tr>
</table>
@see Yeager, Jessie C.: "Implementation and Testing of Turbulence Models for
the F18-HARV" (<a
href="http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19980028448_1998081596.pdf">
pdf</a>), NASA CR-1998-206937, 1998
@see MIL-F-8785C: Military Specification: Flying Qualities of Piloted Aircraft
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -83,7 +135,7 @@ public:
@return false if no error */
bool Run(void);
bool InitModel(void);
enum tType {ttNone, ttStandard, ttBerndt, ttCulp} turbType;
enum tType {ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin} turbType;
/// Returns the temperature in degrees Rankine.
double GetTemperature(void) const {return *temperature;}
@ -209,7 +261,7 @@ public:
/// Retrieves the gust components in NED frame.
FGColumnVector3& GetGustNED(void) {return vGustNED;}
/** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp */
/** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin */
void SetTurbType(tType tt) {turbType = tt;}
tType GetTurbType() const {return turbType;}
@ -227,6 +279,13 @@ public:
FGColumnVector3& GetTurbDirection(void) {return vDirection;}
FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;}
void SetWindspeed20ft(double ws) { windspeed_at_20ft = ws;}
double GetWindspeed20ft() const { return windspeed_at_20ft;}
/// allowable range: 0-7, 3=light, 4=moderate, 6=severe turbulence
void SetProbabilityOfExceedence( int idx) {probability_of_exceedence_index = idx;}
int GetProbabilityOfExceedence() const { return probability_of_exceedence_index;}
protected:
double rho;
@ -261,6 +320,11 @@ protected:
FGColumnVector3 vBodyTurbGrad;
FGColumnVector3 vTurbPQR;
// Dryden turbulence model
double windspeed_at_20ft; ///< in ft/s
int probability_of_exceedence_index; ///< this is bound as the severity property
FGTable *POE_Table; ///< probability of exceedence table
double psiw;
FGColumnVector3 vTotalWindNED;
FGColumnVector3 vWindNED;

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.12 2010/05/07 18:59:55 andgi Exp $";
static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.13 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_BUOYANTFORCES;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -137,7 +137,7 @@ bool FGBuoyantForces::Load(Element *element)
gas_cell_element = document->FindNextElement("gas_cell");
}
FGModel::PostLoad(element);
PostLoad(element, PropertyManager);
if (!NoneDefined) {
bind();

View file

@ -53,7 +53,7 @@ DEFINITIONS
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.8 2009/11/12 13:08:11 jberndt Exp $";
static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.9 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_EXTERNALREACTIONS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -85,7 +85,7 @@ bool FGExternalReactions::Load(Element* el)
force_element = el->FindNextElement("force");
}
FGModel::PostLoad(el);
PostLoad(el, PropertyManager);
return true;
}

View file

@ -63,7 +63,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.69 2010/08/10 12:39:07 jberndt Exp $";
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.70 2010/08/21 22:56:11 jberndt Exp $";
static const char *IdHdr = ID_FCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -183,6 +183,17 @@ bool FGFCS::InitModel(void)
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCS::LateBind(void)
{
int i;
for (i=0; i<Systems.size(); i++) Systems[i]->LateBind();
for (i=0; i<APComponents.size(); i++) APComponents[i]->LateBind();
for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->LateBind();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Notes: In this logic the default engine commands are set. This is simply a
// sort of safe-mode method in case the user has not defined control laws for

View file

@ -51,7 +51,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCS "$Id: FGFCS.h,v 1.28 2010/01/18 13:12:25 jberndt Exp $"
#define ID_FCS "$Id: FGFCS.h,v 1.30 2010/09/05 17:31:40 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -168,7 +168,7 @@ CLASS DOCUMENTATION
@property gear/tailhook-pos-norm
@author Jon S. Berndt
@version $Revision: 1.28 $
@version $Revision: 1.30 $
@see FGActuator
@see FGDeadBand
@see FGFCSFunction
@ -278,8 +278,6 @@ public:
double GetDaLPos( int form = ofRad )
const { return DaLPos[form]; }
/// @name Aerosurface position retrieval
//@{
/** Gets the right aileron position.
@return aileron position in radians */
double GetDaRPos( int form = ofRad )
@ -547,6 +545,8 @@ public:
FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
void LateBind(void);
private:
double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd;
double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms];

View file

@ -46,7 +46,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.29 2010/07/30 11:50:01 jberndt Exp $";
static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.30 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_GROUNDREACTIONS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -150,7 +150,7 @@ bool FGGroundReactions::Run(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGGroundReactions::GetWOW(void)
bool FGGroundReactions::GetWOW(void) const
{
bool result = false;
for (unsigned int i=0; i<lGear.size(); i++) {
@ -195,7 +195,7 @@ bool FGGroundReactions::Load(Element* el)
for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();
FGModel::PostLoad(el);
PostLoad(el, PropertyManager);
return true;
}
@ -276,6 +276,7 @@ void FGGroundReactions::bind(void)
{
typedef double (FGGroundReactions::*PMF)(int) const;
PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits);
PropertyManager->Tie("gear/wow", this, &FGGroundReactions::GetWOW);
PropertyManager->Tie("moments/l-gear-lbsft", this, eL, (PMF)&FGGroundReactions::GetMoments);
PropertyManager->Tie("moments/m-gear-lbsft", this, eM, (PMF)&FGGroundReactions::GetMoments);
PropertyManager->Tie("moments/n-gear-lbsft", this, eN, (PMF)&FGGroundReactions::GetMoments);

View file

@ -45,7 +45,7 @@ INCLUDES
#include "math/FGColumnVector3.h"
#include "input_output/FGXMLElement.h"
#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.17 2010/07/30 11:50:01 jberndt Exp $"
#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.18 2010/09/07 00:40:03 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -106,7 +106,7 @@ public:
double GetMoments(int idx) const {return vMoments(idx);}
string GetGroundReactionStrings(string delimeter);
string GetGroundReactionValues(string delimeter);
bool GetWOW(void);
bool GetWOW(void) const;
void UpdateForcesAndMoments(void);
int GetNumGearUnits(void) const { return (int)lGear.size(); }

View file

@ -51,7 +51,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.32 2010/08/12 04:07:11 jberndt Exp $";
static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.33 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_MASSBALANCE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -156,7 +156,7 @@ bool FGMassBalance::Load(Element* el)
Mass = lbtoslug*Weight;
FGModel::PostLoad(el);
PostLoad(el, PropertyManager);
Debug(2);
return true;

View file

@ -57,7 +57,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGModel.cpp,v 1.14 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdSrc = "$Id: FGModel.cpp,v 1.15 2010/09/07 00:19:38 jberndt Exp $";
static const char *IdHdr = ID_MODEL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -71,7 +71,6 @@ CLASS IMPLEMENTATION
FGModel::FGModel(FGFDMExec* fdmex)
{
FDMExec = fdmex;
NextModel = 0L;
Atmosphere = 0;
FCS = 0;
@ -100,12 +99,6 @@ FGModel::FGModel(FGFDMExec* fdmex)
FGModel::~FGModel()
{
for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
interface_properties.clear();
for (unsigned int i=0; i<PreFunctions.size(); i++) delete PreFunctions[i];
for (unsigned int i=0; i<PostFunctions.size(); i++) delete PostFunctions[i];
if (debug_lvl & 2) cout << "Destroyed: FGModel" << endl;
}
@ -142,93 +135,6 @@ bool FGModel::InitModel(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGModel::Load(Element* el)
{
// Interface properties are all stored in the interface properties array.
string interface_property_string = "";
Element *property_element = el->FindElement("property");
if (property_element && debug_lvl > 0) cout << endl << " Declared properties"
<< endl << endl;
while (property_element) {
interface_property_string = property_element->GetDataLine();
if (PropertyManager->HasNode(interface_property_string)) {
cerr << " Property " << interface_property_string
<< " is already defined." << endl;
} else {
double value=0.0;
if ( ! property_element->GetAttributeValue("value").empty())
value = property_element->GetAttributeValueAsNumber("value");
interface_properties.push_back(new double(value));
PropertyManager->Tie(interface_property_string, interface_properties.back());
if (debug_lvl > 0)
cout << " " << interface_property_string << " (initial value: "
<< value << ")" << endl << endl;
}
property_element = el->FindNextElement("property");
}
// End of interface property loading logic
// Load model pre-functions, if any
Element *function = el->FindElement("function");
while (function) {
if (function->GetAttributeValue("type") == "pre") {
PreFunctions.push_back(new FGFunction(PropertyManager, function));
} else if (function->GetAttributeValue("type").empty()) { // Assume pre-function
string funcname = function->GetAttributeValue("name");
PreFunctions.push_back(new FGFunction(PropertyManager, function));
}
function = el->FindNextElement("function");
}
return true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGModel::PostLoad(Element* el)
{
// Load model post-functions, if any
Element *function = el->FindElement("function");
while (function) {
if (function->GetAttributeValue("type") == "post") {
PostFunctions.push_back(new FGFunction(PropertyManager, function));
}
function = el->FindNextElement("function");
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Tell the Functions to cache values, so when the function values
// are being used in the model, the functions do not get
// calculated each time, but instead use the values that have already
// been calculated for this frame.
void FGModel::RunPreFunctions(void)
{
vector <FGFunction*>::iterator it;
for (it = PreFunctions.begin(); it != PreFunctions.end(); it++)
(*it)->GetValue();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Tell the Functions to cache values, so when the function values
// are being used in the model, the functions do not get
// calculated each time, but instead use the values that have already
// been calculated for this frame.
void FGModel::RunPostFunctions(void)
{
vector <FGFunction*>::iterator it;
for (it = PostFunctions.begin(); it != PostFunctions.end(); it++)
(*it)->GetValue();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGModel::Run()
{
if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;

View file

@ -38,8 +38,8 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include "math/FGFunction.h"
#include "math/FGModelFunctions.h"
#include <string>
#include <vector>
@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_MODEL "$Id: FGModel.h,v 1.14 2009/11/12 13:08:11 jberndt Exp $"
#define ID_MODEL "$Id: FGModel.h,v 1.15 2010/09/07 00:19:46 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -85,7 +85,7 @@ CLASS DOCUMENTATION
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGModel : public FGJSBBase
class FGModel : public FGModelFunctions
{
public:
@ -94,7 +94,6 @@ public:
/// Destructor
~FGModel();
FGModel* NextModel;
std::string Name;
/** Runs the model; called by the Executive
@ -112,15 +111,10 @@ protected:
int exe_ctr;
int rate;
void RunPreFunctions(void);
void RunPostFunctions(void);
/** Loads this model.
@param el a pointer to the element
@return true if model is successfully loaded*/
virtual bool Load(Element* el);
void PostLoad(Element* el);
virtual bool Load(Element* el) {return FGModelFunctions::Load(el, PropertyManager);}
virtual void Debug(int from);
@ -139,10 +133,6 @@ protected:
FGPropagate* Propagate;
FGAuxiliary* Auxiliary;
FGPropertyManager* PropertyManager;
std::vector <FGFunction*> PreFunctions;
std::vector <FGFunction*> PostFunctions;
std::vector <double*> interface_properties;
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -71,7 +71,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.60 2010/08/12 19:11:22 andgi Exp $";
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.65 2010/09/18 22:48:12 jberndt Exp $";
static const char *IdHdr = ID_PROPAGATE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -82,7 +82,7 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
{
Debug(0);
Name = "FGPropagate";
gravType = gtWGS84;
gravType = gtStandard;
vPQRdot.InitMatrix();
vQtrndot = FGQuaternion(0,0,0);
@ -95,7 +95,7 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
integrator_translational_position = eTrapezoidal;
VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqQtrndot.resize(4, FGQuaternion(0.0,0.0,0.0));
@ -129,7 +129,7 @@ bool FGPropagate::InitModel(void)
vInertialVelocity.InitMatrix();
VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
@ -148,9 +148,6 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC());
SetTerrainElevation(FGIC->GetTerrainElevationFtIC());
VehicleRadius = GetRadius();
radInv = 1.0/VehicleRadius;
// Initialize the State Vector elements and the transformation matrices
// Set the position lat/lon/radius
@ -162,12 +159,10 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
Ti2ec = GetTi2ec(); // ECI to ECEF transform
Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
Tl2ec = GetTl2ec(); // local to ECEF transform
Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
Ti2l = GetTi2l();
Tl2i = Ti2l.Transposed();
VState.vInertialPosition = Tec2i * VState.vLocation;
UpdateLocationMatrices();
// Set the orientation from the euler angles (is normalized within the
// constructor). The Euler angles represent the orientation of the body
@ -177,26 +172,22 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
FGIC->GetPsiRadIC() );
VState.qAttitudeECI = Ti2l.GetQuaternion()*VState.qAttitudeLocal;
Ti2b = GetTi2b(); // ECI to body frame transform
Tb2i = Ti2b.Transposed(); // body to ECI frame transform
Tl2b = VState.qAttitudeLocal; // local to body frame transform
Tb2l = Tl2b.Transposed(); // body to local frame transform
Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
UpdateBodyMatrices();
// Set the velocities in the instantaneus body frame
VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(),
FGIC->GetVBodyFpsIC(),
FGIC->GetWBodyFpsIC() );
VState.vInertialPosition = Tec2i * VState.vLocation;
// Compute the local frame ECEF velocity
vVel = Tb2l * VState.vUVW;
// Recompute the LocalTerrainRadius.
RecomputeLocalTerrainRadius();
VehicleRadius = GetRadius();
double radInv = 1.0/VehicleRadius;
// Refer to Stevens and Lewis, 1.5-14a, pg. 49.
// This is the rotation rate of the "Local" frame, expressed in the local frame.
@ -215,26 +206,7 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
// Make an initial run and set past values
CalculatePQRdot(); // Angular rate derivative
CalculateUVWdot(); // Translational rate derivative
ResolveFrictionForces(0.); // Update rate derivatives with friction forces
CalculateQuatdot(); // Angular orientation derivative
CalculateInertialVelocity(); // Translational position derivative
// Initialize past values deques
VState.dqPQRdot.clear();
VState.dqUVWdot.clear();
VState.dqInertialVelocity.clear();
VState.dqQtrndot.clear();
for (int i=0; i<4; i++) {
VState.dqPQRdot.push_front(vPQRdot);
VState.dqUVWdot.push_front(vUVWdot);
VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
VState.dqQtrndot.push_front(vQtrndot);
}
// Recompute the LocalTerrainRadius.
RecomputeLocalTerrainRadius();
InitializeDerivatives();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -271,42 +243,42 @@ bool FGPropagate::Run(void)
CalculateUVWdot(); // Translational rate derivative
ResolveFrictionForces(dt); // Update rate derivatives with friction forces
CalculateQuatdot(); // Angular orientation derivative
CalculateInertialVelocity(); // Translational position derivative
CalculateUVW(); // Translational position derivative (velocities are integrated in the inertial frame)
// Propagate rotational / translational velocity, angular /translational position, respectively.
Integrate(VState.vPQRi, vPQRdot, VState.dqPQRdot, dt, integrator_rotational_rate);
Integrate(VState.vUVW, vUVWdot, VState.dqUVWdot, dt, integrator_translational_rate);
Integrate(VState.vInertialVelocity, vUVWidot, VState.dqUVWidot, dt, integrator_translational_rate);
Integrate(VState.qAttitudeECI, vQtrndot, VState.dqQtrndot, dt, integrator_rotational_position);
Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position);
VState.qAttitudeECI.Normalize(); // Normalize the ECI Attitude quaternion
// CAUTION : the order of the operations below is very important to get transformation
// matrices that are consistent with the new state of the vehicle
VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); // Update the Earth position angle (EPA)
// Update the "Location-based" transformation matrices from the vLocation vector.
// 1. Update the Earth position angle (EPA)
VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle());
// 2. Update the Ti2ec and Tec2i transforms from the updated EPA
Ti2ec = GetTi2ec(); // ECI to ECEF transform
Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
Tl2ec = GetTl2ec(); // local to ECEF transform
Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
Ti2l = GetTi2l();
Tl2i = Ti2l.Transposed();
// Update the "Orientation-based" transformation matrices from the orientation quaternion
// 3. Update the location from the updated Ti2ec and inertial position
VState.vLocation = Ti2ec*VState.vInertialPosition;
Ti2b = GetTi2b(); // ECI to body frame transform
Tb2i = Ti2b.Transposed(); // body to ECI frame transform
Tl2b = Ti2b*Tl2i; // local to body frame transform
Tb2l = Tl2b.Transposed(); // body to local frame transform
Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
// 4. Update the other "Location-based" transformation matrices from the updated
// vLocation vector.
UpdateLocationMatrices();
// 5. Normalize the ECI Attitude quaternion
VState.qAttitudeECI.Normalize();
// 6. Update the "Orientation-based" transformation matrices from the updated
// orientation quaternion and vLocation vector.
UpdateBodyMatrices();
// Set auxililary state variables
VState.vLocation = Ti2ec*VState.vInertialPosition;
RecomputeLocalTerrainRadius();
VehicleRadius = GetRadius(); // Calculate current aircraft radius from center of planet
radInv = 1.0/VehicleRadius;
VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
@ -362,10 +334,10 @@ void FGPropagate::CalculateQuatdot(void)
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// This set of calculations results in the body frame accelerations being
// computed.
// Compute body frame accelerations based on the current body forces.
// Include centripetal and coriolis accelerations.
// This set of calculations results in the body and inertial frame accelerations
// being computed.
// Compute body and inertial frames accelerations based on the current body
// forces including centripetal and coriolis accelerations for the former.
// vOmegaEarth is the Earth angular rate - expressed in the inertial frame -
// so it has to be transformed to the body frame. More completely,
// vOmegaEarth is the rate of the ECEF frame relative to the Inertial
@ -399,6 +371,7 @@ void FGPropagate::CalculateUVWdot(void)
}
vUVWdot += vGravAccel;
vUVWidot = Tb2i * (vForces/mass + vGravAccel);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -413,6 +386,16 @@ void FGPropagate::CalculateInertialVelocity(void)
VState.vInertialVelocity = Tb2i * VState.vUVW + (vOmegaEarth * VState.vInertialPosition);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Transform the velocity vector of the inertial frame to be expressed in the
// body frame relative to the origin (Earth center), and substract the vehicle
// velocity contribution due to the rotation of the planet.
void FGPropagate::CalculateUVW(void)
{
VState.vUVW = Ti2b * (VState.vInertialVelocity - (vOmegaEarth * VState.vInertialPosition));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::Integrate( FGColumnVector3& Integrand,
@ -477,6 +460,8 @@ void FGPropagate::Integrate( FGQuaternion& Integrand,
// multiple points of contact between the aircraft and the ground. As a
// consequence our matrix J*M^-1*J^T is not sparse and the algorithm described
// in Catto's paper has been adapted accordingly.
// The friction forces are resolved in the body frame relative to the origin
// (Earth center).
void FGPropagate::ResolveFrictionForces(double dt)
{
@ -514,13 +499,9 @@ void FGPropagate::ResolveFrictionForces(double dt)
wdot = vPQRdot;
if (dt > 0.) {
// First compute the ground velocity below the aircraft center of gravity
FGLocation contact;
FGColumnVector3 normal, cvel;
// Instruct the algorithm to zero out the relative movement between the
// aircraft and the ground.
vdot += (VState.vUVW - Tec2b * cvel) / dt;
vdot += (VState.vUVW - Tec2b * LocalTerrainVelocity) / dt;
wdot += VState.vPQR / dt;
}
@ -574,6 +555,7 @@ void FGPropagate::ResolveFrictionForces(double dt)
}
vUVWdot += invMass * Fc;
vUVWidot += invMass * Tb2i * Fc;
vPQRdot += Jinv * Mc;
// Save the value of the Lagrange multipliers to accelerate the convergence
@ -587,24 +569,85 @@ void FGPropagate::ResolveFrictionForces(double dt)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::UpdateLocationMatrices(void)
{
Tl2ec = GetTl2ec(); // local to ECEF transform
Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
Ti2l = GetTi2l();
Tl2i = Ti2l.Transposed();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::UpdateBodyMatrices(void)
{
Ti2b = GetTi2b(); // ECI to body frame transform
Tb2i = Ti2b.Transposed(); // body to ECI frame transform
Tl2b = Ti2b*Tl2i; // local to body frame transform
Tb2l = Tl2b.Transposed(); // body to local frame transform
Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::SetInertialOrientation(FGQuaternion Qi) {
VState.qAttitudeECI = Qi;
VState.qAttitudeECI.Normalize();
UpdateBodyMatrices();
VState.qAttitudeLocal = Tl2b.GetQuaternion();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) {
VState.vInertialVelocity = Vi;
CalculateUVW();
vVel = GetTb2l() * VState.vUVW;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::SetInertialRates(FGColumnVector3 vRates) {
VState.vPQRi = Ti2b * vRates;
VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::InitializeDerivatives(void)
{
// Make an initial run and set past values
CalculatePQRdot(); // Angular rate derivative
CalculateUVWdot(); // Translational rate derivative
ResolveFrictionForces(0.); // Update rate derivatives with friction forces
CalculateQuatdot(); // Angular orientation derivative
CalculateInertialVelocity(); // Translational position derivative
// Initialize past values deques
VState.dqPQRdot.clear();
VState.dqUVWidot.clear();
VState.dqInertialVelocity.clear();
VState.dqQtrndot.clear();
for (int i=0; i<4; i++) {
VState.dqPQRdot.push_front(vPQRdot);
VState.dqUVWidot.push_front(vUVWdot);
VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
VState.dqQtrndot.push_front(vQtrndot);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropagate::RecomputeLocalTerrainRadius(void)
{
FGLocation contactloc;
FGColumnVector3 dv;
double t = FDMExec->GetSimTime();
// Get the LocalTerrain radius.
FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv,
LocalTerrainVelocity);
LocalTerrainRadius = contactloc.GetRadius();
}

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.43 2010/07/25 15:35:11 jberndt Exp $"
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -102,7 +102,7 @@ CLASS DOCUMENTATION
@endcode
@author Jon S. Berndt, Mathias Froehlich
@version $Id: FGPropagate.h,v 1.43 2010/07/25 15:35:11 jberndt Exp $
@version $Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -148,9 +148,9 @@ public:
FGColumnVector3 vInertialPosition;
deque <FGColumnVector3> dqPQRdot;
deque <FGColumnVector3> dqUVWdot;
deque <FGColumnVector3> dqUVWidot;
deque <FGColumnVector3> dqInertialVelocity;
deque <FGQuaternion> dqQtrndot;
deque <FGQuaternion> dqQtrndot;
};
/** Constructor.
@ -517,19 +517,23 @@ public:
void SetVState(VehicleState* vstate) {
VState.vLocation = vstate->vLocation;
UpdateLocationMatrices();
SetInertialOrientation(vstate->qAttitudeECI);
VehicleRadius = GetRadius();
VState.vUVW = vstate->vUVW;
vVel = GetTb2l() * VState.vUVW;
VState.vPQR = vstate->vPQR;
VState.qAttitudeLocal = vstate->qAttitudeLocal;
VState.qAttitudeECI = vstate->qAttitudeECI;
VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
VState.vInertialPosition = vstate->vInertialPosition;
VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
InitializeDerivatives();
}
void InitializeDerivatives(void);
void SetInertialOrientation(FGQuaternion Qi);
void SetInertialVelocity(FGColumnVector3 Vi);
void SetInertialRates(FGColumnVector3 vRates);
const FGQuaternion GetQuaternion(void) const { return VState.qAttitudeLocal; }
@ -545,18 +549,46 @@ public:
// SET functions
void SetLongitude(double lon) { VState.vLocation.SetLongitude(lon); }
void SetLongitudeDeg(double lon) {SetLongitude(lon*degtorad);}
void SetLatitude(double lat) { VState.vLocation.SetLatitude(lat); }
void SetLatitudeDeg(double lat) {SetLatitude(lat*degtorad);}
void SetRadius(double r) { VState.vLocation.SetRadius(r); }
void SetLocation(const FGLocation& l) { VState.vLocation = l; }
void SetLongitude(double lon) {
VState.vLocation.SetLongitude(lon);
VState.vInertialPosition = GetTec2i() * VState.vLocation;
UpdateLocationMatrices();
}
void SetLongitudeDeg(double lon) { SetLongitude(lon*degtorad); }
void SetLatitude(double lat) {
VState.vLocation.SetLatitude(lat);
VState.vInertialPosition = GetTec2i() * VState.vLocation;
UpdateLocationMatrices();
}
void SetLatitudeDeg(double lat) { SetLatitude(lat*degtorad); }
void SetRadius(double r) {
VState.vLocation.SetRadius(r);
VState.vInertialPosition = GetTec2i() * VState.vLocation;
UpdateLocationMatrices();
}
void SetLocation(const FGLocation& l) {
VState.vLocation = l;
VState.vInertialPosition = GetTec2i() * VState.vLocation;
UpdateLocationMatrices();
}
void SetLocation(const FGColumnVector3& l) {
VState.vLocation = l;
VState.vInertialPosition = GetTec2i() * VState.vLocation;
UpdateLocationMatrices();
}
void SetAltitudeASL(double altASL);
void SetAltitudeASLmeters(double altASL) {SetAltitudeASL(altASL/fttom);}
void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
void SetTerrainElevation(double tt);
void SetDistanceAGL(double tt);
void SetInitialState(const FGInitialCondition *);
void SetPosition(const double Lon, const double Lat, const double Radius) {
VState.vLocation.SetPosition(Lon, Lat, Radius);
VState.vInertialPosition = GetTec2i() * VState.vLocation;
VehicleRadius = GetRadius();
UpdateLocationMatrices();
}
void RecomputeLocalTerrainRadius(void);
void NudgeBodyLocation(FGColumnVector3 deltaLoc) {
@ -580,7 +612,7 @@ private:
FGColumnVector3 vVel;
FGColumnVector3 vPQRdot;
FGColumnVector3 vUVWdot;
FGColumnVector3 vUVWdot, vUVWidot;
FGColumnVector3 vInertialVelocity;
FGColumnVector3 vLocation;
FGColumnVector3 vDeltaXYZEC;
@ -599,11 +631,9 @@ private:
FGMatrix33 Tb2i; // body to ECI frame rotation matrix
FGMatrix33 Ti2l;
FGMatrix33 Tl2i;
FGLocation contactloc;
FGColumnVector3 dv;
double LocalTerrainRadius, SeaLevelRadius, VehicleRadius;
double radInv;
FGColumnVector3 LocalTerrainVelocity;
eIntegrateType integrator_rotational_rate;
eIntegrateType integrator_translational_rate;
eIntegrateType integrator_rotational_position;
@ -613,6 +643,7 @@ private:
void CalculatePQRdot(void);
void CalculateQuatdot(void);
void CalculateInertialVelocity(void);
void CalculateUVW(void);
void CalculateUVWdot(void);
void Integrate( FGColumnVector3& Integrand,
@ -629,6 +660,9 @@ private:
void ResolveFrictionForces(double dt);
void UpdateLocationMatrices(void);
void UpdateBodyMatrices(void);
void bind(void);
void Debug(int from);
};

View file

@ -65,7 +65,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.39 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.40 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_PROPULSION;
extern short debug_lvl;
@ -336,7 +336,7 @@ bool FGPropulsion::Load(Element* el)
if (el->FindElement("dump-rate"))
DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
FGModel::PostLoad(el);
PostLoad(el, PropertyManager);
return true;
}

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.27 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.29 2010/09/07 00:40:03 jberndt Exp $";
static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -122,14 +122,16 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
} else {
InputSigns.push_back( 1.0);
}
tmp = PropertyManager->GetNode(input);
if (tmp) {
InputNodes.push_back( tmp );
if (PropertyManager->HasNode(input)) {
tmp = PropertyManager->GetNode(input);
} else {
cerr << fgred << " In component: " << Name << " unknown property "
<< input << " referenced. Aborting" << reset << endl;
exit(-1);
tmp = 0L;
// cerr << fgcyan << "In component: " + Name + " property "
// + input + " is initially undefined." << reset << endl;
}
InputNodes.push_back( tmp );
InputNames.push_back( input );
input_element = element->FindNextElement("input");
}
@ -236,6 +238,24 @@ void FGFCSComponent::Clip(void)
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFCSComponent::LateBind(void)
{
FGPropertyManager* node = 0L;
for (unsigned int i=0; i<InputNodes.size(); i++) {
if (!InputNodes[i]) {
if (PropertyManager->HasNode(InputNames[i])) {
node = PropertyManager->GetNode(InputNames[i]);
InputNodes[i] = node;
} else {
throw(InputNames[i]);
}
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// The old way of naming FCS components allowed upper or lower case, spaces, etc.

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $"
#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -80,7 +80,7 @@ CLASS DOCUMENTATION
- FGActuator
@author Jon S. Berndt
@version $Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $
@version $Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $
@see Documentation for the FGFCS class, and for the configuration file class
*/
@ -98,6 +98,7 @@ public:
virtual bool Run(void);
virtual void SetOutput(void);
void LateBind(void);
double GetOutput (void) const {return Output;}
std::string GetName(void) const {return Name;}
std::string GetType(void) const { return Type; }
@ -111,6 +112,7 @@ protected:
FGPropertyManager* ClipMinPropertyNode;
FGPropertyManager* ClipMaxPropertyNode;
std::vector <FGPropertyManager*> InputNodes;
std::vector <std::string> InputNames;
std::vector <float> InputSigns;
std::vector <double> output_array;
std::string Type;

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGSummer.cpp,v 1.7 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdSrc = "$Id: FGSummer.cpp,v 1.8 2010/08/21 22:56:11 jberndt Exp $";
static const char *IdHdr = ID_SUMMER;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -118,9 +118,9 @@ void FGSummer::Debug(int from)
cout << " INPUTS: " << endl;
for (unsigned i=0;i<InputNodes.size();i++) {
if (InputSigns[i] < 0)
cout << " -" << InputNodes[i]->getName() << endl;
cout << " -" << InputNames[i] << endl;
else
cout << " " << InputNodes[i]->getName() << endl;
cout << " " << InputNames[i] << endl;
}
if (Bias != 0.0) cout << " Bias: " << Bias << endl;
if (IsOutput) {

View file

@ -50,7 +50,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGElectric.cpp,v 1.8 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdSrc = "$Id: FGElectric.cpp,v 1.9 2010/08/21 17:13:48 jberndt Exp $";
static const char *IdHdr = ID_ELECTRIC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -83,8 +83,10 @@ FGElectric::~FGElectric()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGElectric::Calculate(void)
void FGElectric::Calculate(void)
{
RunPreFunctions();
Throttle = FCS->GetThrottlePos(EngineNumber);
RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
@ -93,7 +95,9 @@ double FGElectric::Calculate(void)
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
return Thruster->Calculate(PowerAvailable);
Thruster->Calculate(PowerAvailable);
RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -45,7 +45,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ELECTRIC "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $";
#define ID_ELECTRIC "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $";
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -65,7 +65,7 @@ CLASS DOCUMENTATION
there is no battery model available, so this motor does not consume any
energy. There is no internal friction.
@author David Culp
@version "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $"
@version "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -80,7 +80,7 @@ public:
/// Destructor
~FGElectric();
double Calculate(void);
void Calculate(void);
double GetPowerAvailable(void) {return PowerAvailable;}
double getRPM(void) {return RPM;}
std::string GetEngineLabels(const std::string& delimiter);

View file

@ -54,7 +54,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGEngine.cpp,v 1.38 2010/06/02 04:05:13 jberndt Exp $";
static const char *IdSrc = "$Id: FGEngine.cpp,v 1.39 2010/08/21 17:13:48 jberndt Exp $";
static const char *IdHdr = ID_ENGINE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -91,6 +91,8 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
Name = engine_element->GetAttributeValue("name");
Load(engine_element, PropertyManager, to_string(EngineNumber)); // Call ModelFunctions loader
// Find and set engine location
local_element = engine_element->GetParent()->FindElement("location");
@ -146,6 +148,8 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
property_name = base_property_name + "/fuel-flow-rate-pps";
PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate);
PostLoad(engine_element, PropertyManager, to_string(EngineNumber));
//cout << "Engine[" << EngineNumber << "] using fuel density: " << FuelDensity << endl;
Debug(0);

View file

@ -43,7 +43,7 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include "math/FGModelFunctions.h"
#include "input_output/FGXMLFileRead.h"
#include "input_output/FGXMLElement.h"
#include "models/FGFCS.h"
@ -55,7 +55,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ENGINE "$Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $"
#define ID_ENGINE "$Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -118,14 +118,14 @@ CLASS DOCUMENTATION
documentation for engine and thruster classes.
</pre>
@author Jon S. Berndt
@version $Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $
@version $Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGEngine : public FGJSBBase, public FGXMLFileRead
class FGEngine : public FGModelFunctions, public FGXMLFileRead
{
public:
FGEngine(FGFDMExec* exec, Element* el, int engine_number);
@ -165,9 +165,8 @@ public:
/** Resets the Engine parameters to the initial conditions */
void ResetToIC(void);
/** Calculates the thrust of the engine, and other engine functions.
@return Thrust in pounds */
virtual double Calculate(void) {return 0.0;}
/** Calculates the thrust of the engine, and other engine functions. */
virtual void Calculate(void) = 0;
/// Sets engine placement information
virtual void SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation);
@ -237,6 +236,7 @@ protected:
FGThruster* Thruster;
std::vector <int> SourceTanks;
void Debug(int from);
};
}

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPiston.cpp,v 1.52 2010/06/05 12:12:34 jberndt Exp $";
static const char *IdSrc = "$Id: FGPiston.cpp,v 1.53 2010/08/21 17:13:48 jberndt Exp $";
static const char *IdHdr = ID_PISTON;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -385,16 +385,16 @@ void FGPiston::ResetToIC(void)
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGPiston::Calculate(void)
void FGPiston::Calculate(void)
{
RunPreFunctions();
if (FuelFlow_gph > 0.0) ConsumeFuel();
Throttle = FCS->GetThrottlePos(EngineNumber);
Mixture = FCS->GetMixturePos(EngineNumber);
//
// Input values.
//
p_amb = Atmosphere->GetPressure() * psftopa;
double p = Auxiliary->GetTotalPressure() * psftopa;
@ -416,8 +416,9 @@ double FGPiston::Calculate(void)
//Assume lean limit at 22 AFR for now - thats a thi of 0.668
//This might be a bit generous, but since there's currently no audiable warning of impending
//cutout in the form of misfiring and/or rough running its probably reasonable for now.
// if (equivalence_ratio < 0.668)
// Running = false;
// if (equivalence_ratio < 0.668)
// Running = false;
doEnginePower();
if (IndicatedHorsePower < 0.1250) Running = false;
@ -433,8 +434,9 @@ double FGPiston::Calculate(void)
}
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
Thruster->Calculate(PowerAvailable);
return Thruster->Calculate(PowerAvailable);
RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PISTON "$Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $";
#define ID_PISTON "$Id: FGPiston.h,v 1.24 2010/08/21 18:08:13 jberndt Exp $";
#define FG_MAX_BOOST_SPEEDS 3
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -181,7 +181,7 @@ CLASS DOCUMENTATION
@author Dave Luff (engine operational code)
@author David Megginson (initial porting and additional code)
@author Ron Jensen (additional engine code)
@version $Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $
@version $Id: FGPiston.h,v 1.24 2010/08/21 18:08:13 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -199,7 +199,7 @@ public:
std::string GetEngineLabels(const std::string& delimiter);
std::string GetEngineValues(const std::string& delimiter);
double Calculate(void);
void Calculate(void);
double GetPowerAvailable(void) {return PowerAvailable;}
double CalcFuelNeed(void);

View file

@ -49,7 +49,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGRocket.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdSrc = "$Id: FGRocket.cpp,v 1.20 2010/08/21 17:13:48 jberndt Exp $";
static const char *IdHdr = ID_ROCKET;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -59,6 +59,7 @@ CLASS IMPLEMENTATION
FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
: FGEngine(exec, el, engine_number)
{
Type = etRocket;
Element* thrust_table_element = 0;
ThrustTable = 0L;
BurnTime = 0.0;
@ -72,6 +73,7 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
It = 0.0;
ThrustVariation = 0.0;
TotalIspVariation = 0.0;
Flameout = false;
// Defaults
MinThrottle = 0.0;
@ -108,10 +110,6 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
bindmodel();
Debug(0);
Type = etRocket;
Flameout = false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -124,10 +122,11 @@ FGRocket::~FGRocket(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGRocket::Calculate(void)
void FGRocket::Calculate(void)
{
double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
double thrust;
RunPreFunctions();
if (!Flameout && !Starved) ConsumeFuel();
@ -184,10 +183,9 @@ double FGRocket::Calculate(void)
} // End thrust calculations
thrust = Thruster->Calculate(VacThrust);
It += thrust * dT;
It += Thruster->Calculate(VacThrust) * dT;
return thrust;
RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ROCKET "$Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $"
#define ID_ROCKET "$Id: FGRocket.h,v 1.14 2010/08/21 18:08:25 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -118,7 +118,7 @@ for the rocket engine to be throttle up to 1. At that time, the solid rocket
fuel begins burning and thrust is provided.
@author Jon S. Berndt
$Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $
$Id: FGRocket.h,v 1.14 2010/08/21 18:08:25 jberndt Exp $
@see FGNozzle,
FGThruster,
FGForce,
@ -143,9 +143,8 @@ public:
/** Destructor */
~FGRocket(void);
/** Determines the thrust.
@return thrust */
double Calculate(void);
/** Determines the thrust.*/
void Calculate(void);
/** Gets the total impulse of the rocket.
@return The cumulative total impulse of the rocket up to this time.*/

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGThruster.cpp,v 1.12 2009/10/24 22:59:30 jberndt Exp $";
static const char *IdSrc = "$Id: FGThruster.cpp,v 1.13 2010/08/21 22:56:11 jberndt Exp $";
static const char *IdHdr = ID_THRUSTER;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -74,11 +74,11 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
element = thruster_element->FindElement("location");
if (element) location = element->FindElementTripletConvertTo("IN");
else cerr << "No thruster location found." << endl;
else cerr << fgred << " No thruster location found." << reset << endl;
element = thruster_element->FindElement("orient");
if (element) orientation = element->FindElementTripletConvertTo("RAD");
else cerr << "No thruster orientation found." << endl;
else cerr << " No thruster orientation found." << endl;
SetLocation(location);
SetAnglesToBody(orientation);

View file

@ -51,7 +51,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.27 2010/05/24 11:26:37 jberndt Exp $";
static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.29 2010/08/31 04:01:32 jberndt Exp $";
static const char *IdHdr = ID_TURBINE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -113,10 +113,12 @@ void FGTurbine::ResetToIC(void)
// The main purpose of Calculate() is to determine what phase the engine should
// be in, then call the corresponding function.
double FGTurbine::Calculate(void)
void FGTurbine::Calculate(void)
{
double thrust;
RunPreFunctions();
TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
double qbar = Auxiliary->Getqbar();
dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
@ -170,9 +172,9 @@ double FGTurbine::Calculate(void)
default: thrust = Off();
}
thrust = Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing)
Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing)
return thrust;
RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -474,9 +476,6 @@ bool FGTurbine::Load(FGFDMExec* exec, Element *el)
MaxThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix);
} else if (name == "Injection") {
InjectionLookup = new FGFunction(PropertyManager, function_element, property_prefix);
} else {
cerr << "Unknown function type: " << name << " in turbine definition." <<
endl;
}
}

View file

@ -42,7 +42,7 @@ INCLUDES
#include "FGEngine.h"
#define ID_TURBINE "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $"
#define ID_TURBINE "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -146,7 +146,7 @@ CLASS DOCUMENTATION
/engine/direct.xml
</pre>
@author David P. Culp
@version "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $"
@version "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -166,7 +166,7 @@ public:
enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
double Calculate(void);
void Calculate(void);
double CalcFuelNeed(void);
double GetPowerAvailable(void);
/** A lag filter.

View file

@ -52,7 +52,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.16 2010/02/25 05:21:36 jberndt Exp $";
static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.17 2010/08/21 17:13:48 jberndt Exp $";
static const char *IdHdr = ID_TURBOPROP;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -158,8 +158,10 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
// The main purpose of Calculate() is to determine what phase the engine should
// be in, then call the corresponding function.
double FGTurboProp::Calculate(void)
void FGTurboProp::Calculate(void)
{
RunPreFunctions();
TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
@ -250,8 +252,9 @@ double FGTurboProp::Calculate(void)
//printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power);
PowerAvailable = (Eng_HP * hptoftlbssec) - Thruster->GetPowerRequired();
return Thruster->Calculate(PowerAvailable);
Thruster->Calculate(PowerAvailable);
RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -46,7 +46,7 @@ INCLUDES
#include "input_output/FGXMLElement.h"
#include "math/FGTable.h"
#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.11 2009/10/26 03:48:42 jberndt Exp $"
#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.12 2010/08/21 18:08:37 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -104,7 +104,7 @@ public:
enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
double Calculate(void);
void Calculate(void);
double CalcFuelNeed(void);
inline double GetPowerAvailable(void) const {return (Eng_HP * hptoftlbssec);}