]> git.mxchange.org Git - flightgear.git/commitdiff
Sync. with JSBSim CVS
authorErik Hofman <erik@ehofman.com>
Sun, 19 Sep 2010 09:16:29 +0000 (11:16 +0200)
committerErik Hofman <erik@ehofman.com>
Sun, 19 Sep 2010 09:16:29 +0000 (11:16 +0200)
46 files changed:
src/FDM/JSBSim/FGFDMExec.cpp
src/FDM/JSBSim/initialization/FGInitialCondition.cpp
src/FDM/JSBSim/initialization/FGTrimAxis.h
src/FDM/JSBSim/input_output/FGXMLElement.cpp
src/FDM/JSBSim/input_output/string_utilities.h
src/FDM/JSBSim/math/FGFunction.cpp
src/FDM/JSBSim/math/FGLocation.cpp
src/FDM/JSBSim/math/FGLocation.h
src/FDM/JSBSim/math/FGMatrix33.h
src/FDM/JSBSim/math/FGPropertyValue.cpp
src/FDM/JSBSim/math/FGPropertyValue.h
src/FDM/JSBSim/math/FGTable.cpp
src/FDM/JSBSim/math/FGTable.h
src/FDM/JSBSim/math/Makefile.am
src/FDM/JSBSim/models/FGAerodynamics.cpp
src/FDM/JSBSim/models/FGAircraft.cpp
src/FDM/JSBSim/models/FGAtmosphere.cpp
src/FDM/JSBSim/models/FGAtmosphere.h
src/FDM/JSBSim/models/FGBuoyantForces.cpp
src/FDM/JSBSim/models/FGExternalReactions.cpp
src/FDM/JSBSim/models/FGFCS.cpp
src/FDM/JSBSim/models/FGFCS.h
src/FDM/JSBSim/models/FGGroundReactions.cpp
src/FDM/JSBSim/models/FGGroundReactions.h
src/FDM/JSBSim/models/FGMassBalance.cpp
src/FDM/JSBSim/models/FGModel.cpp
src/FDM/JSBSim/models/FGModel.h
src/FDM/JSBSim/models/FGPropagate.cpp
src/FDM/JSBSim/models/FGPropagate.h
src/FDM/JSBSim/models/FGPropulsion.cpp
src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
src/FDM/JSBSim/models/flight_control/FGSummer.cpp
src/FDM/JSBSim/models/propulsion/FGElectric.cpp
src/FDM/JSBSim/models/propulsion/FGElectric.h
src/FDM/JSBSim/models/propulsion/FGEngine.cpp
src/FDM/JSBSim/models/propulsion/FGEngine.h
src/FDM/JSBSim/models/propulsion/FGPiston.cpp
src/FDM/JSBSim/models/propulsion/FGPiston.h
src/FDM/JSBSim/models/propulsion/FGRocket.cpp
src/FDM/JSBSim/models/propulsion/FGRocket.h
src/FDM/JSBSim/models/propulsion/FGThruster.cpp
src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
src/FDM/JSBSim/models/propulsion/FGTurbine.h
src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
src/FDM/JSBSim/models/propulsion/FGTurboProp.h

index 5226a3e37ab8f7c901a90563424d1ff2c1f7ea87..4cba2d0f9f3aa391485866edaa6db6525b1086af 100644 (file)
@@ -71,7 +71,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.79 2010/07/25 13:52:20 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.80 2010/08/21 22:56:10 jberndt Exp $";
 static const char *IdHdr = ID_FDMEXEC;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -683,11 +683,21 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
          << fgdef << endl;
   }
 
-  struct PropertyCatalogStructure masterPCS;
-  masterPCS.base_string = "";
-  masterPCS.node = (FGPropertyManager*)Root;
+  // Late bind previously undefined FCS inputs.
+  try {
+    FCS->LateBind();
+  } catch (string prop) {
+    cerr << endl << fgred << "  Could not late bind property " << prop 
+         << ". Aborting." << endl;
+    result = false;
+  }
 
-  BuildPropertyCatalog(&masterPCS);
+  if (result) {
+    struct PropertyCatalogStructure masterPCS;
+    masterPCS.base_string = "";
+    masterPCS.node = (FGPropertyManager*)Root;
+    BuildPropertyCatalog(&masterPCS);
+  }
 
   return result;
 }
index 2d8f8a67393192c06d109c72541be98852a91c57..ed17c6944aa0b46fa60343d6c5812697fa04a314 100644 (file)
@@ -62,7 +62,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.40 2010/06/02 04:05:13 jberndt Exp $";
+static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.44 2010/09/18 22:48:12 jberndt Exp $";
 static const char *IdHdr = ID_INITIALCONDITION;
 
 //******************************************************************************
@@ -966,10 +966,19 @@ bool FGInitialCondition::Load_v2(void)
   bool result = true;
   FGInertial* Inertial = fdmex->GetInertial();
   FGPropagate* Propagate = fdmex->GetPropagate();
+  FGColumnVector3 vOmegaEarth = FGColumnVector3(0.0, 0.0, Inertial->omega());
 
   if (document->FindElement("earth_position_angle")) {
     double epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD");
     Inertial->SetEarthPositionAngle(epa);
+    Propagate->GetVState()->vLocation.SetEarthPositionAngle(epa);
+  }
+
+  Propagate->SetSeaLevelRadius(GetSeaLevelRadiusFtIC());
+
+  if (document->FindElement("elevation")) {
+    SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT"));
+    Propagate->SetTerrainElevation(terrain_elevation);
   }
 
   // Initialize vehicle position
@@ -983,25 +992,28 @@ bool FGInitialCondition::Load_v2(void)
     vLoc = position->FindElementTripletConvertTo("FT");
     string frame = position->GetAttributeValue("frame");
     frame = to_lower(frame);
-    if (frame == "eci") {
-      // Need to transform vLoc to ECEF for storage and use in FGLocation.
+    if (frame == "eci") { // Need to transform vLoc to ECEF for storage and use in FGLocation.
       vLoc = Propagate->GetTi2ec()*vLoc;
+      Propagate->SetLocation(vLoc);
     } else if (frame == "ecef") {
-      // Move vLoc query until after lat/lon/alt query to eliminate spurious warning msgs.
+      double AltitudeASL = 0.0;
       if (vLoc.Magnitude() == 0.0) {
-        Propagate->SetLatitudeDeg(position->FindElementValueAsNumberConvertTo("latitude", "DEG"));
-        Propagate->SetLongitudeDeg(position->FindElementValueAsNumberConvertTo("longitude", "DEG"));
         if (position->FindElement("radius")) {
-          radius_to_vehicle = position->FindElementValueAsNumberConvertTo("radius", "FT");
-          SetAltitudeASLFtIC(radius_to_vehicle - sea_level_radius);
+          AltitudeASL = position->FindElementValueAsNumberConvertTo("radius", "FT") - sea_level_radius;
         } else if (position->FindElement("altitudeAGL")) {
-          SetAltitudeAGLFtIC(position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
+          AltitudeASL = terrain_elevation + position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT");
         } else if (position->FindElement("altitudeMSL")) {
-          SetAltitudeASLFtIC(position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
+          AltitudeASL = position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT");
         } else {
           cerr << endl << "  No altitude or radius initial condition is given." << endl;
           result = false;
         }
+        Propagate->SetPosition(
+                         position->FindElementValueAsNumberConvertTo("longitude", "RAD"),
+                         position->FindElementValueAsNumberConvertTo("latitude", "RAD"),
+                         AltitudeASL + GetSeaLevelRadiusFtIC());
+      } else {
+        Propagate->SetLocation(vLoc);
       }
     } else {
       cerr << endl << "  Neither ECI nor ECEF frame is specified for initial position." << endl;
@@ -1038,11 +1050,11 @@ bool FGInitialCondition::Load_v2(void)
   // ToDo: Do we need to deal with normalization of the quaternions here?
 
   Element* orientation_el = document->FindElement("orientation");
+  FGQuaternion QuatI2Body;
   if (orientation_el) {
     string frame = orientation_el->GetAttributeValue("frame");
     frame = to_lower(frame);
     vOrient = orientation_el->FindElementTripletConvertTo("RAD");
-    FGQuaternion QuatI2Body;
     if (frame == "eci") {
 
       QuatI2Body = FGQuaternion(vOrient);
@@ -1088,10 +1100,10 @@ bool FGInitialCondition::Load_v2(void)
       result = false;
 
     }
-
-    Propagate->SetInertialOrientation(QuatI2Body);
   }
 
+  Propagate->SetInertialOrientation(QuatI2Body);
+
   // Initialize vehicle velocity
   // Allowable frames
   // - ECI (Earth Centered Inertial)
@@ -1103,23 +1115,23 @@ bool FGInitialCondition::Load_v2(void)
   Element* velocity_el = document->FindElement("velocity");
   FGColumnVector3 vInertialVelocity;
   FGColumnVector3 vInitVelocity = FGColumnVector3(0.0, 0.0, 0.0);
+  FGColumnVector3 omega_cross_r = vOmegaEarth * Propagate->GetInertialPosition();
+  FGMatrix33 mTl2i = Propagate->GetTl2i();
+  FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e
+  FGMatrix33 mTb2i = Propagate->GetTb2i();
   if (velocity_el) {
 
     string frame = velocity_el->GetAttributeValue("frame");
     frame = to_lower(frame);
     FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo("FT/SEC");
-    FGColumnVector3 omega_cross_r = Inertial->omega() * Propagate->GetInertialPosition();
 
     if (frame == "eci") {
       vInertialVelocity = vInitVelocity;
     } else if (frame == "ecef") {
-      FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e
       vInertialVelocity = mTec2i * vInitVelocity + omega_cross_r;
     } else if (frame == "local") {
-      FGMatrix33 mTl2i = Propagate->GetTl2i();
       vInertialVelocity = mTl2i * vInitVelocity + omega_cross_r;
     } else if (frame == "body") {
-      FGMatrix33 mTb2i = Propagate->GetTb2i();
       vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r;
     } else {
 
@@ -1131,13 +1143,13 @@ bool FGInitialCondition::Load_v2(void)
 
   } else {
 
-    FGMatrix33 mTb2i = Propagate->GetTb2i();
-    vInertialVelocity = mTb2i * vInitVelocity + (Inertial->omega() * Propagate->GetInertialPosition());
+    vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r;
 
   }
 
   Propagate->SetInertialVelocity(vInertialVelocity);
 
+  // Initialize vehicle body rates
   // Allowable frames
   // - ECI (Earth Centered Inertial)
   // - ECEF (Earth Centered, Earth Fixed)
@@ -1145,6 +1157,13 @@ bool FGInitialCondition::Load_v2(void)
   
   FGColumnVector3 vInertialRate;
   Element* attrate_el = document->FindElement("attitude_rate");
+  double radInv = 1.0/Propagate->GetRadius();
+  FGColumnVector3 vVel = Propagate->GetVel();
+  FGColumnVector3 vOmegaLocal = FGColumnVector3(
+   radInv*vVel(eEast),
+  -radInv*vVel(eNorth),
+  -radInv*vVel(eEast)*Propagate->GetLocation().GetTanLatitude() );
+
   if (attrate_el) {
 
     string frame = attrate_el->GetAttributeValue("frame");
@@ -1154,11 +1173,9 @@ bool FGInitialCondition::Load_v2(void)
     if (frame == "eci") {
       vInertialRate = vAttRate;
     } else if (frame == "ecef") {
-//      vInertialRate = vAttRate + Inertial->omega(); 
-    } else if (frame == "body") {
-    //Todo: determine local frame rate
-      FGMatrix33 mTb2l = Propagate->GetTb2l();
-//      vInertialRate = mTb2l*vAttRate + Inertial->omega();
+      vInertialRate = vAttRate + vOmegaEarth; 
+    } else if (frame == "local") {
+      vInertialRate = vOmegaEarth + Propagate->GetTl2i() * vOmegaLocal + Propagate->GetTb2i() * vAttRate;
     } else if (!frame.empty()) { // misspelling of frame
       
       cerr << endl << fgred << "  Attitude rate frame type: \"" << frame
@@ -1170,21 +1187,10 @@ bool FGInitialCondition::Load_v2(void)
     }
     
   } else { // Body frame attitude rate assumed 0 relative to local.
-/*
-    //Todo: determine local frame rate
-
-    FGMatrix33 mTi2l = Propagate->GetTi2l();
-    vVel = mTi2l * vInertialVelocity;
-
-    // Compute the local frame ECEF velocity
-    vVel = Tb2l * VState.vUVW;
-
-    FGColumnVector3 vOmegaLocal = FGColumnVector3(
-       radInv*vVel(eEast),
-      -radInv*vVel(eNorth),
-      -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
-*/  
+      vInertialRate = vOmegaEarth + Propagate->GetTl2i() * vOmegaLocal;
   }
+  Propagate->SetInertialRates(vInertialRate);
+  Propagate->InitializeDerivatives();
 
   // Check to see if any engines are specified to be initialized in a running state
   FGPropulsion* propulsion = fdmex->GetPropulsion();
index 9fc7cebb9b5dab021c7834db3f13cd2e99ad81ca..afd516782e4f225984b37e0a51e2f5e1d80b8c6b 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.4 2006/10/01 22:47:47 jberndt Exp $"
+#define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.5 2010/09/07 18:36:29 andgi Exp $"
 
 #define DEFAULT_TOLERANCE 0.001
 
@@ -58,10 +58,10 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
-const string StateNames[10]=   { "all","udot","vdot","wdot","qdot","pdot","rdot",
+const string StateNames[=   { "all","udot","vdot","wdot","qdot","pdot","rdot",
                                 "hmgt","nlf" 
                               };
-const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack",
+const string ControlNames[] =  { "Throttle","Sideslip","Angle of Attack",
                                  "Elevator","Ailerons","Rudder",
                                  "Altitude AGL", "Pitch Angle",
                                  "Roll Angle", "Flight Path Angle", 
index 0c3e91063d96e7f3dabfde3cc92ded234a9a57f1..3f7becc5c4768ed4bd208cdea7a5ee1241f6b5a3 100755 (executable)
@@ -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;
index f2dc22090272ddb1480cc4a8edde9a398ab3f76b..b55073f8b910e1504380587ef1988403bdfb9b0f 100644 (file)
@@ -40,12 +40,13 @@ INCLUDES
 
 #include <string>
 #include <vector>
+#include <stdio.h>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.13 2010/07/07 11:59:48 jberndt Exp $"
+#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.14 2010/08/21 17:13:47 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -69,6 +70,8 @@ CLASS DECLARATION
   extern std::string& to_lower(std::string& str);
   extern bool is_number(const std::string& str);
   std::vector <std::string> split(std::string str, char d);
+  extern std::string to_string(int);
+  extern std::string replace(std::string str, const std::string& old, const std::string& newstr);
 #else
   #include <cctype>
 
@@ -148,6 +151,24 @@ CLASS DECLARATION
     return str_array;
   }
 
+  string to_string(int i)
+  {
+    char buffer[32];
+    sprintf(buffer, "%d", i);
+    return string(buffer);
+  }
+
+  string replace(string str, const string& oldstr, const string& newstr)
+  {
+    int old_idx;
+    string temp;
+    old_idx = str.find(oldstr);
+    if (old_idx >= 0) {
+      temp = str.replace(old_idx, 1, newstr);
+    }
+    return temp;
+  }
+
 #endif
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 183654e2e54b0217aef2598a7b791947db0f199d..9ad7c7a9974ad66ba87eb02f36ce465946e7fc0a 100755 (executable)
@@ -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);
   }
index f3c4d88bc91e15bfad0b04eb90569c3ebcff295b..9e0a62a23dd24d7dd5e7e064afd5682517c2d0b6 100644 (file)
@@ -45,9 +45,10 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGLocation.cpp,v 1.21 2010/07/02 01:48:12 jberndt Exp $";
+static const char *IdSrc = "$Id: FGLocation.cpp,v 1.22 2010/09/18 22:47:17 jberndt Exp $";
 static const char *IdHdr = ID_LOCATION;
-
+using std::cerr;
+using std::endl;
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -103,10 +104,6 @@ FGLocation::FGLocation(double lon, double lat, double radius)
                             radius*cosLat*sinLon,
                             radius*sinLat );
   mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
-  
-//  initial_longitude = 0.0
-
-  ComputeDerived();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -182,7 +179,6 @@ void FGLocation::SetPosition(double lon, double lat, double radius)
   mECLoc = FGColumnVector3( radius*cosLat*cosLon,
                             radius*cosLat*sinLon,
                             radius*sinLat );
-  ComputeDerived();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -202,7 +198,6 @@ void FGLocation::SetPositionGeodetic(double lon, double lat, double height)
   mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon);
   mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon);
   mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat);
-
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -228,6 +223,7 @@ void FGLocation::SetEllipse(double semimajor, double semiminor)
 
 const FGMatrix33& FGLocation::GetTec2i(void)
 {
+  ComputeDerived();
   return mTec2i;
 }
 
@@ -240,6 +236,7 @@ const FGMatrix33& FGLocation::GetTec2i(void)
 
 const FGMatrix33& FGLocation::GetTi2ec(void)
 {
+  ComputeDerived();
   return mTi2ec;
 }
 
@@ -331,7 +328,8 @@ void FGLocation::ComputeDerivedUnconditional(void) const
     if (q>0)
     {
       u  = p/sqrt_q;
-      u2 = p2/q;
+//      u2 = p2/q;
+      u2 = u*u;
       v  = b2*u2/q;
       P  = 27.0*v*s/q;
       Q0 = sqrt(P+1) + sqrt(P);
@@ -340,7 +338,11 @@ void FGLocation::ComputeDerivedUnconditional(void) const
       c  = sqrt(u2 - 1 + 2.0*t);
       w  = (c - u)/2.0;
       signz0 = mECLoc(eZ)>=0?1.0:-1.0;
-      z  = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
+      if ((sqrt(t*t+v)-u*w-0.5*t-0.25) < 0.0) {
+        z = 0.0;
+      } else {
+        z  = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
+      }
       Ne = a*sqrt(1+eps2*z*z/b2);
       mGeodLat = asin((eps2+1.0)*(z/Ne));
       r0 = rxy;
index 2112557de1e5725353ce3bbc665600530246033c..46a1b0d9994242f07bbf030529529c676771be72 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_LOCATION "$Id: FGLocation.h,v 1.23 2010/08/04 07:28:21 ehofman Exp $"
+#define ID_LOCATION "$Id: FGLocation.h,v 1.25 2010/09/18 22:47:24 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -142,7 +142,7 @@ CLASS DOCUMENTATION
     @see W. C. Durham "Aircraft Dynamics & Control", section 2.2
 
     @author Mathias Froehlich
-    @version $Id: FGLocation.h,v 1.23 2010/08/04 07:28:21 ehofman Exp $
+    @version $Id: FGLocation.h,v 1.25 2010/09/18 22:47:24 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -259,7 +259,7 @@ public:
       Inertial frame.
       @param EPA Earth fixed frame (ECEF) rotation offset about the axis with
                  respect to the Inertial (ECI) frame in radians. */
-  void SetEarthPositionAngle(double EPA) {epa = EPA; mCacheValid = false; ComputeDerived();}
+  void SetEarthPositionAngle(double EPA) {epa = EPA; mCacheValid = false;}
 
   /** Get the longitude.
       @return the longitude in rad of the location represented with this
@@ -304,7 +304,7 @@ public:
   double GetGeodLatitudeDeg(void) const { ComputeDerived(); return radtodeg*mGeodLat; }
 
   /** Gets the geodetic altitude in feet. */
-  double GetGeodAltitude(void) const { return GeodeticAltitude;}
+  double GetGeodAltitude(void) const {ComputeDerived(); return GeodeticAltitude;}
 
   /** Get the sine of Latitude. */
   double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); }
@@ -349,9 +349,9 @@ public:
       the earth centered frame to the inertial frame (ECEF to ECI). */
   const FGMatrix33& GetTec2i(void);
 
-  const FGMatrix33& GetTi2l(void) const {return mTi2l;}
+  const FGMatrix33& GetTi2l(void) const {ComputeDerived(); return mTi2l;}
 
-  const FGMatrix33& GetTl2i(void) const {return mTl2i;}
+  const FGMatrix33& GetTl2i(void) const {ComputeDerived(); return mTl2i;}
 
   /** Conversion from Local frame coordinates to a location in the
       earth centered and fixed frame.
@@ -450,6 +450,8 @@ public:
     f = l.f;
 
     initial_longitude = l.initial_longitude;
+    mGeodLat = l.mGeodLat;
+    GeodeticAltitude = l.GeodeticAltitude;
 
     return *this;
   }
index 7af43031b26d7e52776e15788f9a460b090fd39e..d937f910a2f240c783625b83ee4e9fe2a0bde9e2 100644 (file)
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.11 2010/06/30 03:13:40 jberndt Exp $"
+#define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.12 2010/08/21 17:13:47 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -111,7 +111,8 @@ public:
 
       Create copy of the matrix given in the argument.
    */
-  FGMatrix33(const FGMatrix33& M) {
+  FGMatrix33(const FGMatrix33& M)
+  {
     data[0] = M.data[0];
     data[1] = M.data[1];
     data[2] = M.data[2];
@@ -122,7 +123,7 @@ public:
     data[7] = M.data[7];
     data[8] = M.data[8];
 
-//    Debug(0);
+    // Debug(0);
   }
 
   /** Initialization by given values.
index 66f89b89a6d9bde03658758e37f728ab7106ee52..0824a607b93e506cd61c0dfe524b65bf3099dfd1 100755 (executable)
@@ -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;
 }
 
 }
index 3466c66ba4e7cd52cad76c6b3daba56258784a62..753df7c624f14ca36065bc17593cce8810c6bd1b 100755 (executable)
@@ -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
index 2d604dca21aff37c0b315fa9b91dbbce2af94096..3f23fd1446ed94a0615f906ee5ea7ea9cee9187c 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGTable.cpp,v 1.21 2010/04/07 03:08:37 jberndt Exp $";
+static const char *IdSrc = "$Id: FGTable.cpp,v 1.23 2010/09/16 11:01:24 jberndt Exp $";
 static const char *IdHdr = ID_TABLE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -68,6 +68,20 @@ FGTable::FGTable(int NRows) : nRows(NRows), nCols(1), PropertyManager(0)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols), PropertyManager(0)
+{
+  Type = tt2D;
+  colCounter = 1;
+  rowCounter = 0;
+  nTables = 0;
+
+  Data = Allocate();
+  Debug(0);
+  lastRowIndex=lastColumnIndex=2;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 FGTable::FGTable(const FGTable& t) : PropertyManager(t.PropertyManager)
 {
   Type = t.Type;
@@ -165,7 +179,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
       node = PropertyManager->GetNode(property_string);
 
       if (node == 0) {
-        throw("IndependenVar property, " + property_string + " in Table definition is not defined.");
+        throw("IndependentVar property, " + property_string + " in Table definition is not defined.");
       }
 
       lookup_axis = axisElement->GetAttributeValue("lookup");
index e96cf07fea67495d95fb4a47ece653055156ce6b..2f2e271cdf2198318d29c46224c56fe02eda66ba 100644 (file)
@@ -47,7 +47,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TABLE "$Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_TABLE "$Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
 @endcode
 
 @author Jon S. Berndt
-@version $Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $
+@version $Id: FGTable.h,v 1.12 2010/09/16 11:01:24 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -253,6 +253,7 @@ public:
   /// The constructor for a table
   FGTable (FGPropertyManager* propMan, Element* el);
   FGTable (int );
+  FGTable (int, int);
   double GetValue(void) const;
   double GetValue(double key) const;
   double GetValue(double rowKey, double colKey) const;
index 5ae295ede8374994b1bf46424a4a8dd26b328ac1..b97253ac3ffd088480804a81206e7102c8958a6e 100644 (file)
@@ -2,10 +2,10 @@ noinst_LIBRARIES = libMath.a
 
 libMath_a_SOURCES = FGColumnVector3.cpp FGFunction.cpp FGLocation.cpp FGMatrix33.cpp \
                     FGPropertyValue.cpp FGQuaternion.cpp FGRealValue.cpp FGTable.cpp \
-                    FGCondition.cpp FGRungeKutta.cpp
+                    FGCondition.cpp FGRungeKutta.cpp FGModelFunctions.cpp
 
 noinst_HEADERS = FGColumnVector3.h FGFunction.h FGLocation.h FGMatrix33.h \
                  FGParameter.h FGPropertyValue.h FGQuaternion.h FGRealValue.h FGTable.h  \
-                 FGCondition.h FGRungeKutta.h
+                 FGCondition.h FGRungeKutta.h FGModelFunctions.h
 
 INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
index d8c66df201305a18858220a6d5e635b3168ec251..7f5359e98df13028ce2c4baa2f068ecb2a6a7044 100644 (file)
@@ -52,7 +52,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.31 2009/11/28 14:30:11 andgi Exp $";
+static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.32 2010/09/07 00:40:03 jberndt Exp $";
 static const char *IdHdr = ID_AERODYNAMICS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -356,7 +356,7 @@ bool FGAerodynamics::Load(Element *element)
     axis_element = document->FindNextElement("axis");
   }
 
-  FGModel::PostLoad(document); // Perform base class Post-Load
+  PostLoad(document, PropertyManager); // Perform base class Post-Load
 
   return true;
 }
index d292316d6f25445e07a3d15e6b6e82b10eddc7c1..0ed6ac74f33975f09d0dcdca72953d51d0e7ab09 100644 (file)
@@ -68,7 +68,7 @@ DEFINITIONS
 GLOBAL DATA
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.27 2010/07/27 23:18:19 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.28 2010/09/07 00:40:03 jberndt Exp $";
 static const char *IdHdr = ID_AIRCRAFT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -206,7 +206,7 @@ bool FGAircraft::Load(Element* el)
     }
   }
 
-  FGModel::PostLoad(el);
+  PostLoad(el, PropertyManager);
 
   Debug(2);
 
index 2db1c65d931a312ef3db0bf1891722f11231422f..12fb084a70f879c384bcf25f3962d8d0f4f37a9f 100644 (file)
@@ -61,7 +61,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.35 2010/08/11 11:51:33 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.38 2010/09/16 11:01:24 jberndt Exp $";
 static const char *IdHdr = ID_ATMOSPHERE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -100,6 +100,22 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
   vGustNED.InitMatrix();
   vTurbulenceNED.InitMatrix();
 
+  // Milspec turbulence model
+  windspeed_at_20ft = 0.;
+  probability_of_exceedence_index = 0;
+  POE_Table = new FGTable(7,12);
+  // this is Figure 7 from p. 49 of MIL-F-8785C
+  // rows: probability of exceedance curve index, cols: altitude in ft
+  *POE_Table
+           << 500.0 << 1750.0 << 3750.0 << 7500.0 << 15000.0 << 25000.0 << 35000.0 << 45000.0 << 55000.0 << 65000.0 << 75000.0 << 80000.0
+    << 1   <<   3.2 <<    2.2 <<    1.5 <<    0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0
+    << 2   <<   4.2 <<    3.6 <<    3.3 <<    1.6 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0
+    << 3   <<   6.6 <<    6.9 <<    7.4 <<    6.7 <<     4.6 <<     2.7 <<     0.4 <<     0.0 <<     0.0 <<     0.0 <<     0.0 <<     0.0
+    << 4   <<   8.6 <<    9.6 <<   10.6 <<   10.1 <<     8.0 <<     6.6 <<     5.0 <<     4.2 <<     2.7 <<     0.0 <<     0.0 <<     0.0
+    << 5   <<  11.8 <<   13.0 <<   16.0 <<   15.1 <<    11.6 <<     9.7 <<     8.1 <<     8.2 <<     7.9 <<     4.9 <<     3.2 <<     2.1
+    << 6   <<  15.6 <<   17.6 <<   23.0 <<   23.6 <<    22.1 <<    20.0 <<    16.0 <<    15.1 <<    12.1 <<     7.9 <<     6.2 <<     5.1
+    << 7   <<  18.7 <<   21.5 <<   28.4 <<   30.2 <<    30.7 <<    31.0 <<    25.2 <<    23.1 <<    17.5 <<    10.7 <<     8.4 <<     7.2;
+
   bind();
   Debug(0);
 }
@@ -279,7 +295,7 @@ void FGAtmosphere::CalculateDerived(void)
   T_dev = (*temperature) - GetTemperature(h);
 
   if (T_dev == 0.0) density_altitude = h;
-  else              density_altitude = 518.4/0.00357 * (1.0 - pow(GetDensityRatio(),0.235));
+  else              density_altitude = 518.67/0.00356616 * (1.0 - pow(GetDensityRatio(),0.235));
 
   if (turbType != ttNone) Turbulence();
 
@@ -347,6 +363,9 @@ static inline double square_signed (double value)
         return value * value;
 }
 
+/// simply square a value
+static inline double sqr(double x) { return x*x; }
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //
 // psi is the angle that the wind is blowing *towards*
@@ -549,6 +568,134 @@ void FGAtmosphere::Turbulence(void)
     spike = spike * 0.9;
     break;
   }
+  case ttMilspec:
+  case ttTustin: {
+    // an index of zero means turbulence is disabled
+    if (probability_of_exceedence_index == 0) {
+      vTurbulenceNED(1) = vTurbulenceNED(2) = vTurbulenceNED(3) = 0.0;
+      vTurbPQR(1) = vTurbPQR(2) = vTurbPQR(3) = 0.0;
+      return;
+    }
+
+    // Turbulence model according to MIL-F-8785C (Flying Qualities of Piloted Aircraft)
+    double
+      h = Propagate->GetDistanceAGL(),
+      V = Auxiliary->GetVt(), // true airspeed in ft/s
+      b_w = Aircraft->GetWingSpan(),
+      L_u, L_w, sig_u, sig_w;
+
+    // clip height functions at 10 ft
+    if (h <= 10.) h = 10;
+
+    // Scale lengths L and amplitudes sigma as function of height
+    if (h <= 1000) {
+      L_u = h/pow(0.177 + 0.000823*h, 1.2); // MIL-F-8785c, Fig. 10, p. 55
+      L_w = h;
+      sig_w = 0.1*windspeed_at_20ft;
+      sig_u = sig_w/pow(0.177 + 0.000823*h, 0.4); // MIL-F-8785c, Fig. 11, p. 56
+    } else if (h <= 2000) {
+      // linear interpolation between low altitude and high altitude models
+      L_u = L_w = 1000 + (h-1000.)/1000.*750.;
+      sig_u = sig_w = 0.1*windspeed_at_20ft
+                    + (h-1000.)/1000.*(POE_Table->GetValue(probability_of_exceedence_index, h) - 0.1*windspeed_at_20ft);
+    } else {
+      L_u = L_w = 1750.; //  MIL-F-8785c, Sec. 3.7.2.1, p. 48
+      sig_u = sig_w = POE_Table->GetValue(probability_of_exceedence_index, h);
+    }
+
+    // keep values from last timesteps
+    // TODO maybe use deque?
+    static double
+      xi_u_km1 = 0, nu_u_km1 = 0,
+      xi_v_km1 = 0, xi_v_km2 = 0, nu_v_km1 = 0, nu_v_km2 = 0,
+      xi_w_km1 = 0, xi_w_km2 = 0, nu_w_km1 = 0, nu_w_km2 = 0,
+      xi_p_km1 = 0, nu_p_km1 = 0,
+      xi_q_km1 = 0, xi_r_km1 = 0;
+
+
+    double
+      T_V = DeltaT, // for compatibility of nomenclature
+      sig_p = 1.9/sqrt(L_w*b_w)*sig_w, // Yeager1998, eq. (8)
+      sig_q = sqrt(M_PI/2/L_w/b_w), // eq. (14)
+      sig_r = sqrt(2*M_PI/3/L_w/b_w), // eq. (17)
+      L_p = sqrt(L_w*b_w)/2.6, // eq. (10)
+      tau_u = L_u/V, // eq. (6)
+      tau_w = L_w/V, // eq. (3)
+      tau_p = L_p/V, // eq. (9)
+      tau_q = 4*b_w/M_PI/V, // eq. (13)
+      tau_r =3*b_w/M_PI/V, // eq. (17)
+      nu_u = GaussianRandomNumber(),
+      nu_v = GaussianRandomNumber(),
+      nu_w = GaussianRandomNumber(),
+      nu_p = GaussianRandomNumber(),
+      xi_u, xi_v, xi_w, xi_p, xi_q, xi_r;
+
+    // values of turbulence NED velocities
+
+    if (turbType == ttTustin) {
+      // the following is the Tustin formulation of Yeager's report
+      double
+        omega_w = V/L_w, // hidden in nomenclature p. 3
+        omega_v = V/L_u, // this is defined nowhere
+        C_BL  = 1/tau_u/tan(T_V/2/tau_u), // eq. (19)
+        C_BLp = 1/tau_p/tan(T_V/2/tau_p), // eq. (22)
+        C_BLq = 1/tau_q/tan(T_V/2/tau_q), // eq. (24)
+        C_BLr = 1/tau_r/tan(T_V/2/tau_r); // eq. (26)
+
+      xi_u = -(1 - C_BL*tau_u)/(1 + C_BL*tau_u)*xi_u_km1
+           + sig_u*sqrt(2*tau_u/T_V)/(1 + C_BL*tau_u)*(nu_u + nu_u_km1); // eq. (18)
+      xi_v = -2*(sqr(omega_v) - sqr(C_BL))/sqr(omega_v + C_BL)*xi_v_km1
+           - sqr(omega_v - C_BL)/sqr(omega_v + C_BL) * xi_v_km2
+           + sig_u*sqrt(3*omega_v/T_V)/sqr(omega_v + C_BL)*(
+                 (C_BL + omega_v/sqrt(3.))*nu_v
+               + 2/sqrt(3.)*omega_v*nu_v_km1
+               + (omega_v/sqrt(3.) - C_BL)*nu_v_km2); // eq. (20) for v
+      xi_w = -2*(sqr(omega_w) - sqr(C_BL))/sqr(omega_w + C_BL)*xi_w_km1
+           - sqr(omega_w - C_BL)/sqr(omega_w + C_BL) * xi_w_km2
+           + sig_w*sqrt(3*omega_w/T_V)/sqr(omega_w + C_BL)*(
+                 (C_BL + omega_w/sqrt(3.))*nu_w
+               + 2/sqrt(3.)*omega_w*nu_w_km1
+               + (omega_w/sqrt(3.) - C_BL)*nu_w_km2); // eq. (20) for w
+      xi_p = -(1 - C_BLp*tau_p)/(1 + C_BLp*tau_p)*xi_p_km1
+           + sig_p*sqrt(2*tau_p/T_V)/(1 + C_BLp*tau_p) * (nu_p + nu_p_km1); // eq. (21)
+      xi_q = -(1 - 4*b_w*C_BLq/M_PI/V)/(1 + 4*b_w*C_BLq/M_PI/V) * xi_q_km1
+           + C_BLq/V/(1 + 4*b_w*C_BLq/M_PI/V) * (xi_w - xi_w_km1); // eq. (23)
+      xi_r = - (1 - 3*b_w*C_BLr/M_PI/V)/(1 + 3*b_w*C_BLr/M_PI/V) * xi_r_km1
+           + C_BLr/V/(1 + 3*b_w*C_BLr/M_PI/V) * (xi_v - xi_v_km1); // eq. (25)
+
+    } else if (turbType == ttMilspec) {
+      // the following is the MIL-STD-1797A formulation
+      // as cited in Yeager's report
+      xi_u = (1 - T_V/tau_u)  *xi_u_km1 + sig_u*sqrt(2*T_V/tau_u)*nu_u;  // eq. (30)
+      xi_v = (1 - 2*T_V/tau_u)*xi_v_km1 + sig_u*sqrt(4*T_V/tau_u)*nu_v;  // eq. (31)
+      xi_w = (1 - 2*T_V/tau_w)*xi_w_km1 + sig_w*sqrt(4*T_V/tau_w)*nu_w;  // eq. (32)
+      xi_p = (1 - T_V/tau_p)  *xi_p_km1 + sig_p*sqrt(2*T_V/tau_p)*nu_p;  // eq. (33)
+      xi_q = (1 - T_V/tau_q)  *xi_q_km1 + M_PI/4/b_w*(xi_w - xi_w_km1);  // eq. (34)
+      xi_r = (1 - T_V/tau_r)  *xi_r_km1 + M_PI/3/b_w*(xi_v - xi_v_km1);  // eq. (35)
+    }
+
+    // rotate by wind azimuth and assign the velocities
+    double cospsi = cos(psiw), sinpsi = sin(psiw);
+    vTurbulenceNED(1) =  cospsi*xi_u + sinpsi*xi_v;
+    vTurbulenceNED(2) = -sinpsi*xi_u + cospsi*xi_v;
+    vTurbulenceNED(3) = xi_w;
+
+    vTurbPQR(1) =  cospsi*xi_p + sinpsi*xi_q;
+    vTurbPQR(2) = -sinpsi*xi_p + cospsi*xi_q;
+    vTurbPQR(3) = xi_r;
+
+    // vTurbPQR is in the body fixed frame, not NED
+    vTurbPQR = Propagate->GetTl2b()*vTurbPQR;
+
+    // hand on the values for the next timestep
+    xi_u_km1 = xi_u; nu_u_km1 = nu_u;
+    xi_v_km2 = xi_v_km1; xi_v_km1 = xi_v; nu_v_km2 = nu_v_km1; nu_v_km1 = nu_v;
+    xi_w_km2 = xi_w_km1; xi_w_km1 = xi_w; nu_w_km2 = nu_w_km1; nu_w_km1 = nu_w;
+    xi_p_km1 = xi_p; nu_p_km1 = nu_p;
+    xi_q_km1 = xi_q;
+    xi_r_km1 = xi_r;
+
+  }
   default:
     break;
   }
@@ -634,6 +781,14 @@ void FGAtmosphere::bind(void)
   PropertyManager->Tie("atmosphere/turb-gain", this, &FGAtmosphere::GetTurbGain, &FGAtmosphere::SetTurbGain);
   PropertyManager->Tie("atmosphere/turb-rhythmicity", this, &FGAtmosphere::GetRhythmicity,
                                                             &FGAtmosphere::SetRhythmicity);
+
+  PropertyManager->Tie("atmosphere/turbulence/milspec/windspeed_at_20ft_AGL-fps",
+                       this, &FGAtmosphere::GetWindspeed20ft,
+                             &FGAtmosphere::SetWindspeed20ft);
+  PropertyManager->Tie("atmosphere/turbulence/milspec/severity",
+                       this, &FGAtmosphere::GetProbabilityOfExceedence,
+                             &FGAtmosphere::SetProbabilityOfExceedence);
+
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 84d3f072a33857c063152dc63f0315eddad232b9..d6561fa86206547edf9edaf5d2690f55968d9cec 100644 (file)
@@ -44,12 +44,13 @@ INCLUDES
 
 #include "FGModel.h"
 #include "math/FGColumnVector3.h"
+#include "math/FGTable.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $"
+#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.23 2010/09/16 11:01:24 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -63,9 +64,60 @@ CLASS DOCUMENTATION
 
 /** Models the 1976 Standard Atmosphere.
     @author Tony Peden, Jon Berndt
-    @version $Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $
+    @version $Id: FGAtmosphere.h,v 1.23 2010/09/16 11:01:24 jberndt Exp $
     @see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
          1989, ISBN 0-07-001641-0
+
+    Additionally, various turbulence models are available. They are specified
+    via the property <tt>atmosphere/turb-type</tt>. The following models are
+    available:
+    - 0: ttNone (turbulence disabled)
+    - 1: ttStandard
+    - 2: ttBerndt
+    - 3: ttCulp
+    - 4: ttMilspec (Dryden spectrum)
+    - 5: ttTustin (Dryden spectrum)
+
+    The Milspec and Tustin models are described in the Yeager report cited below.
+    They both use a Dryden spectrum model whose parameters (scale lengths and intensities)
+    are modelled according to MIL-F-8785C. Parameters are modelled differently
+    for altitudes below 1000ft and above 2000ft, for altitudes in between they
+    are interpolated linearly.
+
+    The two models differ in the implementation of the transfer functions
+    described in the milspec.
+
+    To use one of these two models, set <tt>atmosphere/turb-type</tt> to 4 resp. 5,
+    and specify values for <tt>atmosphere/turbulence/milspec/windspeed_at_20ft_AGL-fps<tt>
+    and <tt>atmosphere/turbulence/milspec/severity<tt> (the latter corresponds to
+    the probability of exceedence curves from Fig.&nbsp;7 of the milspec, allowable
+    range is 0 (disabled) to 7). <tt>atmosphere/psiw-rad</tt> is respected as well;
+    note that you have to specify a positive wind magnitude to prevent psiw from
+    being reset to zero.
+
+    Reference values (cf. figures 7 and 9 from the milspec):
+    <table>
+      <tr><td><b>Intensity</b></td>
+          <td><b><tt>windspeed_at_20ft_AGL-fps</tt></b></td>
+          <td><b><tt>severity</tt></b></td></tr>
+      <tr><td>light</td>
+          <td>25 (15 knots)</td>
+          <td>3</td></tr>
+      <tr><td>moderate</td>
+          <td>50 (30 knots)</td>
+          <td>4</td></tr>
+      <tr><td>severe</td>
+          <td>75 (45 knots)</td>
+          <td>6</td></tr>
+    </table>
+
+    @see Yeager, Jessie C.: "Implementation and Testing of Turbulence Models for
+         the F18-HARV" (<a
+         href="http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19980028448_1998081596.pdf">
+         pdf</a>), NASA CR-1998-206937, 1998
+
+    @see MIL-F-8785C: Military Specification: Flying Qualities of Piloted Aircraft
+
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -83,7 +135,7 @@ public:
       @return false if no error */
   bool Run(void);
   bool InitModel(void);
-  enum tType {ttNone, ttStandard, ttBerndt, ttCulp} turbType;
+  enum tType {ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin} turbType;
 
   /// Returns the temperature in degrees Rankine.
   double GetTemperature(void) const {return *temperature;}
@@ -209,7 +261,7 @@ public:
   /// Retrieves the gust components in NED frame.
   FGColumnVector3& GetGustNED(void) {return vGustNED;}
 
-  /** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp */
+  /** Turbulence models available: ttNone, ttStandard, ttBerndt, ttCulp, ttMilspec, ttTustin */
   void   SetTurbType(tType tt) {turbType = tt;}
   tType  GetTurbType() const {return turbType;}
 
@@ -227,6 +279,13 @@ public:
   FGColumnVector3& GetTurbDirection(void) {return vDirection;}
   FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;}
 
+  void   SetWindspeed20ft(double ws) { windspeed_at_20ft = ws;}
+  double GetWindspeed20ft() const { return windspeed_at_20ft;}
+
+  /// allowable range: 0-7, 3=light, 4=moderate, 6=severe turbulence
+  void   SetProbabilityOfExceedence( int idx) {probability_of_exceedence_index = idx;}
+  int    GetProbabilityOfExceedence() const { return probability_of_exceedence_index;}
+
 protected:
   double rho;
 
@@ -261,6 +320,11 @@ protected:
   FGColumnVector3 vBodyTurbGrad;
   FGColumnVector3 vTurbPQR;
 
+  // Dryden turbulence model
+  double windspeed_at_20ft; ///< in ft/s
+  int probability_of_exceedence_index; ///< this is bound as the severity property
+  FGTable *POE_Table; ///< probability of exceedence table
+
   double psiw;
   FGColumnVector3 vTotalWindNED;
   FGColumnVector3 vWindNED;
index 64c97ebfb6f520f5cbc418e21f66bebda0601567..1b9a63b74e5907eada749fa3607951babeee0afd 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.12 2010/05/07 18:59:55 andgi Exp $";
+static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.13 2010/09/07 00:40:03 jberndt Exp $";
 static const char *IdHdr = ID_BUOYANTFORCES;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -137,7 +137,7 @@ bool FGBuoyantForces::Load(Element *element)
     gas_cell_element = document->FindNextElement("gas_cell");
   }
   
-  FGModel::PostLoad(element);
+  PostLoad(element, PropertyManager);
 
   if (!NoneDefined) {
     bind();
index 7df087c1e3c576ac95f87bd2488ae592d45b3605..e39f8fb07bf2b83bed5f22d98249731ea0751807 100755 (executable)
@@ -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;
 }
index 4d71ca97db96efbb82d36d9688d0fa4a6faf79ee..368fa90ae4e63fb7067cd876c62a237ebdbdff31 100644 (file)
@@ -63,7 +63,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCS.cpp,v 1.69 2010/08/10 12:39:07 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFCS.cpp,v 1.70 2010/08/21 22:56:11 jberndt Exp $";
 static const char *IdHdr = ID_FCS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -183,6 +183,17 @@ bool FGFCS::InitModel(void)
   return true;
 }
   
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::LateBind(void)
+{
+  int i;
+
+  for (i=0; i<Systems.size(); i++) Systems[i]->LateBind();
+  for (i=0; i<APComponents.size(); i++) APComponents[i]->LateBind();
+  for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->LateBind();
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // Notes: In this logic the default engine commands are set. This is simply a
 // sort of safe-mode method in case the user has not defined control laws for
index 6e10de9c4340d27a28abe93386a8889542f2e4ad..a2b5927688a892c1effc0bc308531bb72d9557ca 100644 (file)
@@ -51,7 +51,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCS "$Id: FGFCS.h,v 1.28 2010/01/18 13:12:25 jberndt Exp $"
+#define ID_FCS "$Id: FGFCS.h,v 1.30 2010/09/05 17:31:40 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -168,7 +168,7 @@ CLASS DOCUMENTATION
     @property gear/tailhook-pos-norm
 
     @author Jon S. Berndt
-    @version $Revision: 1.28 $
+    @version $Revision: 1.30 $
     @see FGActuator
     @see FGDeadBand
     @see FGFCSFunction
@@ -278,8 +278,6 @@ public:
   double GetDaLPos( int form = ofRad )
                          const { return DaLPos[form]; }
 
-  /// @name Aerosurface position retrieval
-  //@{
   /** Gets the right aileron position.
       @return aileron position in radians */
   double GetDaRPos( int form = ofRad )
@@ -547,6 +545,8 @@ public:
 
   FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
 
+  void LateBind(void);
+
 private:
   double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd;
   double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms];
index fdbfa254fb9f05a2fa94282a7b4af1bab446ee88..246cefe8cfef140e1ca53c698b6399c3b502ca23 100644 (file)
@@ -46,7 +46,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.29 2010/07/30 11:50:01 jberndt Exp $";
+static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.30 2010/09/07 00:40:03 jberndt Exp $";
 static const char *IdHdr = ID_GROUNDREACTIONS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -150,7 +150,7 @@ bool FGGroundReactions::Run(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGGroundReactions::GetWOW(void)
+bool FGGroundReactions::GetWOW(void) const
 {
   bool result = false;
   for (unsigned int i=0; i<lGear.size(); i++) {
@@ -195,7 +195,7 @@ bool FGGroundReactions::Load(Element* el)
 
   for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();
 
-  FGModel::PostLoad(el);
+  PostLoad(el, PropertyManager);
 
   return true;
 }
@@ -276,6 +276,7 @@ void FGGroundReactions::bind(void)
 {
   typedef double (FGGroundReactions::*PMF)(int) const;
   PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits);
+  PropertyManager->Tie("gear/wow", this, &FGGroundReactions::GetWOW);
   PropertyManager->Tie("moments/l-gear-lbsft", this, eL, (PMF)&FGGroundReactions::GetMoments);
   PropertyManager->Tie("moments/m-gear-lbsft", this, eM, (PMF)&FGGroundReactions::GetMoments);
   PropertyManager->Tie("moments/n-gear-lbsft", this, eN, (PMF)&FGGroundReactions::GetMoments);
index 5c5ea682c759edbe845f943b3e87938e87f93aa1..a10ff0bb13563ee3ee203c6d5ffe230f7bb0fe1d 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 #include "math/FGColumnVector3.h"
 #include "input_output/FGXMLElement.h"
 
-#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.17 2010/07/30 11:50:01 jberndt Exp $"
+#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.18 2010/09/07 00:40:03 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -106,7 +106,7 @@ public:
   double GetMoments(int idx) const {return vMoments(idx);}
   string GetGroundReactionStrings(string delimeter);
   string GetGroundReactionValues(string delimeter);
-  bool GetWOW(void);
+  bool GetWOW(void) const;
   void UpdateForcesAndMoments(void);
 
   int GetNumGearUnits(void) const { return (int)lGear.size(); }
index 9e485c1a6a6a9bae82a82aaec92038288413bb3e..95608f6bf0bc0c69e61e845044a335957c81a90e 100644 (file)
@@ -51,7 +51,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.32 2010/08/12 04:07:11 jberndt Exp $";
+static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.33 2010/09/07 00:40:03 jberndt Exp $";
 static const char *IdHdr = ID_MASSBALANCE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -156,7 +156,7 @@ bool FGMassBalance::Load(Element* el)
 
   Mass = lbtoslug*Weight;
 
-  FGModel::PostLoad(el);
+  PostLoad(el, PropertyManager);
 
   Debug(2);
   return true;
index cd9a7eabbdb31f9268a9db0290e42c78d5861a43..fe8039919b2addeea9ac37346ef243f231ba89a2 100644 (file)
@@ -57,7 +57,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGModel.cpp,v 1.14 2010/02/25 05:21:36 jberndt Exp $";
+static const char *IdSrc = "$Id: FGModel.cpp,v 1.15 2010/09/07 00:19:38 jberndt Exp $";
 static const char *IdHdr = ID_MODEL;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -71,7 +71,6 @@ CLASS IMPLEMENTATION
 FGModel::FGModel(FGFDMExec* fdmex)
 {
   FDMExec     = fdmex;
-  NextModel   = 0L;
 
   Atmosphere      = 0;
   FCS             = 0;
@@ -100,12 +99,6 @@ FGModel::FGModel(FGFDMExec* fdmex)
 
 FGModel::~FGModel()
 {
-  for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
-  interface_properties.clear();
-
-  for (unsigned int i=0; i<PreFunctions.size(); i++) delete PreFunctions[i];
-  for (unsigned int i=0; i<PostFunctions.size(); i++) delete PostFunctions[i];
-
   if (debug_lvl & 2) cout << "Destroyed:    FGModel" << endl;
 }
 
@@ -142,93 +135,6 @@ bool FGModel::InitModel(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGModel::Load(Element* el)
-{
-  // Interface properties are all stored in the interface properties array.
-  string interface_property_string = "";
-
-  Element *property_element = el->FindElement("property");
-  if (property_element && debug_lvl > 0) cout << endl << "    Declared properties" 
-                                              << endl << endl;
-  while (property_element) {
-    interface_property_string = property_element->GetDataLine();
-    if (PropertyManager->HasNode(interface_property_string)) {
-      cerr << "      Property " << interface_property_string 
-           << " is already defined." << endl;
-    } else {
-      double value=0.0;
-      if ( ! property_element->GetAttributeValue("value").empty())
-        value = property_element->GetAttributeValueAsNumber("value");
-      interface_properties.push_back(new double(value));
-      PropertyManager->Tie(interface_property_string, interface_properties.back());
-      if (debug_lvl > 0)
-        cout << "      " << interface_property_string << " (initial value: " 
-             << value << ")" << endl << endl;
-    }
-    property_element = el->FindNextElement("property");
-  }
-  
-  // End of interface property loading logic
-
-  // Load model pre-functions, if any
-
-  Element *function = el->FindElement("function");
-  while (function) {
-    if (function->GetAttributeValue("type") == "pre") {
-      PreFunctions.push_back(new FGFunction(PropertyManager, function));
-    } else if (function->GetAttributeValue("type").empty()) { // Assume pre-function
-      string funcname = function->GetAttributeValue("name");
-      PreFunctions.push_back(new FGFunction(PropertyManager, function));
-    }
-    function = el->FindNextElement("function");
-  }
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGModel::PostLoad(Element* el)
-{
-  // Load model post-functions, if any
-
-  Element *function = el->FindElement("function");
-  while (function) {
-    if (function->GetAttributeValue("type") == "post") {
-      PostFunctions.push_back(new FGFunction(PropertyManager, function));
-    }
-    function = el->FindNextElement("function");
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// Tell the Functions to cache values, so when the function values 
-// are being used in the model, the functions do not get
-// calculated each time, but instead use the values that have already
-// been calculated for this frame.
-
-void FGModel::RunPreFunctions(void)
-{
-  vector <FGFunction*>::iterator it;
-  for (it = PreFunctions.begin(); it != PreFunctions.end(); it++)
-    (*it)->GetValue();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// Tell the Functions to cache values, so when the function values 
-// are being used in the model, the functions do not get
-// calculated each time, but instead use the values that have already
-// been calculated for this frame.
-
-void FGModel::RunPostFunctions(void)
-{
-  vector <FGFunction*>::iterator it;
-  for (it = PostFunctions.begin(); it != PostFunctions.end(); it++)
-    (*it)->GetValue();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 bool FGModel::Run()
 {
   if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;
index 5f3ac94897d95eac1f738d1f65b5e44820b49ea2..d107d28a507e82572578c5cd8e5af0b2e5c1949b 100644 (file)
@@ -38,8 +38,8 @@ SENTRY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include "FGJSBBase.h"
 #include "math/FGFunction.h"
+#include "math/FGModelFunctions.h"
 
 #include <string>
 #include <vector>
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MODEL "$Id: FGModel.h,v 1.14 2009/11/12 13:08:11 jberndt Exp $"
+#define ID_MODEL "$Id: FGModel.h,v 1.15 2010/09/07 00:19:46 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -85,7 +85,7 @@ CLASS DOCUMENTATION
 CLASS DECLARATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-class FGModel : public FGJSBBase
+class FGModel : public FGModelFunctions
 {
 public:
 
@@ -94,7 +94,6 @@ public:
   /// Destructor
   ~FGModel();
 
-  FGModel* NextModel;
   std::string Name;
 
   /** Runs the model; called by the Executive
@@ -112,15 +111,10 @@ protected:
   int exe_ctr;
   int rate;
 
-  void RunPreFunctions(void);
-  void RunPostFunctions(void);
-
   /** Loads this model.
       @param el a pointer to the element
       @return true if model is successfully loaded*/
-  virtual bool Load(Element* el);
-
-  void PostLoad(Element* el);
+  virtual bool Load(Element* el) {return FGModelFunctions::Load(el, PropertyManager);}
 
   virtual void Debug(int from);
 
@@ -139,10 +133,6 @@ protected:
   FGPropagate*       Propagate;
   FGAuxiliary*       Auxiliary;
   FGPropertyManager* PropertyManager;
-  std::vector <FGFunction*> PreFunctions;
-  std::vector <FGFunction*> PostFunctions;
-
-  std::vector <double*> interface_properties;
 };
 }
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index ebb83211b4d010c48f24aae19e04011525f2e0a1..1e11074f9dcab4ec33b8b16b74dac1cdced7ce83 100644 (file)
@@ -71,7 +71,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.60 2010/08/12 19:11:22 andgi Exp $";
+static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.65 2010/09/18 22:48:12 jberndt Exp $";
 static const char *IdHdr = ID_PROPAGATE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -82,7 +82,7 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
 {
   Debug(0);
   Name = "FGPropagate";
-  gravType = gtWGS84;
+  gravType = gtStandard;
  
   vPQRdot.InitMatrix();
   vQtrndot = FGQuaternion(0,0,0);
@@ -95,7 +95,7 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
   integrator_translational_position = eTrapezoidal;
 
   VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
-  VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
   VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
   VState.dqQtrndot.resize(4, FGQuaternion(0.0,0.0,0.0));
 
@@ -129,7 +129,7 @@ bool FGPropagate::InitModel(void)
   vInertialVelocity.InitMatrix();
 
   VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
-  VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqUVWidot.resize(4, FGColumnVector3(0.0,0.0,0.0));
   VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
   VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
 
@@ -148,9 +148,6 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
   SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC());
   SetTerrainElevation(FGIC->GetTerrainElevationFtIC());
 
-  VehicleRadius = GetRadius();
-  radInv = 1.0/VehicleRadius;
-
   // Initialize the State Vector elements and the transformation matrices
 
   // Set the position lat/lon/radius
@@ -162,12 +159,10 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
 
   Ti2ec = GetTi2ec();         // ECI to ECEF transform
   Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
-  
-  Tl2ec = GetTl2ec();         // local to ECEF transform
-  Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
 
-  Ti2l  = GetTi2l();
-  Tl2i  = Ti2l.Transposed();
+  VState.vInertialPosition = Tec2i * VState.vLocation;
+
+  UpdateLocationMatrices();
 
   // Set the orientation from the euler angles (is normalized within the
   // constructor). The Euler angles represent the orientation of the body
@@ -177,26 +172,22 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
                                         FGIC->GetPsiRadIC() );
 
   VState.qAttitudeECI = Ti2l.GetQuaternion()*VState.qAttitudeLocal;
-
-  Ti2b  = GetTi2b();           // ECI to body frame transform
-  Tb2i  = Ti2b.Transposed();   // body to ECI frame transform
-
-  Tl2b  = VState.qAttitudeLocal; // local to body frame transform
-  Tb2l  = Tl2b.Transposed();     // body to local frame transform
-
-  Tec2b = Tl2b * Tec2l;        // ECEF to body frame transform
-  Tb2ec = Tec2b.Transposed();  // body to ECEF frame tranform
+  UpdateBodyMatrices();
 
   // Set the velocities in the instantaneus body frame
   VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(),
                                  FGIC->GetVBodyFpsIC(),
                                  FGIC->GetWBodyFpsIC() );
 
-  VState.vInertialPosition = Tec2i * VState.vLocation;
-
   // Compute the local frame ECEF velocity
   vVel = Tb2l * VState.vUVW;
 
+  // Recompute the LocalTerrainRadius.
+  RecomputeLocalTerrainRadius();
+
+  VehicleRadius = GetRadius();
+  double radInv = 1.0/VehicleRadius;
+
   // Refer to Stevens and Lewis, 1.5-14a, pg. 49.
   // This is the rotation rate of the "Local" frame, expressed in the local frame.
 
@@ -215,26 +206,7 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
   VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
 
   // Make an initial run and set past values
-  CalculatePQRdot();           // Angular rate derivative
-  CalculateUVWdot();           // Translational rate derivative
-  ResolveFrictionForces(0.);   // Update rate derivatives with friction forces
-  CalculateQuatdot();          // Angular orientation derivative
-  CalculateInertialVelocity(); // Translational position derivative
-
-  // Initialize past values deques
-  VState.dqPQRdot.clear();
-  VState.dqUVWdot.clear();
-  VState.dqInertialVelocity.clear();
-  VState.dqQtrndot.clear();
-  for (int i=0; i<4; i++) {
-    VState.dqPQRdot.push_front(vPQRdot);
-    VState.dqUVWdot.push_front(vUVWdot);
-    VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
-    VState.dqQtrndot.push_front(vQtrndot);
-  }
-
-  // Recompute the LocalTerrainRadius.
-  RecomputeLocalTerrainRadius();
+  InitializeDerivatives();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -271,42 +243,42 @@ bool FGPropagate::Run(void)
   CalculateUVWdot();           // Translational rate derivative
   ResolveFrictionForces(dt);   // Update rate derivatives with friction forces
   CalculateQuatdot();          // Angular orientation derivative
-  CalculateInertialVelocity(); // Translational position derivative
+  CalculateUVW();              // Translational position derivative (velocities are integrated in the inertial frame)
 
   // Propagate rotational / translational velocity, angular /translational position, respectively.
   Integrate(VState.vPQRi,             vPQRdot,           VState.dqPQRdot,           dt, integrator_rotational_rate);
-  Integrate(VState.vUVW,              vUVWdot,           VState.dqUVWdot,           dt, integrator_translational_rate);
+  Integrate(VState.vInertialVelocity, vUVWidot,          VState.dqUVWidot,          dt, integrator_translational_rate);
   Integrate(VState.qAttitudeECI,      vQtrndot,          VState.dqQtrndot,          dt, integrator_rotational_position);
   Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position);
 
-  VState.qAttitudeECI.Normalize(); // Normalize the ECI Attitude quaternion
-
-  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(); 
 }
 
index 4049467916efad3b5c43334e4be2cf9f4576b143..be8ebd224ba189a8bd2b2b84cde6b269c96296b3 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.43 2010/07/25 15:35:11 jberndt Exp $"
+#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -102,7 +102,7 @@ CLASS DOCUMENTATION
     @endcode
 
     @author Jon S. Berndt, Mathias Froehlich
-    @version $Id: FGPropagate.h,v 1.43 2010/07/25 15:35:11 jberndt Exp $
+    @version $Id: FGPropagate.h,v 1.48 2010/09/18 22:48:12 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -148,9 +148,9 @@ public:
     FGColumnVector3 vInertialPosition;
 
     deque <FGColumnVector3> dqPQRdot;
-    deque <FGColumnVector3> dqUVWdot;
+    deque <FGColumnVector3> dqUVWidot;
     deque <FGColumnVector3> dqInertialVelocity;
-    deque <FGQuaternion> dqQtrndot;
+    deque <FGQuaternion>    dqQtrndot;
   };
 
   /** Constructor.
@@ -517,19 +517,23 @@ public:
 
   void SetVState(VehicleState* vstate) {
       VState.vLocation = vstate->vLocation;
+      UpdateLocationMatrices();
+      SetInertialOrientation(vstate->qAttitudeECI);
+      VehicleRadius = GetRadius();
       VState.vUVW = vstate->vUVW;
+      vVel = GetTb2l() * VState.vUVW;
       VState.vPQR = vstate->vPQR;
-      VState.qAttitudeLocal = vstate->qAttitudeLocal;
-      VState.qAttitudeECI = vstate->qAttitudeECI;
+      VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
+      VState.vInertialPosition = vstate->vInertialPosition;
 
-      VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
-      VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
-      VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
-      VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+      InitializeDerivatives();
   }
 
+  void InitializeDerivatives(void);
+
   void SetInertialOrientation(FGQuaternion Qi);
   void SetInertialVelocity(FGColumnVector3 Vi);
+  void SetInertialRates(FGColumnVector3 vRates);
 
   const FGQuaternion GetQuaternion(void) const { return VState.qAttitudeLocal; }
 
@@ -545,18 +549,46 @@ public:
 
 // SET functions
 
-  void SetLongitude(double lon) { VState.vLocation.SetLongitude(lon); }
-  void SetLongitudeDeg(double lon) {SetLongitude(lon*degtorad);}
-  void SetLatitude(double lat) { VState.vLocation.SetLatitude(lat); }
-  void SetLatitudeDeg(double lat) {SetLatitude(lat*degtorad);}
-  void SetRadius(double r) { VState.vLocation.SetRadius(r); }
-  void SetLocation(const FGLocation& l) { VState.vLocation = l; }
+  void SetLongitude(double lon) {
+      VState.vLocation.SetLongitude(lon);
+      VState.vInertialPosition = GetTec2i() * VState.vLocation;
+      UpdateLocationMatrices();
+  }
+  void SetLongitudeDeg(double lon) { SetLongitude(lon*degtorad); }
+  void SetLatitude(double lat) {
+      VState.vLocation.SetLatitude(lat);
+      VState.vInertialPosition = GetTec2i() * VState.vLocation;
+      UpdateLocationMatrices();
+  }
+  void SetLatitudeDeg(double lat) { SetLatitude(lat*degtorad); }
+  void SetRadius(double r) {
+      VState.vLocation.SetRadius(r);
+      VState.vInertialPosition = GetTec2i() * VState.vLocation;
+      UpdateLocationMatrices();
+  }
+  void SetLocation(const FGLocation& l) {
+      VState.vLocation = l;
+      VState.vInertialPosition = GetTec2i() * VState.vLocation;
+      UpdateLocationMatrices();
+  }
+  void SetLocation(const FGColumnVector3& l) {
+      VState.vLocation = l;
+      VState.vInertialPosition = GetTec2i() * VState.vLocation;
+      UpdateLocationMatrices();
+  }
   void SetAltitudeASL(double altASL);
   void SetAltitudeASLmeters(double altASL) {SetAltitudeASL(altASL/fttom);}
   void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
   void SetTerrainElevation(double tt);
   void SetDistanceAGL(double tt);
   void SetInitialState(const FGInitialCondition *);
+  void SetPosition(const double Lon, const double Lat, const double Radius) {
+      VState.vLocation.SetPosition(Lon, Lat, Radius);
+      VState.vInertialPosition = GetTec2i() * VState.vLocation;
+      VehicleRadius = GetRadius();
+      UpdateLocationMatrices();
+  }
+
   void RecomputeLocalTerrainRadius(void);
 
   void NudgeBodyLocation(FGColumnVector3 deltaLoc) {
@@ -580,7 +612,7 @@ private:
 
   FGColumnVector3 vVel;
   FGColumnVector3 vPQRdot;
-  FGColumnVector3 vUVWdot;
+  FGColumnVector3 vUVWdot, vUVWidot;
   FGColumnVector3 vInertialVelocity;
   FGColumnVector3 vLocation;
   FGColumnVector3 vDeltaXYZEC;
@@ -599,11 +631,9 @@ private:
   FGMatrix33 Tb2i;   // body to ECI frame rotation matrix
   FGMatrix33 Ti2l;
   FGMatrix33 Tl2i;
-  FGLocation contactloc;
-  FGColumnVector3 dv;
   
   double LocalTerrainRadius, SeaLevelRadius, VehicleRadius;
-  double radInv;
+  FGColumnVector3 LocalTerrainVelocity;
   eIntegrateType integrator_rotational_rate;
   eIntegrateType integrator_translational_rate;
   eIntegrateType integrator_rotational_position;
@@ -613,6 +643,7 @@ private:
   void CalculatePQRdot(void);
   void CalculateQuatdot(void);
   void CalculateInertialVelocity(void);
+  void CalculateUVW(void);
   void CalculateUVWdot(void);
 
   void Integrate( FGColumnVector3& Integrand,
@@ -629,6 +660,9 @@ private:
 
   void ResolveFrictionForces(double dt);
 
+  void UpdateLocationMatrices(void);
+  void UpdateBodyMatrices(void);
+
   void bind(void);
   void Debug(int from);
 };
index bd3b09f0a2868906ec1bac6eb66ef2bb594e20b0..f0fbe04b37650439eed87baf596331df6bbcbcd7 100644 (file)
@@ -65,7 +65,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.39 2010/02/25 05:21:36 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.40 2010/09/07 00:40:03 jberndt Exp $";
 static const char *IdHdr = ID_PROPULSION;
 
 extern short debug_lvl;
@@ -336,7 +336,7 @@ bool FGPropulsion::Load(Element* el)
   if (el->FindElement("dump-rate"))
     DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
 
-  FGModel::PostLoad(el);
+  PostLoad(el, PropertyManager);
 
   return true;
 }
index 8e713589f2f73712d5971f0b26b6cfc6d724cd11..6cdf9ab8334ab381cb00c91f759369817637b4bb 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.27 2009/10/24 22:59:30 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.29 2010/09/07 00:40:03 jberndt Exp $";
 static const char *IdHdr = ID_FCSCOMPONENT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -122,14 +122,16 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
     } else {
       InputSigns.push_back( 1.0);
     }
-    tmp = PropertyManager->GetNode(input);
-    if (tmp) {
-      InputNodes.push_back( tmp );
+    if (PropertyManager->HasNode(input)) {
+      tmp = PropertyManager->GetNode(input);
     } else {
-      cerr << fgred << "  In component: " << Name << " unknown property "
-           << input << " referenced. Aborting" << reset << endl;
-      exit(-1);
+      tmp = 0L;
+      // cerr << fgcyan << "In component: " + Name + " property "
+      //      + input + " is initially undefined." << reset << endl;
     }
+    InputNodes.push_back( tmp );
+    InputNames.push_back( input );
+
     input_element = element->FindNextElement("input");
   }
 
@@ -236,6 +238,24 @@ void FGFCSComponent::Clip(void)
   }
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCSComponent::LateBind(void)
+{
+  FGPropertyManager* node = 0L;
+
+  for (unsigned int i=0; i<InputNodes.size(); i++) {
+    if (!InputNodes[i]) {
+      if (PropertyManager->HasNode(InputNames[i])) {
+        node = PropertyManager->GetNode(InputNames[i]);
+        InputNodes[i] = node;
+      } else {
+        throw(InputNames[i]);
+      }
+    }
+  }
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //
 // The old way of naming FCS components allowed upper or lower case, spaces, etc.
index 27186fb6de80a6cd50ab389708e4d7610ef40f83..7889cd948a243b05ca40ee82381aef325bc915b9 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -80,7 +80,7 @@ CLASS DOCUMENTATION
     - FGActuator
 
     @author Jon S. Berndt
-    @version $Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $
+    @version $Id: FGFCSComponent.h,v 1.17 2010/08/21 22:56:11 jberndt Exp $
     @see Documentation for the FGFCS class, and for the configuration file class
 */
 
@@ -98,6 +98,7 @@ public:
 
   virtual bool Run(void);
   virtual void SetOutput(void);
+  void LateBind(void);
   double GetOutput (void) const {return Output;}
   std::string GetName(void) const {return Name;}
   std::string GetType(void) const { return Type; }
@@ -111,6 +112,7 @@ protected:
   FGPropertyManager* ClipMinPropertyNode;
   FGPropertyManager* ClipMaxPropertyNode;
   std::vector <FGPropertyManager*> InputNodes;
+  std::vector <std::string> InputNames;
   std::vector <float> InputSigns;
   std::vector <double> output_array;
   std::string Type;
index 40e6753510a627fccf5ea868404e89b205aebf00..b67cbf70d4ad42678236bed2f808ac897c9641db 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGSummer.cpp,v 1.7 2009/10/24 22:59:30 jberndt Exp $";
+static const char *IdSrc = "$Id: FGSummer.cpp,v 1.8 2010/08/21 22:56:11 jberndt Exp $";
 static const char *IdHdr = ID_SUMMER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -118,9 +118,9 @@ void FGSummer::Debug(int from)
       cout << "      INPUTS: " << endl;
       for (unsigned i=0;i<InputNodes.size();i++) {
         if (InputSigns[i] < 0)
-          cout << "       -" << InputNodes[i]->getName() << endl;
+          cout << "       -" << InputNames[i] << endl;
         else
-          cout << "       " << InputNodes[i]->getName() << endl;
+          cout << "       " << InputNames[i] << endl;
       }
       if (Bias != 0.0) cout << "       Bias: " << Bias << endl;
       if (IsOutput) {
index b1459ebaddea16260d37bb8ef805415df9545062..1138d820cceed7fe97b849229c8057af6eb1f8d9 100644 (file)
@@ -50,7 +50,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGElectric.cpp,v 1.8 2010/02/25 05:21:36 jberndt Exp $";
+static const char *IdSrc = "$Id: FGElectric.cpp,v 1.9 2010/08/21 17:13:48 jberndt Exp $";
 static const char *IdHdr = ID_ELECTRIC;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -83,8 +83,10 @@ FGElectric::~FGElectric()
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGElectric::Calculate(void)
+void FGElectric::Calculate(void)
 {
+  RunPreFunctions();
+
   Throttle = FCS->GetThrottlePos(EngineNumber);
 
   RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
@@ -93,7 +95,9 @@ double FGElectric::Calculate(void)
 
   PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
 
-  return Thruster->Calculate(PowerAvailable);
+  Thruster->Calculate(PowerAvailable);
+
+  RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 7bcdb406ff45c24131bf472d5a18f543265c6d10..268522956219d2a10302369e58930c184c1cb777 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ELECTRIC "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $";
+#define ID_ELECTRIC "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $";
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -65,7 +65,7 @@ CLASS DOCUMENTATION
     there is no battery model available, so this motor does not consume any
     energy.  There is no internal friction.
     @author David Culp
-    @version "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $"
+    @version "$Id: FGElectric.h,v 1.9 2010/08/21 18:07:59 jberndt Exp $"
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -80,7 +80,7 @@ public:
   /// Destructor
   ~FGElectric();
 
-  double Calculate(void);
+  void Calculate(void);
   double GetPowerAvailable(void) {return PowerAvailable;}
   double getRPM(void) {return RPM;}
   std::string GetEngineLabels(const std::string& delimiter);
index abaf368e2538b3e82a5b1ff2ee4d3599a342dab0..6cc525a5341422ac881444597d39eeaacacf00e7 100644 (file)
@@ -54,7 +54,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGEngine.cpp,v 1.38 2010/06/02 04:05:13 jberndt Exp $";
+static const char *IdSrc = "$Id: FGEngine.cpp,v 1.39 2010/08/21 17:13:48 jberndt Exp $";
 static const char *IdHdr = ID_ENGINE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -91,6 +91,8 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
 
   Name = engine_element->GetAttributeValue("name");
 
+  Load(engine_element, PropertyManager, to_string(EngineNumber)); // Call ModelFunctions loader
+
 // Find and set engine location
 
   local_element = engine_element->GetParent()->FindElement("location");
@@ -146,6 +148,8 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
   property_name = base_property_name + "/fuel-flow-rate-pps";
   PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate);
 
+  PostLoad(engine_element, PropertyManager, to_string(EngineNumber));
+
   //cout << "Engine[" << EngineNumber << "] using fuel density: " << FuelDensity << endl;
 
   Debug(0);
index 8a3f51a8e47c87da7e255706db99f7901a80db23..c25eebfc0a4abdca19e431987e1ebe11bc49cc8a 100644 (file)
@@ -43,7 +43,7 @@ SENTRY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include "FGJSBBase.h"
+#include "math/FGModelFunctions.h"
 #include "input_output/FGXMLFileRead.h"
 #include "input_output/FGXMLElement.h"
 #include "models/FGFCS.h"
@@ -55,7 +55,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ENGINE "$Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $"
+#define ID_ENGINE "$Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -118,14 +118,14 @@ CLASS DOCUMENTATION
        documentation for engine and thruster classes.
 </pre>     
     @author Jon S. Berndt
-    @version $Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $
+    @version $Id: FGEngine.h,v 1.21 2010/08/21 17:13:48 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DECLARATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-class FGEngine : public FGJSBBase, public FGXMLFileRead
+class FGEngine : public FGModelFunctions, public FGXMLFileRead
 {
 public:
   FGEngine(FGFDMExec* exec, Element* el, int engine_number);
@@ -165,9 +165,8 @@ public:
   /** Resets the Engine parameters to the initial conditions */
   void ResetToIC(void);
 
-  /** Calculates the thrust of the engine, and other engine functions.
-      @return Thrust in pounds */
-  virtual double Calculate(void) {return 0.0;}
+  /** Calculates the thrust of the engine, and other engine functions. */
+  virtual void Calculate(void) = 0;
 
   /// Sets engine placement information
   virtual void SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation);
@@ -237,6 +236,7 @@ protected:
   FGThruster*     Thruster;
 
   std::vector <int> SourceTanks;
+
   void Debug(int from);
 };
 }
index 77dcf245a64858c28b456f373d1f31e24f64f444..b225563c2e0a4516da20e9483e2afdd05eb3d193 100644 (file)
@@ -53,7 +53,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPiston.cpp,v 1.52 2010/06/05 12:12:34 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPiston.cpp,v 1.53 2010/08/21 17:13:48 jberndt Exp $";
 static const char *IdHdr = ID_PISTON;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -385,16 +385,16 @@ void FGPiston::ResetToIC(void)
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGPiston::Calculate(void)
+void FGPiston::Calculate(void)
 {
+  RunPreFunctions();
+
   if (FuelFlow_gph > 0.0) ConsumeFuel();
 
   Throttle = FCS->GetThrottlePos(EngineNumber);
   Mixture = FCS->GetMixturePos(EngineNumber);
 
-  //
   // Input values.
-  //
 
   p_amb = Atmosphere->GetPressure() * psftopa;
   double p = Auxiliary->GetTotalPressure() * psftopa;
@@ -416,8 +416,9 @@ double FGPiston::Calculate(void)
   //Assume lean limit at 22 AFR for now - thats a thi of 0.668
   //This might be a bit generous, but since there's currently no audiable warning of impending
   //cutout in the form of misfiring and/or rough running its probably reasonable for now.
-//  if (equivalence_ratio < 0.668)
-//    Running = false;
+
+  //  if (equivalence_ratio < 0.668)
+  //    Running = false;
 
   doEnginePower();
   if (IndicatedHorsePower < 0.1250) Running = false;
@@ -433,8 +434,9 @@ double FGPiston::Calculate(void)
   }
 
   PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
+  Thruster->Calculate(PowerAvailable);
 
-  return Thruster->Calculate(PowerAvailable);
+  RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index a008e6a7327f526d27b1f96772a0d586e1430ddf..13072afac2ef0883897f35aa79e9c9078de022f4 100644 (file)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PISTON "$Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $";
+#define ID_PISTON "$Id: FGPiston.h,v 1.24 2010/08/21 18:08:13 jberndt Exp $";
 #define FG_MAX_BOOST_SPEEDS 3
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -181,7 +181,7 @@ CLASS DOCUMENTATION
     @author Dave Luff (engine operational code)
     @author David Megginson (initial porting and additional code)
     @author Ron Jensen (additional engine code)
-    @version $Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $
+    @version $Id: FGPiston.h,v 1.24 2010/08/21 18:08:13 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -199,7 +199,7 @@ public:
   std::string GetEngineLabels(const std::string& delimiter);
   std::string GetEngineValues(const std::string& delimiter);
 
-  double Calculate(void);
+  void Calculate(void);
   double GetPowerAvailable(void) {return PowerAvailable;}
   double CalcFuelNeed(void);
 
index 52ab88cb25827b533738d2476323786a924e624b..87c76685fc4809eda32724c43b82d5ce55282c84 100644 (file)
@@ -49,7 +49,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGRocket.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $";
+static const char *IdSrc = "$Id: FGRocket.cpp,v 1.20 2010/08/21 17:13:48 jberndt Exp $";
 static const char *IdHdr = ID_ROCKET;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -59,6 +59,7 @@ CLASS IMPLEMENTATION
 FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
   : FGEngine(exec, el, engine_number)
 {
+  Type = etRocket;
   Element* thrust_table_element = 0;
   ThrustTable = 0L;
   BurnTime = 0.0;
@@ -72,6 +73,7 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
   It = 0.0;
   ThrustVariation = 0.0;
   TotalIspVariation = 0.0;
+  Flameout = false;
 
   // Defaults
    MinThrottle = 0.0;
@@ -108,10 +110,6 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
   bindmodel();
 
   Debug(0);
-
-  Type = etRocket;
-  Flameout = false;
-
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -124,10 +122,11 @@ FGRocket::~FGRocket(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGRocket::Calculate(void)
+void FGRocket::Calculate(void)
 {
   double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
-  double thrust;
+
+  RunPreFunctions();
 
   if (!Flameout && !Starved) ConsumeFuel();
 
@@ -184,10 +183,9 @@ double FGRocket::Calculate(void)
 
   } // End thrust calculations
 
-  thrust = Thruster->Calculate(VacThrust);
-  It += thrust * dT;
+  It += Thruster->Calculate(VacThrust) * dT;
 
-  return thrust;
+  RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 8692a5c1a8ba8ca853946e2d99fedf405870d124..38e367510645e7f88ef94e907ef7c5de00198ccc 100644 (file)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ROCKET "$Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $"
+#define ID_ROCKET "$Id: FGRocket.h,v 1.14 2010/08/21 18:08:25 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -118,7 +118,7 @@ for the rocket engine to be throttle up to 1. At that time, the solid rocket
 fuel begins burning and thrust is provided.
 
     @author Jon S. Berndt
-    $Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $
+    $Id: FGRocket.h,v 1.14 2010/08/21 18:08:25 jberndt Exp $
     @see FGNozzle,
     FGThruster,
     FGForce,
@@ -143,9 +143,8 @@ public:
   /** Destructor */
   ~FGRocket(void);
 
-  /** Determines the thrust.
-      @return thrust */
-  double Calculate(void);
+  /** Determines the thrust.*/
+  void Calculate(void);
 
   /** Gets the total impulse of the rocket.
       @return The cumulative total impulse of the rocket up to this time.*/
index 064177a2b31670a7316879ca1cf6c2dfd57aed84..5af8c1ddd50193ceb8b33b4f3a6542249bec4812 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGThruster.cpp,v 1.12 2009/10/24 22:59:30 jberndt Exp $";
+static const char *IdSrc = "$Id: FGThruster.cpp,v 1.13 2010/08/21 22:56:11 jberndt Exp $";
 static const char *IdHdr = ID_THRUSTER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -74,11 +74,11 @@ FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMEx
 
   element = thruster_element->FindElement("location");
   if (element)  location = element->FindElementTripletConvertTo("IN");
-  else          cerr << "No thruster location found." << endl;
+  else          cerr << fgred << "      No thruster location found." << reset << endl;
 
   element = thruster_element->FindElement("orient");
   if (element)  orientation = element->FindElementTripletConvertTo("RAD");
-  else          cerr << "No thruster orientation found." << endl;
+  else          cerr << "      No thruster orientation found." << endl;
 
   SetLocation(location);
   SetAnglesToBody(orientation);
index c61667b4b2ddc98fac8c9757b62fbab7036e37f8..485c01c9421533e2ef9e81891888d37e561fc33d 100644 (file)
@@ -51,7 +51,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.27 2010/05/24 11:26:37 jberndt Exp $";
+static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.29 2010/08/31 04:01:32 jberndt Exp $";
 static const char *IdHdr = ID_TURBINE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -113,10 +113,12 @@ void FGTurbine::ResetToIC(void)
 // The main purpose of Calculate() is to determine what phase the engine should
 // be in, then call the corresponding function.
 
-double FGTurbine::Calculate(void)
+void FGTurbine::Calculate(void)
 {
   double thrust;
 
+  RunPreFunctions();
+
   TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
   double qbar = Auxiliary->Getqbar();
   dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
@@ -170,9 +172,9 @@ double FGTurbine::Calculate(void)
     default: thrust = Off();
   }
 
-  thrust = Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing)
+  Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing)
 
-  return thrust;
+  RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -474,9 +476,6 @@ bool FGTurbine::Load(FGFDMExec* exec, Element *el)
       MaxThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix);
     } else if (name == "Injection") {
       InjectionLookup = new FGFunction(PropertyManager, function_element, property_prefix);
-    } else {
-      cerr << "Unknown function type: " << name << " in turbine definition." <<
-      endl;
     }
   }
 
index 1fff92c6789256876d2cf29f43c487dd9415e86b..62c6d321a34680294bd16b3d27b56ec8edf4a5e0 100644 (file)
@@ -42,7 +42,7 @@ INCLUDES
 
 #include "FGEngine.h"
 
-#define ID_TURBINE "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_TURBINE "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -146,7 +146,7 @@ CLASS DOCUMENTATION
     /engine/direct.xml
 </pre>
     @author David P. Culp
-    @version "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $"
+    @version "$Id: FGTurbine.h,v 1.19 2010/08/21 18:08:46 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -166,7 +166,7 @@ public:
 
   enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
 
-  double Calculate(void);
+  void Calculate(void);
   double CalcFuelNeed(void);
   double GetPowerAvailable(void);
   /** A lag filter.
index f384877fc502f8fce0599c7c15c1f74ad8c3aa10..9813199618d5fb29edb499ab14b597dee065a0ba 100755 (executable)
@@ -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();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 66febb1915fde6c262e1953ff744f543d1e9ace6..c73c0b76534841090a4eb1c8b3e50f976bcc1c58 100755 (executable)
@@ -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);}