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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
<< 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;
}
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;
//******************************************************************************
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
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;
// 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);
result = false;
}
-
- Propagate->SetInertialOrientation(QuatI2Body);
}
+ Propagate->SetInertialOrientation(QuatI2Body);
+
// Initialize vehicle velocity
// Allowable frames
// - ECI (Earth Centered Inertial)
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 {
} 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)
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");
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
}
} 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();
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
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",
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;
// 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"];
// 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;
#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
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>
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
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 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()));
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;
}
{
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:
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);
}
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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
radius*cosLat*sinLon,
radius*sinLat );
mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
-
-// initial_longitude = 0.0
-
- ComputeDerived();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mECLoc = FGColumnVector3( radius*cosLat*cosLon,
radius*cosLat*sinLon,
radius*sinLat );
- ComputeDerived();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon);
mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon);
mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat);
-
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
const FGMatrix33& FGLocation::GetTec2i(void)
{
+ ComputeDerived();
return mTec2i;
}
const FGMatrix33& FGLocation::GetTi2ec(void)
{
+ ComputeDerived();
return mTi2ec;
}
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);
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;
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
@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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
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); }
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.
f = l.f;
initial_longitude = l.initial_longitude;
+ mGeodLat = l.mGeodLat;
+ GeodeticAltitude = l.GeodeticAltitude;
return *this;
}
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
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];
data[7] = M.data[7];
data[8] = M.data[8];
-// Debug(0);
+ // Debug(0);
}
/** Initialization by given values.
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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;
}
}
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
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
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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;
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");
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
@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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/// 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;
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
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
axis_element = document->FindNextElement("axis");
}
- FGModel::PostLoad(document); // Perform base class Post-Load
+ PostLoad(document, PropertyManager); // Perform base class Post-Load
return true;
}
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
}
- FGModel::PostLoad(el);
+ PostLoad(el, PropertyManager);
Debug(2);
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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);
}
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();
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*
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;
}
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);
+
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#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
/** 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. 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
+
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@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;}
/// 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;}
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;
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;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
gas_cell_element = document->FindNextElement("gas_cell");
}
- FGModel::PostLoad(element);
+ PostLoad(element, PropertyManager);
if (!NoneDefined) {
bind();
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
force_element = el->FindNextElement("force");
}
- FGModel::PostLoad(el);
+ PostLoad(el, PropertyManager);
return true;
}
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
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
@property gear/tailhook-pos-norm
@author Jon S. Berndt
- @version $Revision: 1.28 $
+ @version $Revision: 1.30 $
@see FGActuator
@see FGDeadBand
@see FGFCSFunction
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 )
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];
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGGroundReactions::GetWOW(void)
+bool FGGroundReactions::GetWOW(void) const
{
bool result = false;
for (unsigned int i=0; i<lGear.size(); i++) {
for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();
- FGModel::PostLoad(el);
+ PostLoad(el, PropertyManager);
return true;
}
{
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);
#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
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(); }
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Mass = lbtoslug*Weight;
- FGModel::PostLoad(el);
+ PostLoad(el, PropertyManager);
Debug(2);
return true;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGModel::FGModel(FGFDMExec* fdmex)
{
FDMExec = fdmex;
- NextModel = 0L;
Atmosphere = 0;
FCS = 0;
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;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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;
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#include "FGJSBBase.h"
#include "math/FGFunction.h"
+#include "math/FGModelFunctions.h"
#include <string>
#include <vector>
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
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGModel : public FGJSBBase
+class FGModel : public FGModelFunctions
{
public:
/// Destructor
~FGModel();
- FGModel* NextModel;
std::string Name;
/** Runs the model; called by the Executive
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);
FGPropagate* Propagate;
FGAuxiliary* Auxiliary;
FGPropertyManager* PropertyManager;
- std::vector <FGFunction*> PreFunctions;
- std::vector <FGFunction*> PostFunctions;
-
- std::vector <double*> interface_properties;
};
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{
Debug(0);
Name = "FGPropagate";
- gravType = gtWGS84;
+ gravType = gtStandard;
vPQRdot.InitMatrix();
vQtrndot = FGQuaternion(0,0,0);
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));
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));
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
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
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.
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();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
-
- VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); // Update the Earth position angle (EPA)
+ // CAUTION : the order of the operations below is very important to get transformation
+ // matrices that are consistent with the new state of the vehicle
- // 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;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// 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
}
vUVWdot += vGravAccel;
+ vUVWidot = Tb2i * (vForces/mass + vGravAccel);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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,
// 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)
{
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;
}
}
vUVWdot += invMass * Fc;
+ vUVWidot += invMass * Tb2i * Fc;
vPQRdot += Jinv * Mc;
// Save the value of the Lagrange multipliers to accelerate the convergence
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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();
}
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
@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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3 vInertialPosition;
deque <FGColumnVector3> dqPQRdot;
- deque <FGColumnVector3> dqUVWdot;
+ deque <FGColumnVector3> dqUVWidot;
deque <FGColumnVector3> dqInertialVelocity;
- deque <FGQuaternion> dqQtrndot;
+ deque <FGQuaternion> dqQtrndot;
};
/** Constructor.
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; }
// 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) {
FGColumnVector3 vVel;
FGColumnVector3 vPQRdot;
- FGColumnVector3 vUVWdot;
+ FGColumnVector3 vUVWdot, vUVWidot;
FGColumnVector3 vInertialVelocity;
FGColumnVector3 vLocation;
FGColumnVector3 vDeltaXYZEC;
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;
void CalculatePQRdot(void);
void CalculateQuatdot(void);
void CalculateInertialVelocity(void);
+ void CalculateUVW(void);
void CalculateUVWdot(void);
void Integrate( FGColumnVector3& Integrand,
void ResolveFrictionForces(double dt);
+ void UpdateLocationMatrices(void);
+ void UpdateBodyMatrices(void);
+
void bind(void);
void Debug(int from);
};
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;
if (el->FindElement("dump-rate"))
DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
- FGModel::PostLoad(el);
+ PostLoad(el, PropertyManager);
return true;
}
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} 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");
}
}
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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.
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
- 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
*/
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; }
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;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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) {
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGElectric::Calculate(void)
+void FGElectric::Calculate(void)
{
+ RunPreFunctions();
+
Throttle = FCS->GetThrottlePos(EngineNumber);
RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
- return Thruster->Calculate(PowerAvailable);
+ Thruster->Calculate(PowerAvailable);
+
+ RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
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 $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/// 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);
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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");
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);
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#include "FGJSBBase.h"
+#include "math/FGModelFunctions.h"
#include "input_output/FGXMLFileRead.h"
#include "input_output/FGXMLElement.h"
#include "models/FGFCS.h"
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
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);
/** 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);
FGThruster* Thruster;
std::vector <int> SourceTanks;
+
void Debug(int from);
};
}
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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;
//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;
}
PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
+ Thruster->Calculate(PowerAvailable);
- return Thruster->Calculate(PowerAvailable);
+ RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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);
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
It = 0.0;
ThrustVariation = 0.0;
TotalIspVariation = 0.0;
+ Flameout = false;
// Defaults
MinThrottle = 0.0;
bindmodel();
Debug(0);
-
- Type = etRocket;
- Flameout = false;
-
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGRocket::Calculate(void)
+void FGRocket::Calculate(void)
{
double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
- double thrust;
+
+ RunPreFunctions();
if (!Flameout && !Starved) ConsumeFuel();
} // End thrust calculations
- thrust = Thruster->Calculate(VacThrust);
- It += thrust * dT;
+ It += Thruster->Calculate(VacThrust) * dT;
- return thrust;
+ RunPostFunctions();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
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,
/** 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.*/
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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);
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 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();
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();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
}
}
#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
/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 $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
- double Calculate(void);
+ void Calculate(void);
double CalcFuelNeed(void);
double GetPowerAvailable(void);
/** A lag filter.
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 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();
//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();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#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
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);}