From 4b8fde057be1124c516eb89442eae4bfe4a4db5c Mon Sep 17 00:00:00 2001 From: Erik Hofman Date: Sun, 19 Sep 2010 11:16:29 +0200 Subject: [PATCH] Sync. with JSBSim CVS --- src/FDM/JSBSim/FGFDMExec.cpp | 20 +- .../initialization/FGInitialCondition.cpp | 82 ++++---- src/FDM/JSBSim/initialization/FGTrimAxis.h | 6 +- src/FDM/JSBSim/input_output/FGXMLElement.cpp | 8 +- .../JSBSim/input_output/string_utilities.h | 23 ++- src/FDM/JSBSim/math/FGFunction.cpp | 51 +++-- src/FDM/JSBSim/math/FGLocation.cpp | 22 ++- src/FDM/JSBSim/math/FGLocation.h | 14 +- src/FDM/JSBSim/math/FGMatrix33.h | 7 +- src/FDM/JSBSim/math/FGPropertyValue.cpp | 18 +- src/FDM/JSBSim/math/FGPropertyValue.h | 5 +- src/FDM/JSBSim/math/FGTable.cpp | 18 +- src/FDM/JSBSim/math/FGTable.h | 5 +- src/FDM/JSBSim/math/Makefile.am | 4 +- src/FDM/JSBSim/models/FGAerodynamics.cpp | 4 +- src/FDM/JSBSim/models/FGAircraft.cpp | 4 +- src/FDM/JSBSim/models/FGAtmosphere.cpp | 159 ++++++++++++++- src/FDM/JSBSim/models/FGAtmosphere.h | 72 ++++++- src/FDM/JSBSim/models/FGBuoyantForces.cpp | 4 +- src/FDM/JSBSim/models/FGExternalReactions.cpp | 4 +- src/FDM/JSBSim/models/FGFCS.cpp | 13 +- src/FDM/JSBSim/models/FGFCS.h | 8 +- src/FDM/JSBSim/models/FGGroundReactions.cpp | 7 +- src/FDM/JSBSim/models/FGGroundReactions.h | 4 +- src/FDM/JSBSim/models/FGMassBalance.cpp | 4 +- src/FDM/JSBSim/models/FGModel.cpp | 96 +-------- src/FDM/JSBSim/models/FGModel.h | 18 +- src/FDM/JSBSim/models/FGPropagate.cpp | 187 +++++++++++------- src/FDM/JSBSim/models/FGPropagate.h | 74 +++++-- src/FDM/JSBSim/models/FGPropulsion.cpp | 4 +- .../models/flight_control/FGFCSComponent.cpp | 34 +++- .../models/flight_control/FGFCSComponent.h | 6 +- .../JSBSim/models/flight_control/FGSummer.cpp | 6 +- .../JSBSim/models/propulsion/FGElectric.cpp | 10 +- src/FDM/JSBSim/models/propulsion/FGElectric.h | 6 +- src/FDM/JSBSim/models/propulsion/FGEngine.cpp | 6 +- src/FDM/JSBSim/models/propulsion/FGEngine.h | 14 +- src/FDM/JSBSim/models/propulsion/FGPiston.cpp | 16 +- src/FDM/JSBSim/models/propulsion/FGPiston.h | 6 +- src/FDM/JSBSim/models/propulsion/FGRocket.cpp | 18 +- src/FDM/JSBSim/models/propulsion/FGRocket.h | 9 +- .../JSBSim/models/propulsion/FGThruster.cpp | 6 +- .../JSBSim/models/propulsion/FGTurbine.cpp | 13 +- src/FDM/JSBSim/models/propulsion/FGTurbine.h | 6 +- .../JSBSim/models/propulsion/FGTurboProp.cpp | 9 +- .../JSBSim/models/propulsion/FGTurboProp.h | 4 +- 46 files changed, 729 insertions(+), 385 deletions(-) diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index 5226a3e37..4cba2d0f9 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -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; } diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp index 2d8f8a673..ed17c6944 100644 --- a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp @@ -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(); diff --git a/src/FDM/JSBSim/initialization/FGTrimAxis.h b/src/FDM/JSBSim/initialization/FGTrimAxis.h index 9fc7cebb9..afd516782 100644 --- a/src/FDM/JSBSim/initialization/FGTrimAxis.h +++ b/src/FDM/JSBSim/initialization/FGTrimAxis.h @@ -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", diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.cpp b/src/FDM/JSBSim/input_output/FGXMLElement.cpp index 0c3e91063..3f7becc5c 100755 --- a/src/FDM/JSBSim/input_output/FGXMLElement.cpp +++ b/src/FDM/JSBSim/input_output/FGXMLElement.cpp @@ -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; diff --git a/src/FDM/JSBSim/input_output/string_utilities.h b/src/FDM/JSBSim/input_output/string_utilities.h index f2dc22090..b55073f8b 100644 --- a/src/FDM/JSBSim/input_output/string_utilities.h +++ b/src/FDM/JSBSim/input_output/string_utilities.h @@ -40,12 +40,13 @@ INCLUDES #include #include +#include /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 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 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 @@ -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 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/math/FGFunction.cpp b/src/FDM/JSBSim/math/FGFunction.cpp index 183654e2e..9ad7c7a99 100755 --- a/src/FDM/JSBSim/math/FGFunction.cpp +++ b/src/FDM/JSBSim/math/FGFunction.cpp @@ -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); } diff --git a/src/FDM/JSBSim/math/FGLocation.cpp b/src/FDM/JSBSim/math/FGLocation.cpp index f3c4d88bc..9e0a62a23 100644 --- a/src/FDM/JSBSim/math/FGLocation.cpp +++ b/src/FDM/JSBSim/math/FGLocation.cpp @@ -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; diff --git a/src/FDM/JSBSim/math/FGLocation.h b/src/FDM/JSBSim/math/FGLocation.h index 2112557de..46a1b0d99 100644 --- a/src/FDM/JSBSim/math/FGLocation.h +++ b/src/FDM/JSBSim/math/FGLocation.h @@ -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; } diff --git a/src/FDM/JSBSim/math/FGMatrix33.h b/src/FDM/JSBSim/math/FGMatrix33.h index 7af43031b..d937f910a 100644 --- a/src/FDM/JSBSim/math/FGMatrix33.h +++ b/src/FDM/JSBSim/math/FGMatrix33.h @@ -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. diff --git a/src/FDM/JSBSim/math/FGPropertyValue.cpp b/src/FDM/JSBSim/math/FGPropertyValue.cpp index 66f89b89a..0824a607b 100755 --- a/src/FDM/JSBSim/math/FGPropertyValue.cpp +++ b/src/FDM/JSBSim/math/FGPropertyValue.cpp @@ -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; } } diff --git a/src/FDM/JSBSim/math/FGPropertyValue.h b/src/FDM/JSBSim/math/FGPropertyValue.h index 3466c66ba..753df7c62 100755 --- a/src/FDM/JSBSim/math/FGPropertyValue.h +++ b/src/FDM/JSBSim/math/FGPropertyValue.h @@ -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 diff --git a/src/FDM/JSBSim/math/FGTable.cpp b/src/FDM/JSBSim/math/FGTable.cpp index 2d604dca2..3f23fd144 100644 --- a/src/FDM/JSBSim/math/FGTable.cpp +++ b/src/FDM/JSBSim/math/FGTable.cpp @@ -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"); diff --git a/src/FDM/JSBSim/math/FGTable.h b/src/FDM/JSBSim/math/FGTable.h index e96cf07fe..2f2e271cd 100644 --- a/src/FDM/JSBSim/math/FGTable.h +++ b/src/FDM/JSBSim/math/FGTable.h @@ -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; diff --git a/src/FDM/JSBSim/math/Makefile.am b/src/FDM/JSBSim/math/Makefile.am index 5ae295ede..b97253ac3 100644 --- a/src/FDM/JSBSim/math/Makefile.am +++ b/src/FDM/JSBSim/math/Makefile.am @@ -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 diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp index d8c66df20..7f5359e98 100644 --- a/src/FDM/JSBSim/models/FGAerodynamics.cpp +++ b/src/FDM/JSBSim/models/FGAerodynamics.cpp @@ -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; } diff --git a/src/FDM/JSBSim/models/FGAircraft.cpp b/src/FDM/JSBSim/models/FGAircraft.cpp index d292316d6..0ed6ac74f 100644 --- a/src/FDM/JSBSim/models/FGAircraft.cpp +++ b/src/FDM/JSBSim/models/FGAircraft.cpp @@ -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); diff --git a/src/FDM/JSBSim/models/FGAtmosphere.cpp b/src/FDM/JSBSim/models/FGAtmosphere.cpp index 2db1c65d9..12fb084a7 100644 --- a/src/FDM/JSBSim/models/FGAtmosphere.cpp +++ b/src/FDM/JSBSim/models/FGAtmosphere.cpp @@ -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); + } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/FGAtmosphere.h b/src/FDM/JSBSim/models/FGAtmosphere.h index 84d3f072a..d6561fa86 100644 --- a/src/FDM/JSBSim/models/FGAtmosphere.h +++ b/src/FDM/JSBSim/models/FGAtmosphere.h @@ -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 atmosphere/turb-type. 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 atmosphere/turb-type to 4 resp. 5, + and specify values for atmosphere/turbulence/milspec/windspeed_at_20ft_AGL-fps + and atmosphere/turbulence/milspec/severity (the latter corresponds to + the probability of exceedence curves from Fig. 7 of the milspec, allowable + range is 0 (disabled) to 7). atmosphere/psiw-rad 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): + + + + + + + + + + + + + +
Intensitywindspeed_at_20ft_AGL-fpsseverity
light25 (15 knots)3
moderate50 (30 knots)4
severe75 (45 knots)6
+ + @see Yeager, Jessie C.: "Implementation and Testing of Turbulence Models for + the F18-HARV" ( + pdf), 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; diff --git a/src/FDM/JSBSim/models/FGBuoyantForces.cpp b/src/FDM/JSBSim/models/FGBuoyantForces.cpp index 64c97ebfb..1b9a63b74 100644 --- a/src/FDM/JSBSim/models/FGBuoyantForces.cpp +++ b/src/FDM/JSBSim/models/FGBuoyantForces.cpp @@ -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(); diff --git a/src/FDM/JSBSim/models/FGExternalReactions.cpp b/src/FDM/JSBSim/models/FGExternalReactions.cpp index 7df087c1e..e39f8fb07 100755 --- a/src/FDM/JSBSim/models/FGExternalReactions.cpp +++ b/src/FDM/JSBSim/models/FGExternalReactions.cpp @@ -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; } diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp index 4d71ca97d..368fa90ae 100644 --- a/src/FDM/JSBSim/models/FGFCS.cpp +++ b/src/FDM/JSBSim/models/FGFCS.cpp @@ -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; iLateBind(); + for (i=0; iLateBind(); + for (i=0; iLateBind(); +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // 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 diff --git a/src/FDM/JSBSim/models/FGFCS.h b/src/FDM/JSBSim/models/FGFCS.h index 6e10de9c4..a2b592768 100644 --- a/src/FDM/JSBSim/models/FGFCS.h +++ b/src/FDM/JSBSim/models/FGFCS.h @@ -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]; diff --git a/src/FDM/JSBSim/models/FGGroundReactions.cpp b/src/FDM/JSBSim/models/FGGroundReactions.cpp index fdbfa254f..246cefe8c 100644 --- a/src/FDM/JSBSim/models/FGGroundReactions.cpp +++ b/src/FDM/JSBSim/models/FGGroundReactions.cpp @@ -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; ibind(); - 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); diff --git a/src/FDM/JSBSim/models/FGGroundReactions.h b/src/FDM/JSBSim/models/FGGroundReactions.h index 5c5ea682c..a10ff0bb1 100644 --- a/src/FDM/JSBSim/models/FGGroundReactions.h +++ b/src/FDM/JSBSim/models/FGGroundReactions.h @@ -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(); } diff --git a/src/FDM/JSBSim/models/FGMassBalance.cpp b/src/FDM/JSBSim/models/FGMassBalance.cpp index 9e485c1a6..95608f6bf 100644 --- a/src/FDM/JSBSim/models/FGMassBalance.cpp +++ b/src/FDM/JSBSim/models/FGMassBalance.cpp @@ -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; diff --git a/src/FDM/JSBSim/models/FGModel.cpp b/src/FDM/JSBSim/models/FGModel.cpp index cd9a7eabb..fe8039919 100644 --- a/src/FDM/JSBSim/models/FGModel.cpp +++ b/src/FDM/JSBSim/models/FGModel.cpp @@ -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; iFindElement("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 ::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 ::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; diff --git a/src/FDM/JSBSim/models/FGModel.h b/src/FDM/JSBSim/models/FGModel.h index 5f3ac9489..d107d28a5 100644 --- a/src/FDM/JSBSim/models/FGModel.h +++ b/src/FDM/JSBSim/models/FGModel.h @@ -38,8 +38,8 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGJSBBase.h" #include "math/FGFunction.h" +#include "math/FGModelFunctions.h" #include #include @@ -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 PreFunctions; - std::vector PostFunctions; - - std::vector interface_properties; }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/FGPropagate.cpp b/src/FDM/JSBSim/models/FGPropagate.cpp index ebb83211b..1e11074f9 100644 --- a/src/FDM/JSBSim/models/FGPropagate.cpp +++ b/src/FDM/JSBSim/models/FGPropagate.cpp @@ -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 - - 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; @@ -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(); } diff --git a/src/FDM/JSBSim/models/FGPropagate.h b/src/FDM/JSBSim/models/FGPropagate.h index 404946791..be8ebd224 100644 --- a/src/FDM/JSBSim/models/FGPropagate.h +++ b/src/FDM/JSBSim/models/FGPropagate.h @@ -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 dqPQRdot; - deque dqUVWdot; + deque dqUVWidot; deque dqInertialVelocity; - deque dqQtrndot; + deque 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); }; diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp index bd3b09f0a..f0fbe04b3 100644 --- a/src/FDM/JSBSim/models/FGPropulsion.cpp +++ b/src/FDM/JSBSim/models/FGPropulsion.cpp @@ -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; } diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp index 8e713589f..6cdf9ab83 100644 --- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp @@ -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; iHasNode(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. diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h index 27186fb6d..7889cd948 100644 --- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h +++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h @@ -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 InputNodes; + std::vector InputNames; std::vector InputSigns; std::vector output_array; std::string Type; diff --git a/src/FDM/JSBSim/models/flight_control/FGSummer.cpp b/src/FDM/JSBSim/models/flight_control/FGSummer.cpp index 40e675351..b67cbf70d 100644 --- a/src/FDM/JSBSim/models/flight_control/FGSummer.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGSummer.cpp @@ -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;igetName() << 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) { diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp index b1459ebad..1138d820c 100644 --- a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp @@ -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(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.h b/src/FDM/JSBSim/models/propulsion/FGElectric.h index 7bcdb406f..268522956 100644 --- a/src/FDM/JSBSim/models/propulsion/FGElectric.h +++ b/src/FDM/JSBSim/models/propulsion/FGElectric.h @@ -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); diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp index abaf368e2..6cc525a53 100644 --- a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp @@ -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); diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.h b/src/FDM/JSBSim/models/propulsion/FGEngine.h index 8a3f51a8e..c25eebfc0 100644 --- a/src/FDM/JSBSim/models/propulsion/FGEngine.h +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.h @@ -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. @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 SourceTanks; + void Debug(int from); }; } diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp index 77dcf245a..b225563c2 100644 --- a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp @@ -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(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.h b/src/FDM/JSBSim/models/propulsion/FGPiston.h index a008e6a73..13072afac 100644 --- a/src/FDM/JSBSim/models/propulsion/FGPiston.h +++ b/src/FDM/JSBSim/models/propulsion/FGPiston.h @@ -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); diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp index 52ab88cb2..87c76685f 100644 --- a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp @@ -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(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.h b/src/FDM/JSBSim/models/propulsion/FGRocket.h index 8692a5c1a..38e367510 100644 --- a/src/FDM/JSBSim/models/propulsion/FGRocket.h +++ b/src/FDM/JSBSim/models/propulsion/FGRocket.h @@ -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.*/ diff --git a/src/FDM/JSBSim/models/propulsion/FGThruster.cpp b/src/FDM/JSBSim/models/propulsion/FGThruster.cpp index 064177a2b..5af8c1ddd 100644 --- a/src/FDM/JSBSim/models/propulsion/FGThruster.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGThruster.cpp @@ -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); diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp index c61667b4b..485c01c94 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp @@ -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; } } diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.h b/src/FDM/JSBSim/models/propulsion/FGTurbine.h index 1fff92c67..62c6d321a 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTurbine.h +++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.h @@ -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 @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. diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp index f384877fc..981319961 100755 --- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp @@ -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(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.h b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h index 66febb191..c73c0b765 100755 --- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.h +++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h @@ -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);} -- 2.39.5