]> git.mxchange.org Git - flightgear.git/commitdiff
Sync w. JSBSim CVS
authorehofman <ehofman>
Mon, 14 Jun 2004 11:40:45 +0000 (11:40 +0000)
committerehofman <ehofman>
Mon, 14 Jun 2004 11:40:45 +0000 (11:40 +0000)
88 files changed:
src/FDM/JSBSim/FGAerodynamics.cpp
src/FDM/JSBSim/FGAircraft.cpp
src/FDM/JSBSim/FGAtmosphere.cpp
src/FDM/JSBSim/FGAtmosphere.h
src/FDM/JSBSim/FGAuxiliary.cpp
src/FDM/JSBSim/FGAuxiliary.h
src/FDM/JSBSim/FGCoefficient.cpp
src/FDM/JSBSim/FGCoefficient.h
src/FDM/JSBSim/FGColumnVector3.cpp
src/FDM/JSBSim/FGColumnVector3.h
src/FDM/JSBSim/FGColumnVector4.cpp [deleted file]
src/FDM/JSBSim/FGColumnVector4.h [deleted file]
src/FDM/JSBSim/FGDefs.h [deleted file]
src/FDM/JSBSim/FGElectric.cpp [new file with mode: 0644]
src/FDM/JSBSim/FGElectric.h [new file with mode: 0644]
src/FDM/JSBSim/FGEngine.cpp
src/FDM/JSBSim/FGEngine.h
src/FDM/JSBSim/FGFCS.cpp
src/FDM/JSBSim/FGFCS.h
src/FDM/JSBSim/FGFDMExec.cpp
src/FDM/JSBSim/FGFDMExec.h
src/FDM/JSBSim/FGFactorGroup.h
src/FDM/JSBSim/FGForce.cpp
src/FDM/JSBSim/FGForce.h
src/FDM/JSBSim/FGGroundReactions.cpp
src/FDM/JSBSim/FGInertial.cpp
src/FDM/JSBSim/FGInertial.h
src/FDM/JSBSim/FGInitialCondition.cpp
src/FDM/JSBSim/FGInitialCondition.h
src/FDM/JSBSim/FGJSBBase.cpp
src/FDM/JSBSim/FGJSBBase.h
src/FDM/JSBSim/FGLGear.cpp
src/FDM/JSBSim/FGLGear.h
src/FDM/JSBSim/FGLocation.cpp [new file with mode: 0644]
src/FDM/JSBSim/FGLocation.h [new file with mode: 0644]
src/FDM/JSBSim/FGModel.cpp
src/FDM/JSBSim/FGModel.h
src/FDM/JSBSim/FGNozzle.cpp
src/FDM/JSBSim/FGNozzle.h
src/FDM/JSBSim/FGOutput.cpp
src/FDM/JSBSim/FGOutput.h
src/FDM/JSBSim/FGPiston.cpp
src/FDM/JSBSim/FGPiston.h
src/FDM/JSBSim/FGPosition.cpp [deleted file]
src/FDM/JSBSim/FGPosition.h [deleted file]
src/FDM/JSBSim/FGPropagate.cpp [new file with mode: 0644]
src/FDM/JSBSim/FGPropagate.h [new file with mode: 0644]
src/FDM/JSBSim/FGPropeller.cpp
src/FDM/JSBSim/FGPropeller.h
src/FDM/JSBSim/FGPropulsion.cpp
src/FDM/JSBSim/FGPropulsion.h
src/FDM/JSBSim/FGQuaternion.cpp [new file with mode: 0644]
src/FDM/JSBSim/FGQuaternion.h [new file with mode: 0644]
src/FDM/JSBSim/FGRocket.cpp
src/FDM/JSBSim/FGRocket.h
src/FDM/JSBSim/FGRotation.cpp [deleted file]
src/FDM/JSBSim/FGRotation.h [deleted file]
src/FDM/JSBSim/FGRotor.cpp
src/FDM/JSBSim/FGRotor.h
src/FDM/JSBSim/FGSimTurbine.cpp [deleted file]
src/FDM/JSBSim/FGSimTurbine.h [deleted file]
src/FDM/JSBSim/FGState.cpp
src/FDM/JSBSim/FGState.h
src/FDM/JSBSim/FGTable.cpp
src/FDM/JSBSim/FGTable.h
src/FDM/JSBSim/FGTank.cpp
src/FDM/JSBSim/FGTank.h
src/FDM/JSBSim/FGThruster.cpp
src/FDM/JSBSim/FGThruster.h
src/FDM/JSBSim/FGTranslation.cpp [deleted file]
src/FDM/JSBSim/FGTranslation.h [deleted file]
src/FDM/JSBSim/FGTrim.cpp
src/FDM/JSBSim/FGTrimAxis.cpp
src/FDM/JSBSim/FGTurbine.cpp
src/FDM/JSBSim/FGTurbine.h
src/FDM/JSBSim/FGUtility.cpp [deleted file]
src/FDM/JSBSim/FGUtility.h [deleted file]
src/FDM/JSBSim/JSBSim.cxx
src/FDM/JSBSim/JSBSim.hxx
src/FDM/JSBSim/Makefile.am
src/FDM/JSBSim/filtersjb/FGFilter.cpp
src/FDM/JSBSim/filtersjb/FGGain.cpp
src/FDM/JSBSim/filtersjb/FGGain.h
src/FDM/JSBSim/filtersjb/FGKinemat.cpp
src/FDM/JSBSim/filtersjb/FGKinemat.h
src/FDM/JSBSim/filtersjb/FGSummer.cpp
src/FDM/JSBSim/filtersjb/FGSwitch.cpp
src/FDM/JSBSim/filtersjb/FGSwitch.h

index b6687891e71f76387b68a280c3d7bdf5bbda39d4..d77ab2f6d4c105cc08827a53c2b2172d5eabd40c 100644 (file)
@@ -37,7 +37,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGAerodynamics.h"
-#include "FGTranslation.h"
+#include "FGPropagate.h"
 #include "FGAircraft.h"
 #include "FGState.h"
 #include "FGMassBalance.h"
@@ -49,9 +49,9 @@ namespace JSBSim {
 static const char *IdSrc = "$Id$";
 static const char *IdHdr = ID_AERODYNAMICS;
 
-const unsigned NAxes=6;                           
+const unsigned NAxes=6;
 const char* AxisNames[] = { "drag", "side-force", "lift", "rolling-moment",
-                            "pitching-moment","yawing-moment" }; 
+                            "pitching-moment","yawing-moment" };
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
@@ -70,12 +70,12 @@ FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
   AxisIdx["YAW"]   = 5;
 
   Coeff = new CoeffArray[6];
-  
+
   impending_stall = stall_hyst = 0.0;
   alphaclmin = alphaclmax = 0.0;
   alphahystmin = alphahystmax = 0.0;
   clsq = lod = 0.0;
-  alphaw = 0.0;  
+  alphaw = 0.0;
   bi2vel = ci2vel = 0.0;
   bind();
 
@@ -87,16 +87,16 @@ FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
 FGAerodynamics::~FGAerodynamics()
 {
   unsigned int i,j;
-  
+
   unbind();
-  
+
   for (i=0; i<6; i++) {
     for (j=0; j<Coeff[i].size(); j++) {
       delete Coeff[i][j];
     }
   }
   delete[] Coeff;
-  
+
   Debug(1);
 }
 
@@ -109,16 +109,16 @@ bool FGAerodynamics::Run(void)
 
   if (!FGModel::Run()) {
 
-    twovel = 2*Translation->GetVt();
+    twovel = 2*Auxiliary->GetVt();
     if (twovel != 0) {
       bi2vel = Aircraft->GetWingSpan() / twovel;
       ci2vel = Aircraft->Getcbar() / twovel;
-    }  
-    
-    alphaw = Translation->Getalpha() + Aircraft->GetWingIncidence();
-    
-    alpha = Translation->Getalpha();
-    
+    }
+
+    alphaw = Auxiliary->Getalpha() + Aircraft->GetWingIncidence();
+
+    alpha = Auxiliary->Getalpha();
+
     if (alphaclmax != 0) {
       if (alpha > 0.85*alphaclmax) {
         impending_stall = 10*(alpha/alphaclmax - 0.85);
@@ -126,15 +126,15 @@ bool FGAerodynamics::Run(void)
         impending_stall = 0;
       }
     }
-   
+
     if (alphahystmax != 0.0 && alphahystmin != 0.0) {
       if (alpha > alphahystmax) {
          stall_hyst = 1;
       } else if (alpha < alphahystmin) {
          stall_hyst = 0;
-      }    
+      }
     }
+
     vLastFs = vFs;
     vFs.InitMatrix();
 
@@ -146,14 +146,14 @@ bool FGAerodynamics::Run(void)
 
     //correct signs of drag and lift to wind axes convention
     //positive forward, right, down
-    if ( Translation->Getqbar() > 0) {
-      clsq = vFs(eLift) / (Aircraft->GetWingArea()*Translation->Getqbar());
+    if ( Auxiliary->Getqbar() > 0) {
+      clsq = vFs(eLift) / (Aircraft->GetWingArea()*Auxiliary->Getqbar());
       clsq *= clsq;
     }
     if ( vFs(eDrag)  > 0) {
       lod = vFs(eLift) / vFs(eDrag);
-    }  
-        
+    }
+
     //correct signs of drag and lift to wind axes convention
     //positive forward, right, down
     vFs(eDrag)*=-1; vFs(eLift)*=-1;
@@ -214,7 +214,7 @@ bool FGAerodynamics::Load(FGConfigFile* AC_cfg)
   }
 
   bindModel();
-  
+
   return true;
 }
 
@@ -287,7 +287,7 @@ void FGAerodynamics::bind(void)
   PropertyManager->Tie("forces/lod-norm", this,
                        &FGAerodynamics::GetLoD);
   PropertyManager->Tie("aero/cl-squared-norm", this,
-                       &FGAerodynamics::GetClSquared); 
+                       &FGAerodynamics::GetClSquared);
   PropertyManager->Tie("aero/alpha-max-deg", this,
                        &FGAerodynamics::GetAlphaCLMax,
                        &FGAerodynamics::SetAlphaCLMax,
@@ -311,7 +311,7 @@ void FGAerodynamics::bind(void)
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGAerodynamics::bindModel(void)
-{ 
+{
   unsigned i,j;
   FGPropertyManager* node;
   string axis_node_name;
@@ -320,8 +320,8 @@ void FGAerodynamics::bindModel(void)
      node = node->GetNode( string(AxisNames[i]),true );
      for (j=0; j < Coeff[i].size(); j++) {
        Coeff[i][j]->bind(node);
-     } 
-     node = (FGPropertyManager*)node->getParent();                                         
+     }
+     node = (FGPropertyManager*)node->getParent();
   }
 }
 
@@ -341,7 +341,7 @@ void FGAerodynamics::unbind(void)
   PropertyManager->Untie("forces/fwy-aero-lbs");
   PropertyManager->Untie("forces/fwz-aero-lbs");
   PropertyManager->Untie("forces/lod-norm");
-  PropertyManager->Untie("aero/cl-squared-norm");  
+  PropertyManager->Untie("aero/cl-squared-norm");
   PropertyManager->Untie("aero/alpha-max-deg");
   PropertyManager->Untie("aero/alpha-min-deg");
   PropertyManager->Untie("aero/bi2vel");
@@ -353,7 +353,7 @@ void FGAerodynamics::unbind(void)
   for ( i=0; i<NAxes; i++ ) {
      for ( j=0; j < Coeff[i].size(); j++ ) {
        Coeff[i][j]->unbind();
-       
+
      }
   }
 }
index c86f382b6589bd6ba2928f5bb902c7e10b582d66..aa56cc7e8361de13d9e0d307cb108e596850a11a 100644 (file)
@@ -75,7 +75,7 @@ INCLUDES
 #include "FGAerodynamics.h"
 #include "FGState.h"
 #include "FGFDMExec.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
 #include "FGPropertyManager.h"
 
 namespace JSBSim {
@@ -125,7 +125,6 @@ bool FGAircraft::Run(void)
   if (!FGModel::Run()) {                 // if false then execute this Run()
     vForces.InitMatrix();
     vForces += Aerodynamics->GetForces();
-    vForces += Inertial->GetForces();
     vForces += Propulsion->GetForces();
     vForces += GroundReactions->GetForces();
 
@@ -229,7 +228,6 @@ bool FGAircraft::Load(FGConfigFile* AC_cfg)
     } else if (parameter == "AC_VRP") {
       *AC_cfg >> vXYZvrp(eX) >> vXYZvrp(eY) >> vXYZvrp(eZ);
       if (debug_lvl > 0) cout << "    Visual Ref Pt (x, y, z): " << vXYZvrp << endl;
-      Position->SetVRP(vXYZvrp);
     } else if (parameter == "AC_POINTMASS") {
       *AC_cfg >> pmWt >> pmX >> pmY >> pmZ;
       MassBalance->AddPointMass(pmWt, pmX, pmY, pmZ);
index 14aa0417728d14db06f3640563fca3eef09a3072..1a75a3f8b593c7dc4f2dc184ea857640f3eee4af 100644 (file)
@@ -2,7 +2,7 @@
 
  Module:       FGAtmosphere.cpp
  Author:       Jon Berndt
-               Implementation of 1959 Standard Atmosphere added by Tony Peden 
+               Implementation of 1959 Standard Atmosphere added by Tony Peden
  Date started: 11/24/98
  Purpose:      Models the atmosphere
  Called by:    FGSimExec
@@ -35,7 +35,7 @@ HISTORY
 --------------------------------------------------------------------------------
 11/24/98   JSB   Created
 07/23/99   TP    Added implementation of 1959 Standard Atmosphere
-                 Moved calculation of Mach number to FGTranslation
+                 Moved calculation of Mach number to FGPropagate
                  Later updated to '76 model
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 COMMENTS, REFERENCES,  and NOTES
@@ -51,7 +51,7 @@ INCLUDES
 #include "FGState.h"
 #include "FGFDMExec.h"
 #include "FGAircraft.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
 #include "FGInertial.h"
 #include "FGPropertyManager.h"
 
@@ -86,7 +86,7 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
 //   turbType = ttBerndt;
   TurbGain = 0.0;
   TurbRate = 1.0;
-  
+
   bind();
   Debug(0);
 }
@@ -117,9 +117,9 @@ bool FGAtmosphere::InitModel(void)
   temperature=&intTemperature;
   pressure=&intPressure;
   density=&intDensity;
-  
+
   useExternal=false;
-  
+
   return true;
 }
 
@@ -130,9 +130,9 @@ bool FGAtmosphere::Run(void)
   if (!FGModel::Run()) {                 // if false then execute this Run()
     //do temp, pressure, and density first
     if (!useExternal) {
-      h = Position->Geth();
+      h = Propagate->Geth();
       Calculate(h);
-    } 
+    }
 
     if (turbType != ttNone) {
       Turbulence();
@@ -164,13 +164,13 @@ void FGAtmosphere::Calculate(double altitude)
 
   i = lastIndex;
   if (altitude < htab[lastIndex]) {
-    if (altitude <= 0) { 
+    if (altitude <= 0) {
       i = 0;
       altitude=0;
     } else {
        i = lastIndex-1;
        while (htab[i] > altitude) i--;
-    }   
+    }
   } else if (altitude > htab[lastIndex+1]) {
     if (altitude >= htab[7]) {
       i = 7;
@@ -178,8 +178,8 @@ void FGAtmosphere::Calculate(double altitude)
     } else {
       i = lastIndex+1;
       while (htab[i+1] < altitude) i++;
-    }  
-  } 
+    }
+  }
 
   switch(i) {
   case 1:     // 36089 ft.
@@ -231,9 +231,9 @@ void FGAtmosphere::Calculate(double altitude)
     refpress  = 2116.22;    // psf
     //refdens   = 0.00237767;  // slugs/cubic ft.
     break;
-  
+
   }
+
   if (slope == 0) {
     intTemperature = reftemp;
     intPressure = refpress*exp(-Inertial->SLgravity()/(reftemp*Reng)*(altitude-htab[i]));
@@ -250,10 +250,20 @@ void FGAtmosphere::Calculate(double altitude)
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Return the pressure at an arbitrary altitude and then restore the internal state
+
+double FGAtmosphere::GetPressure(double alt) {
+  Calculate(alt);
+  double p = *pressure;
+  // Reset the internal atmospheric state
+  Run();
+  return(p);
+}
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // square a value, but preserve the original sign
-static inline double 
-square_signed (double value)
+
+static inline double square_signed (double value)
 {
     if (value < 0)
         return value * value * -1;
@@ -261,6 +271,8 @@ square_signed (double value)
         return value * value;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 void FGAtmosphere::Turbulence(void)
 {
   switch (turbType) {
@@ -288,18 +300,18 @@ void FGAtmosphere::Turbulence(void)
     vDirection      += vDirectionAccel*rate*State->Getdt();
 
     vDirection.Normalize();
-    
+
                                 // Diminish turbulence within three wingspans
                                 // of the ground
     vTurbulence = TurbGain * Magnitude * vDirection;
-    double HOverBMAC = Position->GetHOverBMAC();
+    double HOverBMAC = Auxiliary->GetHOverBMAC();
     if (HOverBMAC < 3.0)
         vTurbulence *= (HOverBMAC / 3.0) * (HOverBMAC / 3.0);
 
     vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
 
-    vBodyTurbGrad = State->GetTl2b()*vTurbulenceGrad;
-    
+    vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
+
     if (Aircraft->GetWingSpan() > 0) {
       vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
     } else {
@@ -329,7 +341,7 @@ void FGAtmosphere::Turbulence(void)
     vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
     vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
 
-    
+
     MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
     MagnitudeAccel    += MagnitudedAccelDt*rate*State->Getdt();
     Magnitude         += MagnitudeAccel*rate*State->Getdt();
@@ -341,16 +353,16 @@ void FGAtmosphere::Turbulence(void)
 
                                 // Diminish z-vector within two wingspans
                                 // of the ground
-    double HOverBMAC = Position->GetHOverBMAC();
+    double HOverBMAC = Auxiliary->GetHOverBMAC();
     if (HOverBMAC < 2.0)
         vDirection(eZ) *= HOverBMAC / 2.0;
 
     vDirection.Normalize();
-    
+
     vTurbulence = TurbGain*Magnitude * vDirection;
     vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
 
-    vBodyTurbGrad = State->GetTl2b()*vTurbulenceGrad;
+    vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
     vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
     if (Aircraft->GetHTailArm() > 0)
       vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
@@ -386,7 +398,6 @@ void FGAtmosphere::UseInternal(void) {
   density=&intDensity;
   useExternal=false;
 }
-  
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -397,8 +408,8 @@ void FGAtmosphere::bind(void)
                        &FGAtmosphere::GetTemperature);
   PropertyManager->Tie("atmosphere/rho-slugs_ft3", this,
                        &FGAtmosphere::GetDensity);
-  PropertyManager->Tie("atmosphere/P-psf", this,
-                       &FGAtmosphere::GetPressure);
+//  PropertyManager->Tie("atmosphere/P-psf", this,
+//                       &FGAtmosphere::GetPressure);
   PropertyManager->Tie("atmosphere/a-fps", this,
                        &FGAtmosphere::GetSoundSpeed);
   PropertyManager->Tie("atmosphere/T-sl-R", this,
@@ -433,7 +444,7 @@ void FGAtmosphere::unbind(void)
 {
   PropertyManager->Untie("atmosphere/T-R");
   PropertyManager->Untie("atmosphere/rho-slugs_ft3");
-  PropertyManager->Untie("atmosphere/P-psf");
+//  PropertyManager->Untie("atmosphere/P-psf");
   PropertyManager->Untie("atmosphere/a-fps");
   PropertyManager->Untie("atmosphere/T-sl-R");
   PropertyManager->Untie("atmosphere/rho-sl-slugs_ft3");
index 7c8aec696688f7ba4fd7e1d3a01610908a24e5e7..fb48a80d6d2aafce65532d5030b40956e0821522 100644 (file)
@@ -28,7 +28,7 @@ HISTORY
 --------------------------------------------------------------------------------
 11/24/98   JSB   Created
 07/23/99   TP    Added implementation of 1959 Standard Atmosphere
-                 Moved calculation of Mach number to FGTranslation
+                 Moved calculation of Mach number to FGPropagate
                  Updated to '76 model
  
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -92,6 +92,8 @@ public:
   inline double GetDensity(void)  const {return *density;}
   /// Returns the pressure in psf.
   inline double GetPressure(void)  const {return *pressure;}
+  /// Returns the pressure at an arbitrary altitude in psf
+  double GetPressure(double alt);
   /// Returns the speed of sound in ft/sec.
   inline double GetSoundSpeed(void) const {return soundspeed;}
 
index 09b2aefc74dc08993f3dc40adb88e43302d18545..c9da9ed30553e537c06a23931d984c132be1f0ad 100644 (file)
@@ -1,18 +1,18 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
  Module:       FGAuxiliary.cpp
  Author:       Tony Peden, Jon Berndt
  Date started: 01/26/99
  Purpose:      Calculates additional parameters needed by the visual system, etc.
  Called by:    FGSimExec
+
  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
+
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
@@ -42,8 +42,7 @@ INCLUDES
 
 #include "FGAuxiliary.h"
 #include "FGAerodynamics.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
+#include "FGPropagate.h"
 #include "FGAtmosphere.h"
 #include "FGState.h"
 #include "FGFDMExec.h"
@@ -64,14 +63,29 @@ CLASS IMPLEMENTATION
 FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
 {
   Name = "FGAuxiliary";
-  vcas = veas = mach = qbar = pt = tat = 0;
+  vcas = veas = pt = tat = 0;
   psl = rhosl = 1;
   earthPosAngle = 0.0;
-  
+  qbar = 0;
+  qbarUW = 0.0;
+  qbarUV = 0.0;
+  Mach = 0.0;
+  alpha = beta = 0.0;
+  adot = bdot = 0.0;
+  gamma = Vt = Vground = 0.0;
+  psigt = 0.0;
+  day_of_year = 1;
+  seconds_in_day = 0.0;
+  hoverbmac = hoverbcg = 0.0;
+
+  vPilotAccel.InitMatrix();
   vPilotAccelN.InitMatrix();
-  
+  vToEyePt.InitMatrix();
+  vAeroPQR.InitMatrix();
+  vEulerRates.InitMatrix();
+
   bind();
-  
+
   Debug(0);
 }
 
@@ -87,93 +101,136 @@ FGAuxiliary::~FGAuxiliary()
 
 bool FGAuxiliary::Run()
 {
-  double A,B,D;
-
-  if (!FGModel::Run()) {
-    GetState();
-    
-    //calculate total temperature assuming isentropic flow
-    tat=sat*(1 + 0.2*mach*mach);
-    tatc=RankineToCelsius(tat);
-    
-    if (mach < 1) {   //calculate total pressure assuming isentropic flow
-      pt = p*pow((1 + 0.2*machU*machU),3.5);
+  double A,B,D, hdot_Vt;
+  const FGColumnVector3& vPQR = Propagate->GetPQR();
+  const FGColumnVector3& vUVW = Propagate->GetUVW();
+  const FGColumnVector3& vUVWdot = Propagate->GetUVWdot();
+  const FGColumnVector3& vVel = Propagate->GetVel();
+
+  if (!FGModel::Run())
+  {
+    p = Atmosphere->GetPressure();
+    rhosl = Atmosphere->GetDensitySL();
+    psl = Atmosphere->GetPressureSL();
+    sat = Atmosphere->GetTemperature();
+
+// Rotation
+
+    double cTht = Propagate->GetCostht();
+    double cPhi = Propagate->GetCosphi();
+    double sPhi = Propagate->GetSinphi();
+
+    vEulerRates(eTht) = vPQR(eQ)*cPhi - vPQR(eR)*sPhi;
+    if (cTht != 0.0) {
+      vEulerRates(ePsi) = (vPQR(eQ)*sPhi + vPQR(eR)*cPhi)/cTht;
+      vEulerRates(ePhi) = vPQR(eP) + vEulerRates(ePsi)*sPhi;
+    }
+
+    vAeroPQR = vPQR + Atmosphere->GetTurbPQR();
+
+// Translation
+
+    vAeroUVW = vUVW + Propagate->GetTl2b()*Atmosphere->GetWindNED();
+
+    Vt = vAeroUVW.Magnitude();
+    if ( Vt > 0.05) {
+      if (vAeroUVW(eW) != 0.0)
+        alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
+      if (vAeroUVW(eV) != 0.0)
+        beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV),
+               sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
+
+      double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
+      double signU=1;
+      if (vAeroUVW(eU) != 0.0)
+        signU = vAeroUVW(eU)/fabs(vAeroUVW(eU));
+
+      if ( (mUW == 0.0) || (Vt == 0.0) ) {
+        adot = 0.0;
+        bdot = 0.0;
+      } else {
+        adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW;
+        bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU)
+                + vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
+      }
     } else {
-      // shock in front of pitot tube, we'll assume its normal and use
-      // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
-      // pressure behind the shock to the static pressure in front
+      alpha = beta = adot = bdot = 0;
+    }
+
+    qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt;
+    qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
+    qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
+    Mach = Vt / Atmosphere->GetSoundSpeed();
+    MachU = vMachUVW(eU) = vAeroUVW(eU) / Atmosphere->GetSoundSpeed();
+    vMachUVW(eV) = vAeroUVW(eV) / Atmosphere->GetSoundSpeed();
+    vMachUVW(eW) = vAeroUVW(eW) / Atmosphere->GetSoundSpeed();
+
+// Position
+
+    Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) );
+
+    if (vVel(eNorth) == 0) psigt = 0;
+    else psigt =  atan2(vVel(eEast), vVel(eNorth));
+
+    if (psigt < 0.0) psigt += 2*M_PI;
 
-      B = 5.76*machU*machU/(5.6*machU*machU - 0.8);
+    if (Vt != 0) {
+      hdot_Vt = -vVel(eDown)/Vt;
+      if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);
+    } else {
+      gamma = 0.0;
+    }
 
-      // The denominator above is zero for Mach ~ 0.38, for which
-      // we'll never be here, so we're safe
+    tat = sat*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow
+    tatc = RankineToCelsius(tat);
 
-      D = (2.8*machU*machU-0.4)*0.4167;
+    if (MachU < 1) {   // Calculate total pressure assuming isentropic flow
+      pt = p*pow((1 + 0.2*MachU*MachU),3.5);
+    } else {
+      // Use Rayleigh pitot tube formula for normal shock in front of pitot tube
+      B = 5.76*MachU*MachU/(5.6*MachU*MachU - 0.8);
+      D = (2.8*MachU*MachU-0.4)*0.4167;
       pt = p*pow(B,3.5)*D;
     }
 
     A = pow(((pt-p)/psl+1),0.28571);
-    if (machU > 0.0) {
+    if (MachU > 0.0) {
       vcas = sqrt(7*psl/rhosl*(A-1));
       veas = sqrt(2*qbar/rhosl);
     } else {
       vcas = veas = 0.0;
     }
 
-    // Pilot sensed accelerations are calculated here. This is used
-    // for the coordinated turn ball instrument. Motion base platforms sometimes
-    // use the derivative of pilot sensed accelerations as the driving parameter,
-    // rather than straight accelerations.
-    //
-    // The theory behind pilot-sensed calculations is presented:
-    //
-    // For purposes of discussion and calculation, assume for a minute that the
-    // pilot is in space and motionless in inertial space. She will feel
-    // no accelerations. If the aircraft begins to accelerate along any axis or
-    // axes (without rotating), the pilot will sense those accelerations. If
-    // any rotational moment is applied, the pilot will sense an acceleration
-    // due to that motion in the amount:
-    //
-    // [wdot X R]  +  [w X (w X R)]
-    //   Term I          Term II
-    //
-    // where:
-    //
-    // wdot = omegadot, the rotational acceleration rate vector
-    // w    = omega, the rotational rate vector
-    // R    = the vector from the aircraft CG to the pilot eyepoint
-    //
-    // The sum total of these two terms plus the acceleration of the aircraft
-    // body axis gives the acceleration the pilot senses in inertial space.
-    // In the presence of a large body such as a planet, a gravity field also
-    // provides an accelerating attraction. This acceleration can be transformed
-    // from the reference frame of the planet so as to be expressed in the frame
-    // of reference of the aircraft. This gravity field accelerating attraction
-    // is felt by the pilot as a force on her tushie as she sits in her aircraft
-    // on the runway awaiting takeoff clearance.
-    //
-    // In JSBSim the acceleration of the body frame in inertial space is given
-    // by the F = ma relation. If the vForces vector is divided by the aircraft
-    // mass, the acceleration vector is calculated. The term wdot is equivalent
-    // to the JSBSim vPQRdot vector, and the w parameter is equivalent to vPQR.
-    // The radius R is calculated below in the vector vToEyePt.
-    
-    vPilotAccel.InitMatrix();   
-    if ( Translation->GetVt() > 1 ) {
-       vPilotAccel =  Aerodynamics->GetForces() 
+    vPilotAccel.InitMatrix();
+    if ( Vt > 1.0 ) {
+       vPilotAccel =  Aerodynamics->GetForces()
                       +  Propulsion->GetForces()
                       +  GroundReactions->GetForces();
        vPilotAccel /= MassBalance->GetMass();
        vToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep());
-       vPilotAccel += Rotation->GetPQRdot() * vToEyePt;
-       vPilotAccel += Rotation->GetPQR() * (Rotation->GetPQR() * vToEyePt);
+       vPilotAccel += Propagate->GetPQRdot() * vToEyePt;
+       vPilotAccel += vPQR * (vPQR * vToEyePt);
     } else {
-       vPilotAccel = -1*( State->GetTl2b() * Inertial->GetGravity() );
-    }   
+       vPilotAccel = Propagate->GetTl2b() * FGColumnVector3( 0.0, 0.0, Inertial->gravity() );
+    }
 
     vPilotAccelN = vPilotAccel/Inertial->gravity();
 
     earthPosAngle += State->Getdt()*Inertial->omega();
+
+    // VRP computation
+    const FGLocation& vLocation = Propagate->GetLocation();
+    FGColumnVector3 vrpStructural = Aircraft->GetXYZvrp();
+    FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural );
+    FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody;
+    vLocationVRP = vLocation.LocalToLocation( vrpLocal );
+
+    // Recompute some derived values now that we know the dependent parameters values ...
+    hoverbcg = Propagate->GetDistanceAGL() / Aircraft->GetWingSpan();
+
+    FGColumnVector3 vMac = Propagate->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp());
+    hoverbmac = (Propagate->GetDistanceAGL() + vMac(3)) / Aircraft->GetWingSpan();
+
     return false;
   } else {
     return true;
@@ -184,26 +241,24 @@ bool FGAuxiliary::Run()
 
 double FGAuxiliary::GetHeadWind(void)
 {
-  double psiw,vw,psi;
+  double psiw,vw;
 
   psiw = Atmosphere->GetWindPsi();
-  psi = Rotation->Getpsi();
   vw = Atmosphere->GetWindNED().Magnitude();
 
-  return vw*cos(psiw - psi);
+  return vw*cos(psiw - Propagate->Getpsi());
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 double FGAuxiliary::GetCrossWind(void)
 {
-  double psiw,vw,psi;
+  double psiw,vw;
 
   psiw = Atmosphere->GetWindPsi();
-  psi = Rotation->Getpsi();
   vw = Atmosphere->GetWindNED().Magnitude();
 
-  return  vw*sin(psiw - psi);
+  return  vw*sin(psiw - Propagate->Getpsi());
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -211,43 +266,53 @@ double FGAuxiliary::GetCrossWind(void)
 void FGAuxiliary::bind(void)
 {
   typedef double (FGAuxiliary::*PMF)(int) const;
-  PropertyManager->Tie("velocities/vc-fps", this,
-                       &FGAuxiliary::GetVcalibratedFPS);
-  PropertyManager->Tie("velocities/vc-kts", this,
-                       &FGAuxiliary::GetVcalibratedKTS);
-  PropertyManager->Tie("velocities/ve-fps", this,
-                       &FGAuxiliary::GetVequivalentFPS);
-  PropertyManager->Tie("velocities/ve-kts", this,
-                       &FGAuxiliary::GetVequivalentKTS);
-  PropertyManager->Tie("velocities/machU", this,
-                       &FGAuxiliary::GetMachU);
-  PropertyManager->Tie("velocities/tat-r", this,
-                       &FGAuxiliary::GetTotalTemperature);
-  PropertyManager->Tie("velocities/tat-c", this,
-                       &FGAuxiliary::GetTAT_C);
-  PropertyManager->Tie("velocities/pt-lbs_sqft", this,
-                       &FGAuxiliary::GetTotalPressure);
-                     
-  PropertyManager->Tie("accelerations/a-pilot-x-ft_sec2", this,1,
-                       (PMF)&FGAuxiliary::GetPilotAccel);
-  PropertyManager->Tie("accelerations/a-pilot-y-ft_sec2", this,2,
-                       (PMF)&FGAuxiliary::GetPilotAccel);
-  PropertyManager->Tie("accelerations/a-pilot-z-ft_sec2", this,3,
-                       (PMF)&FGAuxiliary::GetPilotAccel);
-  PropertyManager->Tie("accelerations/n-pilot-x-norm", this,1,
-                       (PMF)&FGAuxiliary::GetNpilot);
-  PropertyManager->Tie("accelerations/n-pilot-y-norm", this,2,
-                       (PMF)&FGAuxiliary::GetNpilot);
-  PropertyManager->Tie("accelerations/n-pilot-z-norm", this,3,
-                       (PMF)&FGAuxiliary::GetNpilot);
-  PropertyManager->Tie("position/epa-rad", this,
-                       &FGAuxiliary::GetEarthPositionAngle);
-  /* PropertyManager->Tie("atmosphere/headwind-fps", this,
-                       &FGAuxiliary::GetHeadWind,
-                       true);
-  PropertyManager->Tie("atmosphere/crosswind-fps", this,
-                       &FGAuxiliary::GetCrossWind,
-                       true); */
+  typedef double (FGAuxiliary::*PF)(void) const;
+  PropertyManager->Tie("velocities/vc-fps", this, &FGAuxiliary::GetVcalibratedFPS);
+  PropertyManager->Tie("velocities/vc-kts", this, &FGAuxiliary::GetVcalibratedKTS);
+  PropertyManager->Tie("velocities/ve-fps", this, &FGAuxiliary::GetVequivalentFPS);
+  PropertyManager->Tie("velocities/ve-kts", this, &FGAuxiliary::GetVequivalentKTS);
+  PropertyManager->Tie("velocities/machU", this, &FGAuxiliary::GetMachU);
+  PropertyManager->Tie("velocities/tat-r", this, &FGAuxiliary::GetTotalTemperature);
+  PropertyManager->Tie("velocities/tat-c", this, &FGAuxiliary::GetTAT_C);
+  PropertyManager->Tie("velocities/pt-lbs_sqft", this, &FGAuxiliary::GetTotalPressure);
+  PropertyManager->Tie("velocities/p-aero-rad_sec", this, eX, (PMF)&FGAuxiliary::GetAeroPQR);
+  PropertyManager->Tie("velocities/q-aero-rad_sec", this, eY, (PMF)&FGAuxiliary::GetAeroPQR);
+  PropertyManager->Tie("velocities/r-aero-rad_sec", this, eZ, (PMF)&FGAuxiliary::GetAeroPQR);
+  PropertyManager->Tie("velocities/phidot-rad_sec", this, ePhi, (PMF)&FGAuxiliary::GetEulerRates);
+  PropertyManager->Tie("velocities/thetadot-rad_sec", this, eTht, (PMF)&FGAuxiliary::GetEulerRates);
+  PropertyManager->Tie("velocities/psidot-rad_sec", this, ePsi, (PMF)&FGAuxiliary::GetEulerRates);
+  PropertyManager->Tie("velocities/u-aero-fps", this, eU, (PMF)&FGAuxiliary::GetAeroUVW);
+  PropertyManager->Tie("velocities/v-aero-fps", this, eV, (PMF)&FGAuxiliary::GetAeroUVW);
+  PropertyManager->Tie("velocities/w-aero-fps", this, eW, (PMF)&FGAuxiliary::GetAeroUVW);
+  PropertyManager->Tie("velocities/vt-fps", this, &FGAuxiliary::GetVt, &FGAuxiliary::SetVt, true);
+  PropertyManager->Tie("velocities/mach-norm", this, &FGAuxiliary::GetMach, &FGAuxiliary::SetMach, true);
+  PropertyManager->Tie("velocities/vg-fps", this, &FGAuxiliary::GetVground);
+  PropertyManager->Tie("accelerations/a-pilot-x-ft_sec2", this, eX, (PMF)&FGAuxiliary::GetPilotAccel);
+  PropertyManager->Tie("accelerations/a-pilot-y-ft_sec2", this, eY, (PMF)&FGAuxiliary::GetPilotAccel);
+  PropertyManager->Tie("accelerations/a-pilot-z-ft_sec2", this, eZ, (PMF)&FGAuxiliary::GetPilotAccel);
+  PropertyManager->Tie("accelerations/n-pilot-x-norm", this, eX, (PMF)&FGAuxiliary::GetNpilot);
+  PropertyManager->Tie("accelerations/n-pilot-y-norm", this, eY, (PMF)&FGAuxiliary::GetNpilot);
+  PropertyManager->Tie("accelerations/n-pilot-z-norm", this, eZ, (PMF)&FGAuxiliary::GetNpilot);
+  PropertyManager->Tie("position/epa-rad", this, &FGAuxiliary::GetEarthPositionAngle);
+  /* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true);
+  PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */
+  PropertyManager->Tie("aero/alpha-rad", this, (PF)&FGAuxiliary::Getalpha, &FGAuxiliary::Setalpha, true);
+  PropertyManager->Tie("aero/beta-rad", this, (PF)&FGAuxiliary::Getbeta, &FGAuxiliary::Setbeta, true);
+  PropertyManager->Tie("aero/mag-beta-rad", this, (PF)&FGAuxiliary::GetMagBeta);
+  PropertyManager->Tie("aero/alpha-deg", this, inDegrees, (PMF)&FGAuxiliary::Getalpha);
+  PropertyManager->Tie("aero/beta-deg", this, inDegrees, (PMF)&FGAuxiliary::Getbeta);
+  PropertyManager->Tie("aero/mag-beta-deg", this, inDegrees, (PMF)&FGAuxiliary::GetMagBeta);
+  PropertyManager->Tie("aero/qbar-psf", this, &FGAuxiliary::Getqbar, &FGAuxiliary::Setqbar, true);
+  PropertyManager->Tie("aero/qbarUW-psf", this, &FGAuxiliary::GetqbarUW, &FGAuxiliary::SetqbarUW, true);
+  PropertyManager->Tie("aero/qbarUV-psf", this, &FGAuxiliary::GetqbarUV, &FGAuxiliary::SetqbarUV, true);
+  PropertyManager->Tie("aero/alphadot-rad_sec", this, (PF)&FGAuxiliary::Getadot, &FGAuxiliary::Setadot, true);
+  PropertyManager->Tie("aero/betadot-rad_sec", this, (PF)&FGAuxiliary::Getbdot, &FGAuxiliary::Setbdot, true);
+  PropertyManager->Tie("aero/alphadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getadot);
+  PropertyManager->Tie("aero/betadot-deg_sec", this, inDegrees, (PMF)&FGAuxiliary::Getbdot);
+  PropertyManager->Tie("aero/h_b-cg-ft", this, &FGAuxiliary::GetHOverBCG);
+  PropertyManager->Tie("aero/h_b-mac-ft", this, &FGAuxiliary::GetHOverBMAC);
+  PropertyManager->Tie("flight-path/gamma-rad", this, &FGAuxiliary::GetGamma, &FGAuxiliary::SetGamma);
+  PropertyManager->Tie("flight-path/psi-gt-rad", this, &FGAuxiliary::GetGroundTrack);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -261,6 +326,19 @@ void FGAuxiliary::unbind(void)
   PropertyManager->Untie("velocities/machU");
   PropertyManager->Untie("velocities/tat-r");
   PropertyManager->Untie("velocities/tat-c");
+  PropertyManager->Untie("velocities/p-aero-rad_sec");
+  PropertyManager->Untie("velocities/q-aero-rad_sec");
+  PropertyManager->Untie("velocities/r-aero-rad_sec");
+  PropertyManager->Untie("velocities/pt-lbs_sqft");
+  PropertyManager->Untie("velocities/phidot-rad_sec");
+  PropertyManager->Untie("velocities/thetadot-rad_sec");
+  PropertyManager->Untie("velocities/psidot-rad_sec");
+  PropertyManager->Untie("velocities/u-aero-fps");
+  PropertyManager->Untie("velocities/v-aero-fps");
+  PropertyManager->Untie("velocities/w-aero-fps");
+  PropertyManager->Untie("velocities/vt-fps");
+  PropertyManager->Untie("velocities/mach-norm");
+  PropertyManager->Untie("velocities/vg-fps");
   PropertyManager->Untie("accelerations/a-pilot-x-ft_sec2");
   PropertyManager->Untie("accelerations/a-pilot-y-ft_sec2");
   PropertyManager->Untie("accelerations/a-pilot-z-ft_sec2");
@@ -270,20 +348,23 @@ void FGAuxiliary::unbind(void)
   PropertyManager->Untie("position/epa-rad");
   /* PropertyManager->Untie("atmosphere/headwind-fps");
   PropertyManager->Untie("atmosphere/crosswind-fps"); */
-
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGAuxiliary::GetState(void)
-{
-  qbar = Translation->Getqbar();
-  mach = Translation->GetMach();
-  machU= Translation->GetMachU();
-  p = Atmosphere->GetPressure();
-  rhosl = Atmosphere->GetDensitySL();
-  psl = Atmosphere->GetPressureSL();
-  sat = Atmosphere->GetTemperature();
+  PropertyManager->Untie("aero/qbar-psf");
+  PropertyManager->Untie("aero/qbarUW-psf");
+  PropertyManager->Untie("aero/qbarUV-psf");
+  PropertyManager->Untie("aero/alpha-rad");
+  PropertyManager->Untie("aero/beta-rad");
+  PropertyManager->Untie("aero/alpha-deg");
+  PropertyManager->Untie("aero/beta-deg");
+  PropertyManager->Untie("aero/alphadot-rad_sec");
+  PropertyManager->Untie("aero/betadot-rad_sec");
+  PropertyManager->Untie("aero/mag-beta-rad");
+  PropertyManager->Untie("aero/alphadot-deg_sec");
+  PropertyManager->Untie("aero/betadot-deg_sec");
+  PropertyManager->Untie("aero/mag-beta-deg");
+  PropertyManager->Untie("aero/h_b-cg-ft");
+  PropertyManager->Untie("aero/h_b-mac-ft");
+  PropertyManager->Untie("flight-path/gamma-rad");
+  PropertyManager->Untie("flight-path/psi-gt-rad");
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -323,6 +404,10 @@ void FGAuxiliary::Debug(int from)
   if (debug_lvl & 8 ) { // Runtime state variables
   }
   if (debug_lvl & 16) { // Sanity checking
+    if (Mach > 100 || Mach < 0.00)
+      cout << "FGPropagate::Mach is out of bounds: " << Mach << endl;
+    if (qbar > 1e6 || qbar < 0.00)
+      cout << "FGPropagate::qbar is out of bounds: " << qbar << endl;
   }
   if (debug_lvl & 64) {
     if (from == 0) { // Constructor
index 5a61290ffc39f31af911118258c5863cf0aa7136..f269f39b77d7e802c1aa3313dda9f506e3b47dd2 100644 (file)
@@ -1,33 +1,33 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
  Header:       FGAuxiliary.h
  Author:       Jon Berndt
  Date started: 01/26/99
+
  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
+
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.
+
  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place - Suite 330, Boston, MA  02111-1307, USA.
+
  Further information about the GNU General Public License can also be found on
  the world wide web at http://www.gnu.org.
+
 HISTORY
 --------------------------------------------------------------------------------
 11/22/98   JSB   Created
   1/1/00   TP    Added calcs and getters for VTAS, VCAS, VEAS, Vground, in knots
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 SENTRY
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -41,6 +41,8 @@ INCLUDES
 
 #include "FGModel.h"
 #include "FGColumnVector3.h"
+#include "FGLocation.h"
+#include "FGPropagate.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
@@ -59,6 +61,44 @@ CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 /** Encapsulates various uncategorized scheduled functions.
+    Pilot sensed accelerations are calculated here. This is used
+    for the coordinated turn ball instrument. Motion base platforms sometimes
+    use the derivative of pilot sensed accelerations as the driving parameter,
+    rather than straight accelerations.
+
+    The theory behind pilot-sensed calculations is presented:
+
+    For purposes of discussion and calculation, assume for a minute that the
+    pilot is in space and motionless in inertial space. She will feel
+    no accelerations. If the aircraft begins to accelerate along any axis or
+    axes (without rotating), the pilot will sense those accelerations. If
+    any rotational moment is applied, the pilot will sense an acceleration
+    due to that motion in the amount:
+
+    [wdot X R]  +  [w X (w X R)]
+    Term I          Term II
+
+    where:
+
+    wdot = omegadot, the rotational acceleration rate vector
+    w    = omega, the rotational rate vector
+    R    = the vector from the aircraft CG to the pilot eyepoint
+
+    The sum total of these two terms plus the acceleration of the aircraft
+    body axis gives the acceleration the pilot senses in inertial space.
+    In the presence of a large body such as a planet, a gravity field also
+    provides an accelerating attraction. This acceleration can be transformed
+    from the reference frame of the planet so as to be expressed in the frame
+    of reference of the aircraft. This gravity field accelerating attraction
+    is felt by the pilot as a force on her tushie as she sits in her aircraft
+    on the runway awaiting takeoff clearance.
+
+    In JSBSim the acceleration of the body frame in inertial space is given
+    by the F = ma relation. If the vForces vector is divided by the aircraft
+    mass, the acceleration vector is calculated. The term wdot is equivalent
+    to the JSBSim vPQRdot vector, and the w parameter is equivalent to vPQR.
+    The radius R is calculated below in the vector vToEyePt.
+
     @author Tony Peden, Jon Berndt
     @version $Id$
 */
@@ -72,6 +112,7 @@ public:
   /** Constructor
       @param Executive a pointer to the parent executive object */
   FGAuxiliary(FGFDMExec* Executive);
+
   /// Destructor
   ~FGAuxiliary();
 
@@ -79,49 +120,122 @@ public:
       @return false if no error */
   bool Run(void);
 
-  // Use FGInitialCondition to set these speeds
-  inline double GetVcalibratedFPS(void) const { return vcas; }
-  inline double GetVcalibratedKTS(void) const { return vcas*fpstokts; }
-  inline double GetVequivalentFPS(void) const { return veas; }
-  inline double GetVequivalentKTS(void) const { return veas*fpstokts; }
-  inline double GetMachU(void) const { return machU; }
-  
-  inline double GetTotalTemperature(void) const { return tat; }
-  inline double GetTAT_C(void) const { return tatc; }
+// GET functions
+
+  // Atmospheric parameters GET functions
+  double GetVcalibratedFPS(void) const { return vcas; }
+  double GetVcalibratedKTS(void) const { return vcas*fpstokts; }
+  double GetVequivalentFPS(void) const { return veas; }
+  double GetVequivalentKTS(void) const { return veas*fpstokts; }
 
   // total pressure above is freestream total pressure for subsonic only
   // for supersonic it is the 1D total pressure behind a normal shock
-  inline double GetTotalPressure(void) const { return pt; }
-  
-  inline FGColumnVector3& GetPilotAccel(void) { return vPilotAccel; }
-  inline double GetPilotAccel(int idx) const { return vPilotAccel(idx); }
-  FGColumnVector3 GetNpilot(void) const { return vPilotAccelN; }
-  double GetNpilot(int idx) const { return vPilotAccelN(idx); }
-
-  inline double GetEarthPositionAngle(void) const { return earthPosAngle; }
-  
+  double GetTotalPressure(void) const { return pt; }
+  double GetTotalTemperature(void) const { return tat; }
+  double GetTAT_C(void) const { return tatc; }
+
+  double GetPilotAccel(int idx)  const { return vPilotAccel(idx);  }
+  double GetNpilot(int idx)      const { return vPilotAccelN(idx); }
+  double GetAeroPQR(int axis)    const { return vAeroPQR(axis);    }
+  double GetEulerRates(int axis) const { return vEulerRates(axis); }
+
+  const FGColumnVector3& GetPilotAccel (void) const { return vPilotAccel;  }
+  const FGColumnVector3& GetNpilot     (void) const { return vPilotAccelN; }
+  const FGColumnVector3& GetAeroPQR    (void) const { return vAeroPQR;     }
+  const FGColumnVector3& GetEulerRates (void) const { return vEulerRates;  }
+  const FGColumnVector3& GetAeroUVW    (void) const { return vAeroUVW;     }
+  const FGLocation&      GetLocationVRP(void) const { return vLocationVRP; }
+
+  double GethVRP(void) const { return vLocationVRP.GetRadius() - Propagate->GetSeaLevelRadius(); }
+  double GetAeroUVW (int idx) const { return vAeroUVW(idx); }
+  double Getalpha   (void) const { return alpha;      }
+  double Getbeta    (void) const { return beta;       }
+  double Getadot    (void) const { return adot;       }
+  double Getbdot    (void) const { return bdot;       }
+  double GetMagBeta (void) const { return fabs(beta); }
+
+  double Getalpha   (int unit) const { if (unit == inDegrees) return alpha*radtodeg;
+                                       else cerr << "Bad units" << endl; return 0.0;}
+  double Getbeta    (int unit) const { if (unit == inDegrees) return beta*radtodeg;
+                                       else cerr << "Bad units" << endl; return 0.0;}
+  double Getadot    (int unit) const { if (unit == inDegrees) return adot*radtodeg;
+                                       else cerr << "Bad units" << endl; return 0.0;}
+  double Getbdot    (int unit) const { if (unit == inDegrees) return bdot*radtodeg;
+                                       else cerr << "Bad units" << endl; return 0.0;}
+  double GetMagBeta (int unit) const { if (unit == inDegrees) return fabs(beta)*radtodeg;
+                                       else cerr << "Bad units" << endl; return 0.0;}
+
+  double Getqbar    (void) const { return qbar;       }
+  double GetqbarUW  (void) const { return qbarUW;     }
+  double GetqbarUV  (void) const { return qbarUV;     }
+  double GetVt      (void) const { return Vt;         }
+  double GetVground (void) const { return Vground;    }
+  double GetMach    (void) const { return Mach;       }
+  double GetMachU   (void) const { return MachU;      }
+
+  double GetHOverBCG(void) const { return hoverbcg; }
+  double GetHOverBMAC(void) const { return hoverbmac; }
+
+  double GetGamma(void)              const { return gamma;         }
+  double GetGroundTrack(void)        const { return psigt;         }
+  double GetEarthPositionAngle(void) const { return earthPosAngle; }
+
   double GetHeadWind(void);
   double GetCrossWind(void);
-  
+
+// SET functions
+
+  void SetAeroUVW(FGColumnVector3 tt) { vAeroUVW = tt; }
+
+  void Setalpha  (double tt) { alpha = tt;  }
+  void Setbeta   (double tt) { beta  = tt;  }
+  void Setqbar   (double tt) { qbar = tt;   }
+  void SetqbarUW (double tt) { qbarUW = tt; }
+  void SetqbarUV (double tt) { qbarUV = tt; }
+  void SetVt     (double tt) { Vt = tt;     }
+  void SetMach   (double tt) { Mach=tt;     }
+  void Setadot   (double tt) { adot = tt;   }
+  void Setbdot   (double tt) { bdot = tt;   }
+
+  void SetAB    (double t1, double t2) { alpha=t1; beta=t2; }
+  void SetGamma (double tt)            { gamma = tt;        }
+
+// Time routines, SET and GET functions
+
+  void SetDayOfYear    (int doy)    { day_of_year = doy;    }
+  void SetSecondsInDay (double sid) { seconds_in_day = sid; }
+
+  int    GetDayOfYear    (void) const { return day_of_year;    }
+  double GetSecondsInDay (void) const { return seconds_in_day; }
+
   void bind(void);
   void unbind(void);
 
 private:
-  double vcas;
-  double veas;
-  double mach;
-  double machU;
-  double qbar,rhosl,rho,p,psl,pt,tat,sat,tatc;
-
-  // Don't add a getter for pt!
+  double vcas, veas;
+  double rhosl, rho, p, psl, pt, tat, sat, tatc; // Don't add a getter for pt!
 
   FGColumnVector3 vPilotAccel;
   FGColumnVector3 vPilotAccelN;
   FGColumnVector3 vToEyePt;
-  
+  FGColumnVector3 vAeroPQR;
+  FGColumnVector3 vAeroUVW;
+  FGColumnVector3 vEuler;
+  FGColumnVector3 vEulerRates;
+  FGColumnVector3 vMachUVW;
+  FGLocation vLocationVRP;
+
+  double Vt, Vground, Mach, MachU;
+  double qbar, qbarUW, qbarUV;
+  double alpha, beta;
+  double adot,bdot;
+  double psigt, gamma;
+  double seconds_in_day;  // seconds since current GMT day began
+  int    day_of_year;     // GMT day, 1 .. 366
+
   double earthPosAngle;
+  double hoverbcg, hoverbmac;
 
-  void GetState(void);
   void Debug(int from);
 };
 
@@ -129,4 +243,3 @@ private:
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 #endif
-
index 66111bc401448f6a9ce0162334710e1b52027f7a..3f42398e329fba88733a1b7a40c7275a782a35a3 100644 (file)
@@ -75,13 +75,13 @@ FGCoefficient::FGCoefficient( FGFDMExec* fdex )
   FDMExec = fdex;
   State   = FDMExec->GetState();
   Table   = 0;
-  
+
   PropertyManager = FDMExec->GetPropertyManager();
-  
+
   Table = (FGTable*)0L;
   LookupR = LookupC = 0;
   numInstances = 0;
-  rows = columns = 0;
+  rows = columns = tables = 0;
 
   StaticValue  = 0.0;
   totalValue   = 0.0;
@@ -122,31 +122,37 @@ bool FGCoefficient::Load(FGConfigFile *AC_cfg)
     *AC_cfg >> description;
     if      (method == "EQUATION") type = EQUATION;
     else if (method == "TABLE")    type = TABLE;
+    else if (method == "TABLE3D")  type = TABLE3D;
     else if (method == "VECTOR")   type = VECTOR;
     else if (method == "VALUE")    type = VALUE;
     else                           type = UNKNOWN;
 
-    if (type == VECTOR || type == TABLE) {
-      *AC_cfg >> rows;
-      if (type == TABLE) {
-        *AC_cfg >> columns;
+    if (type == VECTOR || type == TABLE || type == TABLE3D) {
+
+      if (type == TABLE3D) {
+        *AC_cfg >> rows >> columns >> tables;
+        Table = new FGTable(rows, columns, tables);
+        *AC_cfg >> multparmsRow >> multparmsCol >> multparmsTable;
+        LookupR = PropertyManager->GetNode( multparmsRow );
+        LookupC = PropertyManager->GetNode( multparmsCol );
+        LookupT = PropertyManager->GetNode( multparmsTable );
+      } else if (type == TABLE) {
+        *AC_cfg >> rows >> columns;
         Table = new FGTable(rows, columns);
+        *AC_cfg >> multparmsRow >> multparmsCol;
+        LookupR = PropertyManager->GetNode( multparmsRow );
+        LookupC = PropertyManager->GetNode( multparmsCol );
       } else {
+        *AC_cfg >> rows;
         Table = new FGTable(rows);
+        *AC_cfg >> multparmsRow;
+        LookupR = PropertyManager->GetNode( multparmsRow );
       }
-
-      *AC_cfg >> multparmsRow;
-      LookupR = PropertyManager->GetNode( multparmsRow );
-    }
-
-    if (type == TABLE) {
-      *AC_cfg >> multparmsCol;
-
-      LookupC = PropertyManager->GetNode( multparmsCol );
     }
 
-    // Here, read in the line of the form (e.g.) FG_MACH|FG_QBAR|FG_ALPHA
-    // where each non-dimensionalizing parameter for this coefficient is
+    // Here, read in the line of the form:
+    // {property1} | {property2} | {property3}
+    // where each non-dimensionalizing property for this coefficient is
     // separated by a | character
 
     string line=AC_cfg->GetCurrentLine();
@@ -157,11 +163,11 @@ bool FGCoefficient::Load(FGConfigFile *AC_cfg)
         tmp[j]=line[i];
         j++;
       }
-    } 
-    tmp[j]='\0'; multparms=tmp;  
-    end  = multparms.length();
+    }
+    tmp[j]='\0'; multparms=tmp;
+    end = multparms.length();
 
-    n     = multparms.find("|");
+    n = multparms.find("|");
     start = 0;
     if (multparms != string("none")) {
       while (n < end && n >= 0) {
@@ -176,9 +182,10 @@ bool FGCoefficient::Load(FGConfigFile *AC_cfg)
       // End of non-dimensionalizing parameter read-in
     }
     AC_cfg->GetNextConfigLine();
+
     if (type == VALUE) {
       *AC_cfg >> StaticValue;
-    } else if (type == VECTOR || type == TABLE) {
+    } else if (type == VECTOR || type == TABLE || type == TABLE3D) {
       *Table << *AC_cfg;
     } else {
       cerr << "Unimplemented coefficient type: " << type << endl;
@@ -190,11 +197,26 @@ bool FGCoefficient::Load(FGConfigFile *AC_cfg)
     return true;
   } else {
     return false;
-  }  
+  }
 }
 
 
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGCoefficient::Value(double rVal, double cVal, double tVal)
+{
+  double Value;
+  unsigned int midx;
+
+  SD = Value = gain*Table->GetValue(rVal, cVal, tVal) + bias;
+
+  for (midx=0; midx < multipliers.size(); midx++) {
+      Value *= multipliers[midx]->getDoubleValue();
+  }
+  return Value;
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 double FGCoefficient::Value(double rVal, double cVal)
@@ -215,12 +237,12 @@ double FGCoefficient::Value(double rVal, double cVal)
 double FGCoefficient::Value(double Val)
 {
   double Value;
-  
+
   SD = Value = gain*Table->GetValue(Val) + bias;
-  
-  for (unsigned int midx=0; midx < multipliers.size(); midx++) 
+
+  for (unsigned int midx=0; midx < multipliers.size(); midx++)
       Value *= multipliers[midx]->getDoubleValue();
-  
+
   return Value;
 }
 
@@ -228,7 +250,7 @@ double FGCoefficient::Value(double Val)
 
 double FGCoefficient::Value(void)
 {
-       double Value;
+  double Value;
 
   SD = Value = gain*StaticValue + bias;
 
@@ -258,7 +280,13 @@ double FGCoefficient::TotalValue(void)
 
   case TABLE:
     totalValue = Value( LookupR->getDoubleValue(),
-                      LookupC->getDoubleValue() );
+                        LookupC->getDoubleValue() );
+    break;
+
+  case TABLE3D:
+    totalValue = Value( LookupR->getDoubleValue(),
+                        LookupC->getDoubleValue(),
+                        LookupT->getDoubleValue() );
     break;
 
   case EQUATION:
@@ -279,7 +307,7 @@ void FGCoefficient::DisplayCoeffFactors(void)
   if (multipliers.size() == 0) {
     cout << "none" << endl;
   } else {
-    for (i=0; i<multipliers.size(); i++) 
+    for (i=0; i<multipliers.size(); i++)
       cout << multipliers[i]->getName() << "  ";
   }
   cout << endl;
@@ -289,7 +317,7 @@ void FGCoefficient::DisplayCoeffFactors(void)
 
 string FGCoefficient::GetSDstring(void)
 {
-  char buffer[16];
+  char buffer[20];
   string value;
 
   sprintf(buffer,"%9.6f",SD);
@@ -303,29 +331,29 @@ void FGCoefficient::bind(FGPropertyManager *parent)
 {
   string mult;
   unsigned i;
-  
+
   node = parent->GetNode(name,true);
-  
+
   node->SetString("description",description);
   if (LookupR) node->SetString("row-parm",LookupR->getName() );
   if (LookupC) node->SetString("column-parm",LookupC->getName() );
-  
+
   mult="";
-  if (multipliers.size() == 0) 
+  if (multipliers.size() == 0)
     mult="none";
-    
+
   for (i=0; i<multipliers.size(); i++) {
       mult += multipliers[i]->getName();
-      if ( i < multipliers.size()-1 ) mult += " "; 
+      if ( i < multipliers.size()-1 ) mult += " ";
   }
   node->SetString("multipliers",mult);
-  
+
   node->Tie("SD-norm",this,&FGCoefficient::GetSD );
   node->Tie("value-lbs",this,&FGCoefficient::GetValue );
-  
+
   node->Tie("bias", this, &FGCoefficient::getBias,
                           &FGCoefficient::setBias );
-                          
+
   node->Tie("gain", this, &FGCoefficient::getGain,
                           &FGCoefficient::setGain );
 
@@ -336,8 +364,8 @@ void FGCoefficient::bind(FGPropertyManager *parent)
 void FGCoefficient::unbind(void)
 {
   node->Untie("SD-norm");
-  node->Untie("value-lbs"); 
-  node->Untie("bias");  
+  node->Untie("value-lbs");
+  node->Untie("bias");
   node->Untie("gain");
 }
 
@@ -351,8 +379,8 @@ FGPropertyManager* FGCoefficient::resolveSymbol(string name)
   if ( !tmpn ) {
     cerr << "Coefficient multipliers cannot create properties, check spelling?" << endl;
     exit(1);
-  } 
-  return tmpn; 
+  }
+  return tmpn;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -379,28 +407,23 @@ void FGCoefficient::Debug(int from)
   if (debug_lvl <= 0) return;
 
   if (debug_lvl & 1) { // Standard console startup message output
-    
+
     if (from == 2) { // Loading
       cout << "\n   " << highint << underon << name << underoff << normint << endl;
       cout << "   " << description << endl;
       cout << "   " << method << endl;
 
-      if (type == VECTOR || type == TABLE) {
-        cout << "   Rows: " << rows << " ";
-        if (type == TABLE) {
-          cout << "Cols: " << columns;
+      if (type == VECTOR || type == TABLE || type == TABLE3D) {
+        cout << "   Rows: " << rows << " indexed by: " << LookupR->getName() << endl;
+        if (type == TABLE || type == TABLE3D) {
+          cout << "   Cols: " << columns << " indexed by: " << LookupC->getName() << endl;
+          if (type == TABLE3D) {
+            cout << "   Tables: " << tables << " indexed by: " << LookupT->getName() << endl;
+          }
         }
-        cout << endl << "   Row indexing parameter: " << LookupR->getName() << endl;
-      }
-
-      if (type == TABLE) {
-        cout << "   Column indexing parameter: " << LookupC->getName() << endl;
-      }
-
-      if (type == VALUE) {
-        cout << "      Value = " << StaticValue << endl;
-      } else if (type == VECTOR || type == TABLE) {
         Table->Print();
+      } else if (type == VALUE) {
+        cout << "      Value = " << StaticValue << endl;
       }
 
       DisplayCoeffFactors();
index 01c6abb806337bc84401ecb1efc53a833606ca82..fdb709adc0beb95bff5544754d0436c6f9d14635 100644 (file)
@@ -68,9 +68,7 @@ class FGState;
 class FGAtmosphere;
 class FGFCS;
 class FGAircraft;
-class FGTranslation;
-class FGRotation;
-class FGPosition;
+class FGPropagate;
 class FGAuxiliary;
 class FGOutput;
 
@@ -99,19 +97,19 @@ public:
   FGCoefficient(FGFDMExec* exec);
   /// Destructor.
   virtual ~FGCoefficient();
-  
+
   /** Loads the stability derivative/aero coefficient data from the config file
       as directed by the FGAerodynamics instance.
       @param AC_cfg a pointer to the current config file instance. */
   virtual bool Load(FGConfigFile* AC_cfg);
-  
+
   typedef vector <FGPropertyManager*> MultVec;
 
-  enum Type {UNKNOWN, VALUE, VECTOR, TABLE, EQUATION};
+  enum Type {UNKNOWN, VALUE, VECTOR, TABLE, TABLE3D, EQUATION};
 
   /** Returns the value for this coefficient.
       Each instance of FGCoefficient stores a value for the "type" of coefficient
-      it is, one of: VALUE, VECTOR, TABLE, or EQUATION. This TotalValue function 
+      it is, one of: VALUE, VECTOR, TABLE, or EQUATION. This TotalValue function
       is called when the value for a coefficient needs to be known. When it is called,
       depending on what type of coefficient is represented by the FGCoefficient
       instance, TotalValue() directs the appropriate Value() function to be called.
@@ -149,7 +147,7 @@ public:
   inline void setGain(double g) { gain=g; };
   inline double getBias(void) const { return bias; }
   inline double getGain(void) const { return gain; }
-  
+
   virtual void bind(FGPropertyManager *parent);
   virtual void unbind(void);
 
@@ -165,18 +163,20 @@ private:
   string multparms;
   string multparmsRow;
   string multparmsCol;
+  string multparmsTable;
+  double Value(double, double, double);
   double Value(double, double);
   double Value(double);
   double Value(void);
   double StaticValue;
   double totalValue;
   double bias,gain;
-  FGPropertyManager *LookupR, *LookupC;
-  
+  FGPropertyManager *LookupR, *LookupC, *LookupT;
+
   FGPropertyManager *node; // must be private!!
-  
+
   MultVec multipliers;
-  int rows, columns;
+  int rows, columns, tables;
   Type type;
   double SD; // Actual stability derivative (or other coefficient) value
   FGTable *Table;
@@ -185,13 +185,11 @@ private:
   FGAtmosphere*   Atmosphere;
   FGFCS*          FCS;
   FGAircraft*     Aircraft;
-  FGTranslation*  Translation;
-  FGRotation*     Rotation;
-  FGPosition*     Position;
+  FGPropagate*    Propagate;
   FGAuxiliary*    Auxiliary;
   FGOutput*       Output;
   FGPropertyManager* PropertyManager;
-  
+
   FGPropertyManager* resolveSymbol(string name);
 
   virtual void Debug(int from);
index 96a69e64b2dcb9e032f3a3e82df633eb15c27ae9..ebb16e1dd2e46ef02ac20bd17726262715b3662a 100644 (file)
@@ -66,7 +66,7 @@ FGColumnVector3& FGColumnVector3::operator/=(const double scalar)
 
 double FGColumnVector3::Magnitude(void) const
 {
-  if (data[1] == 0.0 && data[2] == 0.0 && data[3] == 0.0)
+  if (Entry(1) == 0.0 && Entry(2) == 0.0 && Entry(3) == 0.0)
     return 0.0;
   else
     return sqrt( Entry(1)*Entry(1) +  Entry(2)*Entry(2) +  Entry(3)*Entry(3) );
index b0a471dc2b927dd77c68b1bb8e39c362447d91b1..5b28a9e944f574f114463d8431836645406c3872 100644 (file)
@@ -95,11 +95,11 @@ public:
   FGColumnVector3(void);
 
   /** Initialization by given values.
-    
+
       @param X value of the x-conponent.
       @param Y value of the y-conponent.
       @param Z value of the z-conponent.
-    
+
       Create a vector from the doubles given in the arguments.
    */
   FGColumnVector3(double X, double Y, double Z) {
@@ -110,9 +110,9 @@ public:
   }
 
   /** Copy constructor.
-    
+
       @param v Vector which is used for initialization.
-    
+
       Create copy of the vector given in the argument.
    */
   FGColumnVector3(const FGColumnVector3& v) {
@@ -128,61 +128,61 @@ public:
 
 
   /** Read access the entries of the vector.
-    
+
       @param idx the component index.
-    
+
       Return the value of the matrix entry at the given index.
       Indices are counted starting with 1.
-    
+
       Note that the index given in the argument is unchecked.
    */
   double operator()(unsigned int idx) const { return Entry(idx); }
 
   /** Write access the entries of the vector.
-    
+
       @param idx the component index.
-    
+
       Return a reference to the vector entry at the given index.
       Indices are counted starting with 1.
-    
+
       Note that the index given in the argument is unchecked.
    */
   double& operator()(unsigned int idx) { return Entry(idx); }
 
   /** Read access the entries of the vector.
-    
+
       @param idx the component index.
-    
+
       Return the value of the matrix entry at the given index.
       Indices are counted starting with 1.
-    
+
       This function is just a shortcut for the @ref double
       operator()(unsigned int idx) const function. It is
       used internally to access the elements in a more convenient way.
-    
+
       Note that the index given in the argument is unchecked.
    */
   double Entry(unsigned int idx) const { return data[idx-1]; }
 
   /** Write access the entries of the vector.
-    
+
       @param idx the component index.
-    
+
       Return a reference to the vector entry at the given index.
       Indices are counted starting with 1.
-    
+
       This function is just a shortcut for the @ref double&
       operator()(unsigned int idx) function. It is
       used internally to access the elements in a more convenient way.
-    
+
       Note that the index given in the argument is unchecked.
    */
   double& Entry(unsigned int idx) { return data[idx-1]; }
 
   /** Assignment operator.
-    
+
       @param b source vector.
-    
+
       Copy the content of the vector given in the argument into *this.
    */
   FGColumnVector3& operator=(const FGColumnVector3& b) {
@@ -192,11 +192,29 @@ public:
     return *this;
   }
 
+  /**  Comparison operator.
+
+      @param b other vector.
+
+      Returns true if both vectors are exactly the same.
+   */
+  bool operator==(const FGColumnVector3& b) const {
+    return data[0] == b.data[0] && data[1] == b.data[1] && data[2] == b.data[2];
+  }
+
+  /** Comparison operator.
+
+      @param b other vector.
+
+      Returns false if both vectors are exactly the same.
+   */
+  bool operator!=(const FGColumnVector3& b) const { return ! operator==(b); }
+
   /** Multiplication by a scalar.
-    
+
       @param scalar scalar value to multiply the vector with.
       @return The resulting vector from the multiplication with that scalar.
-    
+
       Multiply the vector with the scalar given in the argument.
    */
   FGColumnVector3 operator*(const double scalar) const {
@@ -204,19 +222,19 @@ public:
   }
 
   /** Multiply by 1/scalar.
-    
+
       @param scalar scalar value to devide the vector through.
       @return The resulting vector from the division through that scalar.
-    
+
       Multiply the vector with the 1/scalar given in the argument.
    */
   FGColumnVector3 operator/(const double scalar) const;
 
   /** Cross product multiplication.
-    
+
       @param v vector to multiply with.
       @return The resulting vector from the cross product multiplication.
-    
+
       Compute and return the cross product of the current vector with
       the given argument.
    */
@@ -276,13 +294,13 @@ public:
   }
 
   /** Length of the vector.
-    
+
       Compute and return the euclidean norm of this vector.
    */
   double Magnitude(void) const;
 
-  /** Normialze.
-    
+  /** Normalize.
+
       Normalize the vector to have the Magnitude() == 1.0. If the vector
       is equal to zero it is left untouched.
    */
diff --git a/src/FDM/JSBSim/FGColumnVector4.cpp b/src/FDM/JSBSim/FGColumnVector4.cpp
deleted file mode 100644 (file)
index b387137..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Module: FGMatrix33.cpp
-Author: Originally by Tony Peden [formatted here (and broken??) by JSB]
-Date started: 1998
-Purpose: FGMatrix33 class
-Called by: Various
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-
-HISTORY
---------------------------------------------------------------------------------
-??/??/??   TP   Created
-03/16/2000 JSB  Added exception throwing
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGColumnVector4.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_COLUMNVECTOR4;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGColumnVector4::FGColumnVector4(void)
-{
-  rowCtr = 1;
-  data[1]=0;data[2]=0;data[3]=0;data[4]=0;
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4::FGColumnVector4(double A, double B, double C, double D)
-{
-  rowCtr = 1;
-  data[1]=A;
-  data[2]=B;
-  data[3]=C;
-  data[4]=D;
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4::~FGColumnVector4(void)
-{
-  Debug(1);
-}
-
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4::FGColumnVector4(const FGColumnVector4& b) 
-{
-  data[1] = b.data[1];
-  data[2] = b.data[2];
-  data[3] = b.data[3];
-  data[4] = b.data[4];
-
-  rowCtr = 1;
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 FGColumnVector4::operator=(const FGColumnVector4& b) 
-{
-  data[1] = b.data[1];
-  data[2] = b.data[2];
-  data[3] = b.data[3];
-  data[4] = b.data[4];
-  rowCtr = 1;
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 FGColumnVector4::operator+(const FGColumnVector4& C)
-{
-  FGColumnVector4 Sum;
-
-  Sum(1) = C(1) + data[1];
-  Sum(2) = C(2) + data[2];
-  Sum(3) = C(3) + data[3];
-  Sum(4) = C(4) + data[4];
-  return Sum;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGColumnVector4::operator+=(const FGColumnVector4& C)
-{
-   data[1] += C(1);
-   data[2] += C(2);
-   data[3] += C(3);
-   data[4] += C(4);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 FGColumnVector4::operator*(const double scalar)
-{
-  FGColumnVector4 Product;
-
-  Product(1) = scalar * data[1];
-  Product(2) = scalar * data[2];
-  Product(3) = scalar * data[3];
-  Product(4) = scalar * data[4];
-
-  return Product;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGColumnVector4::operator*=(const double scalar)
-{
-  data[1] *= scalar;
-  data[2] *= scalar;
-  data[3] *= scalar;
-  data[4] *= scalar;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 FGColumnVector4::operator-(const FGColumnVector4& V)
-{
-  
-  FGColumnVector4 Diff; 
-  
-  Diff(1) = data[1] - V(1);
-  Diff(2) = data[2] - V(2);
-  Diff(3) = data[3] - V(3);
-  Diff(4) = data[4] - V(4);
-  
-  return Diff;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGColumnVector4::operator-=(const FGColumnVector4& V)
-{
-  data[1] -= V(1);
-  data[2] -= V(2);
-  data[3] -= V(3);
-  data[4] -= V(4);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 FGColumnVector4::operator/(const double scalar)
-{
-  FGColumnVector4 Quotient;
-
-  if (scalar != 0) {
-         double tmp = 1.0/scalar;
-    Quotient(1) = data[1] * tmp;
-    Quotient(2) = data[2] * tmp;
-    Quotient(3) = data[3] * tmp;
-    Quotient(4) = data[4] * tmp;
-  } else {
-    cerr << "Attempt to divide by zero in method FGColumnVector4::operator/(const double scalar), object " << this << endl; 
-  }
-  return Quotient;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGColumnVector4::operator/=(const double scalar)
-{
-  FGColumnVector4 Quotient;
-
-  if (scalar != 0) {
-         double tmp = 1.0/scalar;
-    data[1] *= tmp;
-    data[2] *= tmp;
-    data[3] *= tmp;
-    data[4] *= tmp;
-  } else {
-    cerr << "Attempt to divide by zero in method FGColumnVector4::operator/=(const double scalar), object " << this << endl; 
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 operator*(const double scalar, const FGColumnVector4& C)
-{
-  FGColumnVector4 Product;
-
-  Product(1) = scalar * C(1);
-  Product(2) = scalar * C(2);
-  Product(3) = scalar * C(3);
-  Product(4) = scalar * C(4);
-  return Product;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGColumnVector4::Magnitude(void)
-{
-  double num;
-
-  if ((data[1] == 0.00) &&
-      (data[2] == 0.00) &&
-      (data[3] == 0.00) &&
-      (data[4] == 0.00))
-  {
-    return 0.00;
-  } else {
-    num  = data[1]*data[1];
-    num += data[2]*data[2];
-    num += data[3]*data[3];
-    num += data[4]*data[4];
-    return sqrt(num);
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 FGColumnVector4::Normalize(void)
-{
-  double Mag = Magnitude();
-
-  if (Mag != 0) {
-         Mag = 1.0/Mag;
-     data[1] *= Mag;
-     data[2] *= Mag;
-     data[3] *= Mag;
-     data[4] *= Mag;  
-  }    
-
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4 FGColumnVector4::multElementWise(const FGColumnVector4& V)
-{
-  FGColumnVector4 Product;
-
-  Product(1) = data[1] * V(1);
-  Product(2) = data[2] * V(2);
-  Product(3) = data[3] * V(3);
-  Product(4) = data[4] * V(4);
-
-  return Product;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-ostream& operator<<(ostream& os, FGColumnVector4& col)
-{
-  os << col(1) << " , " << col(2) << " , " << col(3) << " , " << col(4);
-  return os;
-}  
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector4& FGColumnVector4::operator<<(const double ff)
-{
-  data[rowCtr] = ff;
-  if (++rowCtr > 4) rowCtr = 1;
-  return *this;
-}
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-//    The bitmasked value choices are as follows:
-//    unset: In this case (the default) JSBSim would only print
-//       out the normally expected messages, essentially echoing
-//       the config files as they are read. If the environment
-//       variable is not set, debug_lvl is set to 1 internally
-//    0: This requests JSBSim not to output any messages
-//       whatsoever.
-//    1: This value explicity requests the normal JSBSim
-//       startup messages
-//    2: This value asks for a message to be printed out when
-//       a class is instantiated
-//    4: When this value is set, a message is displayed when a
-//       FGModel object executes its Run() method
-//    8: When this value is set, various runtime state variables
-//       are printed out periodically
-//    16: When set various parameters are sanity checked and
-//       a message is printed out when they go out of bounds
-
-void FGColumnVector4::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGColumnVector4" << endl;
-    if (from == 1) cout << "Destroyed:    FGColumnVector4" << endl;
-  }
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
-  }
-  if (debug_lvl & 8 ) { // Runtime state variables
-  }
-  if (debug_lvl & 16) { // Sanity checking
-  }
-  if (debug_lvl & 64) { // Sanity checking
-    if (from == 0) { // Constructor
-      cout << IdSrc << endl;
-      cout << IdHdr << endl;
-    }
-  }
-}
-}
diff --git a/src/FDM/JSBSim/FGColumnVector4.h b/src/FDM/JSBSim/FGColumnVector4.h
deleted file mode 100644 (file)
index 8b87c48..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Header: FGColumnVector4.h
-Author: Originally by Tony Peden [formatted and adapted here by Jon Berndt]
-Date started: Unknown
-
-HISTORY
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGCOLUMNVECTOR4_H
-#define FGCOLUMNVECTOR4_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <stdlib.h>
-#ifdef FGFS
-#  include <math.h>
-#  include <simgear/compiler.h>
-#  include STL_STRING
-#  include STL_FSTREAM
-#  include STL_IOSTREAM
-   SG_USING_STD(string);
-   SG_USING_STD(ostream);
-   SG_USING_STD(istream);
-   SG_USING_STD(cerr);
-   SG_USING_STD(cout);
-   SG_USING_STD(endl);
-//   SG_USING_STD(sqrt);
-#else
-#  include <string>
-#  if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
-#    include <fstream.h>
-#    include <iostream.h>
-#    include <math.h>
-#  else
-#    include <fstream>
-#  if defined (sgi) && !defined(__GNUC__)
-#    include <math.h>
-#  else
-#    include <cmath>
-#  endif
-#    include <iostream>
-     using std::ostream;
-     using std::istream;
-     using std::cerr;
-     using std::cout;
-     using std::endl;
-     using std::sqrt;
-#  endif
-   using std::string;
-#endif
-
-#include "FGJSBBase.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_COLUMNVECTOR4 "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** This class implements a 4 dimensional vector.
-    @author Jon S. Berndt, Tony Peden, et. al.
-    @version $Id$
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGColumnVector4 : public FGJSBBase
-{
-public:
-  FGColumnVector4(void);
-  FGColumnVector4(double A, double B, double C, double D);
-  FGColumnVector4(const FGColumnVector4& b);
-  ~FGColumnVector4(void);
-
-  FGColumnVector4 operator=(const FGColumnVector4& b);
-
-  FGColumnVector4 operator*(const double scalar);
-  FGColumnVector4 operator/(const double scalar);
-  FGColumnVector4 operator+(const FGColumnVector4& B); // must not return reference
-  FGColumnVector4 operator-(const FGColumnVector4& B);
-
-  void operator-=(const FGColumnVector4 &B);
-  void operator+=(const FGColumnVector4 &B);
-  void operator*=(const double scalar);
-  void operator/=(const double scalar);
-
-  inline double operator()(int m) const { return data[m]; }
-  inline double& operator()(int m) { return data[m]; }
-
-  FGColumnVector4& operator<<(const double ff);
-
-  inline void InitMatrix(void) { data[1]=0; data[2]=0; data[3]=0; data[4]=0; }
-  inline void InitMatrix(double ff) { data[1]=ff; data[2]=ff; data[3]=ff; data[4]=ff;}
-
-  double Magnitude(void);
-  FGColumnVector4 Normalize(void);
-
-  friend FGColumnVector4 operator*(const double scalar, const FGColumnVector4& A);
-
-  friend ostream& operator<<(ostream& os, FGColumnVector4& col);
-
-
-  FGColumnVector4 multElementWise(const FGColumnVector4& V);
-
-private:
-  double data[5];
-  int rowCtr;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGDefs.h b/src/FDM/JSBSim/FGDefs.h
deleted file mode 100644 (file)
index 3f77272..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*******************************************************************************
- Header:       FGDefs.h
- Author:       Jon S. Berndt
- Date started: 02/01/99
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-HISTORY
---------------------------------------------------------------------------------
-02/01/99  JSB   Created
-********************************************************************************
-SENTRY
-*******************************************************************************/
-
-#ifndef FGDEFS_H
-#define FGDEFS_H
-
-#define GRAVITY         32.174
-#define INVGRAVITY      0.031081
-#define EARTHRAD        20925650.00       // feet, equatorial
-#define EARTHRADSQRD    437882827922500.0
-#define ONESECOND       4.848136811E-6
-#define Reng            1716             //Specific Gas Constant,ft^2/(sec^2*R)
-#define SHRATIO         1.4              //Specific Heat Ratio
-#define RADTODEG        57.29578
-#define DEGTORAD        1.745329E-2
-#define KTSTOFPS        1.68781
-#define FPSTOKTS        0.592484
-#define INCHTOFT        0.08333333
-#define OMEGA_EARTH .00007272205217  
-#define NEEDED_CFG_VERSION "1.50"
-#define JSBSIM_VERSION  "0.9.0"
-
-#define HPTOFTLBSSEC 550
-#define METERS_TO_FEET 3.2808
-
-#if defined ( sgi ) && !defined( __GNUC__ )
-#define __STL_FUNCTION_TMPL_PARTIAL_ORDER
-#endif
-
-enum eParam {
-  FG_UNDEF = 0,
-  FG_TIME,
-  FG_QBAR,
-  FG_WINGAREA,
-  FG_WINGSPAN,
-  FG_CBAR,
-  FG_ALPHA,
-  FG_ALPHADOT,
-  FG_BETA,
-  FG_BETADOT,
-  FG_PHI,
-  FG_THT,
-  FG_PSI,
-  FG_PITCHRATE,
-  FG_ROLLRATE,
-  FG_YAWRATE,
-  FG_CL_SQRD,
-  FG_MACH,
-  FG_ALTITUDE,
-  FG_BI2VEL,
-  FG_CI2VEL,
-  FG_ELEVATOR_POS,
-  FG_AILERON_POS,
-  FG_RUDDER_POS,
-  FG_SPDBRAKE_POS,
-  FG_SPOILERS_POS,
-  FG_FLAPS_POS,
-  FG_ELEVATOR_CMD,
-  FG_AILERON_CMD,
-  FG_RUDDER_CMD,
-  FG_SPDBRAKE_CMD,
-  FG_SPOILERS_CMD,
-  FG_FLAPS_CMD,
-  FG_THROTTLE_CMD,
-  FG_THROTTLE_POS,
-  FG_MIXTURE_CMD,
-  FG_MIXTURE_POS,
-  FG_MAGNETO_CMD,
-  FG_STARTER_CMD,
-  FG_ACTIVE_ENGINE,
-  FG_HOVERB,
-  FG_PITCH_TRIM_CMD,
-  FG_LEFT_BRAKE_CMD,
-  FG_CENTER_BRAKE_CMD,
-  FG_RIGHT_BRAKE_CMD,
-  FG_SET_LOGGING,
-  FG_ALPHAH,
-  FG_ALPHAW,
-  FG_LBARH,     //normalized horizontal tail arm
-  FG_LBARV,     //normalized vertical tail arm
-  FG_HTAILAREA,
-  FG_VTAILAREA,
-  FG_VBARH,    //horizontal tail volume 
-  FG_VBARV     //vertical tail volume 
-};
-
-enum eAction {
-  FG_RAMP  = 1,
-  FG_STEP  = 2,
-  FG_EXP   = 3
-};
-
-enum eType {
-  FG_VALUE = 1,
-  FG_DELTA = 2,
-  FG_BOOL  = 3
-};
-
-/******************************************************************************/
-#endif
-
diff --git a/src/FDM/JSBSim/FGElectric.cpp b/src/FDM/JSBSim/FGElectric.cpp
new file mode 100644 (file)
index 0000000..c8a075f
--- /dev/null
@@ -0,0 +1,167 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGElectric.cpp
+ Author:       David Culp
+ Date started: 04/07/2004
+ Purpose:      This module models an electric motor
+
+ --------- Copyright (C) 2004  David Culp (davidculp2@comcast.net) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+This class descends from the FGEngine class and models an electric motor based on
+parameters given in the engine config file for this class
+
+HISTORY
+--------------------------------------------------------------------------------
+04/07/2004  DPC  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGElectric.h"
+#include "FGPropulsion.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_ELECTRIC;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGElectric::FGElectric(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec)
+{
+  string token;
+
+  Type = etElectric;
+  EngineNumber = 0;
+  PowerWatts = 745.7;
+  hptowatts = 745.7;
+
+  dt = State->Getdt();
+
+  Name = Eng_cfg->GetValue("NAME");
+  Eng_cfg->GetNextConfigLine();
+  while (Eng_cfg->GetValue() != string("/FG_ELECTRIC")) {
+    *Eng_cfg >> token;
+    if      (token == "POWER_WATTS") *Eng_cfg >> PowerWatts;
+    else cerr << "Unhandled token in Engine config file: " << token << endl;
+  }
+
+  Debug(0); // Call Debug() routine from constructor if needed
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGElectric::~FGElectric()
+{
+  Debug(1); // Call Debug() routine from constructor if needed
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGElectric::Calculate(void)
+{
+  Throttle = FCS->GetThrottlePos(EngineNumber);
+
+  RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
+
+  HP = PowerWatts * Throttle / hptowatts;
+
+  PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
+
+  return Thruster->Calculate(PowerAvailable);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGElectric::GetEngineLabels(void)
+{
+  return ""; // currently no labels are returned for this engine
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGElectric::GetEngineValues(void)
+{
+  return ""; // currently no values are returned for this engine
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+//    The bitmasked value choices are as follows:
+//    unset: In this case (the default) JSBSim would only print
+//       out the normally expected messages, essentially echoing
+//       the config files as they are read. If the environment
+//       variable is not set, debug_lvl is set to 1 internally
+//    0: This requests JSBSim not to output any messages
+//       whatsoever.
+//    1: This value explicity requests the normal JSBSim
+//       startup messages
+//    2: This value asks for a message to be printed out when
+//       a class is instantiated
+//    4: When this value is set, a message is displayed when a
+//       FGModel object executes its Run() method
+//    8: When this value is set, various runtime state variables
+//       are printed out periodically
+//    16: When set various parameters are sanity checked and
+//       a message is printed out when they go out of bounds
+
+void FGElectric::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+
+      cout << "\n    Engine Name: "         << Name << endl;
+      cout << "      Power Watts: "         << PowerWatts << endl;
+
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGElectric" << endl;
+    if (from == 1) cout << "Destroyed:    FGElectric" << endl;
+  }
+  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
+  }
+  if (debug_lvl & 8 ) { // Runtime state variables
+  }
+  if (debug_lvl & 16) { // Sanity checking
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+
+double
+FGElectric::CalcFuelNeed(void)
+{
+  return 0;
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/FGElectric.h b/src/FDM/JSBSim/FGElectric.h
new file mode 100644 (file)
index 0000000..cef8a0f
--- /dev/null
@@ -0,0 +1,107 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGElectric.h
+ Author:       David Culp
+ Date started: 04/07/2004
+
+ ----- Copyright (C) 2004  David P. Culp (davidculp2@comcast.net) --------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+--------------------------------------------------------------------------------
+04/07/2004  DPC  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGELECTRIC_H
+#define FGELECTRIC_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGEngine.h"
+#include "FGConfigFile.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_ELECTRIC "$Id$";
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models and electric motor.
+    FGElectric models an electric motor based on the configuration file
+    POWER_WATTS parameter.  The throttle controls motor output linearly from
+    zero to POWER_WATTS.  This power value (converted internally to horsepower)
+    is then used by FGPropeller to apply torque to the propeller.
+    @author David Culp
+    @version "$Id$"
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGElectric : public FGEngine
+{
+public:
+  /// Constructor
+  FGElectric(FGFDMExec* exec, FGConfigFile* Eng_cfg);
+  /// Destructor
+  ~FGElectric();
+
+  double Calculate(void);
+  double GetPowerAvailable(void) {return PowerAvailable;}
+  double CalcFuelNeed(void);
+  double getRPM(void) {return RPM;}
+  string GetEngineLabels(void);
+  string GetEngineValues(void);
+
+private:
+
+  double BrakeHorsePower;
+  double PowerAvailable;
+
+  // timestep
+  double dt;
+
+  // constants
+  double hptowatts;
+
+  double PowerWatts;         // maximum engine power
+  double RPM;                // revolutions per minute
+  double HP;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
index bc73911a8630af43e1d3871c2a41b003d6adbb72..b3a1b39294346a2e4107299447537d3b8517b1b7 100644 (file)
@@ -1,39 +1,39 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
  Module:       FGEngine.cpp
  Author:       Jon Berndt
  Date started: 01/21/99
  Called by:    FGAircraft
+
  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
+
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.
+
  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place - Suite 330, Boston, MA  02111-1307, USA.
+
  Further information about the GNU General Public License can also be found on
  the world wide web at http://www.gnu.org.
+
 FUNCTIONAL DESCRIPTION
 --------------------------------------------------------------------------------
 See header file.
+
 HISTORY
 --------------------------------------------------------------------------------
 01/21/99   JSB   Created
 09/03/99   JSB   Changed Rocket thrust equation to correct -= Thrust instead of
                  += Thrust (thanks to Tony Peden)
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -55,6 +55,8 @@ INCLUDES
 
 #include "FGEngine.h"
 #include "FGTank.h"
+#include "FGPropeller.h"
+#include "FGNozzle.h"
 
 namespace JSBSim {
 
@@ -93,12 +95,10 @@ FGEngine::FGEngine(FGFDMExec* exec)
   FCS = FDMExec->GetFCS();
   Propulsion = FDMExec->GetPropulsion();
   Aircraft = FDMExec->GetAircraft();
-  Translation = FDMExec->GetTranslation();
-  Rotation = FDMExec->GetRotation();
-  Position = FDMExec->GetPosition();
+  Propagate = FDMExec->GetPropagate();
   Auxiliary = FDMExec->GetAuxiliary();
   Output = FDMExec->GetOutput();
-  
+
   PropertyManager = FDMExec->GetPropertyManager();
 
   Debug(0);
@@ -119,17 +119,27 @@ FGEngine::~FGEngine()
 
 void FGEngine::ConsumeFuel(void)
 {
-  double Fshortage, Oshortage;
+  double Fshortage, Oshortage, TanksWithFuel;
   FGTank* Tank;
 
   if (TrimMode) return;
-  Fshortage = Oshortage = 0.0;
+  Fshortage = Oshortage = TanksWithFuel = 0.0;
+  // count how many assigned tanks have fuel
+  for (unsigned int i=0; i<SourceTanks.size(); i++) {
+    Tank = Propulsion->GetTank(SourceTanks[i]);
+    if (Tank->GetContents() > 0.0) {
+      ++TanksWithFuel;
+    }
+  }
+  if (!TanksWithFuel) return;
+
   for (unsigned int i=0; i<SourceTanks.size(); i++) {
     Tank = Propulsion->GetTank(SourceTanks[i]);
     if (Tank->GetType() == FGTank::ttFUEL) {
-      Fshortage += Tank->Reduce(CalcFuelNeed()/Propulsion->GetnumSelectedFuelTanks());
+       Fshortage += Tank->Drain(CalcFuelNeed()/TanksWithFuel);
     } else {
-      Oshortage += Tank->Reduce(CalcOxidizerNeed()/Propulsion->GetnumSelectedOxiTanks());
+       Oshortage += Tank->Drain(CalcOxidizerNeed()/TanksWithFuel);
     }
   }
 
@@ -171,6 +181,102 @@ void FGEngine::AddFeedTank(int tkID)
   SourceTanks.push_back(tkID);
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGEngine::GetBodyForces(void)
+{
+  return Thruster->GetBodyForces();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGEngine::GetMoments(void)
+{
+  return Thruster->GetMoments();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGEngine::LoadThruster(FGConfigFile* AC_cfg)
+{
+  string token, fullpath, localpath;
+  string thrusterFileName, thrType, engineFileName;
+  FGConfigFile* Cfg_ptr = 0;
+  double xLoc, yLoc, zLoc, Pitch, Yaw;
+  double P_Factor = 0, Sense = 0.0;
+  string enginePath = FDMExec->GetEnginePath();
+  string aircraftPath = FDMExec->GetAircraftPath();
+  thrusterFileName = AC_cfg->GetValue("FILE");
+
+# ifndef macintosh
+      fullpath = enginePath + "/";
+      localpath = aircraftPath + "/"  + "/Engines/";
+# else
+      fullpath = enginePath + ";";
+      localpath = aircraftPath + ";" + ";Engines;";
+# endif
+
+  // Look in the Aircraft/Engines directory first
+  FGConfigFile Local_Thruster_cfg(localpath + thrusterFileName + ".xml");
+  FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
+
+  if (Local_Thruster_cfg.IsOpen()) {
+    Cfg_ptr = &Local_Thruster_cfg;
+    if (debug_lvl > 0) cout << "\n    Reading thruster from file: " << localpath
+                                      + thrusterFileName + ".xml"<< endl;
+  } else {
+    if (Thruster_cfg.IsOpen()) {
+      Cfg_ptr = &Thruster_cfg;
+      if (debug_lvl > 0) cout << "\n    Reading thruster from file: " << fullpath
+                                        + thrusterFileName + ".xml"<< endl;
+    }
+  }
+
+  if (Cfg_ptr) {
+    Cfg_ptr->GetNextConfigLine();
+    thrType = Cfg_ptr->GetValue();
+
+    if (thrType == "FG_PROPELLER") {
+      Thruster = new FGPropeller(FDMExec, Cfg_ptr);
+    } else if (thrType == "FG_NOZZLE") {
+      Thruster = new FGNozzle(FDMExec, Cfg_ptr);
+    } else if (thrType == "FG_DIRECT") {
+      Thruster = new FGThruster( FDMExec, Cfg_ptr);
+    }
+
+    AC_cfg->GetNextConfigLine();
+    while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
+      *AC_cfg >> token;
+      if (token == "XLOC") *AC_cfg >> xLoc;
+      else if (token == "YLOC") *AC_cfg >> yLoc;
+      else if (token == "ZLOC") *AC_cfg >> zLoc;
+      else if (token == "PITCH") *AC_cfg >> Pitch;
+      else if (token == "YAW") *AC_cfg >> Yaw;
+      else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
+      else if (token == "SENSE")   *AC_cfg >> Sense;
+      else cerr << "Unknown identifier: " << token << " in engine file: "
+                << engineFileName << endl;
+    }
+
+    Thruster->SetLocation(xLoc, yLoc, zLoc);
+    Thruster->SetAnglesToBody(0, Pitch, Yaw);
+    if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
+      ((FGPropeller*)Thruster)->SetPFactor(P_Factor);
+      if (debug_lvl > 0) cout << "      P-Factor: " << P_Factor << endl;
+      ((FGPropeller*)Thruster)->SetSense(fabs(Sense)/Sense);
+      if (debug_lvl > 0) cout << "      Sense: " << Sense <<  endl;
+    }
+    Thruster->SetdeltaT(State->Getdt() * Propulsion->GetRate());
+    return true;
+  } else {
+
+    cerr << "Could not read thruster config file: " << fullpath
+              + thrusterFileName + ".xml" << endl;
+    return false;
+  }
+
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
index 13d657ea35c9f3256023e627182fb1030195c11b..e0d070dd508154b6543fb36f8b5010f0e35e3faa 100644 (file)
@@ -59,6 +59,7 @@ INCLUDES
 #endif
 
 #include "FGJSBBase.h"
+#include "FGThruster.h"
 #include "FGPropertyManager.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -81,12 +82,12 @@ class FGState;
 class FGAtmosphere;
 class FGFCS;
 class FGAircraft;
-class FGTranslation;
-class FGRotation;
+class FGPropagate;
 class FGPropulsion;
-class FGPosition;
 class FGAuxiliary;
 class FGOutput;
+class FGThruster;
+class FGConfigFile;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DOCUMENTATION
@@ -96,7 +97,7 @@ CLASS DOCUMENTATION
     This base class contains methods and members common to all engines, such as
     logic to drain fuel from the appropriate tank, etc.
     @author Jon S. Berndt
-    @version $Id$ 
+    @version $Id$
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -109,7 +110,7 @@ public:
   FGEngine(FGFDMExec* exec);
   virtual ~FGEngine();
 
-  enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etSimTurbine};
+  enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etElectric};
 
   EngineType      GetType(void) { return Type; }
   virtual string  GetName(void) { return Name; }
@@ -138,11 +139,8 @@ public:
   virtual void SetStarter(bool s) { Starter = s; }
 
   /** Calculates the thrust of the engine, and other engine functions.
-      @param PowerRequired this is the power required to run the thrusting device
-             such as a propeller. This resisting effect must be provided to the 
-             engine model.
       @return Thrust in pounds */
-  virtual double Calculate(double PowerRequired) {return 0.0;};
+  virtual double Calculate(void) {return 0.0;}
 
   /** Reduces the fuel in the active tanks by the amount required.
       This function should be called from within the
@@ -174,6 +172,15 @@ public:
   virtual bool GetTrimMode(void) {return TrimMode;}
   virtual void SetTrimMode(bool state) {TrimMode = state;}
 
+  virtual FGColumnVector3& GetBodyForces(void);
+  virtual FGColumnVector3& GetMoments(void);
+
+  bool LoadThruster(FGConfigFile* AC_cfg);
+  FGThruster* GetThruster(void) {return Thruster;}
+
+  virtual string GetEngineLabels(void) = 0;
+  virtual string GetEngineValues(void) = 0;
+
 protected:
   FGPropertyManager* PropertyManager;
   string Name;
@@ -208,11 +215,10 @@ protected:
   FGFCS*          FCS;
   FGPropulsion*   Propulsion;
   FGAircraft*     Aircraft;
-  FGTranslation*  Translation;
-  FGRotation*     Rotation;
-  FGPosition*     Position;
+  FGPropagate*    Propagate;
   FGAuxiliary*    Auxiliary;
   FGOutput*       Output;
+  FGThruster*     Thruster;
 
   vector <int> SourceTanks;
   void Debug(int from);
@@ -223,12 +229,12 @@ protected:
 #include "FGAtmosphere.h"
 #include "FGFCS.h"
 #include "FGAircraft.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
+#include "FGPropagate.h"
 #include "FGPropulsion.h"
-#include "FGPosition.h"
 #include "FGAuxiliary.h"
 #include "FGOutput.h"
+#include "FGThruster.h"
+#include "FGConfigFile.h"
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 #endif
index 9cb89f909a5f1d41a5ef7674d584c3020907d3d4..cf1b8628fe57dbdb5801df73d9a71e305c8480c2 100644 (file)
@@ -75,8 +75,6 @@ FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)
   APAttitudeSetPt = APAltitudeSetPt = APHeadingSetPt = APAirspeedSetPt = 0.0;
   DoNormalize=true;
 
-  eMode = mNone;
-
   bind();
   for (i=0;i<=NForms;i++) {
     DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
@@ -117,26 +115,18 @@ bool FGFCS::Run(void)
 {
   unsigned int i;
 
-  if (!FGModel::Run()) {
-    for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
-    for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
-    for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
-    for (i=0; i<APComponents.size(); i++)  {
-      eMode = mAP;
-      APComponents[i]->Run();
-      eMode = mNone;
-    }
-    for (i=0; i<FCSComponents.size(); i++)  {
-      eMode = mFCS;
-      FCSComponents[i]->Run();
-      eMode = mNone;
-    }
-    if (DoNormalize) Normalize();
+  if (FGModel::Run()) return true; // fast exit if nothing to do
 
-    return false;
-  } else {
-    return true;
-  }
+  for (i=0; i<ThrottlePos.size(); i++) ThrottlePos[i] = ThrottleCmd[i];
+  for (i=0; i<MixturePos.size(); i++) MixturePos[i] = MixtureCmd[i];
+  for (i=0; i<PropAdvance.size(); i++) PropAdvance[i] = PropAdvanceCmd[i];
+
+  for (i=0; i<APComponents.size(); i++) APComponents[i]->Run(); // cycle AP components
+  for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run(); // cycle FCS components
+
+  if (DoNormalize) Normalize();
+
+  return false;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -297,9 +287,11 @@ bool FGFCS::Load(FGConfigFile* AC_cfg)
   }
 
 # ifndef macintosh
-  file = "control/" + fname + ".xml";
+//  file = "control/" + fname + ".xml";
+  file = FDMExec->GetAircraftPath() + "/" + FDMExec->GetModelName() + "/" + fname + ".xml";
 # else
-  file = "control;" + fname + ".xml";
+//  file = "control;" + fname + ".xml";
+  file = FDMExec->GetAircraftPath() + ";" + FDMExec->GetModelName() + ";" + fname + ".xml";
 # endif
 
   if (name.empty()) {
@@ -322,11 +314,9 @@ bool FGFCS::Load(FGConfigFile* AC_cfg)
 
   if (delimiter == "AUTOPILOT") {
     Components = &APComponents;
-    eMode = mAP;
     Name = "Autopilot: " + name;
   } else if (delimiter == "FLIGHT_CONTROL") {
     Components = &FCSComponents;
-    eMode = mFCS;
     Name = "FCS: " + name;
   } else {
     cerr << endl << "Unknown FCS delimiter" << endl << endl;
@@ -400,45 +390,11 @@ bool FGFCS::Load(FGConfigFile* AC_cfg)
 
   if (delimiter == "FLIGHT_CONTROL") bindModel();
 
-  eMode = mNone;
-
   return true;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGFCS::GetComponentOutput(int idx)
-{
-  switch (eMode) {
-  case mFCS:
-    return FCSComponents[idx]->GetOutput();
-  case mAP:
-    return APComponents[idx]->GetOutput();
-  case mNone:
-    cerr << "Unknown FCS mode" << endl;
-    break;
-  }
-  return 0.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGFCS::GetComponentName(int idx)
-{
-  switch (eMode) {
-  case mFCS:
-    return FCSComponents[idx]->GetName();
-  case mAP:
-    return APComponents[idx]->GetName();
-  case mNone:
-    cerr << "Unknown FCS mode" << endl;
-    break;
-  }
-  return string("");
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 double FGFCS::GetBrake(FGLGear::BrakeGroup bg)
 {
   switch (bg) {
@@ -484,7 +440,7 @@ string FGFCS::GetComponentValues(void)
 {
   unsigned int comp;
   string CompValues = "";
-  char buffer[10];
+  char buffer[12];
   bool firstime = true;
 
   for (comp = 0; comp < FCSComponents.size(); comp++) {
index 1d7e484cffdb68616c995316d97fd7a58fdfd5f0..0340fd432ad18a18b87acf42023eeba006e9250c 100644 (file)
@@ -3,30 +3,30 @@
  Header:       FGGFCS.h
  Author:       Jon S. Berndt
  Date started: 12/12/98
+
  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
+
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.
+
  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place - Suite 330, Boston, MA  02111-1307, USA.
+
  Further information about the GNU General Public License can also be found on
  the world wide web at http://www.gnu.org.
+
 HISTORY
 --------------------------------------------------------------------------------
 12/12/98   JSB   Created
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 SENTRY
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -81,61 +81,58 @@ CLASS DOCUMENTATION
     or command and ends at an effector, e.g. an aerosurface. The FCS components
     which comprise the control laws for an axis are defined sequentially in
     the configuration file. For instance, for the X-15:
-    
+
     <pre>
-    &lt FLIGHT_CONTROL NAME="X-15 SAS"&gt
-
-    &lt COMPONENT NAME="Pitch Trim Sum" TYPE="SUMMER"&gt
-      ID            0
-      INPUT        FG_ELEVATOR_CMD
-      INPUT        FG_PITCH_TRIM_CMD
-      CLIPTO       -1 1
-    &lt/COMPONENT&gt
-
-    &lt COMPONENT NAME="Pitch Command Scale" TYPE="AEROSURFACE_SCALE"&gt
-      ID           1
-      INPUT        0
+    \<FLIGHT_CONTROL NAME="X-15 SAS">
+
+    \<COMPONENT NAME="Pitch Trim Sum" TYPE="SUMMER">
+       INPUT        fcs/elevator-cmd-norm
+       INPUT        fcs/pitch-trim-cmd-norm
+       CLIPTO       -1 1
+    \</COMPONENT>
+
+    \<COMPONENT NAME="Pitch Command Scale" TYPE="AEROSURFACE_SCALE">
+      INPUT        fcs/pitch-trim-sum
       MIN         -50
       MAX          50
-    &lt/COMPONENT&gt
+    \</COMPONENT>
 
-    &lt COMPONENT NAME="Pitch Gain 1" TYPE="PURE_GAIN"&gt
-      ID           2
-      INPUT        1
+    \<COMPONENT NAME="Pitch Gain 1" TYPE="PURE_GAIN">
+      INPUT        fcs/pitch-command-scale
       GAIN         -0.36
-    &lt/COMPONENT&gt
-
-    &lt COMPONENT NAME="Pitch Scheduled Gain 1" TYPE="SCHEDULED_GAIN"&gt
-      ID           3
-      INPUT        2
-      GAIN         0.017
-      SCHEDULED_BY FG_ELEVATOR_POS
-      -0.35  -6.0
-      -0.17  -3.0
-       0.00  -2.0
-       0.09  -3.0
-       0.17  -5.0
-       0.60 -12.0
-    &lt/COMPONENT&gt
+    \</COMPONENT>
 
     ... etc.
     </pre>
-    
+
     In the above case we can see the first few components of the pitch channel
     defined. The input to the first component, as can be seen in the "Pitch trim
     sum" component, is really the sum of two parameters: elevator command (from
     the stick - a pilot input), and pitch trim. The type of this component is
-    "Summer". Its ID is 0 - the ID is used by other components to reference it.
+    "Summer".
     The next component created is an aerosurface scale component - a type of
     gain (see the LoadFCS() method for insight on how the various types of
-    components map into the actual component classes). You can see the input of
-    the "Pitch Command Scale" component takes "0" as input. When a number is
-    specified as an input, it refers to the ID of another FCS component. In this
-    case, ID 0 refers to the previously defined and discussed "Pitch Trim Sum"
-    component. This continues until the final component for an axis when the
+    components map into the actual component classes).  This continues until the
+    final component for an axis when the
     OUTPUT keyword specifies where the output is supposed to go. See the
     individual components for more information on how they are mechanized.
-    
+
+    Another option for the flight controls portion of the config file is that in
+    addition to using the "NAME" attribute in,
+
+    <pre>
+    \<FLIGHT_CONTROL NAME="X-15 SAS">
+    </pre>
+
+    one can also supply a filename:
+
+    <pre>
+    \<FLIGHT_CONTROL NAME="X-15 SAS" FILE="X15.xml">
+    \</FLIGHT_CONTROL>
+    </pre>
+
+    In this case, the FCS would be read in from another file.
+
     @author Jon S. Berndt
     @version $Id$
     @see FGFCSComponent
@@ -170,7 +167,7 @@ public:
   /** Gets the aileron command.
       @return aileron command in percent */
   inline double GetDaCmd(void) const { return DaCmd; }
-  
+
   /** Gets the elevator command.
       @return elevator command in percent */
   inline double GetDeCmd(void) const { return DeCmd; }
@@ -209,19 +206,19 @@ public:
   /** Gets the pitch trim command.
       @return pitch trim command in percent */
   inline double GetPitchTrimCmd(void) const { return PTrimCmd; }
-  
+
   /** Gets the rudder trim command.
       @return rudder trim command in percent */
   inline double GetYawTrimCmd(void) const { return YTrimCmd; }
-  
+
   /** Gets the aileron trim command.
       @return aileron trim command in percent */
   inline double GetRollTrimCmd(void) const { return RTrimCmd; }
-  
+
   /** Get the gear extend/retract command. 0 commands gear up, 1 down.
       defaults to down.
       @return the current value of the gear extend/retract command*/
-  inline double GetGearCmd(void) const { return GearCmd; }    
+  inline double GetGearCmd(void) const { return GearCmd; }
   //@}
 
   /// @name AUTOPilot -> FCS effectors command retrieval
@@ -229,7 +226,7 @@ public:
   /** Gets the AUTOPilot aileron command.
       @return aileron command in radians */
   inline double GetAPDaCmd(void) const { return AP_DaCmd; }
-  
+
   /** Gets the AUTOPilot elevator command.
       @return elevator command in radians */
   inline double GetAPDeCmd(void) const { return AP_DeCmd; }
@@ -237,7 +234,7 @@ public:
   /** Gets the AUTOPilot rudder command.
       @return rudder command in radians */
   inline double GetAPDrCmd(void) const { return AP_DrCmd; }
-  
+
   /** Gets the AUTOPilot throttle (all engines) command.
       @return throttle command in percent */
   inline double GetAPThrottleCmd(void) const { return AP_ThrottleCmd; }
@@ -283,19 +280,19 @@ public:
   /** Turns on/off the attitude-seeking autopilot.
       @param set true turns the mode on, false turns it off  **/
   inline void SetAPAcquireAttitude(bool set) {APAcquireAttitude = set;}
-  
+
   /** Turns on/off the altitude-seeking autopilot.
       @param set true turns the mode on, false turns it off  **/
   inline void SetAPAcquireAltitude(bool set) {APAcquireAltitude = set;}
-  
+
   /** Turns on/off the heading-seeking autopilot.
       @param set true turns the mode on, false turns it off  **/
   inline void SetAPAcquireHeading(bool set) {APAcquireHeading = set;}
-  
+
   /** Turns on/off the airspeed-seeking autopilot.
       @param set true turns the mode on, false turns it off  **/
   inline void SetAPAcquireAirspeed(bool set) {APAcquireAirspeed = set;}
-  
+
   /** Turns on/off the attitude-holding autopilot.
       @param set true turns the mode on, false turns it off  **/
   inline void SetAPAttitudeHold(bool set) {APAttitudeHold = set;}
@@ -316,7 +313,7 @@ public:
       @param set true turns the mode on, false turns it off  **/
   inline void SetAPWingsLevelHold(bool set) {APWingsLevelHold = set;}
   //@}
-  
+
   /// @name AUTOPilot mode retrieval
   //@{
   /** Retrieves the on/off mode of the autopilot AcquireAttitude mode
@@ -360,41 +357,41 @@ public:
   //@{
   /** Gets the left aileron position.
       @return aileron position in radians */
-  inline double GetDaLPos( int form = ofRad ) 
+  inline double GetDaLPos( int form = ofRad )
                          const { return DaLPos[form]; }
 
   /// @name Aerosurface position retrieval
   //@{
   /** Gets the right aileron position.
       @return aileron position in radians */
-  inline double GetDaRPos( int form = ofRad ) 
+  inline double GetDaRPos( int form = ofRad )
                          const { return DaRPos[form]; }
 
   /** Gets the elevator position.
       @return elevator position in radians */
-  inline double GetDePos( int form = ofRad ) 
+  inline double GetDePos( int form = ofRad )
                          const { return DePos[form]; }
+
   /** Gets the rudder position.
       @return rudder position in radians */
-  inline double GetDrPos( int form = ofRad ) 
+  inline double GetDrPos( int form = ofRad )
                          const { return DrPos[form]; }
 
   /** Gets the speedbrake position.
       @return speedbrake position in radians */
-  inline double GetDsbPos( int form = ofRad ) 
+  inline double GetDsbPos( int form = ofRad )
                          const { return DsbPos[form]; }
 
   /** Gets the spoiler position.
       @return spoiler position in radians */
-  inline double GetDspPos( int form = ofRad ) 
+  inline double GetDspPos( int form = ofRad )
                          const { return DspPos[form]; }
-  
+
   /** Gets the flaps position.
       @return flaps position in radians */
-  inline double GetDfPos( int form = ofRad ) 
+  inline double GetDfPos( int form = ofRad )
                          const { return DfPos[form]; }
-                         
+
   /** Gets the throttle position.
       @param engine engine ID number
       @return throttle position for the given engine in percent ( 0 - 100)*/
@@ -404,10 +401,10 @@ public:
       @param engine engine ID number
       @return mixture position for the given engine in percent ( 0 - 100)*/
   inline double GetMixturePos(int engine) const { return MixturePos[engine]; }
-  
+
   /** Gets the gear position (0 up, 1 down), defaults to down
       @return gear position (0 up, 1 down) */
-  inline double GetGearPos(void) const { return GearPos; }    
+  inline double GetGearPos(void) const { return GearPos; }
 
   /** Gets the prop pitch position.
       @param engine engine ID number
@@ -420,16 +417,6 @@ public:
       @return pointer to the State object */
   inline FGState* GetState(void) { return State; }
 
-  /** Retrieves a components output value
-      @param idx the index of the component (the component ID)
-      @return output value from the component */
-  double GetComponentOutput(int idx);
-
-  /** Retrieves the component name
-      @param idx the index of the component (the component ID)
-      @return name of the component */
-  string GetComponentName(int idx);
-
   /** Retrieves all component names for inclusion in output stream */
   string GetComponentStrings(void);
 
@@ -483,10 +470,10 @@ public:
       @param engine engine ID number
       @param cmd mixture command in percent (0 - 100)*/
   void SetMixtureCmd(int engine, double cmd);
-  
+
   /** Set the gear extend/retract command, defaults to down
       @param gear command 0 for up, 1 for down */
-   void SetGearCmd(double gearcmd) { GearCmd = gearcmd; }   
+   void SetGearCmd(double gearcmd) { GearCmd = gearcmd; }
 
   /** Sets the propeller pitch command for the specified engine
       @param engine engine ID number
@@ -517,39 +504,39 @@ public:
   //@{
   /** Sets the left aileron position
       @param cmd left aileron position in radians*/
-  inline void SetDaLPos( int form , double pos ) 
+  inline void SetDaLPos( int form , double pos )
                                       { DaLPos[form] = pos; }
 
   /** Sets the right aileron position
       @param cmd right aileron position in radians*/
-  inline void SetDaRPos( int form , double pos ) 
+  inline void SetDaRPos( int form , double pos )
                                       { DaRPos[form] = pos; }
 
   /** Sets the elevator position
       @param cmd elevator position in radians*/
-  inline void SetDePos( int form , double pos ) 
+  inline void SetDePos( int form , double pos )
                                       { DePos[form] = pos; }
 
   /** Sets the rudder position
       @param cmd rudder position in radians*/
-  inline void SetDrPos( int form , double pos ) 
+  inline void SetDrPos( int form , double pos )
                                       { DrPos[form] = pos; }
+
    /** Sets the flaps position
       @param cmd flaps position in radians*/
-  inline void SetDfPos( int form , double pos ) 
+  inline void SetDfPos( int form , double pos )
                                       { DfPos[form] = pos; }
-  
+
   /** Sets the speedbrake position
       @param cmd speedbrake position in radians*/
-  inline void SetDsbPos( int form , double pos ) 
+  inline void SetDsbPos( int form , double pos )
                                       { DsbPos[form] = pos; }
 
   /** Sets the spoiler position
       @param cmd spoiler position in radians*/
-  inline void SetDspPos( int form , double pos ) 
+  inline void SetDspPos( int form , double pos )
                                       { DspPos[form] = pos; }
+
   /** Sets the actual throttle setting for the specified engine
       @param engine engine ID number
       @param cmd throttle setting in percent (0 - 100)*/
@@ -559,10 +546,10 @@ public:
       @param engine engine ID number
       @param cmd mixture setting in percent (0 - 100)*/
   void SetMixturePos(int engine, double cmd);
-  
+
   /** Set the gear extend/retract position, defaults to down
       @param gear position 0 up, 1 down       */
-   void SetGearPos(double gearpos) { GearPos = gearpos; }   
+   void SetGearPos(double gearpos) { GearPos = gearpos; }
 
 
   /** Sets the actual prop pitch setting for the specified engine
@@ -600,17 +587,17 @@ public:
   bool Load(FGConfigFile* AC_cfg);
 
   void AddThrottle(void);
-  
+
   FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
-  
+
   void bind(void);
   void bindModel(void);
   void unbind(FGPropertyManager *node);
-  
+
 private:
   double DaCmd, DeCmd, DrCmd, DfCmd, DsbCmd, DspCmd;
   double AP_DaCmd, AP_DeCmd, AP_DrCmd, AP_ThrottleCmd;
-  double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms];  
+  double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms];
   double DfPos[NForms], DsbPos[NForms], DspPos[NForms];
   double PTrimCmd, YTrimCmd, RTrimCmd;
   vector <double> ThrottleCmd;
@@ -622,8 +609,6 @@ private:
   double LeftBrake, RightBrake, CenterBrake; // Brake settings
   double GearCmd,GearPos;
 
-  enum Mode {mAP, mFCS, mNone} eMode;
-
   double APAttitudeSetPt, APAltitudeSetPt, APHeadingSetPt, APAirspeedSetPt;
   bool APAcquireAttitude, APAcquireAltitude, APAcquireHeading, APAcquireAirspeed;
   bool APAttitudeHold, APAltitudeHold, APHeadingHold, APAirspeedHold, APWingsLevelHold;
index 02e433047c5b71e3dae49d0d12afed0f9256935a..3002ec56bdc2f44175b5eeba46acd7ccbaef58ac 100644 (file)
@@ -64,9 +64,7 @@ INCLUDES
 #include "FGAerodynamics.h"
 #include "FGInertial.h"
 #include "FGAircraft.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
 #include "FGAuxiliary.h"
 #include "FGOutput.h"
 #include "FGConfigFile.h"
@@ -100,16 +98,16 @@ void checkTied ( FGPropertyManager *node )
     } else if ( node->getChild(i)->isTied() ) {
       name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName();
       cerr << name << " is tied" << endl;
-    } 
+    }
   }
-}        
+}
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // Constructor
 
 FGFDMExec::FGFDMExec(FGPropertyManager* root)
 {
-  
+
   Frame           = 0;
   FirstModel      = 0;
   Error           = 0;
@@ -122,9 +120,7 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root)
   Inertial        = 0;
   GroundReactions = 0;
   Aircraft        = 0;
-  Translation     = 0;
-  Rotation        = 0;
-  Position        = 0;
+  Propagate       = 0;
   Auxiliary       = 0;
   Output          = 0;
   IC              = 0;
@@ -150,9 +146,9 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root)
 
   instance = master->GetNode("/fdm/jsbsim",IdFDM,true);
 
-  
+
   Debug(0);
-  
+
   // this is here to catch errors in binding member functions
   // to the property tree.
   try {
@@ -160,7 +156,7 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root)
   } catch ( string msg ) {
     cout << "Caught error: " << msg << endl;
     exit(1);
-  }    
+  }
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -172,11 +168,11 @@ FGFDMExec::~FGFDMExec()
     checkTied( instance );
   } catch ( string msg ) {
     cout << "Caught error: " << msg << endl;
-  }    
-  
+  }
+
   for (unsigned int i=1; i<SlaveFDMList.size(); i++) delete SlaveFDMList[i]->exec;
   SlaveFDMList.clear();
-  
+
   Debug(1);
 }
 
@@ -194,16 +190,14 @@ bool FGFDMExec::Allocate(void)
   Inertial        = new FGInertial(this);
   GroundReactions = new FGGroundReactions(this);
   Aircraft        = new FGAircraft(this);
-  Translation     = new FGTranslation(this);
-  Rotation        = new FGRotation(this);
-  Position        = new FGPosition(this);
+  Propagate       = new FGPropagate(this);
   Auxiliary       = new FGAuxiliary(this);
   Output          = new FGOutput(this);
 
   State        = new FGState(this); // This must be done here, as the FGState
                                     // class needs valid pointers to the above
                                     // model classes
-  
+
   // Initialize models so they can communicate with each other
 
   if (!Atmosphere->InitModel()) {
@@ -230,15 +224,9 @@ bool FGFDMExec::Allocate(void)
   if (!Aircraft->InitModel())   {
     cerr << fgred << "Aircraft model init failed" << fgdef << endl;
     Error+=128;}
-  if (!Translation->InitModel()) {
-    cerr << fgred << "Translation model init failed" << fgdef << endl;
-    Error+=256;}
-  if (!Rotation->InitModel())   {
-    cerr << fgred << "Rotation model init failed" << fgdef << endl;
+  if (!Propagate->InitModel())   {
+    cerr << fgred << "Propagate model init failed" << fgdef << endl;
     Error+=512;}
-  if (!Position->InitModel())   {
-    cerr << fgred << "Position model init failed" << fgdef << endl;
-    Error+=1024;}
   if (!Auxiliary->InitModel())  {
     cerr << fgred << "Auxiliary model init failed" << fgdef << endl;
     Error+=2058;}
@@ -247,9 +235,9 @@ bool FGFDMExec::Allocate(void)
     Error+=4096;}
 
   if (Error > 0) result = false;
-  
-  IC = new FGInitialCondition(this); 
-  
+
+  IC = new FGInitialCondition(this);
+
   // Schedule a model. The second arg (the integer) is the pass number. For
   // instance, the atmosphere model gets executed every fifth pass it is called
   // by the executive. Everything else here gets executed each pass.
@@ -263,9 +251,7 @@ bool FGFDMExec::Allocate(void)
   Schedule(Inertial,        1);
   Schedule(GroundReactions, 1);
   Schedule(Aircraft,        1);
-  Schedule(Rotation,        1);
-  Schedule(Translation,     1);
-  Schedule(Position,        1);
+  Schedule(Propagate,       1);
   Schedule(Auxiliary,       1);
   Schedule(Output,          1);
 
@@ -286,16 +272,14 @@ bool FGFDMExec::DeAllocate(void)
   delete Inertial;
   delete GroundReactions;
   delete Aircraft;
-  delete Translation;
-  delete Rotation;
-  delete Position;
+  delete Propagate;
   delete Auxiliary;
   delete Output;
   delete State;
-  
+
   delete IC;
   delete Trim;
-    
+
   FirstModel  = 0L;
   Error       = 0;
 
@@ -308,9 +292,7 @@ bool FGFDMExec::DeAllocate(void)
   Inertial        = 0;
   GroundReactions = 0;
   Aircraft        = 0;
-  Translation     = 0;
-  Rotation        = 0;
-  Position        = 0;
+  Propagate       = 0;
   Auxiliary       = 0;
   Output          = 0;
 
@@ -341,7 +323,7 @@ int FGFDMExec::Schedule(FGModel* model, int rate)
     model_iterator->NextModel->SetRate(rate);
 
   }
-  
+
   return 0;
 }
 
@@ -408,7 +390,7 @@ bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model)
   FGFDMExec::EnginePath = EnginePath;
 
   return LoadModel(model);
-}  
+}
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -423,18 +405,18 @@ bool FGFDMExec::LoadModel(string model)
     cerr << "aircraft and engine paths" << endl;
     return false;
   }
-    
+
 # ifndef macintosh
-  aircraftCfgFileName = AircraftPath + "/" + model + "/" + model + ".xml";
+  aircraftCfgFileName = AircraftPath + "/"  + model + ".xml";
 # else
-  aircraftCfgFileName = AircraftPath + ";" + model + ";" + model + ".xml";
+  aircraftCfgFileName = AircraftPath + ";"  + model + ".xml";
 # endif
 
   FGConfigFile AC_cfg(aircraftCfgFileName);
   if (!AC_cfg.IsOpen()) return false;
-  
+
   modelName = model;
-  
+
   if (modelLoaded) {
     DeAllocate();
     Allocate();
@@ -512,7 +494,7 @@ bool FGFDMExec::ReadPrologue(FGConfigFile* AC_cfg)
     cerr << "         You have version: " << CFGVersion << endl << fgdef << endl;
     return false;
   }
-  
+
   if (Release == "ALPHA") {
     system("banner ALPHA");
     cout << endl << endl
@@ -557,7 +539,7 @@ bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
   string AircraftName = AC_cfg->GetValue("FILE");
 
   debug_lvl = 0;                 // turn off debug output for slave vehicle
-  
+
   SlaveFDMList.back()->exec->SetAircraftPath( AircraftPath );
   SlaveFDMList.back()->exec->SetEnginePath( EnginePath );
   SlaveFDMList.back()->exec->LoadModel(AircraftName);
@@ -655,18 +637,18 @@ bool FGFDMExec::ReadOutput(FGConfigFile* AC_cfg)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGPropertyManager* FGFDMExec::GetPropertyManager(void) { 
+FGPropertyManager* FGFDMExec::GetPropertyManager(void) {
   return instance;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGTrim* FGFDMExec::GetTrim(void) { 
+FGTrim* FGFDMExec::GetTrim(void) {
   delete Trim;
   Trim = new FGTrim(this,tNone);
   return Trim;
 }
-  
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
index 0be0ff8d1abc69bffaffed61951dbd461916f398..fefe6cd37544e425e307af2c6402549e947b0796 100644 (file)
@@ -27,7 +27,7 @@ HISTORY
 11/17/98   JSB   Created
 7/31/99     TP   Added RunIC function that runs the sim so that every frame
                  begins with the IC values from the given FGInitialCondition
-                                  object and dt=0.
+                 object and dt=0.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 SENTRY
@@ -72,31 +72,30 @@ CLASS DOCUMENTATION
 
     When an aircraft model is loaded the config file is parsed and for each of the
     sections of the config file (propulsion, flight control, etc.) the
-    corresponding "ReadXXX()" method is called. From within this method the 
+    corresponding "ReadXXX()" method is called. From within this method the
     "Load()" method of that system is called (e.g. LoadFCS).
 
     <h4>JSBSim Debugging Directives</h4>
 
     This describes to any interested entity the debug level
     requested by setting the JSBSIM_DEBUG environment variable.
-    The bitmasked value choices are as follows:<ol>
-    <li><b>unset</b>: In this case (the default) JSBSim would only print
+    The bitmasked value choices are as follows:
+    <b>unset</b>: In this case (the default) JSBSim would only print
        out the normally expected messages, essentially echoing
        the config files as they are read. If the environment
-       variable is not set, debug_lvl is set to 1 internally</li>
-    <li><b>0</b>: This requests JSBSim not to output any messages
-       whatsoever.</li>
-    <li><b>1</b>: This value explicity requests the normal JSBSim
-       startup messages</li>
-    <li><b>2</b>: This value asks for a message to be printed out when
-       a class is instantiated</li>
-    <li><b>4</b>: When this value is set, a message is displayed when a
-       FGModel object executes its Run() method</li>
-    <li><b>8</b>: When this value is set, various runtime state variables
-       are printed out periodically</li>
-    <li><b>16</b>: When set various parameters are sanity checked and
-       a message is printed out when they go out of bounds</li>
-    </ol>
+       variable is not set, debug_lvl is set to 1 internally
+    - <b>0</b>: This requests JSBSim not to output any messages
+       whatsoever
+    - <b>1</b>: This value explicity requests the normal JSBSim
+       startup messages
+    - <b>2</b>: This value asks for a message to be printed out when
+       a class is instantiated
+    - <b>4</b>: When this value is set, a message is displayed when a
+       FGModel object executes its Run() method
+    - <b>8</b>: When this value is set, various runtime state variables
+       are printed out periodically
+    - <b>16</b>: When set various parameters are sanity checked and
+       a message is printed out when they go out of bounds
 
     @author Jon S. Berndt
     @version $Id$
@@ -112,7 +111,7 @@ public:
 
   /// Default constructor
   FGFDMExec(FGPropertyManager* root = 0);
-  
+
   /// Default destructor
   ~FGFDMExec();
 
@@ -142,8 +141,8 @@ public:
 
   /// Resumes the sim
   void Resume(void) {frozen = false;}
-  
-  /** Loads an aircraft model.  
+
+  /** Loads an aircraft model.
       @param AircraftPath path to the aircraft directory. For instance:
       "aircraft". Under aircraft, then, would be directories for various
       modeled aircraft such as C172/, x15/, etc.
@@ -155,7 +154,7 @@ public:
       instance: "aircraft/x15/x15.xml"
       @return true if successful*/
   bool LoadModel(string AircraftPath, string EnginePath, string model);
-  
+
 
   /** Loads an aircraft model.  The paths to the aircraft and engine
       config file directories must be set prior to calling this.  See
@@ -166,7 +165,7 @@ public:
       instance: "aircraft/x15/x15.xml"
       @return true if successful*/
   bool LoadModel(string model);
-  
+
 
   /** Sets the path to the engine config file directories.
       @param path path to the directory under which engine config
@@ -180,14 +179,14 @@ public:
       modeled aircraft such as C172/, x15/, etc.
   */
   bool SetAircraftPath(string path) { AircraftPath = path; return true; }
-  
+
   /** Sets the path to the autopilot config file directories.
       @param path path to the control directory. For instance:
       "control".
   */
-  bool SetControlPath(string path) { ControlPath = path; return true; }
-  
+//  bool SetControlPath(string path) { ControlPath = path; return true; }
+
+
   /// @name Top-level executive State and Model retrieval mechanism
   //@{
   /// Returns the FGState pointer.
@@ -208,12 +207,8 @@ public:
   inline FGGroundReactions* GetGroundReactions(void) {return GroundReactions;}
   /// Returns the FGAircraft pointer.
   inline FGAircraft* GetAircraft(void)        {return Aircraft;}
-  /// Returns the FGTranslation pointer.
-  inline FGTranslation* GetTranslation(void)  {return Translation;}
-  /// Returns the FGRotation pointer.
-  inline FGRotation* GetRotation(void)        {return Rotation;}
-  /// Returns the FGPosition pointer.
-  inline FGPosition* GetPosition(void)        {return Position;}
+  /// Returns the FGPropagate pointer.
+  inline FGPropagate* GetPropagate(void)        {return Propagate;}
   /// Returns the FGAuxiliary pointer.
   inline FGAuxiliary* GetAuxiliary(void)      {return Auxiliary;}
   /// Returns the FGOutput pointer.
@@ -223,20 +218,20 @@ public:
   // Returns a pointer to the FGTrim object
   FGTrim* GetTrim(void);
   //@}
-  
+
   /// Retrieves the engine path.
   inline string GetEnginePath(void)          {return EnginePath;}
   /// Retrieves the aircraft path.
   inline string GetAircraftPath(void)        {return AircraftPath;}
-  /// Retrieves the control path.
-  inline string GetControlPath(void)        {return ControlPath;}
-  
+//  /// Retrieves the control path.
+//  inline string GetControlPath(void)        {return ControlPath;}
+
   string GetModelName(void) { return modelName; }
-  
+
   FGPropertyManager* GetPropertyManager(void);
   vector <string> EnumerateFDMs(void);
   void SetSlave(void) {IsSlave = true;}
-  
+
 private:
   FGModel* FirstModel;
 
@@ -251,7 +246,7 @@ private:
   bool IsSlave;
   static FGPropertyManager *master;
   FGPropertyManager *instance;
-  
+
   struct slaveData {
     FGFDMExec* exec;
     string info;
@@ -273,8 +268,8 @@ private:
 
   string AircraftPath;
   string EnginePath;
-  string ControlPath;
-  
+//  string ControlPath;
+
   string CFGVersion;
   string Release;
 
@@ -287,12 +282,10 @@ private:
   FGInertial*        Inertial;
   FGGroundReactions* GroundReactions;
   FGAircraft*        Aircraft;
-  FGTranslation*     Translation;
-  FGRotation*        Rotation;
-  FGPosition*        Position;
+  FGPropagate*       Propagate;
   FGAuxiliary*       Auxiliary;
   FGOutput*          Output;
-  
+
   FGInitialCondition* IC;
   FGTrim *Trim;
 
index d4fb17de7332bef2d7f4e7c855908e2a95630237..413e792f0315790547d6d8fa1fc5b3b510699092 100644 (file)
@@ -69,9 +69,7 @@ class FGState;
 class FGAtmosphere;
 class FGFCS;
 class FGAircraft;
-class FGTranslation;
-class FGRotation;
-class FGPosition;
+class FGPropagate;
 class FGAuxiliary;
 class FGOutput;
 
@@ -93,13 +91,13 @@ class FGFactorGroup: public FGCoefficient
 public:
   FGFactorGroup(FGFDMExec* fdmex);
   ~FGFactorGroup();
-  
+
   bool Load(FGConfigFile *AC_cfg);
   double TotalValue(void);
   inline double GetValue(void) const { return totalValue; }
   inline double GetSD(void) { return SDtotal; }
   inline double GetFactorSD(void) { return FGCoefficient::GetSD(); }
-  
+
   void bind(FGPropertyManager* parent);
   void unbind(void);
 
@@ -113,5 +111,5 @@ private:
   FGPropertyManager *node;
   void Debug(int from);
 };
-}    
-#endif 
+}
+#endif
index 72256d198a91e605bfadb735412ffcbf1c99cc17..bbdefb8b24fa45f9b4f4620c5ea3441392e8d2b0 100644 (file)
@@ -42,7 +42,7 @@ and the cg.
 
 #include "FGFDMExec.h"
 #include "FGAircraft.h"
-#include "FGTranslation.h"
+#include "FGPropagate.h"
 #include "FGMassBalance.h"
 #include "FGState.h"
 #include "FGForce.h"
@@ -97,7 +97,7 @@ FGMatrix33 FGForce::Transform(void)
   case tWindBody:
     return fdmex->GetState()->GetTs2b();
   case tLocalBody:
-    return fdmex->GetState()->GetTl2b();
+    return fdmex->GetPropagate()->GetTl2b();
   case tCustom:
   case tNone:
     return mT;
index 06d587bf3b4c093a77d7c832fdcd7f9ae1237c60..5f33e805836ea9406fc5f6cb9b3fdf1d2fb22031 100644 (file)
@@ -261,7 +261,7 @@ public:
     vXYZn(eZ) = z;
     SetActingLocation(x, y, z);
   }
-  
+
   /** Acting point of application.
       JSBsim structural coords used (inches, x +back, y +right, z +up).
       This function sets the point at which the force acts - this may
@@ -283,7 +283,7 @@ public:
   inline double SetActingLocationZ(double z) {vActingXYZn(eZ) = z; return z;}
   inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; SetActingLocation(vv);}
   inline void SetActingLocation(FGColumnVector3 vv) { vActingXYZn = vv; }
-  
+
   inline double GetLocationX( void ) { return vXYZn(eX);}
   inline double GetLocationY( void ) { return vXYZn(eY);}
   inline double GetLocationZ( void ) { return vXYZn(eZ);}
@@ -320,7 +320,7 @@ protected:
   FGColumnVector3 vFn;
   FGColumnVector3 vMn;
   FGColumnVector3 vH;
-  
+
 private:
   FGColumnVector3 vFb;
   FGColumnVector3 vM;
@@ -331,7 +331,7 @@ private:
 
   FGMatrix33 mT;
 
-  virtual void Debug(int from);
+  void Debug(int from);
 };
 }
 #endif
index 960cda2624119bb28d7e2733fdcca9a6c873794c..57dc4c2ff743783f1e2ff97cc4798dbd0951aa76 100644 (file)
@@ -35,6 +35,9 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <sstream>
+#include <iomanip>
+
 #include "FGGroundReactions.h"
 #include "FGPropertyManager.h"
 
@@ -43,15 +46,6 @@ namespace JSBSim {
 static const char *IdSrc = "$Id$";
 static const char *IdHdr = ID_GROUNDREACTIONS;
 
-#if defined (__APPLE__)
-/* Not all systems have the gcvt function */
-inline char* gcvt (double value, int ndigits, char *buf) {
-    /* note that this is not exactly what gcvt is supposed to do! */
-    snprintf (buf, ndigits+1, "%f", value);
-    return buf;
-}
-#endif
-
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -60,7 +54,7 @@ CLASS IMPLEMENTATION
 FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex)
 {
   Name = "FGGroundReactions";
-  
+
   bind();
 
   Debug(0);
@@ -84,7 +78,7 @@ bool FGGroundReactions::Run(void)
     vMoments.InitMatrix();
 
     // Only execute gear force code below 300 feet
-    if ( Position->GetDistanceAGL() < 300.0 ) {
+    if ( Propagate->GetDistanceAGL() < 300.0 ) {
       vector <FGLGear>::iterator iGear = lGear.begin();
       // Sum forces and moments for all gear, here.
       // Some optimizations may be made here - or rather in the gear code itself.
@@ -126,79 +120,71 @@ bool FGGroundReactions::Load(FGConfigFile* AC_cfg)
 
 string FGGroundReactions::GetGroundReactionStrings(void)
 {
-  string GroundReactionStrings = "";
-  bool firstime = true;
+  std::ostringstream buf;
 
   for (unsigned int i=0;i<lGear.size();i++) {
-    if (!firstime) GroundReactionStrings += ", ";
-    GroundReactionStrings += (lGear[i].GetName() + "_WOW, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_stroke, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_strokeVel, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_CompressForce, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_WhlSideForce, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_WhlVelVecX, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_WhlVelVecY, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_WhlRollForce, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_BodyXForce, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_BodyYForce, ");
-    GroundReactionStrings += (lGear[i].GetName() + "_WhlSlipDegrees");
-
-    firstime = false;
+    string name = lGear[i].GetName();
+    buf << name << "_WOW, "
+        << name << "_stroke, "
+        << name << "_strokeVel, "
+        << name << "_CompressForce, "
+        << name << "_WhlSideForce, "
+        << name << "_WhlVelVecX, "
+        << name << "_WhlVelVecY, "
+        << name << "_WhlRollForce, "
+        << name << "_BodyXForce, "
+        << name << "_BodyYForce, "
+        << name << "_WhlSlipDegrees, ";
   }
 
-  GroundReactionStrings += ", TotalGearForce_X, ";
-  GroundReactionStrings += "TotalGearForce_Y, ";
-  GroundReactionStrings += "TotalGearForce_Z, ";
-  GroundReactionStrings += "TotalGearMoment_L, ";
-  GroundReactionStrings += "TotalGearMoment_M, ";
-  GroundReactionStrings += "TotalGearMoment_N";
+  buf << "TotalGearForce_X, "
+      << "TotalGearForce_Y, "
+      << "TotalGearForce_Z, "
+      << "TotalGearMoment_L, "
+      << "TotalGearMoment_M, "
+      << "TotalGearMoment_N";
 
-  return GroundReactionStrings;
+  return buf.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 string FGGroundReactions::GetGroundReactionValues(void)
 {
-  char buff[20];
-  string GroundReactionValues = "";
-
-  bool firstime = true;
+  std::ostringstream buf;
 
   for (unsigned int i=0;i<lGear.size();i++) {
-    if (!firstime) GroundReactionValues += ", ";
-    GroundReactionValues += string( lGear[i].GetWOW()?"1":"0" ) + ", ";
-    GroundReactionValues += (string(gcvt(lGear[i].GetCompLen(),    5, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetCompVel(),    6, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetCompForce(), 10, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetWheelVel(eX), 6, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetWheelVel(eY), 6, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetWheelSideForce(), 6, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetWheelRollForce(), 6, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetBodyXForce(), 6, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetBodyYForce(), 6, buff)) + ", ");
-    GroundReactionValues += (string(gcvt(lGear[i].GetWheelSlipAngle(), 6, buff)));
-
-    firstime = false;
+    FGLGear& gear = lGear[i];
+    buf << (gear.GetWOW() ? "1, " : "0, ")
+        << setprecision(5) << gear.GetCompLen() << ", "
+        << setprecision(6) << gear.GetCompVel() << ", "
+        << setprecision(10) << gear.GetCompForce() << ", "
+        << setprecision(6) << gear.GetWheelVel(eX) << ", "
+        << gear.GetWheelVel(eY) << ", "
+        << gear.GetWheelSideForce() << ", "
+        << gear.GetWheelRollForce() << ", "
+        << gear.GetBodyXForce() << ", "
+        << gear.GetBodyYForce() << ", "
+        << gear.GetWheelSlipAngle() << ", ";
   }
 
-  GroundReactionValues += (", " + string(gcvt(vForces(eX), 6, buff)) + ", ");
-  GroundReactionValues += (string(gcvt(vForces(eY), 6, buff)) + ", ");
-  GroundReactionValues += (string(gcvt(vForces(eZ), 6, buff)) + ", ");
-  GroundReactionValues += (string(gcvt(vMoments(eX), 6, buff)) + ", ");
-  GroundReactionValues += (string(gcvt(vMoments(eY), 6, buff)) + ", ");
-  GroundReactionValues += (string(gcvt(vMoments(eZ), 6, buff)));
+  buf << vForces(eX) << ", "
+      << vForces(eY) << ", "
+      << vForces(eZ) << ", "
+      << vMoments(eX) << ", "
+      << vMoments(eY) << ", "
+      << vMoments(eZ);
 
-  return GroundReactionValues;
+  return buf.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGGroundReactions::bind(void)
-{ 
+{
   typedef double (FGGroundReactions::*PMF)(int) const;
   PropertyManager->Tie("gear/num-units", this,
-                       &FGGroundReactions::GetNumGearUnits);  
+                       &FGGroundReactions::GetNumGearUnits);
   PropertyManager->Tie("moments/l-gear-lbsft", this,1,
                        (PMF)&FGGroundReactions::GetMoments);
   PropertyManager->Tie("moments/m-gear-lbsft", this,2,
index 29b489320885a457eaa89e699ce7ec2f3522632a..d75854a51545298e37ee3df09306e79e2458e4dd 100644 (file)
@@ -36,7 +36,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGInertial.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
 #include "FGState.h"
 #include "FGMassBalance.h"
 
@@ -60,12 +60,6 @@ FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex)
   RadiusReference = 20925650.00;
   gAccelReference = GM/(RadiusReference*RadiusReference);
   gAccel          = GM/(RadiusReference*RadiusReference);
-  vRadius.InitMatrix();
-  vCoriolis.InitMatrix();
-  vCentrifugal.InitMatrix();
-  vGravity.InitMatrix();
-
-  bind();
 
   Debug(0);
 }
@@ -74,7 +68,6 @@ FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex)
 
 FGInertial::~FGInertial(void)
 {
-  unbind();
   Debug(1);
 }
 
@@ -82,42 +75,14 @@ FGInertial::~FGInertial(void)
 
 bool FGInertial::Run(void)
 {
-  if (!FGModel::Run()) {
-
-    gAccel = GM / (Position->GetRadius()*Position->GetRadius());
-
-    vGravity(eDown) = gAccel;
-
-    // The following equation for vOmegaLocal terms shows the angular velocity
-    // calculation _for_the_local_frame_ given the earth's rotation (first set)
-    // at the current latitude, and also the component due to the aircraft
-    // motion over the curved surface of the earth (second set).
-
-    vOmegaLocal(eX) = omega() * cos(Position->GetLatitude());
-    vOmegaLocal(eY) = 0.0;
-    vOmegaLocal(eZ) = omega() * -sin(Position->GetLatitude());
+  // Fast return if we have nothing to do ...
+  if (FGModel::Run()) return true;
 
-    vOmegaLocal(eX) +=  Position->GetVe() / Position->GetRadius();
-    vOmegaLocal(eY) += -Position->GetVn() / Position->GetRadius();
-    vOmegaLocal(eZ) +=  0.00;
+  // Gravitation accel
+  double r = Propagate->GetRadius();
+  gAccel = GetGAccel(r);
 
-    // Coriolis acceleration is normally written: -2w*dr/dt, but due to the axis
-    // conventions used here the sign is reversed: 2w*dr/dt. The same is true for
-    // Centrifugal acceleration.
-
-    vCoriolis(eEast) = 2.0*omega() * (Position->GetVd()*cos(Position->GetLatitude()) +
-                                      Position->GetVn()*sin(Position->GetLatitude()));
-
-    vRadius(eDown) = Position->GetRadius();
-    vCentrifugal(eDown) = -vOmegaLocal.Magnitude() * vOmegaLocal.Magnitude() * vRadius(eDown);
-
-//    vForces = State->GetTl2b() * MassBalance->GetMass() * (vCoriolis + vCentrifugal + vGravity);
-    vForces = State->GetTl2b() * MassBalance->GetMass() * vGravity;
-
-    return false;
-  } else {
-    return true;
-  }
+  return false;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -129,27 +94,6 @@ bool FGInertial::LoadInertial(FGConfigFile* AC_cfg)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGInertial::bind(void)
-{
-  typedef double (FGInertial::*PMF)(int) const;
-  PropertyManager->Tie("forces/fbx-inertial-lbs", this,1,
-                       (PMF)&FGInertial::GetForces);
-  PropertyManager->Tie("forces/fby-inertial-lbs", this,2,
-                       (PMF)&FGInertial::GetForces);
-  PropertyManager->Tie("forces/fbz-inertial-lbs", this,3,
-                       (PMF)&FGInertial::GetForces);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGInertial::unbind(void)
-{
-  PropertyManager->Untie("forces/fbx-inertial-lbs");
-  PropertyManager->Untie("forces/fby-inertial-lbs");
-  PropertyManager->Untie("forces/fbz-inertial-lbs");
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
 //       out the normally expected messages, essentially echoing
index e32d982bd2b0b62031d048b02cb893ce38384a1b..e679593978294abdc02d829299ed4f0119f74385 100644 (file)
@@ -83,27 +83,14 @@ public:
   ~FGInertial(void);
 
   bool Run(void);
-  FGColumnVector3& GetForces(void) {return vForces;}
-  FGColumnVector3& GetGravity(void) {return vGravity;}
-  FGColumnVector3& GetCoriolis(void) {return vCoriolis;}
-  FGColumnVector3& GetCentrifugal(void) {return vCentrifugal;}
-  double GetForces(int n) const {return vForces(n);}
   bool LoadInertial(FGConfigFile* AC_cfg);
   double SLgravity(void) const {return gAccelReference;}
   double gravity(void) const {return gAccel;}
   double omega(void) const {return RotationRate;}
+  double GetGAccel(double r) const { return GM/(r*r); }
   double RefRadius(void) const {return RadiusReference;}
-  
-  void bind(void);
-  void unbind(void);
 
 private:
-  FGColumnVector3 vOmegaLocal;
-  FGColumnVector3 vForces;
-  FGColumnVector3 vRadius;
-  FGColumnVector3 vGravity;
-  FGColumnVector3 vCoriolis;
-  FGColumnVector3 vCentrifugal;
   double gAccel;
   double gAccelReference;
   double RadiusReference;
@@ -114,4 +101,3 @@ private:
 }
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 #endif
-
index 9d3e19ec09084cd054b30bc9caf2c6db3c2d7971..d38478dffd8cc0f5f69e1de10bf264a2ddc17794 100644 (file)
@@ -47,7 +47,7 @@ INCLUDES
 #include "FGInertial.h"
 #include "FGAtmosphere.h"
 #include "FGAerodynamics.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
 #include "FGConfigFile.h"
 #include "FGPropertyManager.h"
 
@@ -67,6 +67,7 @@ FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec)
   altitude=hdot=0;
   latitude=longitude=0;
   u=v=w=0;
+  p=q=r=0;
   uw=vw=ww=0;
   vnorth=veast=vdown=0;
   wnorth=weast=wdown=0;
@@ -83,7 +84,7 @@ FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec)
 
   if(FDMExec != NULL ) {
     fdmex=FDMExec;
-    fdmex->GetPosition()->Seth(altitude);
+    fdmex->GetPropagate()->Seth(altitude);
     fdmex->GetAtmosphere()->Run();
     PropertyManager=fdmex->GetPropertyManager();
     bind();
@@ -265,7 +266,7 @@ void FGInitialCondition::SetWBodyFpsIC(double tt) {
 
 //******************************************************************************
 
-double FGInitialCondition::GetUBodyFpsIC(void) {
+double FGInitialCondition::GetUBodyFpsIC(void) const {
     if(lastSpeedSet == setvg )
       return u;
     else
@@ -274,7 +275,7 @@ double FGInitialCondition::GetUBodyFpsIC(void) {
 
 //******************************************************************************
 
-double FGInitialCondition::GetVBodyFpsIC(void) {
+double FGInitialCondition::GetVBodyFpsIC(void) const {
     if( lastSpeedSet == setvg )
       return v;
     else {
@@ -284,7 +285,7 @@ double FGInitialCondition::GetVBodyFpsIC(void) {
 
 //******************************************************************************
 
-double FGInitialCondition::GetWBodyFpsIC(void) {
+double FGInitialCondition::GetWBodyFpsIC(void) const {
     if( lastSpeedSet == setvg )
       return w;
     else
@@ -394,7 +395,7 @@ void FGInitialCondition::calcWindUVW(void) {
 
 void FGInitialCondition::SetAltitudeFtIC(double tt) {
   altitude=tt;
-  fdmex->GetPosition()->Seth(altitude);
+  fdmex->GetPropagate()->Seth(altitude);
   fdmex->GetAtmosphere()->Run();
   //lets try to make sure the user gets what they intended
 
@@ -422,8 +423,8 @@ void FGInitialCondition::SetAltitudeFtIC(double tt) {
 //******************************************************************************
 
 void FGInitialCondition::SetAltitudeAGLFtIC(double tt) {
-  fdmex->GetPosition()->SetDistanceAGL(tt);
-  altitude=fdmex->GetPosition()->Geth();
+  fdmex->GetPropagate()->SetDistanceAGL(tt);
+  altitude=fdmex->GetPropagate()->Geth();
   SetAltitudeFtIC(altitude);
 }
 
@@ -925,6 +926,19 @@ void FGInitialCondition::bind(void){
                        &FGInitialCondition::GetLongitudeRadIC,
                        &FGInitialCondition::SetLongitudeRadIC,
                        true);
+  PropertyManager->Tie("ic/p-rad_sec", this,
+                       &FGInitialCondition::GetPRadpsIC,
+                       &FGInitialCondition::SetPRadpsIC,
+                       true);
+  PropertyManager->Tie("ic/q-rad_sec", this,
+                       &FGInitialCondition::GetQRadpsIC,
+                       &FGInitialCondition::SetQRadpsIC,
+                       true);
+  PropertyManager->Tie("ic/r-rad_sec", this,
+                       &FGInitialCondition::GetRRadpsIC,
+                       &FGInitialCondition::SetRRadpsIC,
+                       true);
+
 }
 
 //******************************************************************************
@@ -973,6 +987,10 @@ void FGInitialCondition::unbind(void){
   PropertyManager->Untie("ic/psi-true-rad");
   PropertyManager->Untie("ic/lat-gc-rad");
   PropertyManager->Untie("ic/long-gc-rad");
+  PropertyManager->Untie("ic/p-rad_sec");
+  PropertyManager->Untie("ic/q-rad_sec");
+  PropertyManager->Untie("ic/r-rad_sec");
+
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index fff5c3dcbae217c0efd404469c8dd101d3a2fe9d..00632ae90db6cc673c73296c93e57adc76d1d857 100644 (file)
@@ -192,6 +192,9 @@ public:
   void SetVnorthFpsIC(double tt);
   void SetVeastFpsIC(double tt);
   void SetVdownFpsIC(double tt);
+  void SetPRadpsIC(double tt)  { p = tt; }
+  void SetQRadpsIC(double tt) { q = tt; }
+  void SetRRadpsIC(double tt) { r = tt; }
   
   void SetWindNEDFpsIC(double wN, double wE, double wD);
  
@@ -215,9 +218,12 @@ public:
   inline double GetWindFpsIC(void)  const { return sqrt(wnorth*wnorth + weast*weast); }
   double GetWindDirDegIC(void); 
   inline double GetClimbRateFpsIC(void) const { return hdot; }
-  double GetUBodyFpsIC(void);
-  double GetVBodyFpsIC(void);
-  double GetWBodyFpsIC(void);
+  double GetUBodyFpsIC(void) const;
+  double GetVBodyFpsIC(void) const;
+  double GetWBodyFpsIC(void) const;
+  double GetPRadpsIC() const { return p; }
+  double GetQRadpsIC() const { return q; }
+  double GetRRadpsIC() const { return r; }
   void SetFlightPathAngleRadIC(double tt);
   void SetAlphaRadIC(double tt);
   void SetPitchAngleRadIC(double tt);
@@ -253,6 +259,7 @@ private:
   double altitude,hdot;
   double latitude,longitude;
   double u,v,w;
+  double p,q,r;
   double uw,vw,ww;
   double vnorth,veast,vdown;
   double wnorth,weast,wdown;
index 4ed156854ff6eb019f019ba4c432363eb2b0ae8e..601785b6ba8227f147218413d766dbc783684b1f 100644 (file)
@@ -78,7 +78,7 @@ const double FGJSBBase::SHRatio = 1.40;
 const double FGJSBBase::slugtolb = 32.174049;
 const double FGJSBBase::lbtoslug = 1.0/slugtolb;
 
-const string FGJSBBase::needed_cfg_version = "1.61";
+const string FGJSBBase::needed_cfg_version = "1.65";
 const string FGJSBBase::JSBSim_version = "0.9.5";
 
 std::queue <FGJSBBase::Message*> FGJSBBase::Messages;
@@ -90,12 +90,6 @@ short FGJSBBase::debug_lvl  = 1;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGJSBBase::FGJSBBase()
-{
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 FGJSBBase::Message* FGJSBBase::PutMessage(Message* msg)
 {
   Messages.push(msg);
@@ -104,7 +98,7 @@ FGJSBBase::Message* FGJSBBase::PutMessage(Message* msg)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGJSBBase::Message* FGJSBBase::PutMessage(string text)
+FGJSBBase::Message* FGJSBBase::PutMessage(const string& text)
 {
   Message *msg = new Message();
   msg->text = text;
@@ -117,7 +111,7 @@ FGJSBBase::Message* FGJSBBase::PutMessage(string text)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGJSBBase::Message* FGJSBBase::PutMessage(string text, bool bVal)
+FGJSBBase::Message* FGJSBBase::PutMessage(const string& text, bool bVal)
 {
   Message *msg = new Message();
   msg->text = text;
@@ -131,7 +125,7 @@ FGJSBBase::Message* FGJSBBase::PutMessage(string text, bool bVal)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGJSBBase::Message* FGJSBBase::PutMessage(string text, int iVal)
+FGJSBBase::Message* FGJSBBase::PutMessage(const string& text, int iVal)
 {
   Message *msg = new Message();
   msg->text = text;
@@ -145,7 +139,7 @@ FGJSBBase::Message* FGJSBBase::PutMessage(string text, int iVal)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGJSBBase::Message* FGJSBBase::PutMessage(string text, double dVal)
+FGJSBBase::Message* FGJSBBase::PutMessage(const string& text, double dVal)
 {
   Message *msg = new Message();
   msg->text = text;
index 78b842a8539c46220d1017439212a1990add17d3..d0f24e59154690890096a86383e2edfb6885b6bf 100644 (file)
@@ -38,6 +38,8 @@ SENTRY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <limits>
+
 #ifdef FGFS
 #  include <simgear/compiler.h>
 #  include <math.h>
@@ -73,17 +75,6 @@ using std::string;
 using std::max;
 #endif
 
-#ifdef __FreeBSD__ // define gcvt on FreeBSD
-
-#include <stdio.h>
-
-static char *gcvt(double number, size_t ndigit, char *buf)
-{
-  sprintf(buf, "%f", number);
-  return buf;
-}
-#endif
-
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -112,10 +103,10 @@ CLASS DECLARATION
 class FGJSBBase {
 public:
   /// Constructor for FGJSBBase.
-  FGJSBBase();
+  FGJSBBase() {};
 
   /// Destructor for FGJSBBase.
-  virtual ~FGJSBBase() {};
+  ~FGJSBBase() {};
 
   /// JSBSim Message structure
   typedef struct Msg {
@@ -129,26 +120,6 @@ public:
     double dVal;
   } Message;
 
-  ///@name JSBSim Enums.
-  //@{
-  /// Moments L, M, N
-  enum {eL     = 1, eM,     eN    };
-  /// Rates P, Q, R
-  enum {eP     = 1, eQ,     eR    };
-  /// Velocities U, V, W
-  enum {eU     = 1, eV,     eW    };
-  /// Positions X, Y, Z
-  enum {eX     = 1, eY,     eZ    };
-  /// Euler angles Phi, Theta, Psi
-  enum {ePhi   = 1, eTht,   ePsi  };
-  /// Stability axis forces, Drag, Side force, Lift
-  enum {eDrag  = 1, eSide,  eLift };
-  /// Local frame orientation Roll, Pitch, Yaw
-  enum {eRoll  = 1, ePitch, eYaw  };
-  /// Local frame position North, East, Down
-  enum {eNorth = 1, eEast,  eDown };
-  //@}
-  
   ///@name JSBSim console output highlighting terms.
   //@{
   /// highlights text
@@ -184,22 +155,22 @@ public:
   /** Creates a message with the given text and places it on the queue.
       @param text message text
       @return pointer to a Message structure */
-  Message* PutMessage(string text);
+  Message* PutMessage(const string& text);
   /** Creates a message with the given text and boolean value and places it on the queue.
       @param text message text
       @param bVal boolean value associated with the message
       @return pointer to a Message structure */
-  Message* PutMessage(string text, bool bVal);
+  Message* PutMessage(const string& text, bool bVal);
   /** Creates a message with the given text and integer value and places it on the queue.
       @param text message text
       @param iVal integer value associated with the message
       @return pointer to a Message structure */
-  Message* PutMessage(string text, int iVal);
+  Message* PutMessage(const string& text, int iVal);
   /** Creates a message with the given text and double value and places it on the queue.
       @param text message text
       @param dVal double value associated with the message
       @return pointer to a Message structure */
-  Message* PutMessage(string text, double dVal);
+  Message* PutMessage(const string& text, double dVal);
   /** Reads the message on the queue (but does not delete it).
       @return pointer to a Message structure (or NULL if no mesage) */
   Message* ReadMessage(void);
@@ -208,28 +179,71 @@ public:
   Message* ProcessMessage(void);
   //@}
   string GetVersion(void) {return JSBSim_version;}
-  
+
   void disableHighLighting(void);
 
   static short debug_lvl;
-  double KelvinToFahrenheit (double kelvin) {
+  static double KelvinToFahrenheit (double kelvin) {
     return 1.8*kelvin - 459.4;
   }
 
-  double RankineToCelsius (double rankine) {
+  static double RankineToCelsius (double rankine) {
     return (rankine - 491.67)/1.8;
   }
 
+  static double FahrenheitToCelsius (double fahrenheit) {
+    return (fahrenheit - 32.0)/1.8;
+  }
+
+  static double CelsiusToFahrenheit (double celsius) {
+    return celsius * 1.8 + 32.0;
+  }
+
+
+  /** Finite precision comparison.
+      @param a first value to compare
+      @param b second value to compare
+      @return if the two values can be considered equal up to roundoff */
+  static bool EqualToRoundoff(double a, double b) {
+    double eps = 2.0*std::numeric_limits<double>::epsilon();
+    return fabs(a - b) <= eps*max(fabs(a), fabs(b));
+  }
+
+  /** Finite precision comparison.
+      @param a first value to compare
+      @param b second value to compare
+      @return if the two values can be considered equal up to roundoff */
+  static bool EqualToRoundoff(float a, float b) {
+    float eps = 2.0*std::numeric_limits<float>::epsilon();
+    return fabs(a - b) <= eps*max(fabs(a), fabs(b));
+  }
+
+  /** Finite precision comparison.
+      @param a first value to compare
+      @param b second value to compare
+      @return if the two values can be considered equal up to roundoff */
+  static bool EqualToRoundoff(float a, double b) {
+    return EqualToRoundoff(a, (float)b);
+  }
+
+  /** Finite precision comparison.
+      @param a first value to compare
+      @param b second value to compare
+      @return if the two values can be considered equal up to roundoff */
+  static bool EqualToRoundoff(double a, float b) {
+    return EqualToRoundoff((float)a, b);
+  }
+
 protected:
   static Message localMsg;
-  
+
   static std::queue <Message*> Messages;
 
-  virtual void Debug(int from) {};
+  void Debug(int from) {};
 
   static unsigned int frame;
   static unsigned int messageId;
-  
+
   static const double radtodeg;
   static const double degtorad;
   static const double hptoftlbssec;
@@ -245,6 +259,28 @@ protected:
   static const string needed_cfg_version;
   static const string JSBSim_version;
 };
+
+/// Moments L, M, N
+enum {eL     = 1, eM,     eN    };
+/// Rates P, Q, R
+enum {eP     = 1, eQ,     eR    };
+/// Velocities U, V, W
+enum {eU     = 1, eV,     eW    };
+/// Positions X, Y, Z
+enum {eX     = 1, eY,     eZ    };
+/// Euler angles Phi, Theta, Psi
+enum {ePhi   = 1, eTht,   ePsi  };
+/// Stability axis forces, Drag, Side force, Lift
+enum {eDrag  = 1, eSide,  eLift };
+/// Local frame orientation Roll, Pitch, Yaw
+enum {eRoll  = 1, ePitch, eYaw  };
+/// Local frame position North, East, Down
+enum {eNorth = 1, eEast,  eDown };
+/// Locations Radius, Latitude, Longitude
+enum {eLat = 1, eLong, eRad     };
+/// Conversion specifiers
+enum {inNone = 0, inDegrees, inRadians, inMeters, inFeet };
+
 }
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 #endif
index 276ec70d8af78205d12a454aa5ea3e61463fd784..dd0325b109ff9251ecd689b46725dc9cda460a8e 100644 (file)
@@ -60,10 +60,10 @@ CLASS IMPLEMENTATION
 FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
 {
   string tmp;
-  
+
   *AC_cfg >> tmp >> name >> vXYZ(1) >> vXYZ(2) >> vXYZ(3)
             >> kSpring >> bDamp>> dynamicFCoeff >> staticFCoeff
-                  >> rollingFCoeff >> sSteerType >> sBrakeGroup 
+                  >> rollingFCoeff >> sSteerType >> sBrakeGroup
                      >> maxSteerAngle >> sRetractable;
 
   if      (sBrakeGroup == "LEFT"  ) eBrakeGrp = bgLeft;
@@ -84,13 +84,13 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
     cerr << "Improper steering type specification in config file: "
          << sSteerType << " is undefined." << endl;
   }
-  
+
   if ( sRetractable == "RETRACT" ) {
     isRetractable = true;
   } else  {
     isRetractable = false;
-  }  
-  
+  }
+
   GearUp = false;
   GearDown = true;
   Servicable = true;
@@ -100,8 +100,8 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
 
   State       = Exec->GetState();
   Aircraft    = Exec->GetAircraft();
-  Position    = Exec->GetPosition();
-  Rotation    = Exec->GetRotation();
+  Propagate   = Exec->GetPropagate();
+  Auxiliary   = Exec->GetAuxiliary();
   FCS         = Exec->GetFCS();
   MassBalance = Exec->GetMassBalance();
 
@@ -116,8 +116,8 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
   SinkRate = GroundSpeed = 0.0;
 
   vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);
-  
-  vLocalGear = State->GetTb2l() * vWhlBodyVec;
+
+  vLocalGear = Propagate->GetTb2l() * vWhlBodyVec;
 
   compressLength  = 0.0;
   compressSpeed   = 0.0;
@@ -142,8 +142,8 @@ FGLGear::FGLGear(const FGLGear& lgear)
 {
   State    = lgear.State;
   Aircraft = lgear.Aircraft;
-  Position = lgear.Position;
-  Rotation = lgear.Rotation;
+  Propagate = lgear.Propagate;
+  Auxiliary = lgear.Auxiliary;
   Exec     = lgear.Exec;
   FCS      = lgear.FCS;
   MassBalance = lgear.MassBalance;
@@ -206,7 +206,6 @@ FGLGear::~FGLGear()
 
 FGColumnVector3& FGLGear::Force(void)
 {
-  double SteerGain = 0;
   double SinWheel, CosWheel;
   double deltaSlip;
   double deltaT = State->Getdt()*Aircraft->GetRate();
@@ -228,19 +227,19 @@ FGColumnVector3& FGLGear::Force(void)
   } else {
       GearUp   = false;
       GearDown = true;
-  }         
-      
+  }
+
   if (GearDown) {
 
     vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);
 
 // vWhlBodyVec now stores the vector from the cg to this wheel
 
-    vLocalGear = State->GetTb2l() * vWhlBodyVec;
+    vLocalGear = Propagate->GetTb2l() * vWhlBodyVec;
 
 // vLocalGear now stores the vector from the cg to the wheel in local coords.
 
-    compressLength = vLocalGear(eZ) - Position->GetDistanceAGL();
+    compressLength = vLocalGear(eZ) - Propagate->GetDistanceAGL();
 
 // The compression length is currently measured in the Z-axis, only, at this time.
 // It should be measured along the strut axis. If the local-frame gear position
@@ -262,8 +261,8 @@ FGColumnVector3& FGLGear::Force(void)
 // (used for calculating damping force) is found by taking the Z-component of the
 // wheel velocity.
 
-      vWhlVelVec      =  State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);
-      vWhlVelVec     +=  Position->GetVel();
+      vWhlVelVec      =  Propagate->GetTb2l() * (Propagate->GetPQR() * vWhlBodyVec);
+      vWhlVelVec     +=  Propagate->GetVel();
       compressSpeed   =  vWhlVelVec(eZ);
 
 // If this is the first time the wheel has made contact, remember some values
@@ -272,13 +271,13 @@ FGColumnVector3& FGLGear::Force(void)
       if (!FirstContact) {
         FirstContact  = true;
         SinkRate      =  compressSpeed;
-        GroundSpeed   =  Position->GetVel().Magnitude();
+        GroundSpeed   =  Propagate->GetVel().Magnitude();
         TakeoffReported = false;
       }
 
 // If the takeoff run is starting, initialize.
 
-      if ((Position->GetVel().Magnitude() > 0.1) &&
+      if ((Propagate->GetVel().Magnitude() > 0.1) &&
           (FCS->GetBrake(bgLeft) == 0) &&
           (FCS->GetBrake(bgRight) == 0) &&
           (FCS->GetThrottlePos(0) == 1) && !StartedGroundRun)
@@ -326,7 +325,7 @@ FGColumnVector3& FGLGear::Force(void)
 
       switch (eSteerType) {
       case stSteer:
-        SteerAngle = -maxSteerAngle * FCS->GetDrCmd() * 0.01745; 
+        SteerAngle = -maxSteerAngle * FCS->GetDrCmd() * 0.01745;
         break;
       case stFixed:
         SteerAngle = 0.0;
@@ -344,8 +343,8 @@ FGColumnVector3& FGLGear::Force(void)
 // For now, steering angle is assumed to happen in the Local Z axis,
 // not the strut axis as it should be.  Will fix this later.
 
-      SinWheel      = sin(Rotation->Getpsi() + SteerAngle);
-      CosWheel      = cos(Rotation->Getpsi() + SteerAngle);
+      SinWheel      = sin(Propagate->Getpsi() + SteerAngle);
+      CosWheel      = cos(Propagate->Getpsi() + SteerAngle);
       RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;
       SideWhlVel    = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;
 
@@ -382,19 +381,19 @@ FGColumnVector3& FGLGear::Force(void)
       {
         WheelSlip = 0.0;
       }
-*/    
+*/
       lastWheelSlip = WheelSlip;
 
 // Compute the sideforce coefficients using similar assumptions to LaRCSim for now.
 // Allow a maximum of 10 degrees tire slip angle before wheel slides.  At that point,
 // transition from static to dynamic friction.  There are more complicated formulations
-// of this that avoid the discrete jump.  Will fix this later.
+// of this that avoid the discrete jump (similar to Pacejka).  Will fix this later.
 
       if (fabs(WheelSlip) <= 20.0) {
         FCoeff = staticFCoeff*WheelSlip/20.0;
       } else if (fabs(WheelSlip) <= 40.0) {
 //        FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;
-        FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 20.0)/20.0 + 
+        FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 20.0)/20.0 +
                   staticFCoeff*(40.0 - fabs(WheelSlip))/20.0)*fabs(WheelSlip)/WheelSlip;
       } else {
         FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;
@@ -441,14 +440,14 @@ FGColumnVector3& FGLGear::Force(void)
 
 // Transform the forces back to the body frame and compute the moment.
 
-      vForce  = State->GetTl2b() * vLocalForce;
+      vForce  = Propagate->GetTl2b() * vLocalForce;
       vMoment = vWhlBodyVec * vForce;
 
     } else { // Gear is NOT compressed
 
       WOW = false;
 
-      if (Position->GetDistanceAGL() > 200.0) {
+      if (Propagate->GetDistanceAGL() > 200.0) {
         FirstContact = false;
         StartedGroundRun = false;
         LandingReported = false;
@@ -459,19 +458,19 @@ FGColumnVector3& FGLGear::Force(void)
       compressLength = 0.0; // reset compressLength to zero for data output validity
     }
 
-    if (FirstContact) LandingDistanceTraveled += Position->GetVground()*deltaT;
-  
+    if (FirstContact) LandingDistanceTraveled += Auxiliary->GetVground()*deltaT;
+
     if (StartedGroundRun) {
-       TakeoffDistanceTraveled50ft += Position->GetVground()*deltaT;
-      if (WOW) TakeoffDistanceTraveled += Position->GetVground()*deltaT;
+       TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*deltaT;
+      if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*deltaT;
     }
 
-    if (ReportEnable && Position->GetVground() <= 0.05 && !LandingReported) {
+    if (ReportEnable && Auxiliary->GetVground() <= 0.05 && !LandingReported) {
       if (debug_lvl > 0) Report(erLand);
     }
 
     if (ReportEnable && !TakeoffReported &&
-       (vLocalGear(eZ) - Position->GetDistanceAGL()) < -50.0)
+       (vLocalGear(eZ) - Propagate->GetDistanceAGL()) < -50.0)
     {
       if (debug_lvl > 0) Report(erTakeoff);
     }
@@ -492,8 +491,8 @@ FGColumnVector3& FGLGear::Force(void)
       PutMessage("Crash Detected: Simulation FREEZE.");
       Exec->Freeze();
     }
-  } 
-  return vForce; 
+  }
+  return vForce;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index ef13cf5e2097afa79723f11239f9a7da77a3c121..6bf8778f478ed117d51a519aaef052eac4502e14 100644 (file)
@@ -44,9 +44,9 @@ INCLUDES
 
 #include "FGJSBBase.h"
 #include "FGFDMExec.h"
-#include <string>
 #include "FGConfigFile.h"
 #include "FGColumnVector3.h"
+#include <string>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
@@ -61,11 +61,11 @@ FORWARD DECLARATIONS
 namespace JSBSim {
 
 class FGAircraft;
-class FGPosition;
-class FGRotation;
+class FGPropagate;
 class FGFCS;
 class FGState;
 class FGMassBalance;
+class FGAuxiliary;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DOCUMENTATION
@@ -160,9 +160,9 @@ CLASS DOCUMENTATION
     @author Jon S. Berndt
     @version $Id$
     @see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
-          NASA-Ames", NASA CR-2497, January 1975
+     NASA-Ames", NASA CR-2497, January 1975
     @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
-          Wiley & Sons, 1979 ISBN 0-471-03032-5
+     Wiley & Sons, 1979 ISBN 0-471-03032-5
     @see W. A. Ragsdale, "A Generic Landing Gear Dynamics Model for LASRS++",
      AIAA-2000-4303
 */
@@ -219,7 +219,7 @@ public:
   inline double  GetTirePressure(void) { return TirePressureNorm; }
   /// Sets the new normalized tire pressure
   inline void    SetTirePressure(double p) { TirePressureNorm = p; }
-  
+
   /// Sets the brake value in percent (0 - 100)
   inline void SetBrake(double bp) {brakePct = bp;}
 
@@ -231,10 +231,10 @@ public:
   inline bool GetReport(void)    { return ReportEnable; }
   inline double GetSteerAngle(void) { return SteerAngle;}
   inline double GetstaticFCoeff(void) { return staticFCoeff;}
-  
+
   inline int GetBrakeGroup(void) { return (int)eBrakeGrp; }
   inline int GetSteerType(void)  { return (int)eSteerType; }
-  
+
   inline bool GetRetractable(void)         { return isRetractable;   }
   inline bool GetGearUnitUp(void)          { return GearUp;          }
   inline bool GetGearUnitDown(void)        { return GearDown;        }
@@ -244,7 +244,7 @@ public:
   inline double GetBodyYForce(void)        { return vLocalForce(eY); }
   inline double GetWheelSlipAngle(void)    { return WheelSlip;       }
   double GetWheelVel(int axis)             { return vWhlVelVec(axis);}
-  
+
 private:
   FGColumnVector3 vXYZ;
   FGColumnVector3 vMoment;
@@ -288,17 +288,17 @@ private:
   string sSteerType;
   string sBrakeGroup;
   string sRetractable;
-  
+
   BrakeGroup eBrakeGrp;
   SteerType  eSteerType;
   double  maxSteerAngle;
 
-  FGFDMExec*  Exec;
-  FGState*    State;
-  FGAircraft* Aircraft;
-  FGPosition* Position;
-  FGRotation* Rotation;
-  FGFCS*      FCS;
+  FGFDMExec*     Exec;
+  FGState*       State;
+  FGAircraft*    Aircraft;
+  FGPropagate*   Propagate;
+  FGAuxiliary*   Auxiliary;
+  FGFCS*         FCS;
   FGMassBalance* MassBalance;
 
   void Report(ReportType rt);
@@ -306,13 +306,12 @@ private:
 };
 }
 #include "FGAircraft.h"
-#include "FGPosition.h"
-#include "FGRotation.h"
+#include "FGPropagate.h"
+#include "FGAuxiliary.h"
 #include "FGFCS.h"
 #include "FGMassBalance.h"
+#include "FGState.h"
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-#include "FGState.h"
-
 #endif
diff --git a/src/FDM/JSBSim/FGLocation.cpp b/src/FDM/JSBSim/FGLocation.cpp
new file mode 100644 (file)
index 0000000..758ce3a
--- /dev/null
@@ -0,0 +1,216 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGLocation.cpp
+ Author:       Jon S. Berndt
+ Date started: 04/04/2004
+ Purpose:      Store an arbitrary location on the globe
+
+ ------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) ------------------
+ -------           (C) 2004  Mathias Froehlich (Mathias.Froehlich@web.de) ----
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+FUNCTIONAL DESCRIPTION
+------------------------------------------------------------------------------
+This class encapsulates an arbitrary position in the globe with its accessors.
+It has vector properties, so you can add multiply ....
+
+HISTORY
+------------------------------------------------------------------------------
+04/04/2004   MF    Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <cmath>
+#  else
+#    include <math.h>
+#  endif
+#else
+#  if defined(sgi) && !defined(__GNUC__)
+#    include <math.h>
+#  else
+#    include <cmath>
+#  endif
+#endif
+
+#include "FGLocation.h"
+#include "FGPropertyManager.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_LOCATION;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGLocation::FGLocation(double lon, double lat, double radius)
+{
+  mCacheValid = false;
+
+  double sinLat = sin(lat);
+  double cosLat = cos(lat);
+  double sinLon = sin(lon);
+  double cosLon = cos(lon);
+  mECLoc = FGColumnVector3( radius*cosLat*cosLon,
+                            radius*cosLat*sinLon,
+                            radius*sinLat );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLocation::SetLongitude(double longitude)
+{
+  double rtmp = sqrt(mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY));
+  // Fast return if we are on the north or south pole ...
+  if (rtmp == 0.0)
+    return;
+
+  mCacheValid = false;
+
+  mECLoc(eX) = rtmp*sin(longitude);
+  mECLoc(eY) = rtmp*cos(longitude);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLocation::SetLatitude(double latitude)
+{
+  mCacheValid = false;
+
+  double r = mECLoc.Magnitude();
+  if (r == 0.0) {
+    mECLoc(eX) = 1.0;
+    r = 1.0;
+  }
+
+  double rtmp = sqrt(mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY));
+  if (rtmp != 0.0) {
+    double fac = r/rtmp*cos(latitude);
+    mECLoc(eX) *= fac;
+    mECLoc(eY) *= fac;
+  } else {
+    mECLoc(eX) = r*cos(latitude);
+    mECLoc(eY) = 0.0;
+  }
+  mECLoc(eZ) = r*sin(latitude);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLocation::SetRadius(double radius)
+{
+  mCacheValid = false;
+
+  double rold = mECLoc.Magnitude();
+  if (rold == 0.0)
+    mECLoc(eX) = radius;
+  else
+    mECLoc *= radius/rold;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLocation::ComputeDerivedUnconditional(void) const
+{
+  // The radius is just the Euclidean norm of the vector.
+  mRadius = mECLoc.Magnitude();
+
+  // The distance of the location to the y-axis, which is the axis
+  // through the poles.
+  double rxy = sqrt(mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY));
+
+  // Compute the sin/cos values of the longitude
+  double sinLon, cosLon;
+  if (rxy == 0.0) {
+    sinLon = 0.0;
+    cosLon = 1.0;
+  } else {
+    sinLon = mECLoc(eY)/rxy;
+    cosLon = mECLoc(eX)/rxy;
+  }
+
+  // Compute the sin/cos values of the latitude
+  double sinLat, cosLat;
+  if (mRadius == 0.0)  {
+    sinLat = 0.0;
+    cosLat = 1.0;
+  } else {
+    sinLat = mECLoc(eZ)/mRadius;
+    cosLat = rxy/mRadius;
+  }
+
+  // Compute the longitude and latitude itself
+  if ( mECLoc( eX ) == 0.0 && mECLoc( eY ) == 0.0 )
+    mLon = 0.0;
+  else
+    mLon = atan2( mECLoc( eY ), mECLoc( eX ) );
+
+  if ( rxy == 0.0 && mECLoc( eZ ) == 0.0 )
+    mLat = 0.0;
+  else
+    mLat = atan2( mECLoc(eZ), rxy );
+
+  // Compute the transform matrices from and to the earth centered frame.
+  // see Durham Chapter 4, problem 1, page 52
+  mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat,  cosLat,
+                           -sinLon   ,     cosLon    ,    0.0 ,
+                       -cosLon*cosLat, -sinLon*cosLat, -sinLat  );
+
+  mTl2ec = mTec2l.Transposed();
+
+  // Mark the cached values as valid
+  mCacheValid = true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLocation::bind(FGPropertyManager* PropertyManager, const string& prefix) const
+{
+  PropertyManager->Tie(prefix + "lat-gc-rad", (FGLocation*)this,
+                       &FGLocation::GetLatitude);
+  PropertyManager->Tie(prefix + "lat-gc-deg", (FGLocation*)this,
+                       &FGLocation::GetLatitudeDeg);
+  PropertyManager->Tie(prefix + "long-gc-rad", (FGLocation*)this,
+                       &FGLocation::GetLongitude);
+  PropertyManager->Tie(prefix + "long-gc-deg", (FGLocation*)this,
+                       &FGLocation::GetLongitudeDeg);
+  PropertyManager->Tie(prefix + "radius-ft", (FGLocation*)this,
+                       &FGLocation::GetRadius);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLocation::unbind(FGPropertyManager* PropertyManager, const string& prefix) const
+{
+  PropertyManager->Untie(prefix + "lat-gc-rad");
+  PropertyManager->Untie(prefix + "lat-gc-deg");
+  PropertyManager->Untie(prefix + "long-gc-rad");
+  PropertyManager->Untie(prefix + "long-gc-deg");
+  PropertyManager->Untie(prefix + "radius-ft");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/FGLocation.h b/src/FDM/JSBSim/FGLocation.h
new file mode 100644 (file)
index 0000000..026241e
--- /dev/null
@@ -0,0 +1,437 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGLocation.h
+ Author:       Jon S. Berndt, Mathias Froehlich
+ Date started: 04/04/2004
+
+ ------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) ------------------
+ -------           (C) 2004  Mathias Froehlich (Mathias.Froehlich@web.de) ----
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+-------------------------------------------------------------------------------
+04/04/2004   MF   Created from code previously in the old positions class.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGLOCATION_H
+#define FGLOCATION_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGJSBBase.h"
+#include "FGPropertyManager.h"
+#include "FGColumnVector3.h"
+#include "FGMatrix33.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_LOCATION "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Holds an arbitrary location in the earth centered reference frame.
+    This coordinate frame has its center in the middle of the earth.
+    Its x-axis points from the center of the earth towards a location
+    with zero latitude and longitude on the earths surface. The y-axis
+    points from the center of the earth towards a location with zero
+    latitude and 90deg longitude on the earths surface. The z-axis
+    points from the earths center to the geographic north pole.
+
+    This class provides access functions to set and get the location as
+    either the simple x, y and z values in ft or longitude/latitude and
+    the radial distance of the location from the earth center.
+
+    It is common to associate a parent frame with a location. This
+    frame is usually called the local horizontal frame or simply the local
+    frame. This frame has its x/y plane parallel to the surface of the earth
+    (with the assumption of a spherical earth). The x-axis points
+    towards north, the y-axis points towards east and the z-axis
+    points to the center of the earth.
+
+    Since this frame is determined by the location, this class also
+    provides the rotation matrices required to transform from the
+    earth centered frame to the local horizontal frame and back. There
+    are also conversion functions for conversion of position vectors
+    given in the one frame to positions in the other frame.
+
+    The earth centered reference frame is *NOT* an inertial frame
+    since it rotates with the earth.
+
+    The coordinates in the earth centered frame are the master values.
+    All other values are computed from these master values and are
+    cached as long as the location is changed by access through a
+    non-const member function. Values are cached to improve performance.
+    It is best practice to work with a natural set of master values.
+    Other parameters that are derived from these master values are calculated
+    only when needed, and IF they are needed and calculated, then they are
+    cached (stored and remembered) so they do not need to be re-calculated
+    until the master values they are derived from are themselves changed
+    (and become stale).
+
+    Accuracy and round off:
+
+    Given that we model a vehicle near the earth, the earths surface
+    radius is about 2*10^7, ft and that we use double values for the
+    representation of the location, we have an accuracy of about
+    1e-16*2e7ft/1=2e-9ft left. This should be sufficient for our needs.
+    Note that this is the same relative accuracy we would have when we
+    compute directly with lon/lat/radius. For the radius value this
+    is clear. For the lon/lat pair this is easy to see. Take for
+    example KSFO located at about 37.61deg north 122.35deg west, which
+    corresponds to 0.65642rad north and 2.13541rad west. Both values
+    are of magnitude of about 1. But 1ft corresponds to about
+    1/(2e7*2*pi)=7.9577e-09rad. So the left accuracy with this
+    representation is also about 1*1e-16/7.9577e-09=1.2566e-08 which
+    is of the same magnitude as the representation chosen here.
+
+    The advantage of this representation is that it is a linear space
+    without singularities. The singularities are the north and south
+    pole and most notably the non-steady jump at -pi to pi. It is
+    harder to track this jump correctly especially when we need to
+    work with error norms and derivatives of the equations of motion
+    within the time-stepping code. Also, the rate of change is of the
+    same magnitude for all components in this representation which is
+    an advantage for numerical stability in implicit time-stepping too.
+
+    @see W. C. Durham "Aircraft Dynamics & Control", section 2.2
+
+    @author Mathias Froehlich
+    @version $Id$
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGLocation : virtual FGJSBBase
+{
+public:
+  /** Default constructor. */
+  FGLocation() { mCacheValid = false; }
+
+  /** Constructor to set the longitude, latitude and the distance
+      from the center of the earth. */
+  FGLocation(double lon, double lat, double radius);
+
+  /** Copy constructor. */
+  FGLocation(const FGColumnVector3& lv)
+    : mECLoc(lv), mCacheValid(false) {}
+
+  /** Copy constructor. */
+  FGLocation(const FGLocation& l)
+    : mECLoc(l.mECLoc), mCacheValid(l.mCacheValid) {
+    if (!mCacheValid)
+      return;
+
+    mLon = l.mLon;
+    mLat = l.mLat;
+    mRadius = l.mRadius;
+
+    mTl2ec = l.mTl2ec;
+    mTec2l = l.mTec2l;
+  }
+
+  /** Get the longitude.
+      @return the longitude in rad of the location represented with this
+      class instance. The returned values are in the range between
+      -pi <= lon <= pi. Longitude is positive east and negative west. */
+  double GetLongitude() const { ComputeDerived(); return mLon; }
+
+  /** Get the longitude.
+      @return the longitude in deg of the location represented with this
+      class instance. The returned values are in the range between
+      -180 <= lon <= 180.  Longitude is positive east and negative west. */
+  double GetLongitudeDeg() const { ComputeDerived(); return radtodeg*mLon; }
+
+  /** Set the longitude.
+      @param longitude Longitude in rad to set.
+      Sets the longitude of the location represented with this class
+      instance to the value of the given argument. The value is meant
+      to be in rad. The latitude and the radius value are preserved
+      with this call with the exception of radius being equal to
+      zero. If the radius is previously set to zero it is changed to be
+      equal to 1.0 past this call. Longitude is positive east and negative west. */
+  void SetLongitude(double longitude);
+
+  /** Get the sine of Longitude. */
+  double GetSinLongitude() const { ComputeDerived(); return -mTec2l(2,1); }
+
+  /** Get the cosine of Longitude. */
+  double GetCosLongitude() const { ComputeDerived(); return mTec2l(2,2); }
+
+  /** Get the latitude.
+      @return the latitude in rad of the location represented with this
+      class instance. The returned values are in the range between
+      -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */
+  double GetLatitude() const { ComputeDerived(); return mLat; }
+
+  /** Get the latitude.
+      @return the latitude in deg of the location represented with this
+      class instance. The returned values are in the range between
+      -90 <= lon <= 90. Latitude is positive north and negative south. */
+  double GetLatitudeDeg() const { ComputeDerived(); return radtodeg*mLat; }
+
+  /** Set the latitude.
+      @param latitude Latitude in rad to set.
+      Sets the latitude of the location represented with this class
+      instance to the value of the given argument. The value is meant
+      to be in rad. The longitude and the radius value are preserved
+      with this call with the exception of radius being equal to
+      zero. If the radius is previously set to zero it is changed to be
+      equal to 1.0 past this call.
+      Latitude is positive north and negative south.
+      The arguments should be within the bounds of -pi/2 <= lat <= pi/2.
+      The behavior of this function with arguments outside this range is
+      left as an exercise to the gentle reader ... */
+  void SetLatitude(double latitude);
+
+  /** Get the sine of Latitude. */
+  double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); }
+
+  /** Get the cosine of Latitude. */
+  double GetCosLatitude() const { ComputeDerived(); return mTec2l(1,3); }
+
+  /** Get the cosine of Latitude. */
+  double GetTanLatitude() const {
+    ComputeDerived();
+    double cLat = mTec2l(1,3);
+    if (cLat == 0.0)
+      return 0.0;
+    else
+      return -mTec2l(3,3)/cLat;
+  }
+
+  /** Get the distance from the center of the earth.
+      @return the distance of the location represented with this class
+      instance to the center of the earth in ft. The radius value is
+      always positive. */
+  double GetRadius() const { ComputeDerived(); return mRadius; }
+
+  /** Set the distance from the center of the earth.
+      @param radius Radius in ft to set.
+      Sets the radius of the location represented with this class
+      instance to the value of the given argument. The value is meant
+      to be in ft. The latitude and longitude values are preserved
+      with this call with the exception of radius being equal to
+      zero. If the radius is previously set to zero, latitude and
+      longitude is set equal to zero past this call.
+      The argument should be positive.
+      The behavior of this function called with a negative argument is
+      left as an exercise to the gentle reader ... */
+  void SetRadius(double radius);
+
+  /** Transform matrix from local horizontal to earth centered frame.
+      Returns a const reference to the rotation matrix of the transform from
+      the local horizontal frame to the earth centered frame. */
+  const FGMatrix33& GetTl2ec(void) const { ComputeDerived(); return mTl2ec; }
+
+  /** Transform matrix from the earth centered to local horizontal frame.
+      Returns a const reference to the rotation matrix of the transform from
+      the earth centered frame to the local horizontal frame. */
+  const FGMatrix33& GetTec2l(void) const { ComputeDerived(); return mTec2l; }
+
+  /** Conversion from Local frame coordinates to a location in the
+      earth centered and fixed frame.
+      @parm lvec Vector in the local horizontal coordinate frame
+      @return The location in the earth centered and fixed frame */
+  FGLocation LocalToLocation(const FGColumnVector3& lvec) const {
+    ComputeDerived(); return mTl2ec*lvec + mECLoc;
+  }
+
+  /** Conversion from a location in the earth centered and fixed frame
+      to local horizontal frame coordinates.
+      @parm ecvec Vector in the earth centered and fixed frame
+      @return The vector in the local horizontal coordinate frame */
+  FGColumnVector3 LocationToLocal(const FGColumnVector3& ecvec) const {
+    ComputeDerived(); return mTec2l*(ecvec - mECLoc);
+  }
+
+  // For time-stepping, locations have vector properties...
+
+  /** Read access the entries of the vector.
+      @param idx the component index.
+      Return the value of the matrix entry at the given index.
+      Indices are counted starting with 1.
+      Note that the index given in the argument is unchecked. */
+  double operator()(unsigned int idx) const { return Entry(idx); }
+
+  /** Write access the entries of the vector.
+      @param idx the component index.
+      @return a reference to the vector entry at the given index.
+      Indices are counted starting with 1.
+      Note that the index given in the argument is unchecked. */
+  double& operator()(unsigned int idx) { return Entry(idx); }
+
+  /** Read access the entries of the vector.
+      @param idx the component index.
+      @return the value of the matrix entry at the given index.
+      Indices are counted starting with 1.
+      This function is just a shortcut for the @ref double
+      operator()(unsigned int idx) const function. It is
+      used internally to access the elements in a more convenient way.
+      Note that the index given in the argument is unchecked. */
+  double Entry(unsigned int idx) const { return mECLoc.Entry(idx); }
+
+  /** Write access the entries of the vector.
+      @param idx the component index.
+      @return a reference to the vector entry at the given index.
+      Indices are counted starting with 1.
+      This function is just a shortcut for the double&
+      operator()(unsigned int idx) function. It is
+      used internally to access the elements in a more convenient way.
+      Note that the index given in the argument is unchecked. */
+  double& Entry(unsigned int idx) {
+    mCacheValid = false; return mECLoc.Entry(idx);
+  }
+
+  const FGLocation& operator=(const FGLocation& l) {
+    mECLoc = l.mECLoc;
+    mCacheValid = l.mCacheValid;
+    if (!mCacheValid)
+      return *this;
+
+    mLon = l.mLon;
+    mLat = l.mLat;
+    mRadius = l.mRadius;
+
+    mTl2ec = l.mTl2ec;
+    mTec2l = l.mTec2l;
+
+    return *this;
+  }
+  bool operator==(const FGLocation& l) const {
+    return mECLoc == l.mECLoc;
+  }
+  bool operator!=(const FGLocation& l) const { return ! operator==(l); }
+  const FGLocation& operator+=(const FGLocation &l) {
+    mCacheValid = false;
+    mECLoc += l.mECLoc;
+    return *this;
+  }
+  const FGLocation& operator-=(const FGLocation &l) {
+    mCacheValid = false;
+    mECLoc -= l.mECLoc;
+    return *this;
+  }
+  const FGLocation& operator*=(double scalar) {
+    mCacheValid = false;
+    mECLoc *= scalar;
+    return *this;
+  }
+  const FGLocation& operator/=(double scalar) {
+    return operator*=(1.0/scalar);
+  }
+  FGLocation operator+(const FGLocation& l) const {
+    return FGLocation(mECLoc + l.mECLoc);
+  }
+  FGLocation operator-(const FGLocation& l) const {
+    return FGLocation(mECLoc - l.mECLoc);
+  }
+
+  FGLocation operator*(double scalar) const {
+    return FGLocation(scalar*mECLoc);
+  }
+
+  /** Cast to a simple 3d vector */
+  operator const FGColumnVector3&() const {
+    return mECLoc;
+  }
+
+  /** Ties into the property tree.
+      Ties the variables represented by this class into the property tree. */
+  void bind(FGPropertyManager*, const string&) const;
+
+  /** Remove from property tree.
+      Unties the variables represented by this class into the property tree. */
+  void unbind(FGPropertyManager*, const string&) const;
+
+private:
+  /** Computation of derived values.
+      This function re-computes the derived values like lat/lon and
+      transformation matrices. It does this unconditionally. */
+  void ComputeDerivedUnconditional(void) const;
+
+  /** Computation of derived values.
+      This function checks if the derived values like lat/lon and
+      transformation matrices are already computed. If so, it
+      returns. If they need to be computed this is done here. */
+  void ComputeDerived(void) const {
+    if (!mCacheValid)
+      ComputeDerivedUnconditional();
+  }
+
+  /** The coordinates in the earth centered frame. This is the master copy.
+      The coordinate frame has its center in the middle of the earth.
+      Its x-axis points from the center of the earth towards a
+      location with zero latitude and longitude on the earths
+      surface. The y-axis points from the center of the earth towards a
+      location with zero latitude and 90deg longitude on the earths
+      surface. The z-axis points from the earths center to the
+      geographic north pole.
+      @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 */
+  FGColumnVector3 mECLoc;
+
+  /** The cached lon/lat/radius values. */
+  mutable double mLon;
+  mutable double mLat;
+  mutable double mRadius;
+
+  /** The cached rotation matrices from and to the associated frames. */
+  mutable FGMatrix33 mTl2ec;
+  mutable FGMatrix33 mTec2l;
+
+  /** A data validity flag.
+      This class implements caching of the derived values like the
+      orthogonal rotation matrices or the lon/lat/radius values. For caching we
+      carry a flag which signals if the values are valid or not.
+      The C++ keyword "mutable" tells the compiler that the data member is
+      allowed to change during a const member function. */
+  mutable bool mCacheValid;
+};
+
+/** Scalar multiplication.
+
+    @param scalar scalar value to multiply with.
+    @param l Vector to multiply.
+
+    Multiply the Vector with a scalar value. */
+inline FGLocation operator*(double scalar, const FGLocation& l)
+{
+  return l.operator*(scalar);
+}
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
index a4123e1330eb0cc19f83d4fd3c246b07640cc48c..3482baf52dd275248332801630e8be190af71620 100644 (file)
@@ -27,7 +27,7 @@
 
 FUNCTIONAL DESCRIPTION
 --------------------------------------------------------------------------------
-This base class for the FGAero, FGRotational, etc. classes defines methods
+This base class for the FGAerodynamics, FGPropagate, etc. classes defines methods
 common to all models.
 
 HISTORY
@@ -49,9 +49,7 @@ INCLUDES
 #include "FGInertial.h"
 #include "FGGroundReactions.h"
 #include "FGAircraft.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
 #include "FGAuxiliary.h"
 #include "FGOutput.h"
 
@@ -82,17 +80,15 @@ FGModel::FGModel(FGFDMExec* fdmex)
   Inertial        = 0;
   GroundReactions = 0;
   Aircraft        = 0;
-  Translation     = 0;
-  Rotation        = 0;
-  Position        = 0;
+  Propagate       = 0;
   Auxiliary       = 0;
   Output          = 0;
-  
+
   //in order for FGModel derived classes to self-bind (that is, call
   //their bind function in the constructor, the PropertyManager pointer
   //must be brought up now.
   PropertyManager = FDMExec->GetPropertyManager();
-  
+
   exe_ctr     = 1;
   rate        = 1;
 
@@ -119,12 +115,10 @@ bool FGModel::InitModel(void)
   Inertial        = FDMExec->GetInertial();
   GroundReactions = FDMExec->GetGroundReactions();
   Aircraft        = FDMExec->GetAircraft();
-  Translation     = FDMExec->GetTranslation();
-  Rotation        = FDMExec->GetRotation();
-  Position        = FDMExec->GetPosition();
+  Propagate       = FDMExec->GetPropagate();
   Auxiliary       = FDMExec->GetAuxiliary();
   Output          = FDMExec->GetOutput();
-  
+
   if (!State ||
       !Atmosphere ||
       !FCS ||
@@ -134,9 +128,7 @@ bool FGModel::InitModel(void)
       !Inertial ||
       !GroundReactions ||
       !Aircraft ||
-      !Translation ||
-      !Rotation ||
-      !Position ||
+      !Propagate ||
       !Auxiliary ||
       !Output) return(false);
   else return(true);
index 10501c66d0b2a8d3ed49aa2a7a648b8aff011cc2..6ae3707315e89ae5285f1a145a9c9d34d26eb781 100644 (file)
@@ -82,9 +82,7 @@ class FGAerodynamics;
 class FGInertial;
 class FGGroundReactions;
 class FGAircraft;
-class FGTranslation;
-class FGRotation;
-class FGPosition;
+class FGPropagate;
 class FGAuxiliary;
 class FGOutput;
 class FGConfigFile;
@@ -114,7 +112,7 @@ public:
       @param Config a pointer to the config file instance
       @return true if model is successfully loaded*/
   virtual bool Load(FGConfigFile* Config) {return true;}
+
   FGModel* NextModel;
   string Name;
 
@@ -125,13 +123,13 @@ public:
   virtual bool InitModel(void);
   virtual void SetRate(int tt) {rate = tt;}
   virtual int  GetRate(void)   {return rate;}
-  
+
   void SetPropertyManager(FGPropertyManager *fgpm) { PropertyManager=fgpm;}
 
 protected:
   int exe_ctr;
   int rate;
-  
+
   virtual void Debug(int from);
 
   FGFDMExec*         FDMExec;
@@ -144,9 +142,7 @@ protected:
   FGInertial*        Inertial;
   FGGroundReactions* GroundReactions;
   FGAircraft*        Aircraft;
-  FGTranslation*     Translation;
-  FGRotation*        Rotation;
-  FGPosition*        Position;
+  FGPropagate*       Propagate;
   FGAuxiliary*       Auxiliary;
   FGOutput*          Output;
   FGPropertyManager* PropertyManager;
index 4faa4ea74a93b5f1f8dc6a2826200a47e0fa8083..fa890f2ee884589d2ec3f0f3b4092c4031babfd3 100644 (file)
@@ -35,12 +35,7 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  include STL_ALGORITHM
-#else
-#  include <algorithm>
-#endif
+#include <sstream>
 
 #include "FGNozzle.h"
 #include "FGAtmosphere.h"
@@ -104,6 +99,28 @@ double FGNozzle::GetPowerRequired(void)
   return PE;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGNozzle::GetThrusterLabels(int id)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_Thrust[" << id << ']';
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGNozzle::GetThrusterValues(int id)
+{
+  std::ostringstream buf;
+
+  buf << Thrust;
+
+  return buf.str();
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
index c02e9c5b22fc2f6fe043a7a48e898813ebecff44..8ee26dff6d26f99c42f6362c6225854006e37ee1 100644 (file)
@@ -75,7 +75,9 @@ public:
 
   double Calculate(double CfPc);
   double GetPowerRequired(void);
-  
+  string GetThrusterLabels(int id);
+  string GetThrusterValues(int id);
+
 private:
   double ReverserAngle;
   double PE;
index 15b76d8daf18e7a2d50e24d6643a681acf0729f1..794f8c48937c5e5a4f55a094ac2903a2d34bb88c 100644 (file)
@@ -47,12 +47,12 @@ INCLUDES
 #include "FGGroundReactions.h"
 #include "FGAircraft.h"
 #include "FGMassBalance.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
 #include "FGAuxiliary.h"
 #include "FGInertial.h"
 
+#include <iomanip>
+
 namespace JSBSim {
 
 static const char *IdSrc = "$Id$";
@@ -91,22 +91,17 @@ FGOutput::~FGOutput()
 bool FGOutput::Run(void)
 {
   if (enabled) {
-    if (!FGModel::Run()) {
-
-      if (Type == otSocket) {
-        SocketOutput();
-      } else if (Type == otCSV) {
-        DelimitedOutput(Filename);
-      } else if (Type == otTerminal) {
-        // Not done yet
-      } else if (Type == otNone) {
-        // Do nothing
-      } else {
-        // Not a valid type of output
-      }
-    return false;
+    if (FGModel::Run()) return true;
+    if (Type == otSocket) {
+      SocketOutput();
+    } else if (Type == otCSV) {
+      DelimitedOutput(Filename);
+    } else if (Type == otTerminal) {
+      // Not done yet
+    } else if (Type == otNone) {
+      // Do nothing
     } else {
-    return true;
+      // Not a valid type of output
     }
   }
   return false;
@@ -180,10 +175,7 @@ void FGOutput::DelimitedOutput(string fname)
       outstream << ", ";
       outstream << "Drag, Side, Lift, ";
       outstream << "L/D, ";
-      outstream << "Xforce, Yforce, Zforce, ";
-      outstream << "xGravity, yGravity, zGravity, ";
-      outstream << "xCoriolis, yCoriolis, zCoriolis, ";
-      outstream << "xCentrifugal, yCentrifugal, zCentrifugal";
+      outstream << "Xforce, Yforce, Zforce";
     }
     if (SubSystems & ssMoments) {
       outstream << ", ";
@@ -208,14 +200,14 @@ void FGOutput::DelimitedOutput(string fname)
       outstream << "Mass, ";
       outstream << "Xcg, Ycg, Zcg";
     }
-    if (SubSystems & ssPosition) {
+    if (SubSystems & ssPropagate) {
       outstream << ", ";
       outstream << "Altitude, ";
       outstream << "Phi, Tht, Psi, ";
       outstream << "Alpha, ";
       outstream << "Beta, ";
-      outstream << "Latitude, ";
-      outstream << "Longitude, ";
+      outstream << "Latitude (Deg), ";
+      outstream << "Longitude (Deg), ";
       outstream << "Distance AGL, ";
       outstream << "Runway Radius";
     }
@@ -262,25 +254,22 @@ void FGOutput::DelimitedOutput(string fname)
   }
   if (SubSystems & ssRates) {
     outstream << ", ";
-    outstream << Rotation->GetPQR() << ", ";
-    outstream << Rotation->GetPQRdot();
+    outstream << Propagate->GetPQR() << ", ";
+    outstream << Propagate->GetPQRdot();
   }
   if (SubSystems & ssVelocities) {
     outstream << ", ";
-    outstream << Translation->Getqbar() << ", ";
-    outstream << Translation->GetVt() << ", ";
-    outstream << Translation->GetUVW() << ", ";
-    outstream << Translation->GetAeroUVW() << ", ";
-    outstream << Position->GetVel();
+    outstream << Auxiliary->Getqbar() << ", ";
+    outstream << setprecision(12) << Auxiliary->GetVt() << ", ";
+    outstream << setprecision(12) << Propagate->GetUVW() << ", ";
+    outstream << Auxiliary->GetAeroUVW() << ", ";
+    outstream << Propagate->GetVel();
   }
   if (SubSystems & ssForces) {
     outstream << ", ";
     outstream << Aerodynamics->GetvFs() << ", ";
     outstream << Aerodynamics->GetLoD() << ", ";
-    outstream << Aircraft->GetForces() << ", ";
-    outstream << Inertial->GetGravity() << ", ";
-    outstream << Inertial->GetCoriolis() << ", ";
-    outstream << Inertial->GetCentrifugal();
+    outstream << Aircraft->GetForces();
   }
   if (SubSystems & ssMoments) {
     outstream << ", ";
@@ -297,16 +286,16 @@ void FGOutput::DelimitedOutput(string fname)
     outstream << MassBalance->GetMass() << ", ";
     outstream << MassBalance->GetXYZcg();
   }
-  if (SubSystems & ssPosition) {
+  if (SubSystems & ssPropagate) {
     outstream << ", ";
-    outstream << Position->Geth() << ", ";
-    outstream << Rotation->GetEuler() << ", ";
-    outstream << Translation->Getalpha() << ", ";
-    outstream << Translation->Getbeta() << ", ";
-    outstream << Position->GetLatitude() << ", ";
-    outstream << Position->GetLongitude() << ", ";
-    outstream << Position->GetDistanceAGL() << ", ";
-    outstream << Position->GetRunwayRadius();
+    outstream << Propagate->Geth() << ", ";
+    outstream << Propagate->GetEuler() << ", ";
+    outstream << Auxiliary->Getalpha(inDegrees) << ", ";
+    outstream << Auxiliary->Getbeta(inDegrees) << ", ";
+    outstream << Propagate->GetLocation().GetLatitudeDeg() << ", ";
+    outstream << Propagate->GetLocation().GetLongitudeDeg() << ", ";
+    outstream << Propagate->GetDistanceAGL() << ", ";
+    outstream << Propagate->GetRunwayRadius();
   }
   if (SubSystems & ssCoefficients) {
     scratch = Aerodynamics->GetCoefficientValues();
@@ -373,8 +362,8 @@ void FGOutput::SocketOutput(void)
     socket->Append("Fx");
     socket->Append("Fy");
     socket->Append("Fz");
-    socket->Append("Latitude");
-    socket->Append("Longitude");
+    socket->Append("Latitude (Deg)");
+    socket->Append("Longitude (Deg)");
     socket->Append("QBar");
     socket->Append("Alpha");
     socket->Append("L");
@@ -391,37 +380,37 @@ void FGOutput::SocketOutput(void)
 
   socket->Clear();
   socket->Append(State->Getsim_time());
-  socket->Append(Position->Geth());
-  socket->Append(Rotation->Getphi());
-  socket->Append(Rotation->Gettht());
-  socket->Append(Rotation->Getpsi());
+  socket->Append(Propagate->Geth());
+  socket->Append(Propagate->Getphi());
+  socket->Append(Propagate->Gettht());
+  socket->Append(Propagate->Getpsi());
   socket->Append(Atmosphere->GetDensity());
-  socket->Append(Translation->GetVt());
-  socket->Append(Translation->GetUVW(eU));
-  socket->Append(Translation->GetUVW(eV));
-  socket->Append(Translation->GetUVW(eW));
-  socket->Append(Translation->GetAeroUVW(eU));
-  socket->Append(Translation->GetAeroUVW(eV));
-  socket->Append(Translation->GetAeroUVW(eW));
-  socket->Append(Position->GetVn());
-  socket->Append(Position->GetVe());
-  socket->Append(Position->GetVd());
-  socket->Append(Translation->GetUVWdot(eU));
-  socket->Append(Translation->GetUVWdot(eV));
-  socket->Append(Translation->GetUVWdot(eW));
-  socket->Append(Rotation->GetPQR(eP));
-  socket->Append(Rotation->GetPQR(eQ));
-  socket->Append(Rotation->GetPQR(eR));
-  socket->Append(Rotation->GetPQRdot(eP));
-  socket->Append(Rotation->GetPQRdot(eQ));
-  socket->Append(Rotation->GetPQRdot(eR));
+  socket->Append(Auxiliary->GetVt());
+  socket->Append(Propagate->GetUVW(eU));
+  socket->Append(Propagate->GetUVW(eV));
+  socket->Append(Propagate->GetUVW(eW));
+  socket->Append(Auxiliary->GetAeroUVW(eU));
+  socket->Append(Auxiliary->GetAeroUVW(eV));
+  socket->Append(Auxiliary->GetAeroUVW(eW));
+  socket->Append(Propagate->GetVel(eNorth));
+  socket->Append(Propagate->GetVel(eEast));
+  socket->Append(Propagate->GetVel(eDown));
+  socket->Append(Propagate->GetUVWdot(eU));
+  socket->Append(Propagate->GetUVWdot(eV));
+  socket->Append(Propagate->GetUVWdot(eW));
+  socket->Append(Propagate->GetPQR(eP));
+  socket->Append(Propagate->GetPQR(eQ));
+  socket->Append(Propagate->GetPQR(eR));
+  socket->Append(Propagate->GetPQRdot(eP));
+  socket->Append(Propagate->GetPQRdot(eQ));
+  socket->Append(Propagate->GetPQRdot(eR));
   socket->Append(Aircraft->GetForces(eX));
   socket->Append(Aircraft->GetForces(eY));
   socket->Append(Aircraft->GetForces(eZ));
-  socket->Append(Position->GetLatitude());
-  socket->Append(Position->GetLongitude());
-  socket->Append(Translation->Getqbar());
-  socket->Append(Translation->Getalpha());
+  socket->Append(Propagate->GetLocation().GetLatitudeDeg());
+  socket->Append(Propagate->GetLocation().GetLongitudeDeg());
+  socket->Append(Auxiliary->Getqbar());
+  socket->Append(Auxiliary->Getalpha(inDegrees));
   socket->Append(Aircraft->GetMoments(eL));
   socket->Append(Aircraft->GetMoments(eM));
   socket->Append(Aircraft->GetMoments(eN));
@@ -456,6 +445,7 @@ bool FGOutput::Load(FGConfigFile* AC_cfg)
   int OutRate = 0;
   FGConfigFile* Output_cfg;
   string property;
+  unsigned int port;
 
 # ifndef macintosh
     separator = "/";
@@ -466,13 +456,13 @@ bool FGOutput::Load(FGConfigFile* AC_cfg)
   name = AC_cfg->GetValue("NAME");
   fname = AC_cfg->GetValue("FILE");
   token = AC_cfg->GetValue("TYPE");
+  port = atoi(AC_cfg->GetValue("PORT").c_str());
+
   Output->SetType(token);
 
-#if defined( FG_WITH_JSBSIM_SOCKET ) || !defined( FGFS )
   if (token == "SOCKET") {
-    socket = new FGfdmSocket("localhost",1138);
+    socket = new FGfdmSocket(name,port);
   }
-#endif
 
   if (!fname.empty()) {
     outputInFileName = FDMExec->GetAircraftPath() + separator
@@ -526,7 +516,7 @@ bool FGOutput::Load(FGConfigFile* AC_cfg)
     }
     if (parameter == "POSITION") {
       *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssPosition;
+      if (parameter == "ON") SubSystems += ssPropagate;
     }
     if (parameter == "COEFFICIENTS") {
       *Output_cfg >> parameter;
@@ -618,10 +608,14 @@ void FGOutput::Debug(int from)
       if (SubSystems & ssAtmosphere)      cout << "    Atmosphere parameters logged" << endl;
       if (SubSystems & ssMassProps)       cout << "    Mass parameters logged" << endl;
       if (SubSystems & ssCoefficients)    cout << "    Coefficient parameters logged" << endl;
-      if (SubSystems & ssPosition)        cout << "    Position parameters logged" << endl;
+      if (SubSystems & ssPropagate)       cout << "    Propagate parameters logged" << endl;
       if (SubSystems & ssGroundReactions) cout << "    Ground parameters logged" << endl;
       if (SubSystems & ssFCS)             cout << "    FCS parameters logged" << endl;
       if (SubSystems & ssPropulsion)      cout << "    Propulsion parameters logged" << endl;
+      if (OutputProperties.size() > 0)    cout << "    Properties logged:" << endl;
+      for (unsigned int i=0;i<OutputProperties.size();i++) {
+        cout << "      - " << OutputProperties[i]->GetName() << endl;
+      }
     }
   }
   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
index 70d13ee8241a56bdd7366bc5cc0440eacacebc13..40064d036865252d55ec7e0a208185078e090fca 100644 (file)
@@ -73,7 +73,50 @@ CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 /** Handles simulation output.
-  */
+    OUTPUT section definition
+
+    The following specifies the way that JSBSim writes out data.
+
+    NAME is the filename you want the output to go to
+
+    TYPE can be:
+      CSV       Comma separated data. If a filename is supplied then the data
+                goes to that file. If COUT or cout is specified, the data goes
+                to stdout. If the filename is a null filename the data goes to
+                stdout, as well.
+      SOCKET    Will eventually send data to a socket output, where NAME
+                would then be the IP address of the machine the data should be
+                sent to. DON'T USE THIS YET!
+      TABULAR   Columnar data. NOT IMPLEMENTED YET!
+      TERMINAL  Output to terminal. NOT IMPLEMENTED YET!
+      NONE      Specifies to do nothing. THis setting makes it easy to turn on and
+                off the data output without having to mess with anything else.
+
+    The arguments that can be supplied, currently, are
+
+    RATE_IN_HZ  An integer rate in times-per-second that the data is output. This
+                value may not be *exactly* what you want, due to the dependence
+                on dt, the cycle rate for the FDM.
+
+    The following parameters tell which subsystems of data to output:
+
+    SIMULATION       ON|OFF
+    ATMOSPHERE       ON|OFF
+    MASSPROPS        ON|OFF
+    AEROSURFACES     ON|OFF
+    RATES            ON|OFF
+    VELOCITIES       ON|OFF
+    FORCES           ON|OFF
+    MOMENTS          ON|OFF
+    POSITION         ON|OFF
+    COEFFICIENTS     ON|OFF
+    GROUND_REACTIONS ON|OFF
+    FCS              ON|OFF
+    PROPULSION       ON|OFF
+
+    NOTE that Time is always output with the data.
+    @version $Id$
+ */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DECLARATION
@@ -109,7 +152,7 @@ public:
     /** Subsystem: Atmosphere (= 64)         */ ssAtmosphere      = 64,
     /** Subsystem: Mass Properties (= 128)   */ ssMassProps       = 128,
     /** Subsystem: Coefficients (= 256)      */ ssCoefficients    = 256,
-    /** Subsystem: Position (= 512)          */ ssPosition        = 512,
+    /** Subsystem: Propagate (= 512)         */ ssPropagate       = 512,
     /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024,
     /** Subsystem: FCS (= 2048)              */ ssFCS             = 2048,
     /** Subsystem: Propulsion (= 4096)       */ ssPropulsion      = 4096
index 263591e48b7baeaab9843b5e9d1739a2a23ae316..aa3cef21d6b38e03b44ad8c1692c8a267c7054e9 100644 (file)
@@ -39,8 +39,11 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <sstream>
+
 #include "FGPiston.h"
 #include "FGPropulsion.h"
+#include "FGPropeller.h"
 
 namespace JSBSim {
 
@@ -67,6 +70,9 @@ FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec),
   MinManifoldPressure_inHg = 6.5;
   MaxManifoldPressure_inHg = 28.5;
   ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg
+  minMAP = 21950;
+  maxMAP = 96250;
+  MAP = Atmosphere->GetPressure() * 47.88;  // psf to Pa
   CylinderHeadTemp_degK = 0.0;
   Displacement = 360;
   MaxHP = 200;
@@ -78,6 +84,25 @@ FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec),
 
   dt = State->Getdt();
 
+  // Supercharging
+  BoostSpeeds = 0;  // Default to no supercharging
+  BoostSpeed = 0;
+  Boosted = false;
+  BoostOverride = 0;
+  bBoostOverride = false;
+  bTakeoffBoost = false;
+  TakeoffBoost = 0.0;   // Default to no extra takeoff-boost
+  int i;
+  for(i=0; i<FG_MAX_BOOST_SPEEDS; ++i) {
+    RatedBoost[i] = 0.0;
+    RatedPower[i] = 0.0;
+    RatedAltitude[i] = 0.0;
+    BoostMul[i] = 1.0;
+    RatedMAP[i] = 100000;
+    RatedRPM[i] = 2500;
+    TakeoffMAP[i] = 100000;
+  }
+
   // Initialisation
   volumetric_efficiency = 0.8;  // Actually f(speed, load) but this will get us running
 
@@ -123,9 +148,79 @@ FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec),
     else if (token == "IDLERPM") *Eng_cfg >> IdleRPM;
     else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle;
     else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle;
+    else if (token == "NUMBOOSTSPEEDS") *Eng_cfg >> BoostSpeeds;
+    else if (token == "BOOSTOVERRIDE") *Eng_cfg >> BoostOverride;
+    else if (token == "TAKEOFFBOOST") *Eng_cfg >> TakeoffBoost;
+    else if (token == "RATEDBOOST1") *Eng_cfg >> RatedBoost[0];
+    else if (token == "RATEDBOOST2") *Eng_cfg >> RatedBoost[1];
+    else if (token == "RATEDBOOST3") *Eng_cfg >> RatedBoost[2];
+    else if (token == "RATEDPOWER1") *Eng_cfg >> RatedPower[0];
+    else if (token == "RATEDPOWER2") *Eng_cfg >> RatedPower[1];
+    else if (token == "RATEDPOWER3") *Eng_cfg >> RatedPower[2];
+    else if (token == "RATEDRPM1") *Eng_cfg >> RatedRPM[0];
+    else if (token == "RATEDRPM2") *Eng_cfg >> RatedRPM[1];
+    else if (token == "RATEDRPM3") *Eng_cfg >> RatedRPM[2];
+    else if (token == "RATEDALTITUDE1") *Eng_cfg >> RatedAltitude[0];
+    else if (token == "RATEDALTITUDE2") *Eng_cfg >> RatedAltitude[1];
+    else if (token == "RATEDALTITUDE3") *Eng_cfg >> RatedAltitude[2];
     else cerr << "Unhandled token in Engine config file: " << token << endl;
   }
 
+  minMAP = MinManifoldPressure_inHg * 3376.85;  // inHg to Pa
+  maxMAP = MaxManifoldPressure_inHg * 3376.85;
+
+  // Set up and sanity-check the turbo/supercharging configuration based on the input values.
+  if(TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true;
+  for(i=0; i<BoostSpeeds; ++i) {
+    bool bad = false;
+    if(RatedBoost[i] <= 0.0) bad = true;
+    if(RatedPower[i] <= 0.0) bad = true;
+    if(RatedAltitude[i] < 0.0) bad = true;  // 0.0 is deliberately allowed - this corresponds to unregulated supercharging.
+    if(i > 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true;
+    if(bad) {
+      // We can't recover from the above - don't use this supercharger speed.
+      BoostSpeeds--;
+      // TODO - put out a massive error message!
+      break;
+    }
+    // Now sanity-check stuff that is recoverable.
+    if(i < BoostSpeeds - 1) {
+      if(BoostSwitchAltitude[i] < RatedAltitude[i]) {
+        // TODO - put out an error message
+        // But we can also make a reasonable estimate, as below.
+        BoostSwitchAltitude[i] = RatedAltitude[i] + 1000;
+      }
+      BoostSwitchPressure[i] = Atmosphere->GetPressure(BoostSwitchAltitude[i]) * 47.88;
+      //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n';
+      // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now
+      BoostSwitchHysteresis = 1000;
+    }
+    // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude.
+    RatedMAP[i] = Atmosphere->GetPressureSL() * 47.88 + RatedBoost[i] * 6895;  // psf*47.88 = Pa, psi*6895 = Pa.
+    // Sometimes a separate BCV setting for takeoff or extra power is fitted.
+    if(TakeoffBoost > RatedBoost[0]) {
+      // Assume that the effect on the BCV is the same whichever speed is in use.
+      TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895);
+      bTakeoffBoost = true;
+    } else {
+      TakeoffMAP[i] = RatedMAP[i];
+      bTakeoffBoost = false;
+    }
+    BoostMul[i] = RatedMAP[i] / (Atmosphere->GetPressure(RatedAltitude[i]) * 47.88);
+
+    // TODO - get rid of the debugging output before sending it to Jon
+    //cout << "Speed " << i+1 << '\n';
+    //cout << "BoostMul = " << BoostMul[i] << ", RatedMAP = " << RatedMAP[i] << ", TakeoffMAP = " << TakeoffMAP[i] << '\n';
+  }
+
+  if(BoostSpeeds > 0) {
+    Boosted = true;
+    BoostSpeed = 0;
+  }
+  bBoostOverride = (BoostOverride == 1 ? true : false);
+
+  //cout << "Engine is " << (Boosted ? "supercharged" : "naturally aspirated") << '\n';
+
   Debug(0); // Call Debug() routine from constructor if needed
 }
 
@@ -138,7 +233,7 @@ FGPiston::~FGPiston()
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGPiston::Calculate(double PowerRequired)
+double FGPiston::Calculate(void)
 {
   if (FuelFlow_gph > 0.0) ConsumeFuel();
 
@@ -149,19 +244,19 @@ double FGPiston::Calculate(double PowerRequired)
   // Input values.
   //
 
-  p_amb = Atmosphere->GetPressure() * 48;              // convert from lbs/ft2 to Pa
-  p_amb_sea_level = Atmosphere->GetPressureSL() * 48;
+  p_amb = Atmosphere->GetPressure() * 47.88;              // convert from lbs/ft2 to Pa
+  p_amb_sea_level = Atmosphere->GetPressureSL() * 47.88;
   T_amb = Atmosphere->GetTemperature() * (5.0 / 9.0);  // convert from Rankine to Kelvin
 
-  RPM = Propulsion->GetThruster(EngineNumber)->GetRPM() *
-        Propulsion->GetThruster(EngineNumber)->GetGearRatio();
-    
+  RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
+
   IAS = Auxiliary->GetVcalibratedKTS();
 
-    doEngineStartup();
-    doManifoldPressure();
-    doAirFlow();
-    doFuelFlow();
+  doEngineStartup();
+  if(Boosted) doBoostControl();
+  doMAP();
+  doAirFlow();
+  doFuelFlow();
 
   //Now that the fuel flow is done check if the mixture is too lean to run the engine
   //Assume lean limit at 22 AFR for now - thats a thi of 0.668
@@ -171,13 +266,18 @@ double FGPiston::Calculate(double PowerRequired)
     Running = false;
 
   doEnginePower();
-    doEGT();
-    doCHT();
-    doOilTemperature();
-    doOilPressure();
+  doEGT();
+  doCHT();
+  doOilTemperature();
+  doOilPressure();
+
+  if (Thruster->GetType() == FGThruster::ttPropeller) {
+    ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
+  }
 
-  PowerAvailable = (HP * hptoftlbssec) - PowerRequired;
-  return PowerAvailable;
+  PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
+
+  return Thruster->Calculate(PowerAvailable);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -187,7 +287,7 @@ double FGPiston::Calculate(double PowerRequired)
 
 void FGPiston::doEngineStartup(void)
 {
-  // Check parameters that may alter the operating state of the engine. 
+  // Check parameters that may alter the operating state of the engine.
   // (spark, fuel, starter motor etc)
   bool spark;
   bool fuel;
@@ -205,7 +305,7 @@ void FGPiston::doEngineStartup(void)
   } else {
     spark = false;
   }  // neglects battery voltage, master on switch, etc for now.
-  
+
   if ((Magnetos == 1) || (Magnetos > 2)) Magneto_Left = true;
   if (Magnetos > 1)  Magneto_Right = true;
 
@@ -221,7 +321,7 @@ void FGPiston::doEngineStartup(void)
   }
 
   if (Cranking) crank_counter++;  //Check mode of engine operation
-  
+
   if (!Running && spark && fuel) {  // start the engine if revs high enough
     if (Cranking) {
       if ((RPM > 450) && (crank_counter > 175)) // Add a little delay to startup
@@ -238,7 +338,7 @@ void FGPiston::doEngineStartup(void)
   if ( Running && (!spark || !fuel) ) Running = false;
 
   // Check for stalling (RPM = 0).
-  if (Running) { 
+  if (Running) {
     if (RPM == 0) {
       Running = false;
     } else if ((RPM <= 480) && (Cranking)) {
@@ -250,50 +350,119 @@ void FGPiston::doEngineStartup(void)
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 /**
- * Calculate the nominal manifold pressure in inches hg
+ * Calculate the Current Boost Speed
  *
- * This function calculates nominal manifold pressure directly
- * from the throttle position, and does not adjust it for the
- * difference between the pressure at sea level and the pressure
- * at the current altitude (that adjustment takes place in
- * {@link #doEnginePower}).
+ * This function calculates the current turbo/supercharger boost speed
+ * based on altitude and the (automatic) boost-speed control valve configuration.
+ *
+ * Inputs: p_amb, BoostSwitchPressure, BoostSwitchHysteresis
+ *
+ * Outputs: BoostSpeed
+ */
+
+void FGPiston::doBoostControl(void)
+{
+  if(BoostSpeed < BoostSpeeds - 1) {
+    // Check if we need to change to a higher boost speed
+    if(p_amb < BoostSwitchPressure[BoostSpeed] - BoostSwitchHysteresis) {
+      BoostSpeed++;
+    }
+  } else if(BoostSpeed > 0) {
+    // Check if we need to change to a lower boost speed
+    if(p_amb > BoostSwitchPressure[BoostSpeed - 1] + BoostSwitchHysteresis) {
+      BoostSpeed--;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/**
+ * Calculate the manifold absolute pressure (MAP) in inches hg
+ *
+ * This function calculates manifold absolute pressure (MAP)
+ * from the throttle position, turbo/supercharger boost control
+ * system, engine speed and local ambient air density.
  *
  * TODO: changes in MP should not be instantaneous -- introduce
  * a lag between throttle changes and MP changes, to allow pressure
  * to build up or disperse.
  *
- * Inputs: MinManifoldPressure_inHg, MaxManifoldPressure_inHg, Throttle
+ * Inputs: minMAP, maxMAP, p_amb, Throttle
  *
- * Outputs: ManifoldPressure_inHg
+ * Outputs: MAP, ManifoldPressure_inHg
  */
 
-void FGPiston::doManifoldPressure(void)
+void FGPiston::doMAP(void)
 {
-  if (Running || Cranking) {
-    ManifoldPressure_inHg = MinManifoldPressure_inHg +
-            (Throttle * (MaxManifoldPressure_inHg - MinManifoldPressure_inHg));
+  if(RPM > 10) {
+    // Naturally aspirated
+    MAP = minMAP + (Throttle * (maxMAP - minMAP));
+    MAP *= p_amb / p_amb_sea_level;
+    if(Boosted) {
+      // If takeoff boost is fitted, we currently assume the following throttle map:
+      // (In throttle % - actual input is 0 -> 1)
+      // 99 / 100 - Takeoff boost
+      // 96 / 97 / 98 - Rated boost
+      // 0 - 95 - Idle to Rated boost (MinManifoldPressure to MaxManifoldPressure)
+      // In real life, most planes would be fitted with a mechanical 'gate' between
+      // the rated boost and takeoff boost positions.
+      double T = Throttle; // processed throttle value.
+      bool bTakeoffPos = false;
+      if(bTakeoffBoost) {
+        if(Throttle > 0.98) {
+          //cout << "Takeoff Boost!!!!\n";
+          bTakeoffPos = true;
+        } else if(Throttle <= 0.95) {
+          bTakeoffPos = false;
+          T *= 1.0 / 0.95;
+        } else {
+          bTakeoffPos = false;
+          //cout << "Rated Boost!!\n";
+          T = 1.0;
+        }
+      }
+      // Boost the manifold pressure.
+      MAP *= BoostMul[BoostSpeed];
+      // Now clip the manifold pressure to BCV or Wastegate setting.
+      if(bTakeoffPos) {
+        if(MAP > TakeoffMAP[BoostSpeed]) {
+          MAP = TakeoffMAP[BoostSpeed];
+        }
+      } else {
+        if(MAP > RatedMAP[BoostSpeed]) {
+          MAP = RatedMAP[BoostSpeed];
+        }
+      }
+    }
   } else {
-    ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg
-  }  
+    // rpm < 10 - effectively stopped.
+    // TODO - add a better variation of MAP with engine speed
+    MAP = Atmosphere->GetPressure() * 47.88; // psf to Pa
+  }
+
+  // And set the value in American units as well
+  ManifoldPressure_inHg = MAP / 3376.85;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 /**
  * Calculate the air flow through the engine.
+ * Also calculates ambient air density
+ * (used in CHT calculation for air-cooled engines).
  *
- * At this point, ManifoldPressure_inHg still represents the sea-level
- * MP, not adjusted for altitude.
- *
- * Inputs: p_amb, R_air, T_amb, ManifoldPressure_inHg, Displacement,
+ * Inputs: p_amb, R_air, T_amb, MAP, Displacement,
  *   RPM, volumetric_efficiency
  *
+ * TODO: Model inlet manifold air temperature.
+ *
  * Outputs: rho_air, m_dot_air
  */
 
 void FGPiston::doAirFlow(void)
 {
   rho_air = p_amb / (R_air * T_amb);
-  double rho_air_manifold = rho_air * ManifoldPressure_inHg / 29.6;
+  double rho_air_manifold = MAP / (R_air * T_amb);
   double displacement_SI = Displacement * in3tom3;
   double swept_volume = (displacement_SI * (RPM/60)) / 2;
   double v_dot_air = swept_volume * volumetric_efficiency;
@@ -329,7 +498,7 @@ void FGPiston::doFuelFlow(void)
  * When tested with sufficient RPM, it has no trouble reaching
  * 200HP.
  *
- * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb, 
+ * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb,
  *   equivalence_ratio, Cycles, MaxHP
  *
  * Outputs: Percentage_Power, HP
@@ -337,26 +506,44 @@ void FGPiston::doFuelFlow(void)
 
 void FGPiston::doEnginePower(void)
 {
-  ManifoldPressure_inHg *= p_amb / p_amb_sea_level;
-
-  if (Running) {       
-    double ManXRPM = ManifoldPressure_inHg * RPM;
+  if (Running) {
     double T_amb_degF = KelvinToFahrenheit(T_amb);
-    double T_amb_sea_lev_degF = KelvinToFahrenheit(288); 
+    double T_amb_sea_lev_degF = KelvinToFahrenheit(288);
 
     // FIXME: this needs to be generalized
-    Percentage_Power = (6e-9 * ManXRPM * ManXRPM) + (8e-4 * ManXRPM) - 1.0;
-    Percentage_Power += ((T_amb_sea_lev_degF - T_amb_degF) * 7 /120);
+    double ManXRPM;  // Convienience term for use in the calculations
+    if(Boosted) {
+      // Currently a simple linear fit.
+      // The zero crossing is moved up the speed-load range to reduce the idling power.
+      // This will change!
+      double zeroOffset = (minMAP / 2.0) * (IdleRPM / 2.0);
+      ManXRPM = MAP * (RPM > RatedRPM[BoostSpeed] ? RatedRPM[BoostSpeed] : RPM);
+      // The speed clip in the line above is deliberate.
+      Percentage_Power = ((ManXRPM - zeroOffset) / ((RatedMAP[BoostSpeed] * RatedRPM[BoostSpeed]) - zeroOffset)) * 107.0;
+      Percentage_Power -= 7.0;  // Another idle power reduction offset - see line above with 107.
+      if (Percentage_Power < 0.0) Percentage_Power = 0.0;
+      // Note that %power is allowed to go over 100 for boosted powerplants
+      // such as for the BCV-override or takeoff power settings.
+      // TODO - currently no altitude effect (temperature & exhaust back-pressure) modelled
+      // for boosted engines.
+    } else {
+      ManXRPM = ManifoldPressure_inHg * RPM; // Note that inHg must be used for the following correlation.
+      Percentage_Power = (6e-9 * ManXRPM * ManXRPM) + (8e-4 * ManXRPM) - 1.0;
+      Percentage_Power += ((T_amb_sea_lev_degF - T_amb_degF) * 7 /120);
+      if (Percentage_Power < 0.0) Percentage_Power = 0.0;
+      else if (Percentage_Power > 100.0) Percentage_Power = 100.0;
+    }
 
     double Percentage_of_best_power_mixture_power =
       Power_Mixture_Correlation->GetValue(14.7 / equivalence_ratio);
 
     Percentage_Power *= Percentage_of_best_power_mixture_power / 100.0;
 
-    if (Percentage_Power < 0.0) Percentage_Power = 0.0;
-    else if (Percentage_Power > 100.0) Percentage_Power = 100.0;
-    
-    HP = Percentage_Power * MaxHP / 100.0;
+    if(Boosted) {
+      HP = Percentage_Power * RatedPower[BoostSpeed] / 100.0;
+    } else {
+      HP = Percentage_Power * MaxHP / 100.0;
+    }
 
   } else {
 
@@ -367,7 +554,7 @@ void FGPiston::doEnginePower(void)
                     // the first time step. It may possibly need to be changed
                     // if the prop model is changed.
       } else if (RPM < 480) {
-        HP = 3.0 + ((480 - RPM) / 10.0);  
+        HP = 3.0 + ((480 - RPM) / 10.0);
         // This is a guess - would be nice to find a proper starter moter torque curve
       } else {
         HP = 3.0;
@@ -380,13 +567,14 @@ void FGPiston::doEnginePower(void)
         HP = 0.0;
     }
   }
+  //cout << "Power = " << HP << '\n';
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 /**
  * Calculate the exhaust gas temperature.
  *
- * Inputs: equivalence_ratio, m_dot_fuel, calorific_value_fuel, 
+ * Inputs: equivalence_ratio, m_dot_fuel, calorific_value_fuel,
  *   Cp_air, m_dot_air, Cp_fuel, m_dot_fuel, T_amb, Percentage_Power
  *
  * Outputs: combustion_efficiency, ExhaustGasTemp_degK
@@ -401,7 +589,7 @@ void FGPiston::doEGT(void)
 
   if ((Running) && (m_dot_air > 0.0)) {  // do the energy balance
     combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio);
-    enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * 
+    enthalpy_exhaust = m_dot_fuel * calorific_value_fuel *
                               combustion_efficiency * 0.33;
     heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel);
     delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust;
@@ -438,15 +626,15 @@ void FGPiston::doCHT(void)
   double v_apparent = IAS * 0.5144444;
   double v_dot_cooling_air = arbitary_area * v_apparent;
   double m_dot_cooling_air = v_dot_cooling_air * rho_air;
-  double dqdt_from_combustion = 
+  double dqdt_from_combustion =
     m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;
-  double dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) + 
+  double dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) +
     (h3 * RPM * temperature_difference);
   double dqdt_free = h1 * temperature_difference;
   double dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free;
-    
+
   double HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead;
-    
+
   CylinderHeadTemp_degK +=
     (dqdt_cylinder_head / HeatCapacityCylinderHead) * dt;
 }
@@ -470,7 +658,7 @@ void FGPiston::doOilTemperature(void)
     target_oil_temp = 363;
     time_constant = 500;        // Time constant for engine-on idling.
     if (Percentage_Power > idle_percentage_power) {
-      time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power 
+      time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power
     }
   } else {
     target_oil_temp = 298;
@@ -508,6 +696,29 @@ void FGPiston::doOilPressure(void)
   OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPiston::GetEngineLabels(void)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_PwrAvail[" << EngineNumber << "], "
+      << Thruster->GetThrusterLabels(EngineNumber);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPiston::GetEngineValues(void)
+{
+  std::ostringstream buf;
+
+  buf << PowerAvailable << ", " << Thruster->GetThrusterValues(EngineNumber);
+
+  return buf.str();
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //
 //    The bitmasked value choices are as follows:
index caf97eb939898279046bc49a5720be169ac15326..b2e65b5fcb3aedc017183b67326199cc828f15dc 100644 (file)
@@ -48,6 +48,7 @@ DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #define ID_PISTON "$Id$";
+#define FG_MAX_BOOST_SPEEDS 3
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -59,11 +60,78 @@ namespace JSBSim {
 CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-/** Models Dave Luff's engine model as ported into JSBSim by David Megginson.
+/** Models Dave Luff's Turbo/Supercharged Piston engine model.
+    Additional elements are required for a supercharged engine.  These can be
+    left off a non-supercharged engine, ie. the changes are all backward
+    compatible at present.
+
+    - NUMBOOSTSPEEDS - zero (or not present) for a naturally-aspirated engine,
+      either 1, 2 or 3 for a boosted engine.  This corresponds to the number of
+      supercharger speeds.  Merlin XII had 1 speed, Merlin 61 had 2, a late
+      Griffon engine apparently had 3.  No known engine more than 3, although
+      some German engines apparently had a continuously variable-speed
+      supercharger.
+
+    - BOOSTOVERRIDE - whether the boost pressure control system (either a boost
+      control valve for superchargers or wastegate for turbochargers) can be
+      overriden by the pilot.  During wartime this was commonly possible, and
+      known as "War Emergency Power" by the Brits.  1 or 0 in the config file.
+      This isn't implemented in the model yet though, there would need to be
+      some way of getting the boost control cutout lever position (on or off)
+      from FlightGear first.
+
+    - The next items are all appended with either 1, 2 or 3 depending on which
+      boost speed they refer to, eg RATEDBOOST1.  The rated values seems to have
+      been a common convention at the time to express the maximum continuously
+      available power, and the conditions to attain that power.
+
+    - RATEDBOOST[123] - the absolute rated boost above sea level ambient for a
+      given boost speed, in psi.  Eg the Merlin XII had a rated boost of 9psi,
+      giving approximately 42inHg manifold pressure up to the rated altitude.
+
+    - RATEDALTITUDE[123] - The altitude up to which rated boost can be
+      maintained.  Up to this altitude the boost is maintained constant for a
+      given throttle position by the BCV or wastegate.  Beyond this altitude the
+      manifold pressure must drop, since the supercharger is now at maximum
+      unregulated output.  The actual pressure multiplier of the supercharger
+      system is calculated at initialisation from this value.
+
+    - RATEDPOWER[123] - The power developed at rated boost at rated altitude at
+      rated rpm.
+
+    - RATEDRPM[123] - The rpm at which rated power is developed.
+
+    - TAKEOFFBOOST - Takeoff boost in psi above ambient.  Many aircraft had an
+      extra boost setting beyond rated boost, but not totally uncontrolled as in
+      the already mentioned boost-control-cutout, typically attained by pushing
+      the throttle past a mechanical 'gate' preventing its inadvertant use. This
+      was typically used for takeoff, and emergency situations, generally for
+      not more than five minutes.  This is a change in the boost control
+      setting, not the actual supercharger speed, and so would only give extra
+      power below the rated altitude.  When TAKEOFFBOOST is specified in the
+      config file (and is above RATEDBOOST1), then the throttle position is
+      interpreted as:
+
+    - 0 to 0.95 : idle manifold pressure to rated boost (where attainable)
+    - 0.96, 0.97, 0.98 : rated boost (where attainable).
+    - 0.99, 1.0 : takeoff boost (where attainable).
+
+    A typical takeoff boost for an earlyish Merlin was about 12psi, compared
+    with a rated boost of 9psi.
+
+    It is quite possible that other boost control settings could have been used
+    on some aircraft, or that takeoff/extra boost could have activated by other
+    means than pushing the throttle full forward through a gate, but this will
+    suffice for now.
+
+    Note that MAXMP is still the non-boosted max manifold pressure even for
+    boosted engines - effectively this is simply a measure of the pressure drop
+    through the fully open throttle.
+
     @author Jon S. Berndt (Engine framework code and framework-related mods)
     @author Dave Luff (engine operational code)
-    @author David Megginson (porting and additional code)
-    @version "$Id$"
+    @author David Megginson (initial porting and additional code)
+    @version $Id$
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -78,7 +146,10 @@ public:
   /// Destructor
   ~FGPiston();
 
-  double Calculate(double PowerRequired);
+  string GetEngineLabels(void);
+  string GetEngineValues(void);
+
+  double Calculate(void);
   double GetPowerAvailable(void) {return PowerAvailable;}
   double CalcFuelNeed(void);
 
@@ -92,7 +163,7 @@ public:
   double getCylinderHeadTemp_degF(void) {return KelvinToFahrenheit(CylinderHeadTemp_degK);}
   double getOilPressure_psi(void) const {return OilPressure_psi;}
   double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);}
-  double getRPM(void) {return RPM;} 
+  double getRPM(void) {return RPM;}
 
 private:
   int crank_counter;
@@ -107,7 +178,8 @@ private:
   double dt;
 
   void doEngineStartup(void);
-  void doManifoldPressure(void);
+  void doBoostControl(void);
+  void doMAP(void);
   void doAirFlow(void);
   void doFuelFlow(void);
   void doEnginePower(void);
@@ -138,6 +210,31 @@ private:
   double MaxHP;                    // horsepower
   double Cycles;                   // cycles/power stroke
   double IdleRPM;                  // revolutions per minute
+  int BoostSpeeds;     // Number of super/turbocharger boost speeds - zero implies no turbo/supercharging.
+  int BoostSpeed;      // The current boost-speed (zero-based).
+  bool Boosted;                // Set true for boosted engine.
+  int BoostOverride;   // The raw value read in from the config file - should be 1 or 0 - see description below.
+  bool bBoostOverride; // Set true if pilot override of the boost regulator was fitted.
+              // (Typically called 'war emergency power').
+  bool bTakeoffBoost;  // Set true if extra takeoff / emergency boost above rated boost could be attained.
+              // (Typically by extra throttle movement past a mechanical 'gate').
+  double TakeoffBoost; // Sea-level takeoff boost in psi. (if fitted).
+  double RatedBoost[FG_MAX_BOOST_SPEEDS];      // Sea-level rated boost in psi.
+  double RatedAltitude[FG_MAX_BOOST_SPEEDS];   // Altitude at which full boost is reached (boost regulation ends)
+                          // and at which power starts to fall with altitude [ft].
+  double RatedRPM[FG_MAX_BOOST_SPEEDS]; // Engine speed at which the rated power for each boost speed is delivered [rpm].
+  double RatedPower[FG_MAX_BOOST_SPEEDS];      // Power at rated throttle position at rated altitude [HP].
+  double BoostSwitchAltitude[FG_MAX_BOOST_SPEEDS - 1]; // Altitude at which switchover (currently assumed automatic)
+                              // from one boost speed to next occurs [ft].
+  double BoostSwitchPressure[FG_MAX_BOOST_SPEEDS - 1];  // Pressure at which boost speed switchover occurs [Pa]
+  double BoostMul[FG_MAX_BOOST_SPEEDS];        // Pressure multipier of unregulated supercharger
+  double RatedMAP[FG_MAX_BOOST_SPEEDS];        // Rated manifold absolute pressure [Pa] (BCV clamp)
+  double TakeoffMAP[FG_MAX_BOOST_SPEEDS];      // Takeoff setting manifold absolute pressure [Pa] (BCV clamp)
+  double BoostSwitchHysteresis;        // Pa.
+
+  double minMAP;  // Pa
+  double maxMAP;  // Pa
+  double MAP;     // Pa
 
   //
   // Inputs (in addition to those in FGEngine).
diff --git a/src/FDM/JSBSim/FGPosition.cpp b/src/FDM/JSBSim/FGPosition.cpp
deleted file mode 100644 (file)
index 28b83b8..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGPosition.cpp
- Author:       Jon S. Berndt
- Date started: 01/05/99
- Purpose:      Integrate the EOM to determine instantaneous position
- Called by:    FGFDMExec
-
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-This class encapsulates the integration of rates and accelerations to get the
-current position of the aircraft.
-
-HISTORY
---------------------------------------------------------------------------------
-01/05/99   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
-    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
-    School, January 1994
-[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
-    JSC 12960, July 1977
-[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
-    NASA-Ames", NASA CR-2497, January 1975
-[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
-    Wiley & Sons, 1979 ISBN 0-471-03032-5
-[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
-    1982 ISBN 0-471-08936-2
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <cmath>
-#    include <iomanip>
-#  else
-#    include <math.h>
-#    include <iomanip.h>
-#  endif
-#else
-#  if defined(sgi) && !defined(__GNUC__)
-#    include <math.h>
-#    if (_COMPILER_VERSION < 740)
-#      include <iomanip.h>
-#    else
-#      include <iomanip>
-#    endif
-#  else
-#    include <cmath>
-#    include <iomanip>
-#  endif
-#endif
-
-#include "FGPosition.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-#include "FGAircraft.h"
-#include "FGMassBalance.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGInertial.h"
-#include "FGPropertyManager.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_POSITION;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGPosition::FGPosition(FGFDMExec* fdmex) : FGModel(fdmex)
-{
-  Name = "FGPosition";
-  LongitudeDot = LatitudeDot = RadiusDot = 0.0;
-
-  for (int i=0;i<4;i++) {
-    LatitudeDot_prev[i]  = 0.0;
-    LongitudeDot_prev[i] = 0.0;
-    RadiusDot_prev[i]    = 0.0;
-  }
-
-  vVRPoffset.InitMatrix();
-
-  Longitude = Latitude = 0.0;
-  LongitudeVRP = LatitudeVRP = 0.0;
-  gamma = Vt = Vground = 0.0;
-  hoverbmac = hoverbcg = 0.0;
-  psigt = 0.0;
-  bind();
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPosition::~FGPosition(void)
-{
-  unbind();
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPosition::InitModel(void)
-{
-  FGModel::InitModel();
-
-  h = 3.0;                                 // Est. height of aircraft cg off runway
-  SeaLevelRadius = Inertial->RefRadius();  // For initialization ONLY
-  Radius         = SeaLevelRadius + h;
-  RunwayRadius   = SeaLevelRadius;
-  DistanceAGL    = Radius - RunwayRadius;  // Geocentric
-  vRunwayNormal(3) = -1.0;                 // Initialized for standalone mode
-  b = 1;
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/*
-Purpose: Called on a schedule to perform Positioning algorithms
-Notes:   [TP] Make sure that -Vt <= hdot <= Vt, which, of course, should always
-         be the case
-         [JB] Run in standalone mode, SeaLevelRadius will be reference radius.
-               In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass.
-*/
-
-bool FGPosition::Run(void)
-{
-  double cosLat;
-  double hdot_Vt;
-
-  if (!FGModel::Run()) {
-    GetState();
-
-    Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) );
-
-    if (vVel(eNorth) == 0) psigt = 0;
-    else psigt =  atan2(vVel(eEast), vVel(eNorth));
-
-    if (psigt < 0.0) psigt += 2*M_PI;
-
-    Radius    = h + SeaLevelRadius;
-
-    cosLat = cos(Latitude);
-    if (cosLat != 0) LongitudeDot = vVel(eEast) / (Radius * cosLat);
-    LatitudeDot = vVel(eNorth) / Radius;
-    RadiusDot   = -vVel(eDown);
-
-    Longitude += State->Integrate(FGState::TRAPZ, dt*rate, LongitudeDot, LongitudeDot_prev);
-    Latitude  += State->Integrate(FGState::TRAPZ, dt*rate, LatitudeDot, LatitudeDot_prev);
-    Radius    += State->Integrate(FGState::TRAPZ, dt*rate, RadiusDot, RadiusDot_prev);
-
-    h = Radius - SeaLevelRadius;           // Geocentric
-
-    vVRPoffset = State->GetTb2l() * MassBalance->StructuralToBody(Aircraft->GetXYZvrp());
-
-    // vVRP  - the vector to the Visual Reference Point - now contains the
-    // offset from the CG to the VRP, in units of feet, in the Local coordinate
-    // frame, where X points north, Y points East, and Z points down. This needs
-    // to be converted to Lat/Lon/Alt, now.
-
-    if (cosLat != 0)
-      LongitudeVRP = vVRPoffset(eEast) / (Radius * cosLat) + Longitude;
-
-    LatitudeVRP = vVRPoffset(eNorth) / Radius + Latitude;
-    hVRP = h - vVRPoffset(eDown);
-/*
-cout << "Lat/Lon/Alt : " << Latitude << " / " << Longitude << " / " << h << endl;
-cout << "Lat/Lon/Alt VRP: " << LatitudeVRP << " / " << LongitudeVRP << " / " << hVRP << endl << endl;
-*/
-    DistanceAGL = Radius - RunwayRadius;   // Geocentric
-
-    hoverbcg = DistanceAGL/b;
-
-    vMac = State->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp());
-    hoverbmac = (DistanceAGL + vMac(3)) / b;
-
-    if (Vt > 0) {
-      hdot_Vt = RadiusDot/Vt;
-      if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);
-    } else {
-      gamma = 0.0;
-    }
-
-    return false;
-
-  } else {
-    return true;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPosition::GetState(void)
-{
-  dt = State->Getdt();
-
-  Vt        = Translation->GetVt();
-  vVel      = State->GetTb2l() * Translation->GetUVW();
-  vVelDot   = State->GetTb2l() * Translation->GetUVWdot();
-
-  b = Aircraft->GetWingSpan();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPosition::Seth(double tt)
-{
- h = tt;
- Radius    = h + SeaLevelRadius;
- DistanceAGL = Radius - RunwayRadius;   // Geocentric
- hoverbcg = DistanceAGL/b;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPosition::SetDistanceAGL(double tt)
-{
-  DistanceAGL=tt;
-  Radius = RunwayRadius + DistanceAGL;
-  h = Radius - SeaLevelRadius;
-  hoverbcg = DistanceAGL/b;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPosition::bind(void)
-{
-  PropertyManager->Tie("velocities/v-north-fps", this,
-                       &FGPosition::GetVn);
-  PropertyManager->Tie("velocities/v-east-fps", this,
-                       &FGPosition::GetVe);
-  PropertyManager->Tie("velocities/v-down-fps", this,
-                       &FGPosition::GetVd);
-  PropertyManager->Tie("velocities/vg-fps", this,
-                       &FGPosition::GetVground);
-  PropertyManager->Tie("flight-path/psi-gt-rad", this,
-                       &FGPosition::GetGroundTrack);
-  PropertyManager->Tie("position/h-sl-ft", this,
-                       &FGPosition::Geth,
-                       &FGPosition::Seth,
-                       true);
-  PropertyManager->Tie("velocities/h-dot-fps", this,
-                       &FGPosition::Gethdot);
-  PropertyManager->Tie("position/lat-gc-rad", this,
-                       &FGPosition::GetLatitude,
-                       &FGPosition::SetLatitude);
-  PropertyManager->Tie("position/lat-dot-gc-rad", this,
-                       &FGPosition::GetLatitudeDot);
-  PropertyManager->Tie("position/long-gc-rad", this,
-                       &FGPosition::GetLongitude,
-                       &FGPosition::SetLongitude,
-                       true);
-  PropertyManager->Tie("position/long-dot-gc-rad", this,
-                       &FGPosition::GetLongitudeDot);
-  PropertyManager->Tie("metrics/runway-radius", this,
-                       &FGPosition::GetRunwayRadius,
-                       &FGPosition::SetRunwayRadius);
-  PropertyManager->Tie("position/h-agl-ft", this,
-                       &FGPosition::GetDistanceAGL,
-                       &FGPosition::SetDistanceAGL);
-  PropertyManager->Tie("position/radius-to-vehicle-ft", this,
-                       &FGPosition::GetRadius);
-  PropertyManager->Tie("flight-path/gamma-rad", this,
-                       &FGPosition::GetGamma,
-                       &FGPosition::SetGamma);
-  PropertyManager->Tie("aero/h_b-cg-ft", this,
-                       &FGPosition::GetHOverBCG);
-  PropertyManager->Tie("aero/h_b-mac-ft", this,
-                       &FGPosition::GetHOverBMAC);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPosition::unbind(void)
-{
-  PropertyManager->Untie("velocities/v-north-fps");
-  PropertyManager->Untie("velocities/v-east-fps");
-  PropertyManager->Untie("velocities/v-down-fps");
-  PropertyManager->Untie("velocities/vg-fps");
-  PropertyManager->Untie("flight-path/psi-gt-rad");
-  PropertyManager->Untie("position/h-sl-ft");
-  PropertyManager->Untie("velocities/h-dot-fps");
-  PropertyManager->Untie("position/lat-gc-rad");
-  PropertyManager->Untie("position/lat-dot-gc-rad");
-  PropertyManager->Untie("position/long-gc-rad");
-  PropertyManager->Untie("position/long-dot-gc-rad");
-  PropertyManager->Untie("metrics/runway-radius");
-  PropertyManager->Untie("position/h-agl-ft");
-  PropertyManager->Untie("position/radius-to-vehicle-ft");
-  PropertyManager->Untie("flight-path/gamma-rad");
-  PropertyManager->Untie("aero/h_b-cg-ft");
-  PropertyManager->Untie("aero/h_b-mac-ft");
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    The bitmasked value choices are as follows:
-//    unset: In this case (the default) JSBSim would only print
-//       out the normally expected messages, essentially echoing
-//       the config files as they are read. If the environment
-//       variable is not set, debug_lvl is set to 1 internally
-//    0: This requests JSBSim not to output any messages
-//       whatsoever.
-//    1: This value explicity requests the normal JSBSim
-//       startup messages
-//    2: This value asks for a message to be printed out when
-//       a class is instantiated
-//    4: When this value is set, a message is displayed when a
-//       FGModel object executes its Run() method
-//    8: When this value is set, various runtime state variables
-//       are printed out periodically
-//    16: When set various parameters are sanity checked and
-//       a message is printed out when they go out of bounds
-
-void FGPosition::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGPosition" << endl;
-    if (from == 1) cout << "Destroyed:    FGPosition" << endl;
-  }
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
-  }
-  if (debug_lvl & 8 ) { // Runtime state variables
-  }
-  if (debug_lvl & 16) { // Sanity checking
-  }
-  if (debug_lvl & 64) {
-    if (from == 0) { // Constructor
-      cout << IdSrc << endl;
-      cout << IdHdr << endl;
-    }
-  }
-}
-}
diff --git a/src/FDM/JSBSim/FGPosition.h b/src/FDM/JSBSim/FGPosition.h
deleted file mode 100644 (file)
index 009ebc1..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGPosition.h
- Author:       Jon S. Berndt
- Date started: 1/5/99
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-HISTORY
---------------------------------------------------------------------------------
-01/05/99   JSB   Created
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGPOSITION_H
-#define FGPOSITION_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGModel.h"
-#include "FGColumnVector3.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_POSITION "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models the lateral and longitudinal translational EOM.
-    @author Jon S. Berndt
-    @version $Id$
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGPosition : public FGModel {
-public:
-  /** Constructor
-      @param Executive a pointer to the parent executive object */
-  FGPosition(FGFDMExec* Executive);
-
-  /// Destructor
-  ~FGPosition();
-
-  bool InitModel(void);
-
-  /** Runs the Position model; called by the Executive
-      @see JSBSim.cpp documentation
-      @return false if no error */
-  bool Run(void);
-  
-  inline FGColumnVector3& GetVel(void) { return vVel; }
-  inline FGColumnVector3& GetVelDot(void) { return vVelDot; }
-  inline double GetVn(void)  const { return vVel(eX); }
-  inline double GetVe(void)  const { return vVel(eY); }
-  inline double GetVd(void)  const { return vVel(eZ); }
-  inline double GetVground(void) const { return Vground; }
-  inline double GetGroundTrack(void) const { return psigt; }
-  inline double Geth(void)  const { return h; }
-  inline double GethVRP(void)  const { return hVRP; }
-  inline double Gethdot(void) const { return RadiusDot; }
-  inline double GetLatitude(void) const { return Latitude; }
-  inline double GetLatitudeVRP(void) const { return LatitudeVRP; }
-  inline double GetLatitudeDot(void) const { return LatitudeDot; }
-  inline double GetLongitude(void) const { return Longitude; }
-  inline double GetLongitudeVRP(void) const { return LongitudeVRP; }
-  inline double GetLongitudeDot(void) const { return LongitudeDot; }
-  inline double GetRunwayRadius(void) const { return RunwayRadius; }
-  inline double GetDistanceAGL(void)  const { return DistanceAGL; }
-  inline double GetRadius(void) const { return Radius; }
-  inline FGColumnVector3& GetRunwayNormal(void) { return vRunwayNormal; }
-  
-  inline double GetGamma(void) const { return gamma; }
-  inline void SetGamma(double tt) { gamma = tt; }
-  inline double GetHOverBCG(void) const { return hoverbcg; }
-  inline double GetHOverBMAC(void) const { return hoverbmac; }
-  void SetvVel(const FGColumnVector3& v) { vVel = v; }
-  void SetLatitude(double tt) { Latitude = tt; }
-  void SetLongitude(double tt) { Longitude = tt; }
-  void Seth(double tt);
-  void SetRunwayRadius(double tt) { RunwayRadius = tt; }
-  void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt;}
-  void SetDistanceAGL(double tt);
-  inline void SetRunwayNormal(double fgx, double fgy, double fgz ) {
-      vRunwayNormal << fgx << fgy << fgz;
-  }
-  void SetVRP(FGColumnVector3& vrp) {vVRP = vrp;}
-  
-  void bind(void);
-  void unbind(void);
-  
-private:  
-  FGColumnVector3 vVel;
-  FGColumnVector3 vVelDot;
-  FGColumnVector3 vRunwayNormal;
-  FGColumnVector3 vVRP;
-  FGColumnVector3 vVRPoffset;
-  FGColumnVector3 vMac;
-  
-  double Radius, h, hVRP;
-  double LatitudeDot, LongitudeDot, RadiusDot;
-  double LatitudeDot_prev[4], LongitudeDot_prev[4], RadiusDot_prev[4];
-  double Longitude, Latitude;
-  double LongitudeVRP, LatitudeVRP;
-  double dt;
-  double RunwayRadius;
-  double DistanceAGL;
-  double SeaLevelRadius;
-  double gamma;
-  double Vt, Vground;
-  double hoverbcg,hoverbmac,b;
-
-  double psigt;
-
-  void GetState(void);
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGPropagate.cpp b/src/FDM/JSBSim/FGPropagate.cpp
new file mode 100644 (file)
index 0000000..e971840
--- /dev/null
@@ -0,0 +1,380 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGPropagate.cpp
+ Author:       Jon S. Berndt
+ Date started: 01/05/99
+ Purpose:      Integrate the EOM to determine instantaneous position
+ Called by:    FGFDMExec
+
+ ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+This class encapsulates the integration of rates and accelerations to get the
+current position of the aircraft.
+
+HISTORY
+--------------------------------------------------------------------------------
+01/05/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
+    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
+    School, January 1994
+[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
+    JSC 12960, July 1977
+[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
+    NASA-Ames", NASA CR-2497, January 1975
+[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
+    Wiley & Sons, 1979 ISBN 0-471-03032-5
+[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
+    1982 ISBN 0-471-08936-2
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <cmath>
+#    include <iomanip>
+#  else
+#    include <math.h>
+#    include <iomanip.h>
+#  endif
+#else
+#  if defined(sgi) && !defined(__GNUC__)
+#    include <math.h>
+#    if (_COMPILER_VERSION < 740)
+#      include <iomanip.h>
+#    else
+#      include <iomanip>
+#    endif
+#  else
+#    include <cmath>
+#    include <iomanip>
+#  endif
+#endif
+
+#include "FGPropagate.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+#include "FGAircraft.h"
+#include "FGMassBalance.h"
+#include "FGInertial.h"
+#include "FGPropertyManager.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_PROPAGATE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGPropagate";
+
+  bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPropagate::~FGPropagate(void)
+{
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropagate::InitModel(void)
+{
+  FGModel::InitModel();
+
+  SeaLevelRadius = Inertial->RefRadius();          // For initialization ONLY
+  RunwayRadius   = SeaLevelRadius;
+
+  VState.vLocation.SetRadius( SeaLevelRadius + 4.0 );
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
+{
+  SeaLevelRadius = FGIC->GetSeaLevelRadiusFtIC();
+  RunwayRadius = FGIC->GetSeaLevelRadiusFtIC() + FGIC->GetTerrainAltitudeFtIC();
+
+  // Set the position lat/lon/radius
+  VState.vLocation = FGLocation( FGIC->GetLongitudeRadIC(),
+                          FGIC->GetLatitudeRadIC(),
+                          FGIC->GetAltitudeFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
+
+  // Set the Orientation from the euler angles
+  VState.vQtrn = FGQuaternion( FGIC->GetPhiRadIC(),
+                        FGIC->GetThetaRadIC(),
+                        FGIC->GetPsiRadIC() );
+
+  // Set the velocities in the instantaneus body frame
+  VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(),
+                          FGIC->GetVBodyFpsIC(),
+                          FGIC->GetWBodyFpsIC() );
+
+  // Set the angular velocities in the instantaneus body frame.
+  VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
+                          FGIC->GetQRadpsIC(),
+                          FGIC->GetRRadpsIC() );
+
+  // Compute some derived values.
+  vVel = VState.vQtrn.GetTInv()*VState.vUVW;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/*
+Purpose: Called on a schedule to perform EOM integration
+Notes:   [JB] Run in standalone mode, SeaLevelRadius will be reference radius.
+         In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass.
+
+At the top of this Run() function, see several "shortcuts" (or, aliases) being
+set up for use later, rather than using the longer class->function() notation.
+
+Here, propagation of state is done using a simple explicit Euler scheme (see the
+bottom of the function). This propagation is done using the current state values
+and current derivatives. Based on these values we compute an approximation to the
+state values for (now + dt).
+
+*/
+
+bool FGPropagate::Run(void)
+{
+  if (FGModel::Run()) return true;  // Fast return if we have nothing to do ...
+
+  double dt = State->Getdt()*rate;  // The 'stepsize'
+  const FGColumnVector3 omega( 0.0, 0.0, Inertial->omega() ); // earth rotation
+  const FGColumnVector3& vForces = Aircraft->GetForces();     // current forces
+  const FGColumnVector3& vMoments = Aircraft->GetMoments();   // current moments
+
+  double mass = MassBalance->GetMass();             // mass
+  const FGMatrix33& J = MassBalance->GetJ();        // inertia matrix
+  const FGMatrix33& Jinv = MassBalance->GetJinv();  // inertia matrix inverse
+  double r = GetRadius();                           // radius
+  if (r == 0.0) {cerr << "radius = 0 !" << endl; r = 1e-16;} // radius check
+  double rInv = 1.0/r;
+  FGColumnVector3 gAccel( 0.0, 0.0, Inertial->GetGAccel(r) );
+
+  // The rotation matrices:
+  const FGMatrix33& Tl2b = GetTl2b();  // local to body frame
+  const FGMatrix33& Tb2l = GetTb2l();  // body to local frame
+  const FGMatrix33& Tec2l = VState.vLocation.GetTec2l();  // earth centered to local frame
+  const FGMatrix33& Tl2ec = VState.vLocation.GetTl2ec();  // local to earth centered frame
+
+  // Inertial angular velocity measured in the body frame.
+  const FGColumnVector3 pqri = VState.vPQR + Tl2b*(Tec2l*omega);
+
+  // Compute vehicle velocity wrt EC frame, expressed in Local horizontal frame.
+  vVel = Tb2l * VState.vUVW;
+
+  // First compute the time derivatives of the vehicle state values:
+
+  // Compute body frame rotational accelerations based on the current body moments
+  vPQRdot = Jinv*(vMoments - pqri*(J*pqri));
+
+  // Compute body frame accelerations based on the current body forces
+  vUVWdot = VState.vUVW*VState.vPQR + vForces/mass;
+
+  // Centrifugal acceleration.
+  FGColumnVector3 ecVel = Tl2ec*vVel;
+  FGColumnVector3 ace = 2.0*omega*ecVel;
+  vUVWdot -= Tl2b*(Tec2l*ace);
+
+  // Coriolis acceleration.
+  FGColumnVector3 aeec = omega*(omega*VState.vLocation);
+  vUVWdot -= Tl2b*(Tec2l*aeec);
+
+  // Gravitation accel
+  vUVWdot += Tl2b*gAccel;
+
+  // Compute vehicle velocity wrt EC frame, expressed in EC frame
+  FGColumnVector3 vLocationDot = Tl2ec * vVel;
+
+  FGColumnVector3 omegaLocal( rInv*vVel(eEast),
+                              -rInv*vVel(eNorth),
+                              -rInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
+
+  // Compute quaternion orientation derivative on current body rates
+  FGQuaternion vQtrndot = VState.vQtrn.GetQDot( VState.vPQR - Tl2b*omegaLocal );
+
+  // Propagate velocities
+  VState.vPQR += dt*vPQRdot;
+  VState.vUVW += dt*vUVWdot;
+
+  // Propagate positions
+  VState.vQtrn += dt*vQtrndot;
+  VState.vLocation += dt*vLocationDot;
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::Seth(double tt)
+{
+  VState.vLocation.SetRadius( tt + SeaLevelRadius );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::SetDistanceAGL(double tt)
+{
+  VState.vLocation.SetRadius( tt + RunwayRadius );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::bind(void)
+{
+  typedef double (FGPropagate::*PMF)(int) const;
+  PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot);
+
+  PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel);
+  PropertyManager->Tie("velocities/v-east-fps", this, eEast, (PMF)&FGPropagate::GetVel);
+  PropertyManager->Tie("velocities/v-down-fps", this, eDown, (PMF)&FGPropagate::GetVel);
+
+  PropertyManager->Tie("velocities/u-fps", this, eU, (PMF)&FGPropagate::GetUVW);
+  PropertyManager->Tie("velocities/v-fps", this, eV, (PMF)&FGPropagate::GetUVW);
+  PropertyManager->Tie("velocities/w-fps", this, eW, (PMF)&FGPropagate::GetUVW);
+
+  PropertyManager->Tie("velocities/p-rad_sec", this, eP, (PMF)&FGPropagate::GetPQR);
+  PropertyManager->Tie("velocities/q-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQR);
+  PropertyManager->Tie("velocities/r-rad_sec", this, eR, (PMF)&FGPropagate::GetPQR);
+
+  PropertyManager->Tie("accelerations/pdot-rad_sec", this, eP, (PMF)&FGPropagate::GetPQRdot);
+  PropertyManager->Tie("accelerations/qdot-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQRdot);
+  PropertyManager->Tie("accelerations/rdot-rad_sec", this, eR, (PMF)&FGPropagate::GetPQRdot);
+
+  PropertyManager->Tie("accelerations/udot-fps", this, eU, (PMF)&FGPropagate::GetUVWdot);
+  PropertyManager->Tie("accelerations/vdot-fps", this, eV, (PMF)&FGPropagate::GetUVWdot);
+  PropertyManager->Tie("accelerations/wdot-fps", this, eW, (PMF)&FGPropagate::GetUVWdot);
+
+  PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::Geth, &FGPropagate::Seth, true);
+  PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude);
+  PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude);
+  PropertyManager->Tie("position/h-agl-ft", this,  &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL);
+  PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius);
+
+  PropertyManager->Tie("metrics/runway-radius", this, &FGPropagate::GetRunwayRadius, &FGPropagate::SetRunwayRadius);
+
+  PropertyManager->Tie("attitude/phi-rad", this, &FGPropagate::Getphi);
+  PropertyManager->Tie("attitude/theta-rad", this, &FGPropagate::Gettht);
+  PropertyManager->Tie("attitude/psi-rad", this, &FGPropagate::Getpsi);
+
+  PropertyManager->Tie("attitude/roll-rad", this, &FGPropagate::Getphi);
+  PropertyManager->Tie("attitude/pitch-rad", this, &FGPropagate::Gettht);
+  PropertyManager->Tie("attitude/heading-true-rad", this, &FGPropagate::Getpsi);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::unbind(void)
+{
+  PropertyManager->Untie("velocities/v-north-fps");
+  PropertyManager->Untie("velocities/v-east-fps");
+  PropertyManager->Untie("velocities/v-down-fps");
+  PropertyManager->Untie("velocities/h-dot-fps");
+  PropertyManager->Untie("velocities/u-fps");
+  PropertyManager->Untie("velocities/v-fps");
+  PropertyManager->Untie("velocities/w-fps");
+  PropertyManager->Untie("velocities/p-rad_sec");
+  PropertyManager->Untie("velocities/q-rad_sec");
+  PropertyManager->Untie("velocities/r-rad_sec");
+  PropertyManager->Untie("accelerations/udot-fps");
+  PropertyManager->Untie("accelerations/vdot-fps");
+  PropertyManager->Untie("accelerations/wdot-fps");
+  PropertyManager->Untie("accelerations/pdot-rad_sec");
+  PropertyManager->Untie("accelerations/qdot-rad_sec");
+  PropertyManager->Untie("accelerations/rdot-rad_sec");
+  PropertyManager->Untie("position/h-sl-ft");
+  PropertyManager->Untie("position/lat-gc-rad");
+  PropertyManager->Untie("position/long-gc-rad");
+  PropertyManager->Untie("position/h-agl-ft");
+  PropertyManager->Untie("position/radius-to-vehicle-ft");
+  PropertyManager->Untie("metrics/runway-radius");
+  PropertyManager->Untie("attitude/phi-rad");
+  PropertyManager->Untie("attitude/theta-rad");
+  PropertyManager->Untie("attitude/psi-rad");
+  PropertyManager->Untie("attitude/roll-rad");
+  PropertyManager->Untie("attitude/pitch-rad");
+  PropertyManager->Untie("attitude/heading-true-rad");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    The bitmasked value choices are as follows:
+//    unset: In this case (the default) JSBSim would only print
+//       out the normally expected messages, essentially echoing
+//       the config files as they are read. If the environment
+//       variable is not set, debug_lvl is set to 1 internally
+//    0: This requests JSBSim not to output any messages
+//       whatsoever.
+//    1: This value explicity requests the normal JSBSim
+//       startup messages
+//    2: This value asks for a message to be printed out when
+//       a class is instantiated
+//    4: When this value is set, a message is displayed when a
+//       FGModel object executes its Run() method
+//    8: When this value is set, various runtime state variables
+//       are printed out periodically
+//    16: When set various parameters are sanity checked and
+//       a message is printed out when they go out of bounds
+
+void FGPropagate::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGPropagate" << endl;
+    if (from == 1) cout << "Destroyed:    FGPropagate" << endl;
+  }
+  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
+  }
+  if (debug_lvl & 8 ) { // Runtime state variables
+  }
+  if (debug_lvl & 16) { // Sanity checking
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+}
diff --git a/src/FDM/JSBSim/FGPropagate.h b/src/FDM/JSBSim/FGPropagate.h
new file mode 100644 (file)
index 0000000..4208767
--- /dev/null
@@ -0,0 +1,176 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGPropagate.h
+ Author:       Jon S. Berndt
+ Date started: 1/5/99
+
+ ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+--------------------------------------------------------------------------------
+01/05/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGPROPAGATE_H
+#define FGPROPAGATE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGModel.h"
+#include "FGColumnVector3.h"
+#include "FGInitialCondition.h"
+#include "FGLocation.h"
+#include "FGQuaternion.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_PROPAGATE "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models the EOM and integration/propagation of state
+    @author Jon S. Berndt, Mathias Froehlich
+    @version $Id$
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+// state vector
+
+struct VehicleState {
+  FGLocation vLocation;
+  FGColumnVector3 vUVW;
+  FGColumnVector3 vPQR;
+  FGQuaternion vQtrn;
+};
+
+class FGPropagate : public FGModel {
+public:
+  /** Constructor
+      @param Executive a pointer to the parent executive object */
+  FGPropagate(FGFDMExec* Executive);
+
+  /// Destructor
+  ~FGPropagate();
+
+  bool InitModel(void);
+
+  /** Runs the Propagate model; called by the Executive
+      @return false if no error */
+  bool Run(void);
+
+  const FGColumnVector3& GetVel(void) const { return vVel; }
+  const FGColumnVector3& GetUVW(void) const { return VState.vUVW; }
+  const FGColumnVector3& GetUVWdot(void) const { return vUVWdot; }
+  const FGColumnVector3& GetPQR(void) const {return VState.vPQR;}
+  const FGColumnVector3& GetPQRdot(void) const {return vPQRdot;}
+  const FGColumnVector3& GetEuler(void) const { return VState.vQtrn.GetEuler(); }
+
+  double GetUVW   (int idx) const { return VState.vUVW(idx); }
+  double GetUVWdot(int idx) const { return vUVWdot(idx); }
+  double GetVel(int idx) const { return vVel(idx); }
+  double Geth(void)   const { return VState.vLocation.GetRadius() - SeaLevelRadius; }
+  double GetPQR(int axis) const {return VState.vPQR(axis);}
+  double GetPQRdot(int idx) const {return vPQRdot(idx);}
+  double GetEuler(int axis) const { return VState.vQtrn.GetEuler()(axis); }
+  double Gethdot(void) const { return -vVel(eDown); }
+
+  /** Returns the "constant" RunwayRadius.
+      The RunwayRadius parameter is set by the calling application or set to
+      zero if JSBSim is running in standalone mode.
+      @return distance of the runway from the center of the earth.
+      @units feet */
+  double GetRunwayRadius(void) const { return RunwayRadius; }
+  double GetSeaLevelRadius(void) const { return SeaLevelRadius; }
+  double GetDistanceAGL(void)  const { return VState.vLocation.GetRadius()-RunwayRadius; }
+  double GetRadius(void) const { return VState.vLocation.GetRadius(); }
+  double GetLongitude(void) const { return VState.vLocation.GetLongitude(); }
+  double GetLatitude(void) const { return VState.vLocation.GetLatitude(); }
+  const FGLocation& GetLocation(void) const { return VState.vLocation; }
+
+  double Getphi(void) const { return VState.vQtrn.GetEulerPhi(); }
+  double Gettht(void) const { return VState.vQtrn.GetEulerTheta(); }
+  double Getpsi(void) const { return VState.vQtrn.GetEulerPsi(); }
+
+  double GetCosphi(void) const { return VState.vQtrn.GetCosEulerPhi(); }
+  double GetCostht(void) const { return VState.vQtrn.GetCosEulerTheta(); }
+  double GetCospsi(void) const { return VState.vQtrn.GetCosEulerPsi(); }
+
+  double GetSinphi(void) const { return VState.vQtrn.GetSinEulerPhi(); }
+  double GetSintht(void) const { return VState.vQtrn.GetSinEulerTheta(); }
+  double GetSinpsi(void) const { return VState.vQtrn.GetSinEulerPsi(); }
+
+  /** Retrieves the local-to-body transformation matrix.
+      @return a reference to the local-to-body transformation matrix.  */
+  const FGMatrix33& GetTl2b(void) const { return VState.vQtrn.GetT(); }
+
+  /** Retrieves the body-to-local transformation matrix.
+      @return a reference to the body-to-local matrix.  */
+  const FGMatrix33& GetTb2l(void) const { return VState.vQtrn.GetTInv(); }
+
+// SET functions
+
+  void SetLongitude(double lon) { VState.vLocation.SetLongitude(lon); }
+  void SetLatitude(double lat) { VState.vLocation.SetLatitude(lat); }
+  void SetRadius(double r) { VState.vLocation.SetRadius(r); }
+  void SetLocation(const FGLocation& l) { VState.vLocation = l; }
+  void Seth(double tt);
+  void SetRunwayRadius(double tt) { RunwayRadius = tt; }
+  void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
+  void SetDistanceAGL(double tt);
+  void SetInitialState(const FGInitialCondition *);
+
+  void bind(void);
+  void unbind(void);
+
+private:
+
+// state vector
+
+  struct VehicleState VState;
+
+  FGColumnVector3 vVel;
+  FGColumnVector3 vPQRdot;
+  FGColumnVector3 vUVWdot;
+
+  double RunwayRadius, SeaLevelRadius;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
index 3ad669e14584806bc29615c8b847eaf9b499e4c5..9b352bc55cbc907dbe069de84ecd828c67d1c23f 100644 (file)
@@ -35,11 +35,12 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <sstream>
+
 #include "FGPropeller.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGFCS.h"
+#include "FGPropagate.h"
 #include "FGAtmosphere.h"
+#include "FGAuxiliary.h"
 
 namespace JSBSim {
 
@@ -50,9 +51,9 @@ static const char *IdHdr = ID_PROPELLER;
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-// This class currently makes certain assumptions when calculating torque and 
+// This class currently makes certain assumptions when calculating torque and
 // p-factor. That is, that the axis of rotation is the X axis of the aircraft -
-// not just the X-axis of the engine/propeller. This may or may not work for a 
+// not just the X-axis of the engine/propeller. This may or may not work for a
 // helicopter.
 
 FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(exec)
@@ -60,7 +61,7 @@ FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg) : FGThruster(e
   string token;
   int rows, cols;
 
-  MaxPitch = MinPitch = P_Factor = Sense = Pitch = 0.0;
+  MaxPitch = MinPitch = P_Factor = Sense = Pitch = Advance = 0.0;
   GearRatio = 1.0;
 
   Name = Prop_cfg->GetValue("NAME");
@@ -135,7 +136,7 @@ FGPropeller::~FGPropeller()
 double FGPropeller::Calculate(double PowerAvailable)
 {
   double J, C_Thrust, omega;
-  double Vel = fdmex->GetTranslation()->GetAeroUVW(eU);
+  double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU);
   double rho = fdmex->GetAtmosphere()->GetDensity();
   double RPS = RPM/60.0;
   double alpha, beta;
@@ -153,8 +154,8 @@ double FGPropeller::Calculate(double PowerAvailable)
   }
 
   if (P_Factor > 0.0001) {
-    alpha = fdmex->GetTranslation()->Getalpha();
-    beta  = fdmex->GetTranslation()->Getbeta();
+    alpha = fdmex->GetAuxiliary()->Getalpha();
+    beta  = fdmex->GetAuxiliary()->Getbeta();
     SetActingLocationY( GetLocationY() + P_Factor*alpha*Sense);
     SetActingLocationZ( GetLocationZ() + P_Factor*beta*Sense);
   } else if (P_Factor < 0.000) {
@@ -164,12 +165,6 @@ double FGPropeller::Calculate(double PowerAvailable)
   Thrust = C_Thrust*RPS*RPS*Diameter*Diameter*Diameter*Diameter*rho;
   omega = RPS*2.0*M_PI;
 
-  // Check for windmilling.
-  double radius = Diameter * 0.375; // 75% of radius
-  double windmill_cutoff = tan(Pitch * 1.745329E-2) * omega * radius;
-  if (Vel > windmill_cutoff)
-    Thrust = -Thrust;
-
   vFn(1) = Thrust;
 
   // The Ixx value and rotation speed given below are for rotation about the
@@ -185,13 +180,13 @@ double FGPropeller::Calculate(double PowerAvailable)
   ExcessTorque = PowerAvailable / omega * GearRatio;
   RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0;
 
-                               // The friction from the engine should
-                               // stop it somewhere; I chose an
-                               // arbitrary point.
+        // The friction from the engine should
+        // stop it somewhere; I chose an
+        // arbitrary point.
   if (RPM < 5.0)
     RPM = 0;
 
-  vMn = fdmex->GetRotation()->GetPQR()*vH + vTorque*Sense;
+  vMn = fdmex->GetPropagate()->GetPQR()*vH + vTorque*Sense;
 
   return Thrust; // return thrust in pounds
 }
@@ -204,17 +199,16 @@ double FGPropeller::GetPowerRequired(void)
 
   double cPReq, RPS = RPM / 60.0;
 
-  double J = fdmex->GetTranslation()->GetAeroUVW(eU) / (Diameter * RPS);
+  double J = fdmex->GetAuxiliary()->GetAeroUVW(eU) / (Diameter * RPS);
   double rho = fdmex->GetAtmosphere()->GetDensity();
 
   if (MaxPitch == MinPitch) { // Fixed pitch prop
     Pitch = MinPitch;
     cPReq = cPower->GetValue(J);
   } else {                    // Variable pitch prop
-    double advance = fdmex->GetFCS()->GetPropAdvance(ThrusterNumber);
 
     if (MaxRPM != MinRPM) {   // fixed-speed prop
-      double rpmReq = MinRPM + (MaxRPM - MinRPM) * advance;
+      double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
       double dRPM = rpmReq - RPM;
 
       Pitch -= dRPM / 10;
@@ -223,7 +217,7 @@ double FGPropeller::GetPowerRequired(void)
       else if (Pitch > MaxPitch)  Pitch = MaxPitch;
 
     } else {
-      Pitch = MinPitch + (MaxPitch - MinPitch) * advance;
+      Pitch = MinPitch + (MaxPitch - MinPitch) * Advance;
     }
     cPReq = cPower->GetValue(J, Pitch);
   }
@@ -247,6 +241,41 @@ FGColumnVector3 FGPropeller::GetPFactor()
   return FGColumnVector3(px, py, pz);
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropeller::GetThrusterLabels(int id)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_Torque[" << id << "], "
+      << Name << "_PFactor_Pitch[" << id << "], "
+      << Name << "_PFactor_Yaw[" << id << "], "
+      << Name << "_Thrust[" << id << "], ";
+  if (IsVPitch())
+    buf << Name << "_Pitch[" << id << "], ";
+  buf << Name << "_RPM[" << id << "]";
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropeller::GetThrusterValues(int id)
+{
+  std::ostringstream buf;
+
+  FGColumnVector3 vPFactor = GetPFactor();
+  buf << vTorque(eX) << ", "
+      << vPFactor(ePitch) << ", "
+      << vPFactor(eYaw) << ", "
+      << Thrust << ", ";
+  if (IsVPitch())
+    buf << Pitch << ", ";
+  buf << RPM;
+
+  return buf.str();
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
index 25575c5559fea6d5fa4347f6bb03516eac565884..cc026049cf9479a369c649bab381391c38af5919 100644 (file)
@@ -114,6 +114,8 @@ public:
       @param pitch the pitch of the blade in degrees. */
   void SetPitch(double pitch) {Pitch = pitch;}
 
+  void SetAdvance(double advance) {Advance = advance;}
+
   /// Sets the P-Factor constant
   void SetPFactor(double pf) {P_Factor = pf;}
 
@@ -125,21 +127,21 @@ public:
 
   /// Retrieves the pitch of the propeller in degrees.
   double GetPitch(void)         { return Pitch;         }
-  
+
   /// Retrieves the RPMs of the propeller
   double GetRPM(void)           { return RPM;           }
-  
+
   /// Retrieves the propeller moment of inertia
   double GetIxx(void)           { return Ixx;           }
-  
+
   /// Retrieves the Torque in foot-pounds (Don't you love the English system?)
   double GetTorque(void)        { return vTorque(eX);    }
-  
+
   /** Retrieves the power required (or "absorbed") by the propeller -
       i.e. the power required to keep spinning the propeller at the current
       velocity, air density,  and rotational rate. */
   double GetPowerRequired(void);
-  
+
   /** Calculates and returns the thrust produced by this propeller.
       Given the excess power available from the engine (in foot-pounds), the thrust is
       calculated, as well as the current RPM. The RPM is calculated by integrating
@@ -151,6 +153,8 @@ public:
       @return the thrust in pounds */
   double Calculate(double PowerAvailable);
   FGColumnVector3 GetPFactor(void);
+  string GetThrusterLabels(int id);
+  string GetThrusterValues(int id);
 
 private:
   int   numBlades;
@@ -164,6 +168,7 @@ private:
   double P_Factor;
   double Sense;
   double Pitch;
+  double Advance;
   double ExcessTorque;
   FGColumnVector3 vTorque;
   FGTable *cThrust;
index bd6f404ac52dfd0f7724f1051ce8d6ecdf408edd..a7a31a38b4f4e7415863a55098ab4f261f6fe84b 100644 (file)
@@ -3,7 +3,7 @@
  Module:       FGPropulsion.cpp
  Author:       Jon S. Berndt
  Date started: 08/20/00
- Purpose:      Encapsulates the set of engines, tanks, and thrusters associated
+ Purpose:      Encapsulates the set of engines and tanks associated
                with this aircraft
 
  ------------- Copyright (C) 2000  Jon S. Berndt (jsb@hal-pc.org) -------------
 FUNCTIONAL DESCRIPTION
 --------------------------------------------------------------------------------
 The Propulsion class is the container for the entire propulsion system, which is
-comprised of engines, tanks, and "thrusters" (the device that transforms the
-engine power into a force that acts on the aircraft, such as a nozzle or
-propeller). Once the Propulsion class gets the config file, it reads in
-information which is specific to a type of engine. Then:
+comprised of engines and tanks. Once the Propulsion class gets the config file,
+it reads in information which is specific to a type of engine. Then:
 
 1) The appropriate engine type instance is created
-2) A thruster object is instantiated, and is linked to the engine
-3) At least one tank object is created, and is linked to an engine.
+2) At least one tank object is created, and is linked to an engine.
 
-At Run time each engines Calculate() method is called to return the excess power
-generated during that iteration. The drag from the previous iteration is sub-
-tracted to give the excess power available for thrust this pass. That quantity
-is passed to the thrusters associated with a particular engine - perhaps with a
-scaling mechanism (gearing?) to allow the engine to give its associated thrust-
-ers specific distributed portions of the excess power.
+At Run time each engines Calculate() method is called.
 
 HISTORY
 --------------------------------------------------------------------------------
@@ -54,22 +46,11 @@ INCLUDES
 
 #include "FGPropulsion.h"
 #include "FGRocket.h"
-#include "FGSimTurbine.h"
 #include "FGTurbine.h"
-#include "FGPropeller.h"
-#include "FGNozzle.h"
 #include "FGPiston.h"
+#include "FGElectric.h"
 #include "FGPropertyManager.h"
 
-#if defined (__APPLE__)
-/* Not all systems have the gcvt function */
-inline char* gcvt (double value, int ndigits, char *buf) {
-    /* note that this is not exactly what gcvt is supposed to do! */
-    snprintf (buf, ndigits+1, "%f", value);
-    return buf;
-}
-#endif
-
 namespace JSBSim {
 
 static const char *IdSrc = "$Id$";
@@ -87,11 +68,11 @@ FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
   Name = "FGPropulsion";
 
   numSelectedFuelTanks = numSelectedOxiTanks = 0;
-  numTanks = numEngines = numThrusters = 0;
+  numTanks = numEngines = 0;
   numOxiTanks = numFuelTanks = 0;
-  dt = 0.0;
   ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
   tankJ.InitMatrix();
+  refuel = false;
 
   bind();
 
@@ -112,34 +93,33 @@ FGPropulsion::~FGPropulsion()
 
 bool FGPropulsion::Run(void)
 {
-  double PowerAvailable;
-  dt = State->Getdt();
+  if (FGModel::Run()) return true;
+
+  double dt = State->Getdt();
 
   vForces.InitMatrix();
   vMoments.InitMatrix();
 
-  if (!FGModel::Run()) {
-    for (unsigned int i=0; i<numEngines; i++) {
-      Thrusters[i]->SetdeltaT(dt*rate);
-      PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
-      Thrusters[i]->Calculate(PowerAvailable);
-      vForces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
-      vMoments += Thrusters[i]->GetMoments();     // sum body frame moments
-    }
-
-    return false;
-  } else {
-    return true;
+  for (unsigned int i=0; i<numEngines; i++) {
+    Engines[i]->Calculate();
+    vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
+    vMoments += Engines[i]->GetMoments();     // sum body frame moments
   }
+
+  for (unsigned int i=0; i<numTanks; i++) {
+    Tanks[i]->Calculate( dt * rate );
+  }     
+
+  if (refuel) DoRefuel( dt * rate );
+
+  return false;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 bool FGPropulsion::GetSteadyState(void)
 {
-  double PowerAvailable;
   double currentThrust = 0, lastThrust=-1;
-  dt = State->Getdt();
   int steady_count,j=0;
   bool steady=false;
 
@@ -149,13 +129,12 @@ bool FGPropulsion::GetSteadyState(void)
   if (!FGModel::Run()) {
     for (unsigned int i=0; i<numEngines; i++) {
       Engines[i]->SetTrimMode(true);
-      Thrusters[i]->SetdeltaT(dt*rate);
       steady=false;
       steady_count=0;
       while (!steady && j < 6000) {
-        PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
+        Engines[i]->Calculate();
         lastThrust = currentThrust;
-        currentThrust = Thrusters[i]->Calculate(PowerAvailable);
+        currentThrust = Engines[i]->GetThrust();
         if (fabs(lastThrust-currentThrust) < 0.0001) {
           steady_count++;
           if (steady_count > 120) { steady=true; }
@@ -164,8 +143,8 @@ bool FGPropulsion::GetSteadyState(void)
         }
         j++;
       }
-      vForces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
-      vMoments += Thrusters[i]->GetMoments();     // sum body frame moments
+      vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
+      vMoments += Engines[i]->GetMoments();     // sum body frame moments
       Engines[i]->SetTrimMode(false);
     }
 
@@ -179,24 +158,20 @@ bool FGPropulsion::GetSteadyState(void)
 
 bool FGPropulsion::ICEngineStart(void)
 {
-  double PowerAvailable;
   int j;
-  dt = State->Getdt();
 
   vForces.InitMatrix();
   vMoments.InitMatrix();
 
   for (unsigned int i=0; i<numEngines; i++) {
     Engines[i]->SetTrimMode(true);
-    Thrusters[i]->SetdeltaT(dt*rate);
     j=0;
     while (!Engines[i]->GetRunning() && j < 2000) {
-      PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
-      Thrusters[i]->Calculate(PowerAvailable);
+      Engines[i]->Calculate();
       j++;
     }
-    vForces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
-    vMoments += Thrusters[i]->GetMoments();     // sum body frame moments
+    vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
+    vMoments += Engines[i]->GetMoments();     // sum body frame moments
     Engines[i]->SetTrimMode(false);
   }
   return true;
@@ -206,20 +181,22 @@ bool FGPropulsion::ICEngineStart(void)
 
 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
 {
-  string token, fullpath;
+  string token, fullpath, localpath;
   string engineFileName, engType;
-  string thrusterFileName, thrType;
   string parameter;
   string enginePath = FDMExec->GetEnginePath();
+  string aircraftPath = FDMExec->GetAircraftPath();
   double xLoc, yLoc, zLoc, Pitch, Yaw;
-  double P_Factor = 0, Sense = 0.0;
   int Feed;
   bool ThrottleAdded = false;
+  FGConfigFile* Cfg_ptr = 0;
 
 # ifndef macintosh
       fullpath = enginePath + "/";
+      localpath = aircraftPath + "/Engines/";
 # else
       fullpath = enginePath + ";";
+      localpath = aircraftPath +  ";Engines;";
 # endif
 
   AC_cfg->GetNextConfigLine();
@@ -230,25 +207,44 @@ bool FGPropulsion::Load(FGConfigFile* AC_cfg)
 
       engineFileName = AC_cfg->GetValue("FILE");
 
-      if (debug_lvl > 0) cout << "\n    Reading engine from file: " << fullpath
-                                                + engineFileName + ".xml"<< endl;
+      // Look in the Aircraft/Engines directory first
+      Cfg_ptr = 0;
+      FGConfigFile Local_cfg(localpath + engineFileName + ".xml");
       FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
+      if (Local_cfg.IsOpen()) {
+        Cfg_ptr = &Local_cfg;
+        if (debug_lvl > 0) cout << "\n    Reading engine from file: " << localpath
+                                                + engineFileName + ".xml"<< endl;
+      } else {
+        if (Eng_cfg.IsOpen()) {
+          Cfg_ptr = &Eng_cfg;
+          if (debug_lvl > 0) cout << "\n    Reading engine from file: " << fullpath
+                                                + engineFileName + ".xml"<< endl;
+        }
+      }
 
-      if (Eng_cfg.IsOpen()) {
-        Eng_cfg.GetNextConfigLine();
-        engType = Eng_cfg.GetValue();
+      if (Cfg_ptr) {
+        Cfg_ptr->GetNextConfigLine();
+        engType = Cfg_ptr->GetValue();
 
         FCS->AddThrottle();
         ThrottleAdded = true;
 
         if (engType == "FG_ROCKET") {
-          Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
+          Engines.push_back(new FGRocket(FDMExec, Cfg_ptr));
         } else if (engType == "FG_PISTON") {
-          Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
+          Engines.push_back(new FGPiston(FDMExec, Cfg_ptr));
         } else if (engType == "FG_TURBINE") {
-          Engines.push_back(new FGTurbine(FDMExec, &Eng_cfg));
+          Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr));
         } else if (engType == "FG_SIMTURBINE") {
-          Engines.push_back(new FGSimTurbine(FDMExec, &Eng_cfg));
+          cerr << endl;
+          cerr << "The FG_SIMTURBINE engine type has been renamed to FG_TURBINE." << endl;
+          cerr << "To fix this problem, simply replace the FG_SIMTURBINE name " << endl;
+          cerr << "in your engine file to FG_TURBINE." << endl;
+          cerr << endl;
+          Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr));
+        } else if (engType == "FG_ELECTRIC") {
+          Engines.push_back(new FGElectric(FDMExec, Cfg_ptr));
         } else {
           cerr << fgred << "    Unrecognized engine type: " << underon << engType
                     << underoff << " found in config file." << fgdef << endl;
@@ -262,7 +258,12 @@ bool FGPropulsion::Load(FGConfigFile* AC_cfg)
           else if (token == "YLOC")  { *AC_cfg >> yLoc; }
           else if (token == "ZLOC")  { *AC_cfg >> zLoc; }
           else if (token == "PITCH") { *AC_cfg >> Pitch;}
-          else if (token == "YAW")   { *AC_cfg >> Yaw;}
+          else if (token == "YAW")   { *AC_cfg >> Yaw;  }
+          else if (token.find("AC_THRUSTER") != string::npos) {
+            if (debug_lvl > 0) cout << "\n    Reading thruster definition" << endl;
+              Engines.back()->LoadThruster(AC_cfg);
+              AC_cfg->GetNextConfigLine();
+          }
           else if (token == "FEED")  {
             *AC_cfg >> Feed;
             Engines[numEngines]->AddFeedTank(Feed);
@@ -286,14 +287,14 @@ bool FGPropulsion::Load(FGConfigFile* AC_cfg)
       } else {
 
         cerr << fgred << "\n  Could not read engine config file: " << underon <<
-                    fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
+                    engineFileName + ".xml" << underoff << fgdef << endl;
         return false;
       }
 
     } else if (token == "AC_TANK") {              // ============== READING TANKS
 
       if (debug_lvl > 0) cout << "\n    Reading tank definition" << endl;
-      Tanks.push_back(new FGTank(AC_cfg));
+      Tanks.push_back(new FGTank(AC_cfg, FDMExec));
       switch(Tanks[numTanks]->GetType()) {
       case FGTank::ttFUEL:
         numSelectedFuelTanks++;
@@ -306,59 +307,6 @@ bool FGPropulsion::Load(FGConfigFile* AC_cfg)
       }
 
       numTanks++;
-
-    } else if (token == "AC_THRUSTER") {          // ========== READING THRUSTERS
-
-      thrusterFileName = AC_cfg->GetValue("FILE");
-
-      if (debug_lvl > 0) cout << "\n    Reading thruster from file: " <<
-                                    fullpath + thrusterFileName + ".xml" << endl;
-      FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
-
-      if (Thruster_cfg.IsOpen()) {
-        Thruster_cfg.GetNextConfigLine();
-        thrType = Thruster_cfg.GetValue();
-
-        if (thrType == "FG_PROPELLER") {
-          Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
-        } else if (thrType == "FG_NOZZLE") {
-          Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg ));
-        } else if (thrType == "FG_DIRECT") {
-          Thrusters.push_back(new FGThruster( FDMExec, &Thruster_cfg) );
-        }
-
-        AC_cfg->GetNextConfigLine();
-        while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
-          *AC_cfg >> token;
-          if (token == "XLOC") *AC_cfg >> xLoc;
-          else if (token == "YLOC") *AC_cfg >> yLoc;
-          else if (token == "ZLOC") *AC_cfg >> zLoc;
-          else if (token == "PITCH") *AC_cfg >> Pitch;
-          else if (token == "YAW") *AC_cfg >> Yaw;
-          else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
-          else if (token == "SENSE")   *AC_cfg >> Sense;
-          else cerr << "Unknown identifier: " << token << " in engine file: "
-                                                        << engineFileName << endl;
-        }
-
-        Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
-        Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
-        if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
-          ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
-          if (debug_lvl > 0) cout << "      P-Factor: " << P_Factor << endl;
-          ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
-          if (debug_lvl > 0) cout << "      Sense: " << Sense <<  endl;
-        }
-        Thrusters[numThrusters]->SetdeltaT(dt*rate);
-        Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
-        numThrusters++;
-
-      } else {
-        cerr << "Could not read thruster config file: " << fullpath
-                                                + thrusterFileName + ".xml" << endl;
-        return false;
-      }
-
     }
     AC_cfg->GetNextConfigLine();
   }
@@ -375,58 +323,12 @@ string FGPropulsion::GetPropulsionStrings(void)
 {
   string PropulsionStrings = "";
   bool firstime = true;
-  char buffer[5];
 
   for (unsigned int i=0;i<Engines.size();i++) {
     if (firstime)  firstime = false;
     else           PropulsionStrings += ", ";
 
-    sprintf(buffer, "%d", i);
-
-    switch(Engines[i]->GetType()) {
-    case FGEngine::etPiston:
-      PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
-      break;
-    case FGEngine::etRocket:
-      PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
-      break;
-    case FGEngine::etTurbine:
-      break;
-    case FGEngine::etSimTurbine:
-      PropulsionStrings += (Engines[i]->GetName() + "_N1[" + buffer + "], ");
-      PropulsionStrings += (Engines[i]->GetName() + "_N2[" + buffer + "]");
-      break;
-    default:
-      PropulsionStrings += "INVALID ENGINE TYPE";
-      break;
-    }
-
-    PropulsionStrings += ", ";
-
-    FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
-    switch(Thrusters[i]->GetType()) {
-    case FGThruster::ttNozzle:
-      PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
-      break;
-    case FGThruster::ttRotor:
-      break;
-    case FGThruster::ttPropeller:
-      PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
-      PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
-      PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
-      PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
-      PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
-      if (Propeller->IsVPitch())
-        PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
-      PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
-      break;
-    case FGThruster::ttDirect:
-      PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
-      break;
-    default:
-      PropulsionStrings += "INVALID THRUSTER TYPE";
-      break;
-    }
+    PropulsionStrings += Engines[i]->GetEngineLabels() + ", ";
   }
 
   return PropulsionStrings;
@@ -436,7 +338,6 @@ string FGPropulsion::GetPropulsionStrings(void)
 
 string FGPropulsion::GetPropulsionValues(void)
 {
-  char buff[20];
   string PropulsionValues = "";
   bool firstime = true;
 
@@ -444,45 +345,7 @@ string FGPropulsion::GetPropulsionValues(void)
     if (firstime)  firstime = false;
     else           PropulsionValues += ", ";
 
-    switch(Engines[i]->GetType()) {
-    case FGEngine::etPiston:
-      PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
-      break;
-    case FGEngine::etRocket:
-      PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
-      break;
-    case FGEngine::etTurbine:
-      break;
-    case FGEngine::etSimTurbine:
-      PropulsionValues += (string(gcvt(((FGSimTurbine*)Engines[i])->GetN1(), 10, buff))) + ", ";
-      PropulsionValues += (string(gcvt(((FGSimTurbine*)Engines[i])->GetN2(), 10, buff)));
-      break;
-    }
-
-    PropulsionValues += ", ";
-
-    switch(Thrusters[i]->GetType()) {
-    case FGThruster::ttNozzle:
-      PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
-      break;
-    case FGThruster::ttRotor:
-      break;
-    case FGThruster::ttDirect:
-      PropulsionValues += (string(gcvt(((FGThruster*)Thrusters[i])->GetThrust(), 10, buff)));
-      break;
-    case FGThruster::ttPropeller:
-      FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
-      FGColumnVector3 vPFactor = Propeller->GetPFactor();
-      PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
-      PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
-      PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
-      PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
-      PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
-      if (Propeller->IsVPitch())
-        PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
-      PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
-      break;
-    }
+    PropulsionValues += Engines[i]->GetEngineValues() + ", ";
   }
 
   return PropulsionValues;
@@ -574,15 +437,15 @@ void FGPropulsion::SetCutoff(int setting)
   if (ActiveEngine < 0) {
     for (unsigned i=0; i<Engines.size(); i++) {
       if (setting == 0)
-        ((FGSimTurbine*)Engines[i])->SetCutoff(false);
+        ((FGTurbine*)Engines[i])->SetCutoff(false);
       else
-        ((FGSimTurbine*)Engines[i])->SetCutoff(true);
+        ((FGTurbine*)Engines[i])->SetCutoff(true);
     }
   } else {
     if (setting == 0)
-      ((FGSimTurbine*)Engines[ActiveEngine])->SetCutoff(false);
+      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
     else
-      ((FGSimTurbine*)Engines[ActiveEngine])->SetCutoff(true);
+      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
   }
 }
 
@@ -598,6 +461,44 @@ void FGPropulsion::SetActiveEngine(int engine)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+double FGPropulsion::Transfer(int source, int target, double amount)
+{
+ double shortage, overage;
+
+  if (source == -1) {
+     shortage = 0.0;
+  } else {
+     shortage = Tanks[source]->Drain(amount);
+  }
+  if (target == -1) {
+     overage = 0.0;
+  } else {
+     overage = Tanks[target]->Fill(amount - shortage);
+  }
+  return overage;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::DoRefuel(double time_slice)
+{
+  double fillrate = 100 * time_slice;   // 100 lbs/sec = 6000 lbs/min
+  int TanksNotFull = 0;
+
+  for (unsigned int i=0; i<numTanks; i++) {
+    if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
+  }
+
+  if (TanksNotFull) {
+    for (unsigned int i=0; i<numTanks; i++) {
+      if (Tanks[i]->GetPctFull() < 99.99)
+          Transfer(-1, i, fillrate/TanksNotFull);
+    }
+  }      
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 void FGPropulsion::bind(void)
 {
   typedef double (FGPropulsion::*PMF)(int) const;
index 49f8ac8a60d06cc7431a2c27469134cd2cba5bee..11a1fbb5169c232a6914e34eec2b950bc3bccbd8 100644 (file)
@@ -55,7 +55,6 @@ INCLUDES
 #include "FGModel.h"
 #include "FGEngine.h"
 #include "FGTank.h"
-#include "FGThruster.h"
 #include "FGMatrix33.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -76,27 +75,18 @@ CLASS DOCUMENTATION
 
 /** Propulsion management class.
     The Propulsion class is the container for the entire propulsion system, which is
-    comprised of engines, tanks, and "thrusters" (the device that transforms the
-    engine power into a force that acts on the aircraft, such as a nozzle or
-    propeller). Once the Propulsion class gets the config file, it reads in
-    information which is specific to a type of engine. Then:
+    comprised of engines, and tanks. Once the Propulsion class gets the config file,
+    it reads in information which is specific to a type of engine. Then:
 
     -# The appropriate engine type instance is created
-    -# A thruster object is instantiated, and is linked to the engine
     -# At least one tank object is created, and is linked to an engine.
 
-    At Run time each engines Calculate() method is called to return the excess power
-    generated during that iteration. The drag from the previous iteration is sub-
-    tracted to give the excess power available for thrust this pass. That quantity
-    is passed to the thrusters associated with a particular engine - perhaps with a
-    scaling mechanism (gearing?) to allow the engine to give its associated thrust-
-    ers specific distributed portions of the excess power.
+    At Run time each engines Calculate() method is called.
     @author Jon S. Berndt
     @version $Id$
     @see
     FGEngine
     FGTank
-    FGThruster
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -113,22 +103,12 @@ public:
 
   /** Executes the propulsion model.
       The initial plan for the FGPropulsion class calls for Run() to be executed,
-      performing the following tasks:
-      <ol>
-  <li>Determine the drag - or power required - for the attached thrust effector
-      for this engine so that any feedback to the engine can be performed. This
-      is done by calling FGThruster::CalculatePReq()</li>
-  <li>Given 1, above, calculate the power available from the engine. This is
-      done by calling FGEngine::CalculatePAvail()</li>
-  <li>Next, calculate the thrust output from the thruster model given the power
-      available and the power required. This may also result in new performance
-      numbers for the thruster in the case of the propeller, at least. This
-      result is returned from a call to Calculate().</li></ol>
+      calculating the power available from the engine.
 
       [Note: Should we be checking the Starved flag here?] */
   bool Run(void);
 
-  /** Loads the propulsion system (engine[s], tank[s], thruster[s]).
+  /** Loads the propulsion system (engine[s] and tank[s]).
       Characteristics of the propulsion system are read in from the config file.
       @param AC_cfg pointer to the config file instance that describes the
              aircraft being modeled.
@@ -157,21 +137,13 @@ public:
                       if (index <= Tanks.size()-1) return Tanks[index];
                       else                         return 0L;        }
 
-  /** Retrieves a thruster object pointer from the list of thrusters.
-      @param index the thruster index within the vector container
-      @return the address of the specific thruster, or zero if no such thruster is
-              available */
-  inline FGThruster* GetThruster(unsigned int index) {
-                      if (index <= Thrusters.size()-1) return Thrusters[index];
-                      else                             return 0L;    }
-
   /** Returns the number of fuel tanks currently actively supplying fuel */
   inline int GetnumSelectedFuelTanks(void) const {return numSelectedFuelTanks;}
 
   /** Returns the number of oxidizer tanks currently actively supplying oxidizer */
   inline int GetnumSelectedOxiTanks(void) const {return numSelectedOxiTanks;}
 
-  /** Loops the engines/thrusters until thrust output steady (used for trimming) */
+  /** Loops the engines until thrust output steady (used for trimming) */
   bool GetSteadyState(void);
 
   /** starts the engines in IC mode (dt=0).  All engine-specific setup must
@@ -186,6 +158,11 @@ public:
   inline FGColumnVector3& GetMoments(void) {return vMoments;}
   inline double GetMoments(int n) const {return vMoments(n);}
 
+  inline bool GetRefuel(void) {return refuel;}
+  inline void SetRefuel(bool setting) {refuel = setting;} 
+  double Transfer(int source, int target, double amount);
+  void DoRefuel(double time_slice);
+
   FGColumnVector3& GetTanksMoment(void);
   double GetTanksWeight(void);
 
@@ -209,21 +186,20 @@ private:
   vector <FGEngine*>   Engines;
   vector <FGTank*>     Tanks;
   vector <FGTank*>::iterator iTank;
-  vector <FGThruster*> Thrusters;
   unsigned int numSelectedFuelTanks;
   unsigned int numSelectedOxiTanks;
   unsigned int numFuelTanks;
   unsigned int numOxiTanks;
   unsigned int numEngines;
   unsigned int numTanks;
-  unsigned int numThrusters;
   int ActiveEngine;
-  double dt;
   FGColumnVector3 vForces;
   FGColumnVector3 vMoments;
   FGColumnVector3 vTankXYZ;
   FGColumnVector3 vXYZtank_arm;
   FGMatrix33 tankJ;
+  bool refuel;
+
   void Debug(int from);
 };
 }
diff --git a/src/FDM/JSBSim/FGQuaternion.cpp b/src/FDM/JSBSim/FGQuaternion.cpp
new file mode 100644 (file)
index 0000000..8c62dd5
--- /dev/null
@@ -0,0 +1,235 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGQuaternion.cpp
+ Author:       Jon Berndt, Mathias Froehlich
+ Date started: 12/02/98
+
+ ------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) ------------------
+ -------           (C) 2004  Mathias Froehlich (Mathias.Froehlich@web.de) ----
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+-------------------------------------------------------------------------------
+12/02/98   JSB   Created
+15/01/04   Mathias Froehlich implemented a quaternion class from many places
+           in JSBSim.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  INCLUDES
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <math.h>
+#  include <simgear/compiler.h>
+#  include STL_IOSTREAM
+   SG_USING_STD(cerr);
+   SG_USING_STD(cout);
+   SG_USING_STD(endl);
+#else
+#  include <string>
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <iostream.h>
+#    include <math.h>
+#  else
+#    include <iostream>
+#    if defined(sgi) && !defined(__GNUC__)
+#      include <math.h>
+#    else
+#      include <cmath>
+#    endif
+     using std::cerr;
+     using std::cout;
+     using std::endl;
+#  endif
+#endif
+
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+
+#include "FGQuaternion.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  DEFINITIONS
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+  
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_QUATERNION;
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// Initialize from q
+FGQuaternion::FGQuaternion(const FGQuaternion& q)
+  : mCacheValid(q.mCacheValid) {
+  Entry(1) = q(1);
+  Entry(2) = q(2);
+  Entry(3) = q(3);
+  Entry(4) = q(4);
+  if (mCacheValid) {
+    mT = q.mT;
+    mTInv = q.mTInv;
+    mEulerAngles = q.mEulerAngles;
+    mEulerSines = q.mEulerSines;
+    mEulerCosines = q.mEulerCosines;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// Initialize with the three euler angles
+FGQuaternion::FGQuaternion(double phi, double tht, double psi)
+  : mCacheValid(false) {
+  double thtd2 = 0.5*tht;
+  double psid2 = 0.5*psi;
+  double phid2 = 0.5*phi;
+  
+  double Sthtd2 = sin(thtd2);
+  double Spsid2 = sin(psid2);
+  double Sphid2 = sin(phid2);
+  
+  double Cthtd2 = cos(thtd2);
+  double Cpsid2 = cos(psid2);
+  double Cphid2 = cos(phid2);
+  
+  double Cphid2Cthtd2 = Cphid2*Cthtd2;
+  double Cphid2Sthtd2 = Cphid2*Sthtd2;
+  double Sphid2Sthtd2 = Sphid2*Sthtd2;
+  double Sphid2Cthtd2 = Sphid2*Cthtd2;
+  
+  Entry(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2;
+  Entry(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2;
+  Entry(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2;
+  Entry(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/**
+   Returns the derivative of the quaternion coresponding to the
+   angular velocities PQR.
+*/
+FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR) const {
+  FGQuaternion QDot;
+  QDot(1) = -0.5*(Entry(2)*PQR(eP) + Entry(3)*PQR(eQ) + Entry(4)*PQR(eR));
+  QDot(2) =  0.5*(Entry(1)*PQR(eP) + Entry(3)*PQR(eR) - Entry(4)*PQR(eQ));
+  QDot(3) =  0.5*(Entry(1)*PQR(eQ) + Entry(4)*PQR(eP) - Entry(2)*PQR(eR));
+  QDot(4) =  0.5*(Entry(1)*PQR(eR) + Entry(2)*PQR(eQ) - Entry(3)*PQR(eP));
+  return QDot;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGQuaternion::Normalize()
+{
+  // Note: this does not touch the cache
+  // since it does not change the orientation ...
+  
+  double norm = Magnitude();
+  if (norm == 0.0)
+    return;
+  
+  double rnorm = 1.0/norm;
+  Entry(1) *= rnorm;
+  Entry(2) *= rnorm;
+  Entry(3) *= rnorm;
+  Entry(4) *= rnorm;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// Compute the derived values if required ...
+void FGQuaternion::ComputeDerivedUnconditional(void) const
+{
+  mCacheValid = true;
+  
+  // First normalize the 4-vector
+  double norm = Magnitude();
+  if (norm == 0.0)
+    return;
+
+  double rnorm = 1.0/norm;
+  double q1 = rnorm*Entry(1);
+  double q2 = rnorm*Entry(2);
+  double q3 = rnorm*Entry(3);
+  double q4 = rnorm*Entry(4);
+
+  // Now compute the transformation matrix.
+  double q1q1 = q1*q1;
+  double q2q2 = q2*q2;
+  double q3q3 = q3*q3;
+  double q4q4 = q4*q4;
+  double q1q2 = q1*q2;
+  double q1q3 = q1*q3;
+  double q1q4 = q1*q4;
+  double q2q3 = q2*q3;
+  double q2q4 = q2*q4;
+  double q3q4 = q3*q4;
+  
+  mT(1,1) = q1q1 + q2q2 - q3q3 - q4q4;
+  mT(1,2) = 2.0*(q2q3 + q1q4);
+  mT(1,3) = 2.0*(q2q4 - q1q3);
+  mT(2,1) = 2.0*(q2q3 - q1q4);
+  mT(2,2) = q1q1 - q2q2 + q3q3 - q4q4;
+  mT(2,3) = 2.0*(q3q4 + q1q2);
+  mT(3,1) = 2.0*(q2q4 + q1q3);
+  mT(3,2) = 2.0*(q3q4 - q1q2);
+  mT(3,3) = q1q1 - q2q2 - q3q3 + q4q4;
+  // Since this is an orthogonal matrix, the inverse is simply
+  // the transpose.
+  mTInv = mT;
+  mTInv.T();
+  
+  // Compute the Euler-angles
+  if (mT(3,3) == 0.0)
+    mEulerAngles(ePhi) = 0.5*M_PI;
+  else
+    mEulerAngles(ePhi) = atan2(mT(2,3), mT(3,3));
+  
+  if (mT(1,3) < -1.0)
+    mEulerAngles(eTht) = 0.5*M_PI;
+  else if (1.0 < mT(1,3))
+    mEulerAngles(eTht) = -0.5*M_PI;
+  else
+    mEulerAngles(eTht) = asin(-mT(1,3));
+  
+  if (mT(1,1) == 0.0)
+    mEulerAngles(ePsi) = 0.5*M_PI;
+  else {
+    double psi = atan2(mT(1,2), mT(1,1));
+    if (psi < 0.0)
+      psi += 2*M_PI;
+    mEulerAngles(ePsi) = psi;
+  }
+  
+  // FIXME: may be one can compute those values easier ???
+  mEulerSines(ePhi) = sin(mEulerAngles(ePhi));
+  // mEulerSines(eTht) = sin(mEulerAngles(eTht));
+  mEulerSines(eTht) = -mT(1,3);
+  mEulerSines(ePsi) = sin(mEulerAngles(ePsi));
+  mEulerCosines(ePhi) = cos(mEulerAngles(ePhi));
+  mEulerCosines(eTht) = cos(mEulerAngles(eTht));
+  mEulerCosines(ePsi) = cos(mEulerAngles(ePsi));
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/FGQuaternion.h b/src/FDM/JSBSim/FGQuaternion.h
new file mode 100644 (file)
index 0000000..7f5db75
--- /dev/null
@@ -0,0 +1,499 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGQuaternion.h
+ Author:       Jon Berndt, Mathis Froehlich
+ Date started: 12/02/98
+
+ ------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) ------------------
+ -------           (C) 2004  Mathias Froehlich (Mathias.Froehlich@web.de) ----
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+-------------------------------------------------------------------------------
+12/02/98   JSB   Created
+15/01/04   MF    Quaternion class from old FGColumnVector4
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGQUATERNION_H
+#define FGQUATERNION_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  INCLUDES
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGJSBBase.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGPropertyManager.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  DEFINITIONS
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_QUATERNION "$Id$"
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  CLASS DOCUMENTATION
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/**  Models the Quaternion representation of rotations.
+    FGQuaternion is a representation of an arbitrary rotation through a
+    quaternion. It has vector properties. This class also contains access
+    functions to the euler angle representation of rotations and access to
+    transformation matrices for 3D vectors. Transformations and euler angles are
+    therefore computed once they are requested for the first time. Then they are
+    cached for later usage as long as the class is not accessed trough
+    a nonconst member function.
+
+    Note: The order of rotations used in this class corresponds to a 3-2-1 sequence,
+    or Y-P-R, or Z-Y-X, if you prefer.
+
+    @see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
+    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
+    School, January 1994
+    @see D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
+    JSC 12960, July 1977
+    @see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
+    NASA-Ames", NASA CR-2497, January 1975
+    @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
+    Wiley & Sons, 1979 ISBN 0-471-03032-5
+    @see Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
+    1982 ISBN 0-471-08936-2
+    @author Mathias Froehlich, extended FGColumnVector4 originally by Tony Peden
+            and Jon Berndt
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  CLASS DECLARATION
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGQuaternion
+  : virtual FGJSBBase {
+public:
+  /** Default initializer.
+      Default initializer, initializes the class with the identity rotation.  */
+  FGQuaternion() : mCacheValid(false) {
+    Entry(1) = 1.0;
+    Entry(2) = Entry(3) = Entry(4) = 0.0;
+  }
+
+  /** Copy constructor.
+      Copy constructor, initializes the quaternion.
+      @param q  a constant reference to another FGQuaternion instance  */
+  FGQuaternion(const FGQuaternion& q);
+
+  /** Initializer by euler angles.
+      Initialize the quaternion with the euler angles.
+      @param phi The euler X axis (roll) angle in radians
+      @param tht The euler Y axis (attitude) angle in radians
+      @param psi The euler Z axis (heading) angle in radians  */
+  FGQuaternion(double phi, double tht, double psi);
+
+  /// Destructor.
+  ~FGQuaternion() {}
+
+  /** Quaternion 'velocity' for given angular rates.
+      Computes the quaternion derivative which results from the given
+      angular velocities
+      @param PQR a constant reference to the body rate vector
+      @return the quaternion derivative */
+  FGQuaternion GetQDot(const FGColumnVector3& PQR) const;
+
+  /** Transformation matrix.
+      @return a reference to the transformation/rotation matrix
+      corresponding to this quaternion rotation.  */
+  const FGMatrix33& GetT() const { ComputeDerived(); return mT; }
+
+  /** Backward transformation matrix.
+      @return a reference to the inverse transformation/rotation matrix
+      corresponding to this quaternion rotation.  */
+  const FGMatrix33& GetTInv() const { ComputeDerived(); return mTInv; }
+
+  /** Retrieves the Euler angles.
+      @return a reference to the triad of euler angles corresponding
+      to this quaternion rotation.
+      @units radians  */
+  const FGColumnVector3& GetEuler() const {
+    ComputeDerived();
+    return mEulerAngles;
+  }
+
+  /** Euler angle theta.
+      @return the euler angle theta (pitch attitude) corresponding to this
+      quaternion rotation.
+      @units radians  */
+  double GetEulerTheta() const {
+    ComputeDerived();
+    return mEulerAngles(eTht);
+  }
+
+  /** Euler angle theta.
+      @return the euler angle theta (pitch attitude) corresponding to
+      this quaternion rotation.
+      @units degrees  */
+  double GetEulerThetaDeg() const {
+    ComputeDerived();
+    return radtodeg*mEulerAngles(eTht);
+  }
+
+  /** Euler angle psi.
+      @return the heading euler angle (psi) corresponding to this quaternion
+      rotation.
+      @units radians  */
+  double GetEulerPsi() const {
+    ComputeDerived();
+    return mEulerAngles(ePsi);
+  }
+
+  /** Retrieves the heading angle.
+      @return the Euler angle psi (heading) corresponding to this quaternion
+      rotation.
+      @units degrees  */
+  double GetEulerPsiDeg() const {
+    ComputeDerived();
+    return radtodeg*mEulerAngles(ePsi);
+  }
+
+  /** Retrieves the roll angle.
+      @return the euler angle phi (roll) corresponding to this quaternion
+      rotation.
+      @units radians  */
+  double GetEulerPhi() const {
+    ComputeDerived();
+    return mEulerAngles(ePhi);
+  }
+
+  /** Retrieves the roll angle.
+      Returns the Euler angle phi (roll) corresponding to this quaternion rotation.
+      @units degrees  */
+  double GetEulerPhiDeg() const {
+    ComputeDerived();
+    return radtodeg*mEulerAngles(ePhi);
+  }
+
+  /** Retrieves sine theta.
+      @return the sine of the Euler angle theta (pitch attitude) corresponding
+      to this quaternion rotation.  */
+  double GetSinEulerTheta() const {
+    ComputeDerived();
+    return mEulerSines(eTht);
+  }
+
+  /** Retrieves sine psi.
+      @return the sine of the Euler angle psi (heading) corresponding to this
+      quaternion rotation.  */
+  double GetSinEulerPsi() const {
+    ComputeDerived();
+    return mEulerSines(ePsi);
+  }
+
+  /** Sine of euler angle phi.
+      @return the sine of the Euler angle phi (roll) corresponding to this
+      quaternion rotation.  */
+  double GetSinEulerPhi() const {
+    ComputeDerived();
+    return mEulerSines(ePhi);
+  }
+
+  /** Cosine of euler angle theta.
+      @return the cosine of the Euler angle theta (pitch) corresponding to this
+      quaternion rotation.  */
+  double GetCosEulerTheta() const {
+    ComputeDerived();
+    return mEulerCosines(eTht);
+  }
+
+  /** Cosine of euler angle psi.
+      @return the cosine of the Euler angle psi (heading) corresponding to this
+      quaternion rotation.  */
+  double GetCosEulerPsi() const {
+    ComputeDerived();
+    return mEulerCosines(ePsi);
+  }
+
+  /** Cosine of euler angle phi.
+      @return the cosine of the Euler angle phi (roll) corresponding to this
+      quaternion rotation.  */
+  double GetCosEulerPhi() const {
+    ComputeDerived();
+    return mEulerCosines(ePhi);
+  }
+
+  /** Read access the entries of the vector.
+    
+      @param idx the component index.
+    
+      Return the value of the matrix entry at the given index.
+      Indices are counted starting with 1.
+    
+      Note that the index given in the argument is unchecked.
+   */
+  double operator()(unsigned int idx) const { return Entry(idx); }
+
+  /** Write access the entries of the vector.
+    
+      @param idx the component index.
+    
+      Return a reference to the vector entry at the given index.
+      Indices are counted starting with 1.
+    
+      Note that the index given in the argument is unchecked.
+   */
+  double& operator()(unsigned int idx) { return Entry(idx); }
+
+  /** Read access the entries of the vector.
+    
+      @param idx the component index.
+    
+      Return the value of the matrix entry at the given index.
+      Indices are counted starting with 1.
+    
+      This function is just a shortcut for the @ref double
+      operator()(unsigned int idx) const function. It is
+      used internally to access the elements in a more convenient way.
+    
+      Note that the index given in the argument is unchecked.
+  */
+  double Entry(unsigned int idx) const { return mData[idx-1]; }
+
+  /** Write access the entries of the vector.
+    
+      @param idx the component index.
+    
+      Return a reference to the vector entry at the given index.
+      Indices are counted starting with 1.
+    
+      This function is just a shortcut for the @ref double&
+      operator()(unsigned int idx) function. It is
+      used internally to access the elements in a more convenient way.
+    
+      Note that the index given in the argument is unchecked.
+  */
+  double& Entry(unsigned int idx) { mCacheValid = false; return mData[idx-1]; }
+
+  /** Assignment operator "=".
+      Assign the value of q to the current object. Cached values are
+      conserved.
+      @param q reference to an FGQuaternion instance
+      @return reference to a quaternion object  */
+  const FGQuaternion& operator=(const FGQuaternion& q) {
+    // Copy the master values ...
+    Entry(1) = q(1);
+    Entry(2) = q(2);
+    Entry(3) = q(3);
+    Entry(4) = q(4);
+    // .. and copy the derived values if they are valid
+    mCacheValid = q.mCacheValid;
+    if (mCacheValid) {
+        mT = q.mT;
+        mTInv = q.mTInv;
+        mEulerAngles = q.mEulerAngles;
+        mEulerSines = q.mEulerSines;
+        mEulerCosines = q.mEulerCosines;
+    }
+    return *this;
+  }
+
+  /** Comparison operator "==".
+      @param q a quaternion reference
+      @return true if both quaternions represent the same rotation.  */
+  bool operator==(const FGQuaternion& q) const {
+    return Entry(1) == q(1) && Entry(2) == q(2)
+      && Entry(3) == q(3) && Entry(4) == q(4);
+  }
+
+  /** Comparison operator "!=".
+      @param q a quaternion reference
+      @return true if both quaternions do not represent the same rotation.  */
+  bool operator!=(const FGQuaternion& q) const { return ! operator==(q); }
+  const FGQuaternion& operator+=(const FGQuaternion& q) {
+    // Copy the master values ...
+    Entry(1) += q(1);
+    Entry(2) += q(2);
+    Entry(3) += q(3);
+    Entry(4) += q(4);
+    mCacheValid = false;
+    return *this;
+  }
+
+  /** Arithmetic operator "-=".
+      @param q a quaternion reference.
+      @return a quaternion reference representing Q, where Q = Q - q. */
+  const FGQuaternion& operator-=(const FGQuaternion& q) {
+    // Copy the master values ...
+    Entry(1) -= q(1);
+    Entry(2) -= q(2);
+    Entry(3) -= q(3);
+    Entry(4) -= q(4);
+    mCacheValid = false;
+    return *this;
+  }
+
+  /** Arithmetic operator "*=".
+      @param scalar a multiplicative value.
+      @return a quaternion reference representing Q, where Q = Q * scalar. */
+  const FGQuaternion& operator*=(double scalar) {
+    Entry(1) *= scalar;
+    Entry(2) *= scalar;
+    Entry(3) *= scalar;
+    Entry(4) *= scalar;
+    mCacheValid = false;
+    return *this;
+  }
+
+  /** Arithmetic operator "/=".
+      @param scalar a divisor value.
+      @return a quaternion reference representing Q, where Q = Q / scalar. */
+  const FGQuaternion& operator/=(double scalar) {
+    return operator*=(1.0/scalar);
+  }
+
+  /** Arithmetic operator "+".
+      @param q a quaternion to be summed.
+      @return a quaternion representing Q, where Q = Q + q. */
+  FGQuaternion operator+(const FGQuaternion& q) const {
+    return FGQuaternion(Entry(1)+q(1), Entry(2)+q(2),
+                        Entry(3)+q(3), Entry(4)+q(4));
+  }
+
+  /** Arithmetic operator "-".
+      @param q a quaternion to be subtracted.
+      @return a quaternion representing Q, where Q = Q - q. */
+  FGQuaternion operator-(const FGQuaternion& q) const {
+    return FGQuaternion(Entry(1)-q(1), Entry(2)-q(2),
+                        Entry(3)-q(3), Entry(4)-q(4));
+  }
+
+  /** Arithmetic operator "*".
+      Multiplication of two quaternions is like performing successive rotations.
+      @param q a quaternion to be multiplied.
+      @return a quaternion representing Q, where Q = Q * q. */
+  FGQuaternion operator*(const FGQuaternion& q) const {
+    return FGQuaternion(Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4),
+                        Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3),
+                        Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2),
+                        Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1));
+  }
+
+  /** Arithmetic operator "*=".
+      Multiplication of two quaternions is like performing successive rotations.
+      @param q a quaternion to be multiplied.
+      @return a quaternion reference representing Q, where Q = Q * q. */
+  const FGQuaternion& operator*=(const FGQuaternion& q) {
+    double q0 = Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4);
+    double q1 = Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3);
+    double q2 = Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2);
+    double q3 = Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1);
+    Entry(1) = q0;
+    Entry(2) = q1;
+    Entry(3) = q2;
+    Entry(4) = q3;
+    mCacheValid = false;
+    return *this;
+  }
+
+  friend FGQuaternion operator*(double, const FGQuaternion&);
+  
+  /** Length of the vector.
+    
+      Compute and return the euclidean norm of this vector.
+  */
+  double Magnitude() const { return sqrt(SqrMagnitude()); }
+
+  /** Square of the length of the vector.
+    
+      Compute and return the square of the euclidean norm of this vector.
+  */
+  double SqrMagnitude() const {
+    return Entry(1)*Entry(1)+Entry(2)*Entry(2)
+      +Entry(3)*Entry(3)+Entry(4)*Entry(4);
+  }
+
+  /** Normialze.
+    
+      Normalize the vector to have the Magnitude() == 1.0. If the vector
+      is equal to zero it is left untouched.
+   */
+  void Normalize();
+
+  /** Zero quaternion vector. Does not represent any orientation.
+      Useful for initialization of increments */
+  static FGQuaternion zero(void) { return FGQuaternion( 0.0, 0.0, 0.0, 0.0 ); }
+
+private:
+  /** Copying by assigning the vector valued components.  */
+  FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false)
+    { Entry(1) = q1; Entry(2) = q2; Entry(3) = q3; Entry(4) = q4; }
+
+  /** Computation of derived values.
+      This function recomputes the derived values like euler angles and
+      transformation matrices. It does this unconditionally.  */
+  void ComputeDerivedUnconditional(void) const;
+
+  /** Computation of derived values.
+      This function checks if the derived values like euler angles and
+      transformation matrices are already computed. If so, it
+      returns. If they need to be computed this is done here.  */
+  void ComputeDerived(void) const {
+    if (!mCacheValid)
+      ComputeDerivedUnconditional();
+  }
+
+  /** The quaternion values itself. This is the master copy. */
+  double mData[4];
+
+  /** A data validity flag.
+      This class implements caching of the derived values like the
+      orthogonal rotation matrices or the Euler angles. For caching we
+      carry a flag which signals if the values are valid or not.
+      The C++ keyword "mutable" tells the compiler that the data member is
+      allowed to change during a const member function.  */
+  mutable bool mCacheValid;
+
+  /** This stores the transformation matrices.  */
+  mutable FGMatrix33 mT;
+  mutable FGMatrix33 mTInv;
+
+  /** The cached euler angles.  */
+  mutable FGColumnVector3 mEulerAngles;
+
+  /** The cached sines and cosines of the euler angles.  */
+  mutable FGColumnVector3 mEulerSines;
+  mutable FGColumnVector3 mEulerCosines;
+};
+
+/** Scalar multiplication.
+
+    @param scalar scalar value to multiply with.
+    @param p Vector to multiply.
+
+    Multiply the Vector with a scalar value.
+*/
+inline FGQuaternion operator*(double scalar, const FGQuaternion& q) {
+  return FGQuaternion(scalar*q(1), scalar*q(2), scalar*q(3), scalar*q(4));
+}
+
+} // namespace JSBSim
+
+#endif
index f2c7fb3775ee8b5d0567870fe48725c68a40a48d..dc99191921c92de3b2227ef2fd84f8d62cb9563c 100644 (file)
@@ -38,6 +38,8 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <sstream>
+
 #include "FGRocket.h"
 
 namespace JSBSim {
@@ -88,7 +90,7 @@ FGRocket::~FGRocket(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGRocket::Calculate(double pe)
+double FGRocket::Calculate(void)
 {
   double Cf=0;
 
@@ -103,11 +105,34 @@ double FGRocket::Calculate(double pe)
   } else {
     PctPower = Throttle / MaxThrottle;
     PC = maxPC*PctPower * (1.0 + Variance * ((double)rand()/(double)RAND_MAX - 0.5));
-    Cf = sqrt(kFactor*(1 - pow(pe/(PC), (SHR-1)/SHR)));
+    Cf = sqrt(kFactor*(1 - pow(Thruster->GetPowerRequired()/(PC), (SHR-1)/SHR)));
     Flameout = false;
   }
 
-  return Cf*maxPC*PctPower*propEff;
+  return Thruster->Calculate(Cf*maxPC*PctPower*propEff);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRocket::GetEngineLabels(void)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_ChamberPress[" << EngineNumber << "], "
+      << Thruster->GetThrusterLabels(EngineNumber);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRocket::GetEngineValues(void)
+{
+  std::ostringstream buf;
+
+  buf << PC << ", " << Thruster->GetThrusterValues(EngineNumber);
+
+  return buf.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index b9b3dc80422323c6467dded52fe7d9ecf24480e0..9d64c6ad4e9e0e513a50b7cb09faefd1e99f7abd 100644 (file)
@@ -110,21 +110,20 @@ public:
   ~FGRocket(void);
 
   /** Determines the thrust coefficient.
-      This routine takes the nozzle exit pressure and calculates the thrust
-      coefficient times the chamber pressure.
-      @param pe nozzle exit pressure
       @return thrust coefficient times chamber pressure */
-  double Calculate(double pe);
-  
+  double Calculate(void);
+
   /** Gets the chamber pressure.
       @return chamber pressure in psf. */
   double GetChamberPressure(void) {return PC;}
 
   /** Gets the flame-out status.
-      The engine will "flame out" if the throttle is set below the minimum 
+      The engine will "flame out" if the throttle is set below the minimum
       sustainable setting.
       @return true if engine has flamed out. */
   bool GetFlameout(void) {return Flameout;}
+  string GetEngineLabels(void);
+  string GetEngineValues(void);
 
 private:
   double SHR;
diff --git a/src/FDM/JSBSim/FGRotation.cpp b/src/FDM/JSBSim/FGRotation.cpp
deleted file mode 100644 (file)
index 6ecd770..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGRotation.cpp
- Author:       Jon Berndt
- Date started: 12/02/98
- Purpose:      Integrates the rotational EOM
- Called by:    FGFDMExec
-
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-This class integrates the rotational EOM.
-
-HISTORY
---------------------------------------------------------------------------------
-12/02/98   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
-    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
-    School, January 1994
-[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
-    JSC 12960, July 1977
-[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
-    NASA-Ames", NASA CR-2497, January 1975
-[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
-    Wiley & Sons, 1979 ISBN 0-471-03032-5
-[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
-    1982 ISBN 0-471-08936-2
-
-  The order of rotations used in this class corresponds to a 3-2-1 sequence,
-  or Y-P-R, or Z-Y-X, if you prefer.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGRotation.h"
-#include "FGAtmosphere.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-#include "FGAircraft.h"
-#include "FGMassBalance.h"
-#include "FGPropertyManager.h"
-
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_ROTATION;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGRotation::FGRotation(FGFDMExec* fdmex) : FGModel(fdmex)
-{
-  Name = "FGRotation";
-  cTht = cPhi = cPsi = 1.0;
-  sTht = sPhi = sPsi = 0.0;
-
-  vPQRdot.InitMatrix();
-  vPQRdot_prev[0].InitMatrix();
-  vPQRdot_prev[1].InitMatrix();
-  vPQRdot_prev[2].InitMatrix();
-  vPQRdot_prev[3].InitMatrix();
-
-  bind();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGRotation::~FGRotation()
-{
-  unbind();
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGRotation::Run(void)
-{
-  double tTheta;
-
-  if (!FGModel::Run()) {
-    GetState();
-
-    vPQRdot = MassBalance->GetJinv()*(vMoments - vPQR*(MassBalance->GetJ()*vPQR));
-    vPQR += State->Integrate(FGState::TRAPZ, dt*rate, vPQRdot, vPQRdot_prev);
-
-    vAeroPQR = vPQR + Atmosphere->GetTurbPQR();
-
-    State->IntegrateQuat(vPQR, rate);
-    State->CalcMatrices();
-    vEuler = State->CalcEuler();
-
-    cTht = cos(vEuler(eTht));   sTht = sin(vEuler(eTht));
-    cPhi = cos(vEuler(ePhi));   sPhi = sin(vEuler(ePhi));
-    cPsi = cos(vEuler(ePsi));   sPsi = sin(vEuler(ePsi));
-
-    vEulerRates(eTht) = vPQR(2)*cPhi - vPQR(3)*sPhi;
-    if (cTht != 0.0) {
-      tTheta = sTht/cTht;       // what's cheaper: / or tan() ?
-      vEulerRates(ePhi) = vPQR(1) + (vPQR(2)*sPhi + vPQR(3)*cPhi)*tTheta;
-      vEulerRates(ePsi) = (vPQR(2)*sPhi + vPQR(3)*cPhi)/cTht;
-    }
-
-    if (debug_lvl > 1) Debug(2);
-
-    return false;
-  } else {
-    return true;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGRotation::GetState(void)
-{
-  dt = State->Getdt();
-  vMoments = Aircraft->GetMoments();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGRotation::bind(void)
-{
-  typedef double (FGRotation::*PMF)(int) const;
-  PropertyManager->Tie("velocities/p-rad_sec", this,1,
-                       (PMF)&FGRotation::GetPQR);
-  PropertyManager->Tie("velocities/q-rad_sec", this,2,
-                       (PMF)&FGRotation::GetPQR);
-  PropertyManager->Tie("velocities/r-rad_sec", this,3,
-                       (PMF)&FGRotation::GetPQR);
-  PropertyManager->Tie("velocities/p-aero-rad_sec", this,1,
-                       (PMF)&FGRotation::GetAeroPQR);
-  PropertyManager->Tie("velocities/q-aero-rad_sec", this,2,
-                       (PMF)&FGRotation::GetAeroPQR);
-  PropertyManager->Tie("velocities/r-aero-rad_sec", this,3,
-                       (PMF)&FGRotation::GetAeroPQR);
-  PropertyManager->Tie("accelerations/pdot-rad_sec", this,1,
-                       (PMF)&FGRotation::GetPQRdot);
-  PropertyManager->Tie("accelerations/qdot-rad_sec", this,2,
-                       (PMF)&FGRotation::GetPQRdot);
-  PropertyManager->Tie("accelerations/rdot-rad_sec", this,3,
-                       (PMF)&FGRotation::GetPQRdot);
-  PropertyManager->Tie("attitude/roll-rad", this,1,
-                       (PMF)&FGRotation::GetEuler);
-  PropertyManager->Tie("attitude/pitch-rad", this,2,
-                       (PMF)&FGRotation::GetEuler);
-  PropertyManager->Tie("attitude/heading-true-rad", this,3,
-                       (PMF)&FGRotation::GetEuler);
-  PropertyManager->Tie("velocities/phidot-rad_sec", this,1,
-                       (PMF)&FGRotation::GetEulerRates);
-  PropertyManager->Tie("velocities/thetadot-rad_sec", this,2,
-                       (PMF)&FGRotation::GetEulerRates);
-  PropertyManager->Tie("velocities/psidot-rad_sec", this,3,
-                       (PMF)&FGRotation::GetEulerRates);
-  PropertyManager->Tie("attitude/phi-rad", this,
-                       &FGRotation::Getphi);
-  PropertyManager->Tie("attitude/theta-rad", this,
-                       &FGRotation::Gettht);
-  PropertyManager->Tie("attitude/psi-true-rad", this,
-                       &FGRotation::Getpsi);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGRotation::unbind(void)
-{
-  PropertyManager->Untie("velocities/p-rad_sec");
-  PropertyManager->Untie("velocities/q-rad_sec");
-  PropertyManager->Untie("velocities/r-rad_sec");
-  PropertyManager->Untie("velocities/p-aero-rad_sec");
-  PropertyManager->Untie("velocities/q-aero-rad_sec");
-  PropertyManager->Untie("velocities/r-aero-rad_sec");
-  PropertyManager->Untie("accelerations/pdot-rad_sec");
-  PropertyManager->Untie("accelerations/qdot-rad_sec");
-  PropertyManager->Untie("accelerations/rdot-rad_sec");
-  PropertyManager->Untie("attitude/roll-rad");
-  PropertyManager->Untie("attitude/pitch-rad");
-  PropertyManager->Untie("attitude/heading-true-rad");
-  PropertyManager->Untie("velocities/phidot-rad_sec");
-  PropertyManager->Untie("velocities/thetadot-rad_sec");
-  PropertyManager->Untie("velocities/psidot-rad_sec");
-  PropertyManager->Untie("attitude/phi-rad");
-  PropertyManager->Untie("attitude/theta-rad");
-  PropertyManager->Untie("attitude/psi-true-rad");
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    The bitmasked value choices are as follows:
-//    unset: In this case (the default) JSBSim would only print
-//       out the normally expected messages, essentially echoing
-//       the config files as they are read. If the environment
-//       variable is not set, debug_lvl is set to 1 internally
-//    0: This requests JSBSim not to output any messages
-//       whatsoever.
-//    1: This value explicity requests the normal JSBSim
-//       startup messages
-//    2: This value asks for a message to be printed out when
-//       a class is instantiated
-//    4: When this value is set, a message is displayed when a
-//       FGModel object executes its Run() method
-//    8: When this value is set, various runtime state variables
-//       are printed out periodically
-//    16: When set various parameters are sanity checked and
-//       a message is printed out when they go out of bounds
-
-void FGRotation::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGRotation" << endl;
-    if (from == 1) cout << "Destroyed:    FGRotation" << endl;
-  }
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
-  }
-  if (debug_lvl & 8 ) { // Runtime state variables
-  }
-  if (debug_lvl & 16) { // Sanity check variables
-    if (from == 2) {
-      if (fabs(vPQR(eP)) > 100)
-        cout << "FGRotation::P (Roll Rate) out of bounds: " << vPQR(eP) << endl;
-      if (fabs(vPQR(eQ)) > 100)
-        cout << "FGRotation::Q (Pitch Rate) out of bounds: " << vPQR(eQ) << endl;
-      if (fabs(vPQR(eR)) > 100)
-        cout << "FGRotation::R (Yaw Rate) out of bounds: " << vPQR(eR) << endl;
-    }
-  }
-  if (debug_lvl & 64) {
-    if (from == 0) { // Constructor
-      cout << IdSrc << endl;
-      cout << IdHdr << endl;
-    }
-  }
-}
-}
diff --git a/src/FDM/JSBSim/FGRotation.h b/src/FDM/JSBSim/FGRotation.h
deleted file mode 100644 (file)
index 85ee9b2..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGRotation.h
- Author:       Jon Berndt
- Date started: 12/02/98
-
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-HISTORY
---------------------------------------------------------------------------------
-12/02/98   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGROTATION_H
-#define FGROTATION_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  include <math.h>
-#else
-#  if defined (sgi) && !defined(__GNUC__)
-#    include <math.h>
-#  else
-#    include <cmath>
-#  endif
-#endif
-
-#include "FGModel.h"
-#include "FGColumnVector3.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_ROTATION "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models the rotational portion of the Equations of Motion.
-    Note: The order of rotations used in this class corresponds to a 3-2-1 sequence,
-    or Y-P-R, or Z-Y-X, if you prefer.
-    @see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
-    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
-    School, January 1994
-    @see D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
-    JSC 12960, July 1977
-    @see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
-    NASA-Ames", NASA CR-2497, January 1975
-    @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
-    Wiley & Sons, 1979 ISBN 0-471-03032-5
-    @see Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
-    1982 ISBN 0-471-08936-2
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGRotation : public FGModel
-{
-public:
-  FGRotation(FGFDMExec*);
-  ~FGRotation();
-
-  bool Run(void);
-
-  inline FGColumnVector3& GetPQR(void) {return vPQR;}
-  inline double GetPQR(int axis) const {return vPQR(axis);}
-  inline FGColumnVector3& GetAeroPQR(void) {return vAeroPQR;}
-  inline double GetAeroPQR(int axis) const {return vAeroPQR(axis);}
-  inline FGColumnVector3& GetPQRdot(void) {return vPQRdot;}
-  inline double GetPQRdot(int idx) const {return vPQRdot(idx);}
-  inline FGColumnVector3& GetEuler(void) {return vEuler;}
-  inline double GetEuler(int axis) const {return vEuler(axis);}
-  inline FGColumnVector3& GetEulerRates(void) { return vEulerRates; }
-  inline double GetEulerRates(int axis) const { return vEulerRates(axis); }
-  inline void SetPQR(FGColumnVector3 tt) {vPQR = tt;}
-  inline void SetPQR(double p, double q, double r) {vPQR(eP)=p;
-                                                    vPQR(eQ)=q;
-                                                    vPQR(eR)=r;}
-  inline void SetAeroPQR(FGColumnVector3 tt) {vAeroPQR = tt;}
-  inline void SetAeroPQR(double p, double q, double r) {vAeroPQR(eP)=p;
-                                                        vAeroPQR(eQ)=q;
-                                                        vAeroPQR(eR)=r;}
-  inline void SetEuler(FGColumnVector3 tt) {vEuler = tt;}
-
-  inline double Getphi(void) const {return vEuler(1);}
-  inline double Gettht(void) const {return vEuler(2);}
-  inline double Getpsi(void) const {return vEuler(3);}
-
-  inline double GetCosphi(void) const {return cPhi;}
-  inline double GetCostht(void) const {return cTht;}
-  inline double GetCospsi(void) const {return cPsi;}
-
-  inline double GetSinphi(void) const {return sPhi;}
-  inline double GetSintht(void) const {return sTht;}
-  inline double GetSinpsi(void) const {return sPsi;}
-
-  void bind(void);
-  void unbind(void);
-
-private:
-  FGColumnVector3 vPQR;
-  FGColumnVector3 vAeroPQR;
-  FGColumnVector3 vPQRdot;
-  FGColumnVector3 vPQRdot_prev[4];
-  FGColumnVector3 vMoments;
-  FGColumnVector3 vEuler;
-  FGColumnVector3 vEulerRates;
-
-  double cTht,sTht;
-  double cPhi,sPhi;
-  double cPsi,sPsi;
-
-  double dt;
-
-  void GetState(void);
-
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
index 71436a97c61e7fc11b9fdf4ad81d9e8a4ba3441b..8332f13a859d0d40478cbdbab308d66d8e7f9df8 100644 (file)
@@ -66,6 +66,20 @@ double FGRotor::Calculate(double PowerAvailable)
   return 0.0;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRotor::GetThrusterLabels(int id)
+{
+  return "";
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRotor::GetThrusterValues(int id)
+{
+  return "";
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
index b699391f7ed48d1e1be5fda2165b90f555eea5e3..2fddbaf2a79b7d9998cc4fe3f8876d55cd1254b1 100644 (file)
@@ -70,6 +70,8 @@ public:
   ~FGRotor();
 
   double Calculate(double);
+  string GetThrusterLabels(int id);
+  string GetThrusterValues(int id);
 
 private:
   void Debug(int from);
diff --git a/src/FDM/JSBSim/FGSimTurbine.cpp b/src/FDM/JSBSim/FGSimTurbine.cpp
deleted file mode 100644 (file)
index cb65334..0000000
+++ /dev/null
@@ -1,447 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGSimTurbine.cpp
- Author:       David Culp
- Date started: 03/11/2003
- Purpose:      This module models a turbine engine.
-
- ------------- Copyright (C) 2003  David Culp (davidculp2@comcast.net) ---------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-
-This class descends from the FGEngine class and models a Turbine engine based
-on parameters given in the engine config file for this class
-
-HISTORY
---------------------------------------------------------------------------------
-03/11/2003  DPC  Created
-09/08/2003  DPC  Changed Calculate() and added engine phases 
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <vector>
-#include "FGSimTurbine.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_SIMTURBINE;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGSimTurbine::FGSimTurbine(FGFDMExec* exec, FGConfigFile* cfg) : FGEngine(exec)
-{
-  SetDefaults();
-
-  Load(cfg);
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGSimTurbine::~FGSimTurbine()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// The main purpose of Calculate() is to determine what phase the engine should
-// be in, then call the corresponding function. 
-
-double FGSimTurbine::Calculate(double dummy)
-{
-  TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
-  dt = State->Getdt() * Propulsion->GetRate();
-  ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
-
-  // When trimming is finished check if user wants engine OFF or RUNNING
-  if ((phase == tpTrim) && (dt > 0)) {
-    if (Running && !Starved) {
-      phase = tpRun;
-      N2 = IdleN2;
-      N1 = IdleN1;
-      OilTemp_degK = 366.0;  
-      Cutoff = false;
-      }
-    else {
-      phase = tpOff;
-      Cutoff = true;
-      EGT_degC = TAT; 
-      }
-    }
-  
-  if (!Running && Cutoff && Starter) {
-     if (phase == tpOff) phase = tpSpinUp;
-     }
-  if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart;
-  if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
-  if (dt == 0) phase = tpTrim;
-  if (Starved) phase = tpOff;
-  if (Stalled) phase = tpStall;
-  if (Seized) phase = tpSeize;
-  
-  switch (phase) {
-    case tpOff:    Thrust = Off(); break;
-    case tpRun:    Thrust = Run(); break;
-    case tpSpinUp: Thrust = SpinUp(); break;
-    case tpStart:  Thrust = Start(); break;
-    case tpStall:  Thrust = Stall(); break;
-    case tpSeize:  Thrust = Seize(); break;
-    case tpTrim:   Thrust = Trim(); break;
-    default: Thrust = Off();
-  }   
-
-  return Thrust;  
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::Off(void)
-{
-  double qbar = Translation->Getqbar();
-  Running = false;
-  FuelFlow_pph = Seek(&FuelFlow_pph, 0, 1000.0, 10000.0);
-  N1 = Seek(&N1, qbar/10.0, N1/2.0, N1/2.0);
-  N2 = Seek(&N2, qbar/15.0, N2/2.0, N2/2.0);
-  EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3);
-  OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2);  
-  OilPressure_psi = N2 * 0.62;
-  NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
-  EPR = Seek(&EPR, 1.0, 0.2, 0.2);
-  Augmentation = false;
-  return 0.0; 
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::Run(void)
-{
-  double idlethrust, milthrust, thrust;
-  double N2norm;   // 0.0 = idle N2, 1.0 = maximum N2
-  idlethrust = MilThrust * ThrustTables[0]->TotalValue();
-  milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
-
-  Running = true;
-  Starter = false;
-  N2 = Seek(&N2, IdleN2 + ThrottleCmd * N2_factor, delay, delay * 3.0);
-  N1 = Seek(&N1, IdleN1 + ThrottleCmd * N1_factor, delay, delay * 2.4);
-  N2norm = (N2 - IdleN2) / N2_factor;
-  thrust = idlethrust + (milthrust * N2norm * N2norm); 
-  thrust = thrust * (1.0 - BleedDemand);
-  EGT_degC = TAT + 363.1 + ThrottleCmd * 357.1;
-  OilPressure_psi = N2 * 0.62;
-  OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1);
-  EPR = 1.0 + thrust/MilThrust;
-
-  if (!Augmentation) {
-    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * TSFC, 1000.0, 100000);
-    if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
-    NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
-  }
-
-  if (AugMethod == 1) {
-    if ((ThrottleCmd > 0.99) && (N2 > 97.0)) {Augmentation = true;} 
-    else {Augmentation = false;}
-  }
-
-  if ((Augmented == 1) && Augmentation) {
-    thrust = MaxThrust * ThrustTables[2]->TotalValue();
-    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
-    NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
-  }
-
-  if ((Injected == 1) && Injection)
-    thrust = thrust * ThrustTables[3]->TotalValue(); 
-
-  ConsumeFuel();
-  if (Cutoff) phase = tpOff;
-  if (Starved) phase = tpOff;
-
-  return thrust;
-}
-        
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::SpinUp(void)
-{
-  Running = false;
-  FuelFlow_pph = 0.0;
-  N2 = Seek(&N2, 25.18, 3.0, N2/2.0);
-  N1 = Seek(&N1, 5.21, 1.0, N1/2.0);
-  EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3);
-  OilPressure_psi = N2 * 0.62;
-  OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2);
-  EPR = 1.0;
-  NozzlePosition = 1.0;
-
-  return 0.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::Start(void)
-{
-  if ((N2 > 15.0) && !Starved) {       // minimum 15% N2 needed for start
-    Cranking = true;                   // provided for sound effects signal
-    if (N2 < IdleN2) {
-      N2 = Seek(&N2, IdleN2, 2.0, N2/2.0);
-      N1 = Seek(&N1, IdleN1, 1.4, N1/2.0);
-      EGT_degC = Seek(&EGT_degC, TAT + 363.1, 21.3, 7.3);
-      FuelFlow_pph = Seek(&FuelFlow_pph, IdleFF, 103.7, 103.7);
-      OilPressure_psi = N2 * 0.62;
-      }
-    else {
-      phase = tpRun;
-      Running = true;
-      Starter = false;
-      Cranking = false;
-      } 
-    }
-  else {                 // no start if N2 < 15%
-    phase = tpOff;
-    Starter = false;
-    }
-
-  return 0.0; 
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::Stall(void)
-{
-  double qbar = Translation->Getqbar();
-  EGT_degC = TAT + 903.14;
-  FuelFlow_pph = IdleFF;
-  N1 = Seek(&N1, qbar/10.0, 0, N1/10.0); 
-  N2 = Seek(&N2, qbar/15.0, 0, N2/10.0);
-  if (ThrottleCmd == 0) phase = tpRun;        // clear the stall with throttle
-
-  return 0.0; 
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::Seize(void)
-{
-    double qbar = Translation->Getqbar();
-    N2 = 0.0;
-    N1 = Seek(&N1, qbar/20.0, 0, N1/15.0);
-    FuelFlow_pph = IdleFF;
-    OilPressure_psi = 0.0;
-    OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0, 0.2);
-    Running = false;
-    return 0.0; 
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::Trim(void)
-{
-    double idlethrust, milthrust, thrust;
-    idlethrust = MilThrust * ThrustTables[0]->TotalValue();
-    milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
-    thrust = idlethrust + (milthrust * ThrottleCmd * ThrottleCmd);
-    return thrust; 
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::CalcFuelNeed(void)
-{
-  return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::GetPowerAvailable(void) {
-  if( ThrottleCmd <= 0.77 )
-    return 64.94*ThrottleCmd;
-  else
-    return 217.38*ThrottleCmd - 117.38;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGSimTurbine::Seek(double *var, double target, double accel, double decel) {
-  double v = *var;
-  if (v > target) {
-    v -= dt * decel;
-    if (v < target) v = target;
-  } else if (v < target) {
-    v += dt * accel;
-    if (v > target) v = target;
-  }
-  return v;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGSimTurbine::SetDefaults(void)
-{
-  Name = "Not defined";
-  N1 = N2 = 0.0;
-  Type = etSimTurbine;
-  MilThrust = 10000.0;
-  MaxThrust = 10000.0;
-  BypassRatio = 0.0;
-  TSFC = 0.8;
-  ATSFC = 1.7;
-  IdleN1 = 30.0;
-  IdleN2 = 60.0;
-  MaxN1 = 100.0;
-  MaxN2 = 100.0;
-  Augmented = 0;
-  AugMethod = 0;
-  Injected = 0;
-  BleedDemand = 0.0;
-  ThrottleCmd = 0.0;
-  InletPosition = 1.0;
-  NozzlePosition = 1.0;
-  Augmentation = false;
-  Injection = false;
-  Reversed = false;
-  Cutoff = true;
-  phase = tpOff;
-  Stalled = false;
-  Seized = false;
-  Overtemp = false;
-  Fire = false;
-  EGT_degC = 0.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGSimTurbine::Load(FGConfigFile *Eng_cfg)
-{
-  string token;
-
-  Name = Eng_cfg->GetValue("NAME");
-  Eng_cfg->GetNextConfigLine();
-  int counter=0;
-
-  while (Eng_cfg->GetValue() != string("/FG_SIMTURBINE")) {
-    *Eng_cfg >> token;
-
-    if (token[0] == '<') token.erase(0,1); // Tables are read "<TABLE"
-
-    if      (token == "MILTHRUST") *Eng_cfg >> MilThrust;
-    else if (token == "MAXTHRUST") *Eng_cfg >> MaxThrust;
-    else if (token == "BYPASSRATIO") *Eng_cfg >> BypassRatio;
-    else if (token == "TSFC") *Eng_cfg >> TSFC;
-    else if (token == "ATSFC") *Eng_cfg >> ATSFC;
-    else if (token == "IDLEN1") *Eng_cfg >> IdleN1;
-    else if (token == "IDLEN2") *Eng_cfg >> IdleN2;
-    else if (token == "MAXN1") *Eng_cfg >> MaxN1;
-    else if (token == "MAXN2") *Eng_cfg >> MaxN2;
-    else if (token == "AUGMENTED") *Eng_cfg >> Augmented;
-    else if (token == "AUGMETHOD") *Eng_cfg >> AugMethod;
-    else if (token == "INJECTED") *Eng_cfg >> Injected;
-    else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle;
-    else if (token == "TABLE") {
-      if (counter++ == 0) Debug(2); // print engine specs prior to table read
-      ThrustTables.push_back( new FGCoefficient(FDMExec) );
-      ThrustTables.back()->Load(Eng_cfg);
-    }
-    else cerr << "Unhandled token in Engine config file: " << token << endl;
-  }
-
-  // Pre-calculations and initializations
-
-  delay = 60.0 / (BypassRatio + 3.0);
-  N1_factor = MaxN1 - IdleN1;
-  N2_factor = MaxN2 - IdleN2;
-  OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
-  IdleFF = pow(MilThrust, 0.2) * 107.0;  // just an estimate
-
-  return true;
-}
-
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    The bitmasked value choices are as follows:
-//    unset: In this case (the default) JSBSim would only print
-//       out the normally expected messages, essentially echoing
-//       the config files as they are read. If the environment
-//       variable is not set, debug_lvl is set to 1 internally
-//    0: This requests JSBSim not to output any messages
-//       whatsoever.
-//    1: This value explicity requests the normal JSBSim
-//       startup messages
-//    2: This value asks for a message to be printed out when
-//       a class is instantiated
-//    4: When this value is set, a message is displayed when a
-//       FGModel object executes its Run() method
-//    8: When this value is set, various runtime state variables
-//       are printed out periodically
-//    16: When set various parameters are sanity checked and
-//       a message is printed out when they go out of bounds
-
-void FGSimTurbine::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-
-    }
-    if (from == 2) { // called from Load()
-      cout << "\n    Engine Name: "         << Name << endl;
-      cout << "      MilThrust:   "         << MilThrust << endl;
-      cout << "      MaxThrust:   "         << MaxThrust << endl;
-      cout << "      BypassRatio: "         << BypassRatio << endl;
-      cout << "      TSFC:        "         << TSFC << endl;
-      cout << "      ATSFC:       "         << ATSFC << endl;
-      cout << "      IdleN1:      "         << IdleN1 << endl;
-      cout << "      IdleN2:      "         << IdleN2 << endl;
-      cout << "      MaxN1:       "         << MaxN1 << endl;
-      cout << "      MaxN2:       "         << MaxN2 << endl;
-      cout << "      Augmented:   "         << Augmented << endl;
-      cout << "      AugMethod:   "         << AugMethod << endl;
-      cout << "      Injected:    "         << Injected << endl;
-      cout << "      MinThrottle: "         << MinThrottle << endl;
-
-      cout << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGSimTurbine" << endl;
-    if (from == 1) cout << "Destroyed:    FGSimTurbine" << endl;
-  }
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
-  }
-  if (debug_lvl & 8 ) { // Runtime state variables
-  }
-  if (debug_lvl & 16) { // Sanity checking
-  }
-  if (debug_lvl & 64) {
-    if (from == 0) { // Constructor
-      cout << IdSrc << endl;
-      cout << IdHdr << endl;
-    }
-  }
-}
-}
diff --git a/src/FDM/JSBSim/FGSimTurbine.h b/src/FDM/JSBSim/FGSimTurbine.h
deleted file mode 100644 (file)
index b62dd94..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGSimTurbine.h
- Author:       David Culp
- Date started: 03/11/2003
-
- ------------- Copyright (C) 2003  David Culp (davidculp2@comcast.net)----------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-HISTORY
---------------------------------------------------------------------------------
-03/11/2003  DPC  Created, based on FGTurbine
-09/22/2003  DPC  Added starting, stopping, new framework 
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGSIMTURBINE_H
-#define FGSIMTURBINE_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <vector>
-#include "FGEngine.h"
-#include "FGConfigFile.h"
-#include "FGCoefficient.h"
-
-#define ID_SIMTURBINE "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** This class models a turbine engine.  Based on Jon Berndt's FGTurbine module.
-    Here the term "phase" signifies the engine's mode of operation.  At any given
-    time the engine is in only one phase.  At simulator startup the engine will be
-    placed in the Trim phase in order to provide a simplified thrust value without
-    throttle lag.  When trimming is complete the engine will go to the Off phase,
-    unless the value FGEngine::Running has been previously set to true, in which
-    case the engine will go to the Run phase.  Once an engine is in the Off phase
-    the full starting procedure (or airstart) must be used to get it running.
-<P>
-    - STARTING (on ground):
-      -# Set the control FGEngine::Starter to true.  The engine will spin up to
-         a maximum of about %25 N2 (%5.2 N1).  This simulates the action of a
-         pneumatic starter.
-      -# After reaching %15 N2 set the control FGEngine::Cutoff to false. If fuel
-         is available the engine will now accelerate to idle.  The starter will
-         automatically be set to false after the start cycle.
-<P>
-    - STARTING (in air):
-      -# Increase speed to obtain a minimum of %15 N2.  If this is not possible,
-         the starter may be used to assist.
-      -# Place the control FGEngine::Cutoff to false.
-<P>
-    Ignition is assumed to be on anytime the Cutoff control is set to false, 
-    therefore a seperate ignition system is not modeled.
-
-Configuration File Format
-<pre>
-\<FG_SIMTURBINE NAME="<name>">
-  MILTHRUST   \<thrust>
-  MAXTHRUST   \<thrust>
-  BYPASSRATIO \<bypass ratio>
-  TSFC        \<thrust specific fuel consumption>
-  ATSFC       \<afterburning thrust specific fuel consumption>
-  IDLEN1      \<idle N1>
-  IDLEN2      \<idle N2>
-  MAXN1       \<max N1>
-  MAXN2       \<max N2>
-  AUGMENTED   \<0|1>
-  AUGMETHOD   \<0|1>
-  INJECTED    \<0|1>
-  ...
-\</FG_SIMTURBINE>
-</pre>
-Definition of the turbine engine configuration file parameters:
-<pre>
-<b>MILTHRUST</b> - Maximum thrust, static, at sea level, lbf.
-<b>MAXTHRUST</b> - Afterburning thrust, static, at sea level, lbf
-[this value will be ignored when AUGMENTED is zero (false)].
-<b>BYPASSRATIO</b> - Ratio of bypass air flow to core air flow.
-<b>TSFC</b> - Thrust-specific fuel consumption, lbm/hr/lbf
-[i.e. fuel flow divided by thrust].
-<b>ATSFC</b> - Afterburning TSFC, lbm/hr/lbf
-[this value will be ignored when AUGMENTED is zero (false)]
-<b>IDLEN1</b> - Fan rotor rpm (% of max) at idle
-<b>IDLEN2</b> - Core rotor rpm (% of max) at idle
-<b>MAXN1</b> - Fan rotor rpm (% of max) at full throttle [not always 100!] 
-<b>MAXN2</b> - Core rotor rpm (% of max) at full throttle [not always 100!]
-<b>AUGMENTED</b>
-  0 == afterburner not installed
-  1 == afterburner installed
-<b>AUGMETHOD</b>
-  0 == afterburner activated by property /engines/engine[n]/augmentation
-  1 == afterburner activated by pushing throttle above 99% position
-  [this item will be ignored when AUGMENTED == 0]
-<b>INJECTED</b>
-  0 == Water injection not installed
-  1 == Water injection installed
-</pre>
-    @author David P. Culp
-    @version "$Id$"
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGSimTurbine : public FGEngine
-{
-public:
-  /** Constructor
-      @param Executive pointer to executive structure
-      @param Eng_cfg pointer to engine config file instance */
-  FGSimTurbine(FGFDMExec* Executive, FGConfigFile* Eng_cfg);
-  /// Destructor
-  ~FGSimTurbine();
-
-  enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
-
-  double Calculate(double PowerRequired);
-  double CalcFuelNeed(void);
-  double GetPowerAvailable(void);
-  double Seek(double* var, double target, double accel, double decel);
-
-  phaseType GetPhase(void) { return phase; }
-
-  bool GetOvertemp(void)  {return Overtemp; }
-  bool GetInjection(void) {return Injection;}
-  bool GetFire(void) { return Fire; }
-  bool GetAugmentation(void) {return Augmentation;}
-  bool GetReversed(void) { return Reversed; }
-  bool GetCutoff(void) { return Cutoff; }
-  int GetIgnition(void) {return Ignition;}
-
-  double GetInlet(void) { return InletPosition; }
-  double GetNozzle(void) { return NozzlePosition; } 
-  double GetBleedDemand(void) {return BleedDemand;}
-  double GetN1(void) {return N1;}
-  double GetN2(void) {return N2;}
-  double GetEPR(void) {return EPR;}
-  double GetEGT(void) {return EGT_degC;}
-
-  double getOilPressure_psi () const {return OilPressure_psi;}
-  double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);}
-
-  void SetInjection(bool injection) {Injection = injection;}
-  void SetIgnition(int ignition) {Ignition = ignition;}
-  void SetAugmentation(bool augmentation) {Augmentation = augmentation;}
-  void SetPhase( phaseType p ) { phase = p; }
-  void SetEPR(double epr) {EPR = epr;}
-  void SetBleedDemand(double bleedDemand) {BleedDemand = bleedDemand;}
-  void SetReverse(bool reversed) { Reversed = reversed; }
-  void SetCutoff(bool cutoff) { Cutoff = cutoff; }
-
-private:
-
-  typedef vector<FGCoefficient*> CoeffArray;
-  CoeffArray ThrustTables;
-
-  phaseType phase;         ///< Operating mode, or "phase"
-  double MilThrust;        ///< Maximum Unaugmented Thrust, static @ S.L. (lbf)
-  double MaxThrust;        ///< Maximum Augmented Thrust, static @ S.L. (lbf)
-  double BypassRatio;      ///< Bypass Ratio
-  double TSFC;             ///< Thrust Specific Fuel Consumption (lbm/hr/lbf)
-  double ATSFC;            ///< Augmented TSFC (lbm/hr/lbf)
-  double IdleN1;           ///< Idle N1
-  double IdleN2;           ///< Idle N2
-  double N1;               ///< N1
-  double N2;               ///< N2
-  double MaxN1;            ///< N1 at 100% throttle
-  double MaxN2;            ///< N2 at 100% throttle
-  double IdleFF;           ///< Idle Fuel Flow (lbm/hr)
-  double delay;            ///< Inverse spool-up time from idle to 100% (seconds)
-  double dt;               ///< Simulator time slice
-  double N1_factor;        ///< factor to tie N1 and throttle
-  double N2_factor;        ///< factor to tie N2 and throttle
-  double ThrottleCmd;      ///< FCS-supplied throttle position
-  double TAT;              ///< total air temperature (deg C)
-  bool Stalled;            ///< true if engine is compressor-stalled
-  bool Seized;             ///< true if inner spool is seized
-  bool Overtemp;           ///< true if EGT exceeds limits
-  bool Fire;               ///< true if engine fire detected
-  bool Injection;
-  bool Augmentation;
-  bool Reversed;
-  bool Cutoff;
-  int Injected;            ///< = 1 if water injection installed
-  int Ignition;
-  int Augmented;           ///< = 1 if augmentation installed
-  int AugMethod;           ///< = 0 if using property /engine[n]/augmentation
-                           ///< = 1 if using last 1% of throttle movement
-  double EGT_degC;
-  double EPR;
-  double OilPressure_psi;
-  double OilTemp_degK;
-  double BleedDemand;
-  double InletPosition;
-  double NozzlePosition;
-
-  double Off(void);
-  double Run(void);
-  double SpinUp(void);
-  double Start(void);
-  double Stall(void);
-  double Seize(void);
-  double Trim(void);
-
-  void SetDefaults(void);
-  bool Load(FGConfigFile *ENG_cfg);
-  void Debug(int from);
-
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
index 6144d7eea61cc31932ab34e6dd2650cee6c99a0c..d21a82b66d34b2867982120fc939f0de7b590ddf 100644 (file)
@@ -47,8 +47,8 @@ INCLUDES
 #  endif
 #endif
 
-#ifdef _MSC_VER
-#define snprintf _snprintf
+#ifdef _WIN32
+//#define snprintf _snprintf
 #endif
 
 #include "FGState.h"
@@ -74,9 +74,8 @@ FGState::FGState(FGFDMExec* fdex)
   dt = 1.0/120.0;
 
   Aircraft     = FDMExec->GetAircraft();
-  Translation  = FDMExec->GetTranslation();
-  Rotation     = FDMExec->GetRotation();
-  Position     = FDMExec->GetPosition();
+  Propagate    = FDMExec->GetPropagate();
+  Auxiliary    = FDMExec->GetAuxiliary();
   FCS          = FDMExec->GetFCS();
   Output       = FDMExec->GetOutput();
   Atmosphere   = FDMExec->GetAtmosphere();
@@ -85,8 +84,6 @@ FGState::FGState(FGFDMExec* fdex)
   Propulsion      = FDMExec->GetPropulsion();
   PropertyManager = FDMExec->GetPropertyManager();
 
-  for(int i=0;i<4;i++) vQdot_prev[i].InitMatrix();
-
   bind();
 
   Debug(0);
@@ -100,39 +97,23 @@ FGState::~FGState()
   Debug(1);
 }
 
-//***************************************************************************
-//
-// Initialize: Assume all angles GIVEN IN RADIANS !!
-//
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGState::Initialize(double U, double V, double W,
-                         double phi, double tht, double psi,
-                         double Latitude, double Longitude, double H,
-                         double wnorth, double weast, double wdown)
+void FGState::Initialize(FGInitialCondition *FGIC)
 {
-  double alpha, beta;
-  double qbar, Vt;
-  FGColumnVector3 vAeroUVW;
-  FGColumnVector3 vUVW;
+  sim_time = 0.0;
 
-  Position->SetLatitude(Latitude);
-  Position->SetLongitude(Longitude);
-  Position->Seth(H);
+  Propagate->SetInitialState( FGIC );
 
   Atmosphere->Run();
+  Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(),
+                          FGIC->GetWindEFpsIC(),
+                          FGIC->GetWindDFpsIC() );
 
-  vLocalEuler << phi << tht << psi;
-  Rotation->SetEuler(vLocalEuler);
-
-  InitMatrices(phi, tht, psi);
-
-  vUVW << U << V << W;
-  Translation->SetUVW(vUVW);
-
-  Atmosphere->SetWindNED(wnorth, weast, wdown);
-
-  vAeroUVW = vUVW + mTl2b*Atmosphere->GetWindNED();
+  FGColumnVector3 vAeroUVW;
+  vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetWindNED();
 
+  double alpha, beta;
   if (vAeroUVW(eW) != 0.0)
     alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
   else
@@ -142,148 +123,15 @@ void FGState::Initialize(double U, double V, double W,
   else
     beta = 0.0;
 
-  Translation->SetAB(alpha, beta);
+  Auxiliary->SetAB(alpha, beta);
 
-  Vt = sqrt(U*U + V*V + W*W);
-  Translation->SetVt(Vt);
+  double Vt = vAeroUVW.Magnitude();
+  Auxiliary->SetVt(Vt);
 
-  Translation->SetMach(Vt/Atmosphere->GetSoundSpeed());
+  Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed());
 
-  qbar = 0.5*(U*U + V*V + W*W)*Atmosphere->GetDensity();
-  Translation->Setqbar(qbar);
-
-  vLocalVelNED = mTb2l*vUVW;
-  Position->SetvVel(vLocalVelNED);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGState::Initialize(FGInitialCondition *FGIC)
-{
-  double tht,psi,phi;
-  double U, V, W, h;
-  double latitude, longitude;
-  double wnorth,weast, wdown;
-
-  latitude = FGIC->GetLatitudeRadIC();
-  longitude = FGIC->GetLongitudeRadIC();
-  h = FGIC->GetAltitudeFtIC();
-  U = FGIC->GetUBodyFpsIC();
-  V = FGIC->GetVBodyFpsIC();
-  W = FGIC->GetWBodyFpsIC();
-  tht = FGIC->GetThetaRadIC();
-  phi = FGIC->GetPhiRadIC();
-  psi = FGIC->GetPsiRadIC();
-  wnorth = FGIC->GetWindNFpsIC();
-  weast = FGIC->GetWindEFpsIC();
-  wdown = FGIC->GetWindDFpsIC();
-
-  Position->SetSeaLevelRadius( FGIC->GetSeaLevelRadiusFtIC() );
-  Position->SetRunwayRadius( FGIC->GetSeaLevelRadiusFtIC() +
-                                             FGIC->GetTerrainAltitudeFtIC() );
-
-  // need to fix the wind speed args, here.
-  Initialize(U, V, W, phi, tht, psi, latitude, longitude, h, wnorth, weast, wdown);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGState::InitMatrices(double phi, double tht, double psi)
-{
-  double thtd2, psid2, phid2;
-  double Sthtd2, Spsid2, Sphid2;
-  double Cthtd2, Cpsid2, Cphid2;
-  double Cphid2Cthtd2;
-  double Cphid2Sthtd2;
-  double Sphid2Sthtd2;
-  double Sphid2Cthtd2;
-
-  thtd2 = tht/2.0;
-  psid2 = psi/2.0;
-  phid2 = phi/2.0;
-
-  Sthtd2 = sin(thtd2);
-  Spsid2 = sin(psid2);
-  Sphid2 = sin(phid2);
-
-  Cthtd2 = cos(thtd2);
-  Cpsid2 = cos(psid2);
-  Cphid2 = cos(phid2);
-
-  Cphid2Cthtd2 = Cphid2*Cthtd2;
-  Cphid2Sthtd2 = Cphid2*Sthtd2;
-  Sphid2Sthtd2 = Sphid2*Sthtd2;
-  Sphid2Cthtd2 = Sphid2*Cthtd2;
-
-  vQtrn(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2;
-  vQtrn(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2;
-  vQtrn(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2;
-  vQtrn(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2;
-
-  CalcMatrices();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGState::CalcMatrices(void)
-{
-  double Q0Q0, Q1Q1, Q2Q2, Q3Q3;
-  double Q0Q1, Q0Q2, Q0Q3, Q1Q2;
-  double Q1Q3, Q2Q3;
-
-  Q0Q0 = vQtrn(1)*vQtrn(1);
-  Q1Q1 = vQtrn(2)*vQtrn(2);
-  Q2Q2 = vQtrn(3)*vQtrn(3);
-  Q3Q3 = vQtrn(4)*vQtrn(4);
-  Q0Q1 = vQtrn(1)*vQtrn(2);
-  Q0Q2 = vQtrn(1)*vQtrn(3);
-  Q0Q3 = vQtrn(1)*vQtrn(4);
-  Q1Q2 = vQtrn(2)*vQtrn(3);
-  Q1Q3 = vQtrn(2)*vQtrn(4);
-  Q2Q3 = vQtrn(3)*vQtrn(4);
-
-  mTl2b(1,1) = Q0Q0 + Q1Q1 - Q2Q2 - Q3Q3;
-  mTl2b(1,2) = 2*(Q1Q2 + Q0Q3);
-  mTl2b(1,3) = 2*(Q1Q3 - Q0Q2);
-  mTl2b(2,1) = 2*(Q1Q2 - Q0Q3);
-  mTl2b(2,2) = Q0Q0 - Q1Q1 + Q2Q2 - Q3Q3;
-  mTl2b(2,3) = 2*(Q2Q3 + Q0Q1);
-  mTl2b(3,1) = 2*(Q1Q3 + Q0Q2);
-  mTl2b(3,2) = 2*(Q2Q3 - Q0Q1);
-  mTl2b(3,3) = Q0Q0 - Q1Q1 - Q2Q2 + Q3Q3;
-
-  mTb2l = mTl2b;
-  mTb2l.T();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGState::IntegrateQuat(FGColumnVector3 vPQR, int rate)
-{
-  vQdot(1) = -0.5*(vQtrn(2)*vPQR(eP) + vQtrn(3)*vPQR(eQ) + vQtrn(4)*vPQR(eR));
-  vQdot(2) =  0.5*(vQtrn(1)*vPQR(eP) + vQtrn(3)*vPQR(eR) - vQtrn(4)*vPQR(eQ));
-  vQdot(3) =  0.5*(vQtrn(1)*vPQR(eQ) + vQtrn(4)*vPQR(eP) - vQtrn(2)*vPQR(eR));
-  vQdot(4) =  0.5*(vQtrn(1)*vPQR(eR) + vQtrn(2)*vPQR(eQ) - vQtrn(3)*vPQR(eP));
-
-  vQtrn += Integrate(TRAPZ, dt*rate, vQdot, vQdot_prev);
-
-  vQtrn.Normalize();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector3& FGState::CalcEuler(void)
-{
-  if (mTl2b(3,3) == 0.0) mTl2b(3,3) = 0.0000001;
-  if (mTl2b(1,1) == 0.0) mTl2b(1,1) = 0.0000001;
-
-  vEuler(ePhi) = atan2(mTl2b(2,3), mTl2b(3,3));
-  vEuler(eTht) = asin(-mTl2b(1,3));
-  vEuler(ePsi) = atan2(mTl2b(1,2), mTl2b(1,1));
-
-  if (vEuler(ePsi) < 0.0) vEuler(ePsi) += 2*M_PI;
-
-  return vEuler;
+  double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity();
+  Auxiliary->Setqbar(qbar);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -292,8 +140,8 @@ FGMatrix33& FGState::GetTs2b(void)
 {
   double ca, cb, sa, sb;
 
-  double alpha = Translation->Getalpha();
-  double beta  = Translation->Getbeta();
+  double alpha = Auxiliary->Getalpha();
+  double beta  = Auxiliary->Getbeta();
 
   ca = cos(alpha);
   sa = sin(alpha);
@@ -320,8 +168,8 @@ FGMatrix33& FGState::GetTb2s(void)
   float alpha,beta;
   float ca, cb, sa, sb;
 
-  alpha = Translation->Getalpha();
-  beta  = Translation->Getbeta();
+  alpha = Auxiliary->Getalpha();
+  beta  = Auxiliary->Getbeta();
 
   ca = cos(alpha);
   sa = sin(alpha);
@@ -345,6 +193,7 @@ FGMatrix33& FGState::GetTb2s(void)
 
 void FGState::ReportState(void)
 {
+#if 0
 #if !defined(__BORLANDCPP__)
   char out[80], flap[10], gear[12];
 
@@ -370,33 +219,33 @@ void FGState::ReportState(void)
   snprintf(out,80, "    Flaps: %3s  Gear: %12s\n",flap,gear);
   cout << out;
   snprintf(out,80, "    Speed: %4.0f KCAS  Mach: %5.2f\n",
-                    FDMExec->GetAuxiliary()->GetVcalibratedKTS(),
-                    Translation->GetMach() );
+                    Auxiliary->GetVcalibratedKTS(),
+                    Auxiliary->GetMach() );
   cout << out;
   snprintf(out,80, "    Altitude: %7.0f ft.  AGL Altitude: %7.0f ft.\n",
-                    Position->Geth(),
-                    Position->GetDistanceAGL() );
+                    Propagate->Geth(),
+                    Propagate->GetDistanceAGL() );
   cout << out;
   snprintf(out,80, "    Angle of Attack: %6.2f deg  Pitch Angle: %6.2f deg\n",
-                    Translation->Getalpha()*radtodeg,
-                    Rotation->Gettht()*radtodeg );
+                    Auxiliary->Getalpha()*radtodeg,
+                    Propagate->Gettht()*radtodeg );
   cout << out;
   snprintf(out,80, "    Flight Path Angle: %6.2f deg  Climb Rate: %5.0f ft/min\n",
-                    Position->GetGamma()*radtodeg,
-                    Position->Gethdot()*60 );
+                    Auxiliary->GetGamma()*radtodeg,
+                    Propagate->Gethdot()*60 );
   cout << out;
   snprintf(out,80, "    Normal Load Factor: %4.2f g's  Pitch Rate: %5.2f deg/s\n",
                     Aircraft->GetNlf(),
-                    Rotation->GetPQR(2)*radtodeg );
+                    Propagate->GetPQR(2)*radtodeg );
   cout << out;
   snprintf(out,80, "    Heading: %3.0f deg true  Sideslip: %5.2f deg  Yaw Rate: %5.2f deg/s\n",
-                    Rotation->Getpsi()*radtodeg,
-                    Translation->Getbeta()*radtodeg,
-                    Rotation->GetPQR(3)*radtodeg  );
+                    Propagate->Getpsi()*radtodeg,
+                    Auxiliary->Getbeta()*radtodeg,
+                    Propagate->GetPQR(3)*radtodeg  );
   cout << out;
   snprintf(out,80, "    Bank Angle: %5.2f deg  Roll Rate: %5.2f deg/s\n",
-                    Rotation->Getphi()*radtodeg,
-                    Rotation->GetPQR(1)*radtodeg );
+                    Propagate->Getphi()*radtodeg,
+                    Propagate->GetPQR(1)*radtodeg );
   cout << out;
   snprintf(out,80, "    Elevator: %5.2f deg  Left Aileron: %5.2f deg  Rudder: %5.2f deg\n",
                     FCS->GetDePos(ofRad)*radtodeg,
@@ -408,15 +257,16 @@ void FGState::ReportState(void)
   cout << out;
 
   snprintf(out,80, "    Wind Components: %5.2f kts head wind, %5.2f kts cross wind\n",
-                    FDMExec->GetAuxiliary()->GetHeadWind()*fpstokts,
-                    FDMExec->GetAuxiliary()->GetCrossWind()*fpstokts );
+                    Auxiliary->GetHeadWind()*fpstokts,
+                    Auxiliary->GetCrossWind()*fpstokts );
   cout << out;
 
   snprintf(out,80, "    Ground Speed: %4.0f knots , Ground Track: %3.0f deg true\n",
-                    Position->GetVground()*fpstokts,
-                    Position->GetGroundTrack()*radtodeg );
+                    Auxiliary->GetVground()*fpstokts,
+                    Auxiliary->GetGroundTrack()*radtodeg );
   cout << out;
 #endif
+#endif
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 5b43ea502336306a73cdaa0f0ff036e9827531cb..8709b00b35d7418f2ea4b1252f28784eda92bd6d 100644 (file)
@@ -1,35 +1,35 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
  Header:       FGState.h
  Author:       Jon S. Berndt
  Date started: 11/17/98
+
  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
+
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.
+
  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place - Suite 330, Boston, MA  02111-1307, USA.
+
  Further information about the GNU General Public License can also be found on
  the world wide web at http://www.gnu.org.
+
 FUNCTIONAL DESCRIPTION
 --------------------------------------------------------------------------------
+
 HISTORY
 --------------------------------------------------------------------------------
 11/17/98   JSB   Created
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 SENTRY
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -62,14 +62,12 @@ INCLUDES
 #include "FGInitialCondition.h"
 #include "FGMatrix33.h"
 #include "FGColumnVector3.h"
-#include "FGColumnVector4.h"
-
+#include "FGQuaternion.h"
 #include "FGFDMExec.h"
 #include "FGAtmosphere.h"
 #include "FGFCS.h"
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGPosition.h"
+#include "FGPropagate.h"
+#include "FGAuxiliary.h"
 #include "FGAerodynamics.h"
 #include "FGOutput.h"
 #include "FGAircraft.h"
@@ -110,33 +108,6 @@ public:
   /// Destructor
   ~FGState();
 
- /** Initializes the simulation state based on the passed-in parameters.
-      @param U the body X-Axis velocity in fps.
-      @param V the body Y-Axis velocity in fps.
-      @param W the body Z-Axis velocity in fps.
-      @param lat latitude measured in radians from the equator, negative values are south.
-      @param lon longitude, measured in radians from the Greenwich meridian, negative values are west.
-      @param phi the roll angle in radians.
-      @param tht the pitch angle in radians.
-      @param psi the heading angle in radians measured clockwise from north.
-      @param h altitude in feet.
-      @param wnorth north velocity in feet per second
-      @param weast eastward velocity in feet per second
-      @param wdown downward velocity in feet per second
-      */
-  void Initialize(double U,
-                  double V,
-                  double W,
-                  double lat,
-                  double lon,
-                  double phi,
-                  double tht,
-                  double psi,
-                  double h,
-                  double wnorth,
-                  double weast,
-                  double wdown);
-
   /** Initializes the simulation state based on parameters from an Initial Conditions object.
       @param FGIC pointer to an initial conditions object.
       @see FGInitialConditions.
@@ -161,7 +132,7 @@ public:
     sim_time = cur_time;
     return sim_time;
   }
-  
+
   /** Sets the integration time step for the simulation executive.
       @param delta_t the time step in seconds.
       */
@@ -175,154 +146,21 @@ public:
     return sim_time;
   }
 
-  /** Initializes the transformation matrices.
-      @param phi the roll angle in radians.
-      @param tht the pitch angle in radians.
-      @param psi the heading angle in radians
-      */
-  void InitMatrices(double phi, double tht, double psi);
-
-  /** Calculates the local-to-body and body-to-local conversion matrices.
-      */
-  void CalcMatrices(void);
-
-  /** Integrates the quaternion.
-      Given the supplied rotational rate vector and integration rate, the quaternion
-      is integrated. The quaternion is later used to update the transformation
-      matrices.
-      @param vPQR the body rotational rate column vector.
-      @param rate the integration rate in seconds.
-      */
-  void IntegrateQuat(FGColumnVector3 vPQR, int rate);
-  
-  // ======================================= General Purpose INTEGRATOR
-
-  enum iType {AB4, AB3, AB2, AM3, AM4, EULER, TRAPZ};
-  
-  /** Multi-method integrator.
-      @param type Type of intergation scheme to use. Can be one of:
-             <ul>
-             <li>AB4 - Adams-Bashforth, fourth order</li>
-             <li>AB3 - Adams-Bashforth, third order</li>
-             <li>AB2 - Adams-Bashforth, second order</li>
-             <li>AM3 - Adams Moulton, third order</li>
-             <li>AM4 - Adams Moulton, fourth order</li>
-             <li>EULER - Euler</li>
-             <li>TRAPZ - Trapezoidal</li>
-             </ul>
-      @param delta_t the integration time step in seconds
-      @param vTDeriv a reference to the current value of the time derivative of
-             the quantity being integrated (i.e. if vUVW is being integrated
-             vTDeriv is the current value of vUVWdot)
-      @param vLastArray an array of previously calculated and saved values of 
-             the quantity being integrated (i.e. if vUVW is being integrated
-             vLastArray[0] is the past value of vUVWdot, vLastArray[1] is the value of
-             vUVWdot prior to that, etc.)
-      @return the current, incremental value of the item integrated to add to the
-              previous value. */
-  
-  template <class T> T Integrate(iType type, double delta_t, T& vTDeriv, T *vLastArray)
-  {
-    T vResult;
-
-    switch (type) {
-    case AB4:
-      vResult = (delta_t/24.0)*(  55.0 * vLastArray[0]
-                                - 59.0 * vLastArray[1]
-                                + 37.0 * vLastArray[2]
-                                -  9.0 * vLastArray[3] );
-      vLastArray[3] = vLastArray[2];
-      vLastArray[2] = vLastArray[1];
-      vLastArray[1] = vLastArray[0];
-      vLastArray[0] = vTDeriv;
-      break;
-    case AB3:
-      vResult = (delta_t/12.0)*(  23.0 * vLastArray[0]
-                                - 16.0 * vLastArray[1]
-                                +  5.0 * vLastArray[2] );
-      vLastArray[2] = vLastArray[1];
-      vLastArray[1] = vLastArray[0];
-      vLastArray[0] = vTDeriv;
-      break;
-    case AB2:
-      vResult = (delta_t/2.0)*( 3.0 * vLastArray[0] - vLastArray[1] );
-      vLastArray[1] = vLastArray[0];
-      vLastArray[0] = vTDeriv;
-      break;
-    case AM4:
-      vResult = (delta_t/24.0)*(   9.0 * vTDeriv
-                                + 19.0 * vLastArray[0]
-                                -  5.0 * vLastArray[1]
-                                +  1.0 * vLastArray[2] );
-      vLastArray[2] = vLastArray[1];
-      vLastArray[1] = vLastArray[0];
-      vLastArray[0] = vTDeriv;
-      break;
-    case AM3:
-      vResult = (delta_t/12.0)*(  5.0 * vTDeriv
-                                + 8.0 * vLastArray[0]
-                                - 1.0 * vLastArray[1] );
-      vLastArray[1] = vLastArray[0];
-      vLastArray[0] = vTDeriv;
-      break;
-    case EULER:
-      vResult = delta_t * vTDeriv;
-      break;
-    case TRAPZ:
-      vResult = (delta_t*0.5) * (vTDeriv + vLastArray[0]);
-      vLastArray[0] = vTDeriv;
-      break;
-    }
-
-    return vResult;
-  }
-
-  // =======================================
-
-  /** Calculates Euler angles from the local-to-body matrix.
-      @return a reference to the vEuler column vector.
-      */
-  FGColumnVector3& CalcEuler(void);
-
   /** Calculates and returns the stability-to-body axis transformation matrix.
       @return a reference to the stability-to-body transformation matrix.
       */
   FGMatrix33& GetTs2b(void);
-  
+
   /** Calculates and returns the body-to-stability axis transformation matrix.
       @return a reference to the stability-to-body transformation matrix.
       */
   FGMatrix33& GetTb2s(void);
 
-  /** Retrieves the local-to-body transformation matrix.
-      @return a reference to the local-to-body transformation matrix.
-      */
-  FGMatrix33& GetTl2b(void) { return mTl2b; }
-
-  /** Retrieves a specific local-to-body matrix element.
-      @param r matrix row index.
-      @param c matrix column index.
-      @return the matrix element described by the row and column supplied.
-      */
-  double GetTl2b(int r, int c) { return mTl2b(r,c);}
-
-  /** Retrieves the body-to-local transformation matrix.
-      @return a reference to the body-to-local matrix.
-      */
-  FGMatrix33& GetTb2l(void) { return mTb2l; }
-
-  /** Retrieves a specific body-to-local matrix element.
-      @param r matrix row index.
-      @param c matrix column index.
-      @return the matrix element described by the row and column supplied.
-      */
-  double GetTb2l(int i, int j) { return mTb2l(i,j);}
-  
-  /** Prints a summary of simulator state (speed, altitude, 
+  /** Prints a summary of simulator state (speed, altitude,
       configuration, etc.)
   */
   void ReportState(void);
-  
+
   void bind();
   void unbind();
 
@@ -331,29 +169,18 @@ private:
   double saved_dt;
 
   FGFDMExec* FDMExec;
-  FGMatrix33 mTb2l;
-  FGMatrix33 mTl2b;
   FGMatrix33 mTs2b;
   FGMatrix33 mTb2s;
-  FGColumnVector4 vQtrn;
-  FGColumnVector4 vQdot_prev[4];
-  FGColumnVector4 vQdot;
-  FGColumnVector3 vLocalVelNED;
-  FGColumnVector3 vLocalEuler;
-  
-  FGColumnVector4 vTmp;
-  FGColumnVector3 vEuler;
 
   FGAircraft* Aircraft;
-  FGPosition* Position;
-  FGTranslation* Translation;
-  FGRotation* Rotation;
+  FGPropagate* Propagate;
   FGOutput* Output;
   FGAtmosphere* Atmosphere;
   FGFCS* FCS;
   FGAerodynamics* Aerodynamics;
   FGGroundReactions* GroundReactions;
   FGPropulsion* Propulsion;
+  FGAuxiliary* Auxiliary;
   FGPropertyManager* PropertyManager;
 
   void Debug(int from);
index 5dbbadb99ceb09bad37c3bac74c3da8843498ce7..bf02b178788cc7284681a85fe221052901ba9d73 100644 (file)
@@ -56,6 +56,22 @@ CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 
+FGTable::FGTable(int NRows, int NCols, int NTables)
+                                 : nRows(NTables), nCols(1), nTables(NTables)
+{
+  Type = tt3D;
+  colCounter = 1;
+  rowCounter = 1;
+
+  Data = Allocate(); // this data array will contain the keys for the associated tables
+  Tables.reserve(nTables);
+  for (int i=0; i<nTables; i++) Tables.push_back(FGTable(NRows, NCols));
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols)
 {
   if (NCols > 1) {
@@ -90,6 +106,31 @@ FGTable::FGTable(int NRows) : nRows(NRows), nCols(1)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+FGTable::FGTable(const FGTable& t)
+{
+  Type = t.Type;
+  colCounter = t.colCounter;
+  rowCounter = t.rowCounter;
+  tableCounter = t.tableCounter;
+
+  nRows = t.nRows;
+  nCols = t.nCols;
+  nTables = t.nTables;
+
+  Tables = t.Tables;
+  Data = Allocate();
+  for (int r=0; r<=nRows; r++) {
+    for (int c=0; c<=nCols; c++) {
+      Data[r][c] = t.Data[r][c];
+    }
+  }
+  lastRowIndex = t.lastRowIndex;
+  lastColumnIndex = t.lastColumnIndex;
+  lastTableIndex = t.lastTableIndex;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 double** FGTable::Allocate(void)
 {
   Data = new double*[nRows+1];
@@ -106,6 +147,7 @@ double** FGTable::Allocate(void)
 
 FGTable::~FGTable()
 {
+  if (nTables > 0) Tables.clear();
   for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r];
   if (Data) delete[] Data;
   Debug(1);
@@ -117,8 +159,8 @@ double FGTable::GetValue(double key)
 {
   double Factor, Value, Span;
   int r=lastRowIndex;
-  
-  //if the key is off the end of the table, just return the 
+
+  //if the key is off the end of the table, just return the
   //end-of-table value, do not extrapolate
   if( key <= Data[1][0] ) {
     lastRowIndex=2;
@@ -128,21 +170,21 @@ double FGTable::GetValue(double key)
     lastRowIndex=nRows;
     //cout << "Key over table: " << key << endl;
     return Data[nRows][1];
-  }    
+  }
 
   // the key is somewhere in the middle, search for the right breakpoint
   // assume the correct breakpoint has not changed since last frame or
   // has only changed very little
-  
+
   if ( r > 2 && Data[r-1][0] > key ) {
     while( Data[r-1][0] > key && r > 2) { r--; }
-  } else if ( Data[r][0] < key ) { 
-    while( Data[r][0] <= key && r <= nRows) { r++; }  
-  }  
-  
-  lastRowIndex=r;  
+  } else if ( Data[r][0] < key ) {
+    while( Data[r][0] <= key && r <= nRows) { r++; }
+  }
+
+  lastRowIndex=r;
   // make sure denominator below does not go to zero.
-  
+
   Span = Data[r][0] - Data[r-1][0];
   if (Span != 0.0) {
     Factor = (key - Data[r-1][0]) / Span;
@@ -164,25 +206,25 @@ double FGTable::GetValue(double rowKey, double colKey)
   double rFactor, cFactor, col1temp, col2temp, Value;
   int r=lastRowIndex;
   int c=lastColumnIndex;
-  
+
   if ( r > 2 && Data[r-1][0] > rowKey ) {
     while ( Data[r-1][0] > rowKey && r > 2) { r--; }
-  } else if ( Data[r][0] < rowKey ) { 
+  } else if ( Data[r][0] < rowKey ) {
 //    cout << Data[r][0] << endl;
     while ( r <= nRows && Data[r][0] <= rowKey ) { r++; }
-    if ( r > nRows ) r = nRows;  
-  }  
-  
+    if ( r > nRows ) r = nRows;
+  }
+
   if ( c > 2 && Data[0][c-1] > colKey ) {
     while( Data[0][c-1] > colKey && c > 2) { c--; }
-  } else if ( Data[0][c] < colKey ) { 
-    while( Data[0][c] <= colKey && c <= nCols) { c++; } 
-    if ( c > nCols ) c = nCols;  
-  }  
+  } else if ( Data[0][c] < colKey ) {
+    while( Data[0][c] <= colKey && c <= nCols) { c++; }
+    if ( c > nCols ) c = nCols;
+  }
 
   lastRowIndex=r;
   lastColumnIndex=c;
-  
+
   rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]);
   cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]);
 
@@ -202,17 +244,68 @@ double FGTable::GetValue(double rowKey, double colKey)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+double FGTable::GetValue(double rowKey, double colKey, double tableKey)
+{
+  double Factor, Value, Span;
+  int r=lastRowIndex;
+
+  //if the key is off the end  (or before the beginning) of the table,
+  // just return the boundary-table value, do not extrapolate
+
+  if( tableKey <= Data[1][1] ) {
+    lastRowIndex=2;
+    return Tables[0].GetValue(rowKey, colKey);
+  } else if ( tableKey >= Data[nRows][1] ) {
+    lastRowIndex=nRows;
+    return Tables[nRows-1].GetValue(rowKey, colKey);
+  }
+
+  // the key is somewhere in the middle, search for the right breakpoint
+  // assume the correct breakpoint has not changed since last frame or
+  // has only changed very little
+
+  if ( r > 2 && Data[r-1][1] > tableKey ) {
+    while( Data[r-1][1] > tableKey && r > 2) { r--; }
+  } else if ( Data[r][1] < tableKey ) {
+    while( Data[r][1] <= tableKey && r <= nRows) { r++; }
+  }
+
+  lastRowIndex=r;
+  // make sure denominator below does not go to zero.
+
+  Span = Data[r][1] - Data[r-1][1];
+  if (Span != 0.0) {
+    Factor = (tableKey - Data[r-1][1]) / Span;
+    if (Factor > 1.0) Factor = 1.0;
+  } else {
+    Factor = 1.0;
+  }
+
+  Value = Factor*(Tables[r-1].GetValue(rowKey, colKey) - Tables[r-2].GetValue(rowKey, colKey))
+                              + Tables[r-1].GetValue(rowKey, colKey);
+
+  return Value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 void FGTable::operator<<(FGConfigFile& infile)
 {
-  int startRow;
+  int startRow=0;
+  int startCol=0;
+  int tableCtr=0;
 
-  if (Type == tt1D) startRow = 1;
-  else startRow = 0;
+  if (Type == tt1D || Type == tt3D) startRow = 1;
+  if (Type == tt3D) startCol = 1;
 
   for (int r=startRow; r<=nRows; r++) {
-    for (int c=0; c<=nCols; c++) {
+    for (int c=startCol; c<=nCols; c++) {
       if (r != 0 || c != 0) {
         infile >> Data[r][c];
+        if (Type == tt3D) {
+          Tables[tableCtr] << infile;
+          tableCtr++;
+        }
       }
     }
   }
@@ -244,10 +337,11 @@ FGTable& FGTable::operator<<(const int n)
 
 void FGTable::Print(void)
 {
-  int startRow;
+  int startRow=0;
+  int startCol=0;
 
-  if (Type == tt1D) startRow = 1;
-  else startRow = 0;
+  if (Type == tt1D || Type == tt3D) startRow = 1;
+  if (Type == tt3D) startCol = 1;
 
 #if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
   unsigned long flags = cout.setf(ios::fixed);
@@ -256,14 +350,17 @@ void FGTable::Print(void)
 #endif
 
   cout.precision(4);
-
   for (int r=startRow; r<=nRows; r++) {
     cout << "  ";
-    for (int c=0; c<=nCols; c++) {
+    for (int c=startCol; c<=nCols; c++) {
       if (r == 0 && c == 0) {
-      cout << "        ";
+        cout << "      ";
       } else {
-      cout << Data[r][c] << "  ";
+        cout << Data[r][c] << "        ";
+        if (Type == tt3D) {
+          cout << endl;
+          Tables[r-1].Print();
+        }
       }
     }
     cout << endl;
index 6e28e9628cf75ac9875a1a0efaaf5f20703c69bc..85e2a0abf39fc7b5e951dd99698706b8206bd38c 100644 (file)
@@ -40,6 +40,7 @@ INCLUDES
 
 #include "FGConfigFile.h"
 #include "FGJSBBase.h"
+#include <vector>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
@@ -51,6 +52,8 @@ DEFINITIONS
 FORWARD DECLARATIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+using std::vector;
+
 namespace JSBSim {
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -58,7 +61,134 @@ CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 /** Lookup table class.
-    Models a lookup table for use in FGCoefficient, FGPropeller, etc.
+    Models a one, two, or three dimensional lookup table for use in FGCoefficient,
+    FGPropeller, etc.  A one-dimensional table is called a "VECTOR" in a coefficient
+    definition. For example:
+<pre>
+    \<COEFFICIENT NAME="{short name}" TYPE="VECTOR">
+      {name}
+      {number of rows}
+      {row lookup property}
+      {non-dimensionalizing properties}
+      {row_1_key} {col_1_data}
+      {row_2_key} {...       }
+      { ...     } {...       }
+      {row_n_key} {...       }
+    \</COEFFICIENT>
+</pre>
+    A "real life" example is as shown here:
+<pre>
+    \<COEFFICIENT NAME="CLDf" TYPE="VECTOR">
+      Delta_lift_due_to_flap_deflection
+      4
+      fcs/flap-pos-deg
+      aero/qbar-psf | metrics/Sw-sqft
+      0   0
+      10  0.20
+      20  0.30
+      30  0.35
+    \</COEFFICIENT>
+</pre>
+    The first column in the data table represents the lookup index (or "key").  In
+    this case, the lookup index is fcs/flap-pos-deg (flap extension in degrees).
+    If the flap position is 10 degrees, the value returned from the lookup table
+    would be 0.20.  This value would be multiplied by qbar (aero/qbar-psf) and wing
+    area (metrics/Sw-sqft) to get the total lift force that is a result of flap
+    deflection (measured in pounds force).  If the value of the flap-pos-deg property
+    was 15 (degrees), the value output by the table routine would be 0.25 - an
+    interpolation.  If the flap position in degrees ever went below 0.0, or above
+    30 (degrees), the output from the table routine would be 0 and 0.35, respectively.
+    That is, there is no _extrapolation_ to values outside the range of the lookup
+    index.  This is why it is important to chose the data for the table wisely.
+
+    The definition for a 2D table - referred to simply as a TABLE, is as follows:
+<pre>
+    \<COEFFICIENT NAME="{short name}" TYPE="TABLE">
+      {name}
+      {number of rows}
+      {number of columns}
+      {row lookup property}
+      {column lookup property}
+      {non-dimensionalizing}
+                  {col_1_key   col_2_key   ...  col_n_key }
+      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
+      {row_2_key} {...         ...         ...  ...       }
+      { ...     } {...         ...         ...  ...       }
+      {row_n_key} {...         ...         ...  ...       }
+    \</COEFFICIENT>
+</pre>
+    A "real life" example is as shown here:
+<pre>
+    \<COEFFICIENT NAME="CYb" TYPE="TABLE">
+      Side_force_due_to_beta
+      3
+      2
+      aero/beta-rad
+      fcs/flap-pos-deg
+      aero/qbar-psf | metrics/Sw-sqft
+               0     30
+      -0.349   0.137  0.106
+       0       0      0
+       0.349  -0.137 -0.106
+    \</COEFFICIENT>
+</pre>
+    The definition for a 3D table in a coefficient would be (for example):
+<pre>
+    \<COEFFICIENT NAME="{short name}" TYPE="TABLE3D">
+      {name}
+      {number of rows}
+      {number of columns}
+      {number of tables}
+      {row lookup property}
+      {column lookup property}
+      {table lookup property}
+      {non-dimensionalizing}
+      {first table key}
+                  {col_1_key   col_2_key   ...  col_n_key }
+      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
+      {row_2_key} {...         ...         ...  ...       }
+      { ...     } {...         ...         ...  ...       }
+      {row_n_key} {...         ...         ...  ...       }
+
+      {second table key}
+                  {col_1_key   col_2_key   ...  col_n_key }
+      {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
+      {row_2_key} {...         ...         ...  ...       }
+      { ...     } {...         ...         ...  ...       }
+      {row_n_key} {...         ...         ...  ...       }
+
+      ...
+
+    \</COEFFICIENT>
+</pre>
+    [At the present time, all rows and columns for each table must have the
+    same dimension.]
+
+    In addition to using a Table for something like a coefficient, where all the
+    row and column elements are read in from a file, a Table could be created
+    and populated completely within program code:
+<pre>
+    // First column is thi, second is neta (combustion efficiency)
+    Lookup_Combustion_Efficiency = new FGTable(12);
+    *Lookup_Combustion_Efficiency << 0.00 << 0.980;
+    *Lookup_Combustion_Efficiency << 0.90 << 0.980;
+    *Lookup_Combustion_Efficiency << 1.00 << 0.970;
+    *Lookup_Combustion_Efficiency << 1.05 << 0.950;
+    *Lookup_Combustion_Efficiency << 1.10 << 0.900;
+    *Lookup_Combustion_Efficiency << 1.15 << 0.850;
+    *Lookup_Combustion_Efficiency << 1.20 << 0.790;
+    *Lookup_Combustion_Efficiency << 1.30 << 0.700;
+    *Lookup_Combustion_Efficiency << 1.40 << 0.630;
+    *Lookup_Combustion_Efficiency << 1.50 << 0.570;
+    *Lookup_Combustion_Efficiency << 1.60 << 0.525;
+    *Lookup_Combustion_Efficiency << 2.00 << 0.345;
+</pre>
+    The first column in the table, above, is thi (the lookup index, or key). The
+    second column is the output data - in this case, "neta" (the Greek letter
+    referring to combustion efficiency). Later on, the table is used like this:
+
+    combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio);
+
     @author Jon S. Berndt
     @version $Id$
     @see FGCoefficient
@@ -72,11 +202,21 @@ CLASS DECLARATION
 class FGTable : public FGJSBBase
 {
 public:
+  /// Destructor
   ~FGTable();
+
+  /** This is the very important copy constructor.
+      @param table a const reference to a table.*/
+  FGTable(const FGTable& table);
+
+  /** The constructor for a VECTOR table
+      @param nRows the number of rows in this VECTOR table. */
   FGTable(int nRows);
   FGTable(int nRows, int nCols);
+  FGTable(int nRows, int nCols, int numTables);
   double GetValue(double key);
   double GetValue(double rowKey, double colKey);
+  double GetValue(double rowKey, double colKey, double TableKey);
   /** Read the table in.
       Data in the config file should be in matrix format with the row
       independents as the first column and the column independents in
@@ -87,20 +227,32 @@ public:
       -5   1  2   3  4  ...
        ...
        </pre>
+
+       For multiple-table (i.e. 3D) data sets there is an additional number
+       key in the table definition. For example:
+
+      <pre>
+       0.0
+           0  10  20 30 ...
+      -5   1  2   3  4  ...
+       ...
+       </pre>
        */
+
   void operator<<(FGConfigFile&);
   FGTable& operator<<(const double n);
   FGTable& operator<<(const int n);
   inline double GetElement(int r, int c) {return Data[r][c];}
+  inline double GetElement(int r, int c, int t);
   void Print(void);
 
 private:
-  enum type {tt1D, tt2D} Type;
+  enum type {tt1D, tt2D, tt3D} Type;
   double** Data;
-  int nRows, nCols;
-  int colCounter;
-  int rowCounter;
-  int lastRowIndex, lastColumnIndex;
+  vector <FGTable> Tables;
+  int nRows, nCols, nTables;
+  int colCounter, rowCounter, tableCounter;
+  int lastRowIndex, lastColumnIndex, lastTableIndex;
   double** Allocate(void);
   void Debug(int from);
 };
index 93092c15979d7c3ed67b26c4d52d52ff7dcac976..f66fcbdfae62be77d61135edc9b1899dc5924231 100644 (file)
@@ -53,10 +53,13 @@ static const char *IdHdr = ID_TANK;
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-FGTank::FGTank(FGConfigFile* AC_cfg)
+FGTank::FGTank(FGConfigFile* AC_cfg, FGFDMExec* exec)
 {
   string token;
   double X, Y, Z;
+  Area = 1.0;
+  Temperature = -9999.0;
+  Auxiliary = exec->GetAuxiliary();
 
   type = AC_cfg->GetValue("TYPE");
 
@@ -72,6 +75,7 @@ FGTank::FGTank(FGConfigFile* AC_cfg)
     else if (token == "RADIUS") *AC_cfg >> Radius;
     else if (token == "CAPACITY") *AC_cfg >> Capacity;
     else if (token == "CONTENTS") *AC_cfg >> Contents;
+    else if (token == "TEMPERATURE") *AC_cfg >> Temperature; 
     else cerr << "Unknown identifier: " << token << " in tank definition." << endl;
   }
 
@@ -86,6 +90,9 @@ FGTank::FGTank(FGConfigFile* AC_cfg)
     PctFull  = 0;
   }
 
+  if (Temperature != -9999.0)  Temperature = FahrenheitToCelsius(Temperature); 
+  Area = 40.0 * pow(Capacity/1975, 0.666666667);
+
   Debug(0);
 }
 
@@ -98,7 +105,7 @@ FGTank::~FGTank()
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGTank::Reduce(double used)
+double FGTank::Drain(double used)
 {
   double shortage = Contents - used;
 
@@ -113,6 +120,53 @@ double FGTank::Reduce(double used)
   return shortage;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTank::Fill(double amount)
+{
+  double overage = 0.0;
+
+  Contents += amount;
+
+  if (Contents > Capacity) {
+    overage = Contents - Capacity;
+    Contents = Capacity;
+    PctFull = 100.0;
+  } else {
+    PctFull = Contents/Capacity*100.0;
+  }
+  return overage;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTank::SetContents(double amount)
+{
+  Contents = amount;
+  if (Contents > Capacity) {
+    Contents = Capacity;
+    PctFull = 100.0;
+  } else {
+    PctFull = Contents/Capacity*100.0;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTank::Calculate(double dt)
+{
+  if (Temperature == -9999.0) return 0.0;
+  double HeatCapacity = 900.0;        // Joules/lbm/C
+  double TempFlowFactor = 1.115;      // Watts/sqft/C
+  double TAT = Auxiliary->GetTAT_C();
+  double Tdiff = TAT - Temperature;
+  double dT = 0.0;                    // Temp change due to one surface
+  if (fabs(Tdiff) > 0.1) {
+    dT = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity);
+  }
+  return Temperature += (dT + dT);    // For now, assume upper/lower the same
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
index 9cd81c58e927f3b2fb0daa741dca81a201789610..ec8ecbb530b96c8f0190d2bd771f490a841cc7f5 100644 (file)
@@ -47,6 +47,7 @@ INCLUDES
 #include "FGJSBBase.h"
 #include "FGConfigFile.h"
 #include "FGColumnVector3.h"
+#include "FGAuxiliary.h"
 
 #ifdef FGFS
 #  include <simgear/compiler.h>
@@ -82,6 +83,48 @@ CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 /** Models a fuel tank.
+    @author Jon Berndt
+    @see Akbar, Raza et al. "A Simple Analysis of Fuel Addition to the CWT of
+    747", California Institute of Technology, 1998
+<P>
+    Fuel temperature is calculated using the following assumptions:
+<P>
+    Fuel temperature will only be calculated for tanks which have an initial fuel
+    temperature specified in the configuration file.
+<P>
+    The surface area of the tank is estimated from the capacity in pounds.  It
+    is assumed that the tank is a wing tank with dimensions h by 4h by 10h. The
+    volume of the tank is then 40(h)(h)(h). The area of the upper or lower 
+    surface is then 40(h)(h).  The volume is also equal to the capacity divided
+    by 49.368 lbs/cu-ft, for jet fuel.  The surface area of one side can then be
+    derived from the tank's capacity.  
+<P>
+    The heat capacity of jet fuel is assumed to be 900 Joules/lbm/K, and the 
+    heat transfer factor of the tank is 1.115 Watts/sq-ft/K.
+<P>
+Configuration File Format
+<pre>
+\<AC_TANK TYPE="\<FUEL | OXIDIZER>" NUMBER="\<n>">
+  XLOC        \<x location>
+  YLOC        \<y location>
+  ZLOC        \<z location>
+  RADIUS      \<radius>
+  CAPACITY    \<capacity>
+  CONTENTS    \<contents>
+  TEMPERATURE \<fuel temperature>
+\</AC_TANK>
+</pre>
+Definition of the tank configuration file parameters:
+<pre>
+<b>TYPE</b> - One of FUEL or OXIDIZER.
+<b>XLOC</b> - Location of tank on aircraft's x-axis, inches.
+<b>YLOC</b> - Location of tank on aircraft's y-axis, inches.
+<b>ZLOC</b> - Location of tank on aircraft's z-axis, inches.
+<b>RADIUS</b> - Equivalent radius of tank, inches, for modeling slosh.
+<b>CAPACITY</b> - Capacity in pounds.
+<b>CONTENTS</b> - Initial contents in pounds.
+<b>TEMPERATURE</b> - Initial temperature in degrees Fahrenheit.
+</pre>
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -91,18 +134,23 @@ CLASS DECLARATION
 class FGTank : public FGJSBBase
 {
 public:
-  FGTank(FGConfigFile*);
+  FGTank(FGConfigFile*, FGFDMExec*);
   ~FGTank();
 
-  double Reduce(double);
+  double Drain(double);
+  double Calculate(double dt);
   int GetType(void) {return Type;}
   bool GetSelected(void) {return Selected;}
   double GetPctFull(void) {return PctFull;}
   double GetContents(void) {return Contents;}
+  double GetTemperature_degC(void) {return Temperature;}
+  double GetTemperature(void) {return CelsiusToFahrenheit(Temperature);}
   const FGColumnVector3& GetXYZ(void) {return vXYZ;}
   double GetXYZ(int idx) {return vXYZ(idx);}
 
-  void SetContents(double contents) { Contents = contents; }
+  double Fill(double amount);
+  void SetContents(double amount);
+  void SetTemperature(double temp) { Temperature = temp; }
 
   enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER};
 
@@ -114,7 +162,10 @@ private:
   double Radius;
   double PctFull;
   double Contents;
+  double Area;
+  double Temperature;      
   bool  Selected;
+  FGAuxiliary* Auxiliary;
   void Debug(int from);
 };
 }
index bd4f3991215282d0c50c689c0dac47557ae54ed2..a03df18f433d76ec8fe9bfcc1d901333a329226d 100644 (file)
@@ -35,6 +35,8 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <sstream>
+
 #include "FGThruster.h"
 
 namespace JSBSim {
@@ -47,8 +49,7 @@ CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 
-FGThruster::FGThruster(FGFDMExec *FDMExec) : FGForce(FDMExec),
-                                             ThrusterNumber(0)
+FGThruster::FGThruster(FGFDMExec *FDMExec) : FGForce(FDMExec)
 {
   Type = ttDirect;
   SetTransformType(FGForce::tCustom);
@@ -61,13 +62,12 @@ FGThruster::FGThruster(FGFDMExec *FDMExec) : FGForce(FDMExec),
 FGThruster::FGThruster(FGFDMExec *FDMExec,
                        FGConfigFile *Eng_cfg ): FGForce(FDMExec)
 {
-  ThrusterNumber = 0;
   Type = ttDirect;
   SetTransformType(FGForce::tCustom);
   Name = Eng_cfg->GetValue();
   GearRatio = 1.0;
   Debug(0);
-}   
+}
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -76,6 +76,28 @@ FGThruster::~FGThruster()
   Debug(1);
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGThruster::GetThrusterLabels(int id)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_Thrust[" << id << "]";
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGThruster::GetThrusterValues(int id)
+{
+  std::ostringstream buf;
+
+  buf << Thrust;
+
+  return buf.str();
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
index a546b316395e09dfdb8cdd7779b66a914ffddc72..b9bef6d3e1229f95bf37f64467bc3aeeaf7d96a7 100644 (file)
@@ -40,6 +40,7 @@ INCLUDES
 
 #include "FGForce.h"
 #include "FGConfigFile.h"
+#include <string>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
@@ -79,21 +80,20 @@ public:
 
   virtual double Calculate(double tt) { Thrust = tt; vFn(1) = Thrust; return 0.0; }
   void SetName(string name) {Name = name;}
-  void SetThrusterNumber(int nn) {ThrusterNumber = nn;}
   virtual void SetRPM(double rpm) {};
   virtual double GetPowerRequired(void) {return 0.0;}
   virtual void SetdeltaT(double dt) {deltaT = dt;}
   double GetThrust(void) {return Thrust;}
   eType GetType(void) {return Type;}
   string GetName(void) {return Name;}
-  int GetThrusterNumber(void) {return ThrusterNumber;}
   virtual double GetRPM(void) { return 0.0; };
-  double GetGearRatio(void) {return GearRatio; } 
+  double GetGearRatio(void) {return GearRatio; }
+  virtual string GetThrusterLabels(int id);
+  virtual string GetThrusterValues(int id);
 
 protected:
   eType Type;
   string Name;
-  int ThrusterNumber;
   double Thrust;
   double PowerRequired;
   double deltaT;
diff --git a/src/FDM/JSBSim/FGTranslation.cpp b/src/FDM/JSBSim/FGTranslation.cpp
deleted file mode 100644 (file)
index f2c84f2..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGTranslation.cpp
- Author:       Jon Berndt
- Date started: 12/02/98
- Purpose:      Integrates the translational EOM
- Called by:    FDMExec
-
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-This class integrates the translational EOM.
-
-HISTORY
---------------------------------------------------------------------------------
-12/02/98   JSB   Created
- 7/23/99   TP    Added data member and modified Run and PutState to calcuate
-                 Mach number
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
-    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
-    School, January 1994
-[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
-    JSC 12960, July 1977
-[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
-    NASA-Ames", NASA CR-2497, January 1975
-[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
-    Wiley & Sons, 1979 ISBN 0-471-03032-5
-[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
-    1982 ISBN 0-471-08936-2
-
-  The order of rotations used in this class corresponds to a 3-2-1 sequence,
-  or Y-P-R, or Z-Y-X, if you prefer.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGTranslation.h"
-#include "FGRotation.h"
-#include "FGAtmosphere.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-#include "FGFCS.h"
-#include "FGMassBalance.h"
-#include "FGAircraft.h"
-#include "FGPosition.h"
-#include "FGAuxiliary.h"
-#include "FGOutput.h"
-#include "FGPropertyManager.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_TRANSLATION;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGTranslation::FGTranslation(FGFDMExec* fdmex) : FGModel(fdmex)
-{
-  Name = "FGTranslation";
-  qbar = 0;
-  qbarUW = 0.0;
-  qbarUV = 0.0;
-  Vt = 0.0;
-  Mach = 0.0;
-  alpha = beta = 0.0;
-  adot = bdot = 0.0;
-
-  vUVWdot.InitMatrix();
-  vUVWdot_prev[0].InitMatrix();
-  vUVWdot_prev[1].InitMatrix();
-  vUVWdot_prev[2].InitMatrix();
-  vUVWdot_prev[3].InitMatrix();
-
-  bind();
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTranslation::~FGTranslation(void)
-{
-  unbind();
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGTranslation::Run(void)
-{
-  if (!FGModel::Run()) {
-
-    vUVWdot = vUVW*Rotation->GetPQR() + Aircraft->GetBodyAccel();
-
-    vUVW += State->Integrate(FGState::TRAPZ, State->Getdt()*rate, vUVWdot, vUVWdot_prev);
-
-    vAeroUVW = vUVW + State->GetTl2b()*Atmosphere->GetWindNED();
-
-    Vt = vAeroUVW.Magnitude();
-    if ( Vt > 1) {
-      if (vAeroUVW(eW) != 0.0)
-        alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0;
-      if (vAeroUVW(eV) != 0.0)
-        beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV),
-               sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0;
-
-      double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
-      double signU=1;
-      if (vAeroUVW(eU) != 0.0)
-        signU = vAeroUVW(eU)/fabs(vAeroUVW(eU));
-
-      if ( (mUW == 0.0) || (Vt == 0.0) ) {
-        adot = 0.0;
-        bdot = 0.0;
-      } else {
-        adot = (vAeroUVW(eU)*vAeroUVW(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW;
-        bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU)
-                + vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW));
-      }
-    } else {
-      alpha = beta = adot = bdot = 0;
-    }
-
-    qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt;
-    qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW));
-    qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV));
-    Mach = Vt / Atmosphere->GetSoundSpeed();
-    vMachUVW(eU) = vAeroUVW(eU) / Atmosphere->GetSoundSpeed();
-    vMachUVW(eV) = vAeroUVW(eV) / Atmosphere->GetSoundSpeed();
-    vMachUVW(eW) = vAeroUVW(eW) / Atmosphere->GetSoundSpeed();
-
-    if (debug_lvl > 1) Debug(1);
-
-    return false;
-  } else {
-    return true;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTranslation::bind(void)
-{
-  typedef double (FGTranslation::*PMF)(int) const;
-  PropertyManager->Tie("velocities/u-fps", this,1,
-                       (PMF)&FGTranslation::GetUVW /*,
-                       &FGTranslation::SetUVW,
-                       true */);
-  PropertyManager->Tie("velocities/v-fps", this,2,
-                       (PMF)&FGTranslation::GetUVW /*,
-                       &FGTranslation::SetUVW,
-                       true*/);
-  PropertyManager->Tie("velocities/w-fps", this,3,
-                       (PMF)&FGTranslation::GetUVW /*,
-                       &FGTranslation::SetUVW,
-                       true*/);
-  PropertyManager->Tie("accelerations/udot-fps", this,1,
-                       (PMF)&FGTranslation::GetUVWdot);
-  PropertyManager->Tie("accelerations/vdot-fps", this,2,
-                       (PMF)&FGTranslation::GetUVWdot);
-  PropertyManager->Tie("accelerations/wdot-fps", this,3,
-                       (PMF)&FGTranslation::GetUVWdot);
-  PropertyManager->Tie("velocities/u-aero-fps", this,1,
-                       (PMF)&FGTranslation::GetAeroUVW);
-  PropertyManager->Tie("velocities/v-aero-fps", this,2,
-                       (PMF)&FGTranslation::GetAeroUVW);
-  PropertyManager->Tie("velocities/w-aero-fps", this,3,
-                       (PMF)&FGTranslation::GetAeroUVW);
-  PropertyManager->Tie("aero/alpha-rad", this,
-                       &FGTranslation::Getalpha,
-                       &FGTranslation::Setalpha,
-                       true);
-  PropertyManager->Tie("aero/beta-rad", this,
-                       &FGTranslation::Getbeta,
-                       &FGTranslation::Setbeta,
-                       true);
-  PropertyManager->Tie("aero/mag-beta-rad", this,
-                       &FGTranslation::GetMagBeta);
-  PropertyManager->Tie("aero/qbar-psf", this,
-                       &FGTranslation::Getqbar,
-                       &FGTranslation::Setqbar,
-                       true);
-  PropertyManager->Tie("aero/qbarUW-psf", this,
-                       &FGTranslation::GetqbarUW,
-                       &FGTranslation::SetqbarUW,
-                       true);
-  PropertyManager->Tie("aero/qbarUV-psf", this,
-                       &FGTranslation::GetqbarUV,
-                       &FGTranslation::SetqbarUV,
-                       true);
-  PropertyManager->Tie("velocities/vt-fps", this,
-                       &FGTranslation::GetVt,
-                       &FGTranslation::SetVt,
-                       true);
-  PropertyManager->Tie("velocities/mach-norm", this,
-                       &FGTranslation::GetMach,
-                       &FGTranslation::SetMach,
-                       true);
-  PropertyManager->Tie("aero/alphadot-rad_sec", this,
-                       &FGTranslation::Getadot,
-                       &FGTranslation::Setadot,
-                       true);
-  PropertyManager->Tie("aero/betadot-rad_sec", this,
-                       &FGTranslation::Getbdot,
-                       &FGTranslation::Setbdot,
-                       true);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTranslation::unbind(void)
-{
-  PropertyManager->Untie("velocities/u-fps");
-  PropertyManager->Untie("velocities/v-fps");
-  PropertyManager->Untie("velocities/w-fps");
-  PropertyManager->Untie("accelerations/udot-fps");
-  PropertyManager->Untie("accelerations/vdot-fps");
-  PropertyManager->Untie("accelerations/wdot-fps");
-  PropertyManager->Untie("velocities/u-aero-fps");
-  PropertyManager->Untie("velocities/v-aero-fps");
-  PropertyManager->Untie("velocities/w-aero-fps");
-  PropertyManager->Untie("aero/alpha-rad");
-  PropertyManager->Untie("aero/beta-rad");
-  PropertyManager->Untie("aero/qbar-psf");
-  PropertyManager->Untie("aero/qbarUW-psf");
-  PropertyManager->Untie("aero/qbarUV-psf");
-  PropertyManager->Untie("velocities/vt-fps");
-  PropertyManager->Untie("velocities/mach-norm");
-  PropertyManager->Untie("aero/alphadot-rad_sec");
-  PropertyManager->Untie("aero/betadot-rad_sec");
-  PropertyManager->Untie("aero/mag-beta-rad");
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    The bitmasked value choices are as follows:
-//    unset: In this case (the default) JSBSim would only print
-//       out the normally expected messages, essentially echoing
-//       the config files as they are read. If the environment
-//       variable is not set, debug_lvl is set to 1 internally
-//    0: This requests JSBSim not to output any messages
-//       whatsoever.
-//    1: This value explicity requests the normal JSBSim
-//       startup messages
-//    2: This value asks for a message to be printed out when
-//       a class is instantiated
-//    4: When this value is set, a message is displayed when a
-//       FGModel object executes its Run() method
-//    8: When this value is set, various runtime state variables
-//       are printed out periodically
-//    16: When set various parameters are sanity checked and
-//       a message is printed out when they go out of bounds
-
-void FGTranslation::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGTranslation" << endl;
-    if (from == 1) cout << "Destroyed:    FGTranslation" << endl;
-  }
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
-  }
-  if (debug_lvl & 8 ) { // Runtime state variables
-  }
-  if (debug_lvl & 16) { // Sanity checking
-    if (fabs(vUVW(eU)) > 1e6)
-      cout << "FGTranslation::U velocity out of bounds: " << vUVW(eU) << endl;
-    if (fabs(vUVW(eV)) > 1e6)
-      cout << "FGTranslation::V velocity out of bounds: " << vUVW(eV) << endl;
-    if (fabs(vUVW(eW)) > 1e6)
-      cout << "FGTranslation::W velocity out of bounds: " << vUVW(eW) << endl;
-    if (fabs(vUVWdot(eU)) > 1e4)
-      cout << "FGTranslation::U acceleration out of bounds: " << vUVWdot(eU) << endl;
-    if (fabs(vUVWdot(eV)) > 1e4)
-      cout << "FGTranslation::V acceleration out of bounds: " << vUVWdot(eV) << endl;
-    if (fabs(vUVWdot(eW)) > 1e4)
-      cout << "FGTranslation::W acceleration out of bounds: " << vUVWdot(eW) << endl;
-    if (Mach > 100 || Mach < 0.00)
-      cout << "FGTranslation::Mach is out of bounds: " << Mach << endl;
-    if (qbar > 1e6 || qbar < 0.00)
-      cout << "FGTranslation::qbar is out of bounds: " << qbar << endl;
-  }
-  if (debug_lvl & 64) {
-    if (from == 0) { // Constructor
-      cout << IdSrc << endl;
-      cout << IdHdr << endl;
-    }
-  }
-}
-}
diff --git a/src/FDM/JSBSim/FGTranslation.h b/src/FDM/JSBSim/FGTranslation.h
deleted file mode 100644 (file)
index 70766f4..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Header:       FGTranslation.h
- Author:       Jon Berndt
- Date started: 12/02/98
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-HISTORY
---------------------------------------------------------------------------------
-12/02/98   JSB   Created
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGTRANSLATION_H
-#define FGTRANSLATION_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <cmath>
-#  else
-#    include <math.h>
-#  endif
-#else
-#  if defined(sgi) && !defined(__GNUC__)
-#    include <math.h>
-#  else
-#    include <cmath>
-#  endif
-#endif
-
-#include "FGModel.h"
-#include "FGColumnVector3.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_TRANSLATION "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models the translation aspects of the EOM.
-    Note: The order of rotations used in this class corresponds to a 3-2-1 sequence,
-    or Y-P-R, or Z-Y-X, if you prefer.
-    @see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
-    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
-    School, January 1994
-    @see D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
-    JSC 12960, July 1977
-    @see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
-    NASA-Ames", NASA CR-2497, January 1975
-    @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
-    Wiley & Sons, 1979 ISBN 0-471-03032-5
-    @see Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
-    1982 ISBN 0-471-08936-2
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGTranslation : public FGModel {
-public:
-  FGTranslation(FGFDMExec*);
-  ~FGTranslation();
-  
-  inline double           GetUVW   (int idx) const { return vUVW(idx); }
-  inline FGColumnVector3& GetUVW   (void)    { return vUVW; }
-  inline FGColumnVector3& GetUVWdot(void)    { return vUVWdot; }
-  inline double           GetUVWdot(int idx) const { return vUVWdot(idx); }
-  inline FGColumnVector3& GetAeroUVW (void)    { return vAeroUVW; }
-  inline double           GetAeroUVW (int idx) const { return vAeroUVW(idx); }
-
-  double Getalpha(void) const { return alpha; }
-  double Getbeta (void) const { return beta; }
-  inline double GetMagBeta(void) const { return fabs(beta); }
-  double Getqbar (void) const { return qbar; }
-  double GetqbarUW (void) const { return qbarUW; }
-  double GetqbarUV (void) const { return qbarUV; }
-  inline double GetVt   (void) const { return Vt; }
-  double GetMach (void) const { return Mach; }
-  double GetMachU(void) const { return vMachUVW(eU); }
-  double Getadot (void) const { return adot; }
-  double Getbdot (void) const { return bdot; }
-
-  void SetUVW(FGColumnVector3 tt) { vUVW = tt; }
-  void SetAeroUVW(FGColumnVector3 tt) { vAeroUVW = tt; }
-
-  inline void Setalpha(double tt) { alpha = tt; }
-  inline void Setbeta (double tt) { beta  = tt; }
-  inline void Setqbar (double tt) { qbar = tt; }
-  inline void SetqbarUW (double tt) { qbarUW = tt; }
-  inline void SetqbarUV (double tt) { qbarUV = tt; }
-  inline void SetVt   (double tt) { Vt = tt; }
-  inline void SetMach (double tt) { Mach=tt; }
-  inline void Setadot (double tt) { adot = tt; }
-  inline void Setbdot (double tt) { bdot = tt; }
-
-  inline void SetAB(double t1, double t2) { alpha=t1; beta=t2; }
-  
-  bool Run(void);
-
-  void bind(void);
-  void unbind(void);
-
-private:
-  FGColumnVector3 vUVW;
-  FGColumnVector3 vUVWdot;
-  FGColumnVector3 vUVWdot_prev[4];
-  FGColumnVector3 vAeroUVW;
-  FGColumnVector3 vMachUVW;
-
-  double Vt, Mach;
-  double qbar, qbarUW, qbarUV;
-  double alpha, beta;
-  double adot,bdot;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
index 83ff7351e36f7343b4aefe8b2390aa35346c3b1c..4b7313d26031c2bcfdb4e768b9794880be2fa10f 100644 (file)
@@ -242,6 +242,10 @@ bool FGTrim::DoTrim(void) {
   }
 
   fdmex->GetOutput()->Disable();
+  
+  fgic->SetPRadpsIC(0.0);
+  fgic->SetQRadpsIC(0.0);
+  fgic->SetRRadpsIC(0.0);
 
   //clear the sub iterations counts & zero out the controls
   for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
@@ -557,7 +561,7 @@ void FGTrim::setupPullup() {
        << fgic->GetVtrueFpsIC() << endl;
   q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
   cout << targetNlf << ", " << q << endl;
-  fdmex->GetRotation()->SetPQR(0,q,0);
+  fgic->SetQRadpsIC(q);
   cout << "setPitchRateInPullup() complete" << endl;
   
 }  
@@ -593,13 +597,15 @@ void FGTrim::updateRates(void){
     } else {
       p=q=r=0;
     }      
-    fdmex->GetRotation()->SetPQR(p,q,r);
+    fgic->SetPRadpsIC(p);
+    fgic->SetQRadpsIC(q);
+    fgic->SetRRadpsIC(r);
   } else if( mode == tPullup && fabs(targetNlf-1) > 0.01) {
       float g,q,cgamma;
       g=fdmex->GetInertial()->gravity();
       cgamma=cos(fgic->GetFlightPathAngleRadIC());
       q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
-      fdmex->GetRotation()->SetPQR(0,q,0);
+      fgic->SetQRadpsIC(q);
   }  
 }  
 
index 9181bae7c1dcc72812c713e3e14d170ef90c935e..02ee8a0d56100efca1efe8292bff6aea26ce921d 100644 (file)
@@ -1,33 +1,33 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
  Header:       FGTrimAxis.cpp
  Author:       Tony Peden
  Date started: 7/3/00
+
  --------- Copyright (C) 1999  Anthony K. Peden (apeden@earthlink.net) ---------
+
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
+
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.
+
  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place - Suite 330, Boston, MA  02111-1307, USA.
+
  Further information about the GNU General Public License can also be found on
  the world wide web at http://www.gnu.org.
+
+
  HISTORY
 --------------------------------------------------------------------------------
 7/3/00   TP   Created
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -81,8 +81,8 @@ FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
     case tHmgt: tolerance = 0.01; break;
     case  tNlf: state_target=1.0; tolerance = 1E-5; break;
     case tAll: break;
-  }  
-  
+  }
+
   solver_eps=tolerance;
   switch(control) {
   case tThrottle:
@@ -120,17 +120,17 @@ FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
   case tAltAGL:
     control_min=0;
     control_max=30;
-    control_value=fdmex->GetPosition()->GetDistanceAGL();
+    control_value=fdmex->GetPropagate()->GetDistanceAGL();
     solver_eps=tolerance/100;
     break;
   case tTheta:
-    control_min=fdmex->GetRotation()->Gettht() - 5*degtorad;
-    control_max=fdmex->GetRotation()->Gettht() + 5*degtorad;
+    control_min=fdmex->GetPropagate()->Gettht() - 5*degtorad;
+    control_max=fdmex->GetPropagate()->Gettht() + 5*degtorad;
     state_convert=radtodeg;
     break;
   case tPhi:
-    control_min=fdmex->GetRotation()->Getphi() - 30*degtorad;
-    control_max=fdmex->GetRotation()->Getphi() + 30*degtorad;
+    control_min=fdmex->GetPropagate()->Getphi() - 30*degtorad;
+    control_max=fdmex->GetPropagate()->Getphi() + 30*degtorad;
     state_convert=radtodeg;
     control_convert=radtodeg;
     break;
@@ -141,13 +141,13 @@ FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
     control_convert=radtodeg;
     break;
   case tHeading:
-    control_min=fdmex->GetRotation()->Getpsi() - 30*degtorad;
-    control_max=fdmex->GetRotation()->Getpsi() + 30*degtorad;
+    control_min=fdmex->GetPropagate()->Getpsi() - 30*degtorad;
+    control_max=fdmex->GetPropagate()->Getpsi() + 30*degtorad;
     state_convert=radtodeg;
     break;
   }
-  
-  
+
+
   Debug(0);
 }
 
@@ -162,12 +162,12 @@ FGTrimAxis::~FGTrimAxis(void)
 
 void FGTrimAxis::getState(void) {
   switch(state) {
-  case tUdot: state_value=fdmex->GetTranslation()->GetUVWdot(1)-state_target; break;
-  case tVdot: state_value=fdmex->GetTranslation()->GetUVWdot(2)-state_target; break;
-  case tWdot: state_value=fdmex->GetTranslation()->GetUVWdot(3)-state_target; break;
-  case tQdot: state_value=fdmex->GetRotation()->GetPQRdot(2)-state_target;break;
-  case tPdot: state_value=fdmex->GetRotation()->GetPQRdot(1)-state_target; break;
-  case tRdot: state_value=fdmex->GetRotation()->GetPQRdot(3)-state_target; break;
+  case tUdot: state_value=fdmex->GetPropagate()->GetUVWdot(1)-state_target; break;
+  case tVdot: state_value=fdmex->GetPropagate()->GetUVWdot(2)-state_target; break;
+  case tWdot: state_value=fdmex->GetPropagate()->GetUVWdot(3)-state_target; break;
+  case tQdot: state_value=fdmex->GetPropagate()->GetPQRdot(2)-state_target;break;
+  case tPdot: state_value=fdmex->GetPropagate()->GetPQRdot(1)-state_target; break;
+  case tRdot: state_value=fdmex->GetPropagate()->GetPQRdot(3)-state_target; break;
   case tHmgt: state_value=computeHmgt()-state_target; break;
   case tNlf:  state_value=fdmex->GetAircraft()->GetNlf()-state_target; break;
   case tAll: break;
@@ -181,19 +181,19 @@ void FGTrimAxis::getState(void) {
 void FGTrimAxis::getControl(void) {
   switch(control) {
   case tThrottle:  control_value=fdmex->GetFCS()->GetThrottleCmd(0); break;
-  case tBeta:      control_value=fdmex->GetTranslation()->Getalpha(); break;
-  case tAlpha:     control_value=fdmex->GetTranslation()->Getbeta();  break;
+  case tBeta:      control_value=fdmex->GetAuxiliary()->Getalpha(); break;
+  case tAlpha:     control_value=fdmex->GetAuxiliary()->Getbeta();  break;
   case tPitchTrim: control_value=fdmex->GetFCS() -> GetPitchTrimCmd(); break;
   case tElevator:  control_value=fdmex->GetFCS() -> GetDeCmd(); break;
   case tRollTrim:
   case tAileron:   control_value=fdmex->GetFCS() -> GetDaCmd(); break;
   case tYawTrim:
   case tRudder:    control_value=fdmex->GetFCS() -> GetDrCmd(); break;
-  case tAltAGL:    control_value=fdmex->GetPosition()->GetDistanceAGL();break;
-  case tTheta:     control_value=fdmex->GetRotation()->Gettht(); break;
-  case tPhi:       control_value=fdmex->GetRotation()->Getphi(); break;
-  case tGamma:     control_value=fdmex->GetPosition()->GetGamma();break;
-  case tHeading:   control_value=fdmex->GetRotation()->Getpsi(); break;
+  case tAltAGL:    control_value=fdmex->GetPropagate()->GetDistanceAGL();break;
+  case tTheta:     control_value=fdmex->GetPropagate()->Gettht(); break;
+  case tPhi:       control_value=fdmex->GetPropagate()->Getphi(); break;
+  case tGamma:     control_value=fdmex->GetAuxiliary()->GetGamma();break;
+  case tHeading:   control_value=fdmex->GetPropagate()->Getpsi(); break;
   }
 }
 
@@ -201,10 +201,10 @@ void FGTrimAxis::getControl(void) {
 
 double FGTrimAxis::computeHmgt(void) {
   double diff;
-  
-  diff   = fdmex->GetRotation()->Getpsi() - 
-             fdmex->GetPosition()->GetGroundTrack();
-  
+
+  diff   = fdmex->GetPropagate()->Getpsi() -
+             fdmex->GetAuxiliary()->GetGroundTrack();
+
   if( diff < -M_PI ) {
      return (diff + 2*M_PI);
   } else if( diff > M_PI ) {
@@ -214,7 +214,7 @@ double FGTrimAxis::computeHmgt(void) {
   }
 
 }
-       
+
 /*****************************************************************************/
 
 
@@ -238,22 +238,22 @@ void FGTrimAxis::setControl(void) {
 }
 
 
-  
+
 
 
 /*****************************************************************************/
 
 // the aircraft center of rotation is no longer the cg once the gear
-// contact the ground so the altitude needs to be changed when pitch 
-// and roll angle are adjusted.  Instead of attempting to calculate the 
+// contact the ground so the altitude needs to be changed when pitch
+// and roll angle are adjusted.  Instead of attempting to calculate the
 // new center of rotation, pick a gear unit as a reference and use its
 // location vector to calculate the new height change. i.e. new altitude =
-// earth z component of that vector (which is in body axes )  
+// earth z component of that vector (which is in body axes )
 void FGTrimAxis::SetThetaOnGround(double ff) {
   int center,i,ref;
 
   // favor an off-center unit so that the same one can be used for both
-  // pitch and roll.  An on-center unit is used (for pitch)if that's all 
+  // pitch and roll.  An on-center unit is used (for pitch)if that's all
   // that's in contact with the ground.
   i=0; ref=-1; center=-1;
   while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) {
@@ -262,45 +262,47 @@ void FGTrimAxis::SetThetaOnGround(double ff) {
         ref=i;
       else
         center=i;
-    } 
-    i++; 
+    }
+    i++;
   }
   if((ref < 0) && (center >= 0)) {
     ref=center;
   }
   cout << "SetThetaOnGround ref gear: " << ref << endl;
   if(ref >= 0) {
-    double sp=fdmex->GetRotation()->GetSinphi();
-    double cp=fdmex->GetRotation()->GetCosphi();
-    double lx=fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1);
-    double ly=fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2);
-    double lz=fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3);
+    double sp = fdmex->GetPropagate()->GetSinphi();
+    double cp = fdmex->GetPropagate()->GetCosphi();
+    double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1);
+    double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2);
+    double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3);
     double hagl = -1*lx*sin(ff) +
                     ly*sp*cos(ff) +
                     lz*cp*cos(ff);
-   
+
     fgic->SetAltitudeAGLFtIC(hagl);
     cout << "SetThetaOnGround new alt: " << hagl << endl;
-  }                   
-  fgic->SetPitchAngleRadIC(ff);  
-  cout << "SetThetaOnGround new theta: " << ff << endl;      
-}      
+  }
+  fgic->SetPitchAngleRadIC(ff);
+  cout << "SetThetaOnGround new theta: " << ff << endl;
+}
 
 /*****************************************************************************/
 
 bool FGTrimAxis::initTheta(void) {
-  int i,N,iAft, iForward;
-  double zAft,zForward,zDiff,theta; 
+  int i,N;
+  int iForward = 0;
+  int iAft = 1;
+  double zAft,zForward,zDiff,theta;
   double xAft,xForward,xDiff;
-  bool level;  
+  bool level;
   double saveAlt;
-  
+
   saveAlt=fgic->GetAltitudeAGLFtIC();
   fgic->SetAltitudeAGLFtIC(100);
-  
-  
+
+
   N=fdmex->GetGroundReactions()->GetNumGearUnits();
-  
+
   //find the first wheel unit forward of the cg
   //the list is short so a simple linear search is fine
   for( i=0; i<N; i++ ) {
@@ -316,48 +318,43 @@ bool FGTrimAxis::initTheta(void) {
         break;
     }
   }
-         
-  // now adjust theta till the wheels are the same distance from the ground
-   xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(1);
-   xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(1);
-   xDiff = xForward - xAft;
-   zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3);
-   zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3);
-   zDiff = zForward - zAft;
-   level=false;
-   theta=fgic->GetPitchAngleDegIC();
-   while(!level && (i < 100)) {
-     theta+=180.0/M_PI*zDiff/fabs(xDiff);
-     fgic->SetPitchAngleDegIC(theta);
-     fdmex->RunIC();
-     xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(1);
-     xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(1);
-     xDiff = xForward - xAft;
-     zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3);
-     zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3);
-     zDiff = zForward - zAft;
 
+  // now adjust theta till the wheels are the same distance from the ground
+  xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetBodyLocation(1);
+  xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetBodyLocation(1);
+  xDiff = xForward - xAft;
+  zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3);
+  zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3);
+  zDiff = zForward - zAft;
+  level=false;
+  theta=fgic->GetPitchAngleDegIC();
+  while(!level && (i < 100)) {
+    theta+=radtodeg*atan(zDiff/xDiff);
+    fgic->SetPitchAngleDegIC(theta);
+    fdmex->RunIC();
+    zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3);
+    zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3);
     zDiff = zForward - zAft;
-         //cout << endl << theta << "  " << zDiff << endl;
-         //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl;
-         //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl;
-         if(fabs(zDiff ) < 0.1) 
-             level=true;
-         i++;   
-  }                    
+    //cout << endl << theta << "  " << zDiff << endl;
+    //cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl;
+    //cout << "1: " << fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear() << endl;
+    if(fabs(zDiff ) < 0.1)
+        level=true;
+    i++;
+  }
   //cout << i << endl;
   if (debug_lvl > 0) {
-      cout << "    Initial Theta: " << fdmex->GetRotation()->Gettht()*radtodeg << endl;
+      cout << "    Initial Theta: " << fdmex->GetPropagate()->Gettht()*radtodeg << endl;
       cout << "    Used gear unit " << iAft << " as aft and " << iForward << " as forward" << endl;
   }
   control_min=(theta+5)*degtorad;
   control_max=(theta-5)*degtorad;
   fgic->SetAltitudeAGLFtIC(saveAlt);
-  if(i < 100) 
+  if(i < 100)
     return true;
   else
-    return false;  
-} 
+    return false;
+}
 
 /*****************************************************************************/
 
@@ -365,28 +362,28 @@ void FGTrimAxis::SetPhiOnGround(double ff) {
   int i,ref;
 
   i=0; ref=-1;
-  //must have an off-center unit here 
-  while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) {
-    if( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) && 
+  //must have an off-center unit here
+  while ( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) {
+    if ( (fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) &&
       (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01))
         ref=i;
-    i++; 
+    i++;
   }
-  if(ref >= 0) {
-    double st=fdmex->GetRotation()->GetSintht();
-    double ct=fdmex->GetRotation()->GetCostht();
-    double lx=fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1);
-    double ly=fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2);
-    double lz=fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3);
+  if (ref >= 0) {
+    double st = sin(fdmex->GetPropagate()->Gettht());
+    double ct = cos(fdmex->GetPropagate()->Gettht());
+    double lx = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(1);
+    double ly = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(2);
+    double lz = fdmex->GetGroundReactions()->GetGearUnit(ref)->GetBodyLocation(3);
     double hagl = -1*lx*st +
                     ly*sin(ff)*ct +
                     lz*cos(ff)*ct;
-   
+
     fgic->SetAltitudeAGLFtIC(hagl);
-  }                   
+  }
   fgic->SetRollAngleRadIC(ff);
 
-}      
+}
 
 /*****************************************************************************/
 
@@ -432,11 +429,11 @@ void FGTrimAxis::setThrottlesPct(void) {
 /*****************************************************************************/
 
 void FGTrimAxis::AxisReport(void) {
-  
+
   char out[80];
   sprintf(out,"  %20s: %6.2f %5s: %9.2e Tolerance: %3.0e\n",
            GetControlName().c_str(), GetControl()*control_convert,
-           GetStateName().c_str(), GetState()+state_target, GetTolerance()); 
+           GetStateName().c_str(), GetState()+state_target, GetTolerance());
   cout << out;
 
 }
index e329f2c211e430d9ae53cfc60c30244845081ebf..437b04917e10ba085dcc502429972b5c546dd53b 100644 (file)
@@ -1,11 +1,11 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
  Module:       FGTurbine.cpp
- Author:       Jon S. Berndt
- Date started: 08/23/2002
+ Author:       David Culp
+ Date started: 03/11/2003
  Purpose:      This module models a turbine engine.
 
- ------------- Copyright (C) 2002  Jon S. Berndt (jsb@hal-pc.org) --------------
+ ------------- Copyright (C) 2003  David Culp (davidculp2@comcast.net) ---------
 
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
 FUNCTIONAL DESCRIPTION
 --------------------------------------------------------------------------------
 
-This class descends from the FGEngine class and models a Turbine engine based
+This class descends from the FGEngine class and models a turbine engine based
 on parameters given in the engine config file for this class
 
 HISTORY
 --------------------------------------------------------------------------------
-08/23/2002  JSB  Created
+03/11/2003  DPC  Created
+09/08/2003  DPC  Changed Calculate() and added engine phases
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include <vector>
-#include "FGTurbine.h"
+#include <sstream>
 
+#include "FGTurbine.h"
 
 namespace JSBSim {
 
@@ -54,8 +56,9 @@ CLASS IMPLEMENTATION
 
 FGTurbine::FGTurbine(FGFDMExec* exec, FGConfigFile* cfg) : FGEngine(exec)
 {
+  SetDefaults();
+
   Load(cfg);
-  PowerCommand=0;
   Debug(0);
 }
 
@@ -67,147 +70,367 @@ FGTurbine::~FGTurbine()
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// The main purpose of Calculate() is to determine what phase the engine should
+// be in, then call the corresponding function.
 
-double FGTurbine::Calculate(double dummy)
+double FGTurbine::Calculate(void)
 {
-  double idle,mil,aug;
-  double throttle=FCS->GetThrottlePos(EngineNumber);
-  double dt=State->Getdt();
-  if( dt > 0 ) {
-    PowerCommand+=dt*PowerLag( PowerCommand, 
-                         ThrottleToPowerCommand(throttle) );
-    if(PowerCommand > 100 )
-      PowerCommand=100;
-    else if(PowerCommand < 0 )
-      PowerCommand=0;
-                    
-  } else {
-    PowerCommand=ThrottleToPowerCommand(throttle);
-  }                         
-  
-  mil=MaxMilThrust*ThrustTables[1]->TotalValue();
-  
-  if( PowerCommand <= 50 ) {
-    idle=MaxMilThrust*ThrustTables[0]->TotalValue();
-    Thrust = idle + (mil-idle)*PowerCommand*0.02;
+  TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
+  dt = State->Getdt() * Propulsion->GetRate();
+  ThrottlePos = FCS->GetThrottlePos(EngineNumber);
+  if (ThrottlePos > 1.0) {
+    AugmentCmd = ThrottlePos - 1.0;
+    ThrottlePos -= AugmentCmd;
   } else {
-    aug=MaxAugThrust*ThrustTables[2]->TotalValue();
-    Thrust = mil + (aug-mil)*(PowerCommand-50)*0.02;
-  }    
-  
-  ConsumeFuel();
-  
-  return Thrust;
+    AugmentCmd = 0.0;
+  }
+
+  // When trimming is finished check if user wants engine OFF or RUNNING
+  if ((phase == tpTrim) && (dt > 0)) {
+    if (Running && !Starved) {
+      phase = tpRun;
+      N2 = IdleN2 + ThrottlePos * N2_factor;
+      N1 = IdleN1 + ThrottlePos * N1_factor;
+      OilTemp_degK = 366.0;
+      Cutoff = false;
+      }
+    else {
+      phase = tpOff;
+      Cutoff = true;
+      EGT_degC = TAT;
+      }
+    }
+
+  if (!Running && Cutoff && Starter) {
+     if (phase == tpOff) phase = tpSpinUp;
+     }
+  if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart;
+  if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
+  if (dt == 0) phase = tpTrim;
+  if (Starved) phase = tpOff;
+  if (Stalled) phase = tpStall;
+  if (Seized) phase = tpSeize;
+
+  switch (phase) {
+    case tpOff:    Thrust = Off(); break;
+    case tpRun:    Thrust = Run(); break;
+    case tpSpinUp: Thrust = SpinUp(); break;
+    case tpStart:  Thrust = Start(); break;
+    case tpStall:  Thrust = Stall(); break;
+    case tpSeize:  Thrust = Seize(); break;
+    case tpTrim:   Thrust = Trim(); break;
+    default: Thrust = Off();
+  }
+
+  return Thruster->Calculate(Thrust);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGTurbine::ThrottleToPowerCommand(double throttle) {
-  if( throttle <= 0.77 ) 
-    return 64.94*throttle;
-  else
-    return 217.38*throttle - 117.38;
-}      
+double FGTurbine::Off(void)
+{
+  double qbar = Auxiliary->Getqbar();
+  Running = false;
+  FuelFlow_pph = Seek(&FuelFlow_pph, 0, 1000.0, 10000.0);
+  N1 = Seek(&N1, qbar/10.0, N1/2.0, N1/2.0);
+  N2 = Seek(&N2, qbar/15.0, N2/2.0, N2/2.0);
+  EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3);
+  OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2);
+  OilPressure_psi = N2 * 0.62;
+  NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
+  EPR = Seek(&EPR, 1.0, 0.2, 0.2);
+  Augmentation = false;
+  return 0.0;
+}
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGTurbine::PowerLag(double actual_power, double power_command) {
-  double t, p2;
-  if( power_command >= 50 ) {
-    if( actual_power >= 50 ) {
-      t=5;
-      p2=power_command;
-    } else {
-      p2=60;
-      t=rtau(p2-actual_power);
-    }
+double FGTurbine::Run(void)
+{
+  double idlethrust, milthrust, thrust;
+  double N2norm;   // 0.0 = idle N2, 1.0 = maximum N2
+  idlethrust = MilThrust * ThrustTables[0]->TotalValue();
+  milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
+
+  Running = true;
+  Starter = false;
+
+  N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, delay, delay * 3.0);
+  N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, delay, delay * 2.4);
+  N2norm = (N2 - IdleN2) / N2_factor;
+  thrust = idlethrust + (milthrust * N2norm * N2norm);
+  EGT_degC = TAT + 363.1 + ThrottlePos * 357.1;
+  OilPressure_psi = N2 * 0.62;
+  OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1);
+
+  if (!Augmentation) {
+    double correctedTSFC = TSFC + TSFC - (N2norm * TSFC);
+    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 100000);
+    if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
+    NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
+    thrust = thrust * (1.0 - BleedDemand);
+    EPR = 1.0 + thrust/MilThrust;
+  }
+
+  if (AugMethod == 1) {
+    if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;}
+    else {Augmentation = false;}
+  }
+
+  if ((Augmented == 1) && Augmentation && (AugMethod < 2)) {
+    thrust = MaxThrust * ThrustTables[2]->TotalValue();
+    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
+    NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
+  }
+
+  if ((AugmentCmd > 0.0) && (AugMethod == 2)) {
+    Augmentation = true;
+    double tdiff = (MaxThrust * ThrustTables[2]->TotalValue()) - thrust;
+    thrust += (tdiff * AugmentCmd);
+    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
+    NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
   } else {
-    if( actual_power >= 50 ) {
-      t=5;
-      p2=40;
-    } else {
-      p2=power_command;
-      t=rtau(p2-actual_power);
-    }
+    Augmentation = false;
   }
-  return t*(p2-actual_power);
-}    
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGTurbine::rtau(double delta_power) {
-  if( delta_power <= 25 ) 
-    return 1.0;
-  else if ( delta_power >= 50)
-    return 0.1;
-  else
-    return 1.9-0.036*delta_power;
+  if ((Injected == 1) && Injection)
+    thrust = thrust * ThrustTables[3]->TotalValue();
+
+  ConsumeFuel();
+  if (Cutoff) phase = tpOff;
+  if (Starved) phase = tpOff;
+
+  return thrust;
 }
-        
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurbine::doInlet(void)
+double FGTurbine::SpinUp(void)
 {
+  Running = false;
+  FuelFlow_pph = 0.0;
+  N2 = Seek(&N2, 25.18, 3.0, N2/2.0);
+  N1 = Seek(&N1, 5.21, 1.0, N1/2.0);
+  EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3);
+  OilPressure_psi = N2 * 0.62;
+  OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2);
+  EPR = 1.0;
+  NozzlePosition = 1.0;
+  return 0.0;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurbine::doCompressor(void)
+double FGTurbine::Start(void)
 {
+  if ((N2 > 15.0) && !Starved) {       // minimum 15% N2 needed for start
+    Cranking = true;                   // provided for sound effects signal
+    if (N2 < IdleN2) {
+      N2 = Seek(&N2, IdleN2, 2.0, N2/2.0);
+      N1 = Seek(&N1, IdleN1, 1.4, N1/2.0);
+      EGT_degC = Seek(&EGT_degC, TAT + 363.1, 21.3, 7.3);
+      FuelFlow_pph = Seek(&FuelFlow_pph, IdleFF, 103.7, 103.7);
+      OilPressure_psi = N2 * 0.62;
+      }
+    else {
+      phase = tpRun;
+      Running = true;
+      Starter = false;
+      Cranking = false;
+      }
+    }
+  else {                 // no start if N2 < 15%
+    phase = tpOff;
+    Starter = false;
+    }
+
+  return 0.0;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurbine::doBleedDuct(void)
+double FGTurbine::Stall(void)
 {
+  double qbar = Auxiliary->Getqbar();
+  EGT_degC = TAT + 903.14;
+  FuelFlow_pph = IdleFF;
+  N1 = Seek(&N1, qbar/10.0, 0, N1/10.0);
+  N2 = Seek(&N2, qbar/15.0, 0, N2/10.0);
+  if (ThrottlePos < 0.01) phase = tpRun;        // clear the stall with throttle
+
+  return 0.0;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurbine::doCombustor(void)
+double FGTurbine::Seize(void)
 {
+    double qbar = Auxiliary->Getqbar();
+    N2 = 0.0;
+    N1 = Seek(&N1, qbar/20.0, 0, N1/15.0);
+    FuelFlow_pph = IdleFF;
+    OilPressure_psi = 0.0;
+    OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0, 0.2);
+    Running = false;
+    return 0.0;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurbine::doTurbine(void)
+double FGTurbine::Trim(void)
 {
+    double idlethrust, milthrust, thrust, tdiff;
+    idlethrust = MilThrust * ThrustTables[0]->TotalValue();
+    milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
+    thrust = (idlethrust + (milthrust * ThrottlePos * ThrottlePos)) * (1.0 - BleedDemand);
+    if (AugmentCmd > 0.0) {
+      tdiff = (MaxThrust * ThrustTables[2]->TotalValue()) - thrust;
+      thrust += (tdiff * AugmentCmd);
+      }
+    return thrust;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurbine::doConvergingNozzle(void)
+double FGTurbine::CalcFuelNeed(void)
 {
+  return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurbine::doTransition(void)
-{
+double FGTurbine::GetPowerAvailable(void) {
+  if( ThrottlePos <= 0.77 )
+    return 64.94*ThrottlePos;
+  else
+    return 217.38*ThrottlePos - 117.38;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurbine::Seek(double *var, double target, double accel, double decel) {
+  double v = *var;
+  if (v > target) {
+    v -= dt * decel;
+    if (v < target) v = target;
+  } else if (v < target) {
+    v += dt * accel;
+    if (v > target) v = target;
+  }
+  return v;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+void FGTurbine::SetDefaults(void)
+{
+  Name = "Not defined";
+  N1 = N2 = 0.0;
+  Type = etTurbine;
+  MilThrust = 10000.0;
+  MaxThrust = 10000.0;
+  BypassRatio = 0.0;
+  TSFC = 0.8;
+  ATSFC = 1.7;
+  IdleN1 = 30.0;
+  IdleN2 = 60.0;
+  MaxN1 = 100.0;
+  MaxN2 = 100.0;
+  Augmented = 0;
+  AugMethod = 0;
+  Injected = 0;
+  BleedDemand = 0.0;
+  ThrottlePos = 0.0;
+  AugmentCmd = 0.0;
+  InletPosition = 1.0;
+  NozzlePosition = 1.0;
+  Augmentation = false;
+  Injection = false;
+  Reversed = false;
+  Cutoff = true;
+  phase = tpOff;
+  Stalled = false;
+  Seized = false;
+  Overtemp = false;
+  Fire = false;
+  EGT_degC = 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 bool FGTurbine::Load(FGConfigFile *Eng_cfg)
 {
-  int i;
   string token;
+
   Name = Eng_cfg->GetValue("NAME");
-  cout << Name << endl;
   Eng_cfg->GetNextConfigLine();
-  *Eng_cfg >> token >> MaxMilThrust;
-  *Eng_cfg >> token >> MaxAugThrust;
-  i=0;
-  while( Eng_cfg->GetValue() != string("/FG_TURBINE") && i < 10){
-    ThrustTables.push_back( new FGCoefficient(FDMExec) );
-    ThrustTables.back()->Load(Eng_cfg);
-    i++;
+  int counter=0;
+
+  while ( ((token = Eng_cfg->GetValue()) != string("/FG_TURBINE")) &&
+          (token != string("/FG_SIMTURBINE")) ) {
+    *Eng_cfg >> token;
+
+    if (token[0] == '<') token.erase(0,1); // Tables are read "<TABLE"
+
+    if      (token == "MILTHRUST") *Eng_cfg >> MilThrust;
+    else if (token == "MAXTHRUST") *Eng_cfg >> MaxThrust;
+    else if (token == "BYPASSRATIO") *Eng_cfg >> BypassRatio;
+    else if (token == "BLEED") *Eng_cfg >> BleedDemand;
+    else if (token == "TSFC") *Eng_cfg >> TSFC;
+    else if (token == "ATSFC") *Eng_cfg >> ATSFC;
+    else if (token == "IDLEN1") *Eng_cfg >> IdleN1;
+    else if (token == "IDLEN2") *Eng_cfg >> IdleN2;
+    else if (token == "MAXN1") *Eng_cfg >> MaxN1;
+    else if (token == "MAXN2") *Eng_cfg >> MaxN2;
+    else if (token == "AUGMENTED") *Eng_cfg >> Augmented;
+    else if (token == "AUGMETHOD") *Eng_cfg >> AugMethod;
+    else if (token == "INJECTED") *Eng_cfg >> Injected;
+    else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle;
+    else if (token == "TABLE") {
+      if (counter++ == 0) Debug(2); // print engine specs prior to table read
+      ThrustTables.push_back( new FGCoefficient(FDMExec) );
+      ThrustTables.back()->Load(Eng_cfg);
+    }
+    else cerr << "Unhandled token in Engine config file: " << token << endl;
   }
 
+  // Pre-calculations and initializations
+
+  delay = 60.0 / (BypassRatio + 3.0);
+  N1_factor = MaxN1 - IdleN1;
+  N2_factor = MaxN2 - IdleN2;
+  OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
+  IdleFF = pow(MilThrust, 0.2) * 107.0;  // just an estimate
+
   return true;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGTurbine::GetEngineLabels(void)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_N1[" << EngineNumber << "], "
+      << Name << "_N2[" << EngineNumber << "], "
+      << Thruster->GetThrusterLabels(EngineNumber);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGTurbine::GetEngineValues(void)
+{
+  std::ostringstream buf;
+
+  buf << N1 << ", "
+      << N2 << ", "
+      << Thruster->GetThrusterValues(EngineNumber);
+
+  return buf.str();
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
@@ -235,6 +458,24 @@ void FGTurbine::Debug(int from)
     if (from == 0) { // Constructor
 
     }
+    if (from == 2) { // called from Load()
+      cout << "\n    Engine Name: "         << Name << endl;
+      cout << "      MilThrust:   "         << MilThrust << endl;
+      cout << "      MaxThrust:   "         << MaxThrust << endl;
+      cout << "      BypassRatio: "         << BypassRatio << endl;
+      cout << "      TSFC:        "         << TSFC << endl;
+      cout << "      ATSFC:       "         << ATSFC << endl;
+      cout << "      IdleN1:      "         << IdleN1 << endl;
+      cout << "      IdleN2:      "         << IdleN2 << endl;
+      cout << "      MaxN1:       "         << MaxN1 << endl;
+      cout << "      MaxN2:       "         << MaxN2 << endl;
+      cout << "      Augmented:   "         << Augmented << endl;
+      cout << "      AugMethod:   "         << AugMethod << endl;
+      cout << "      Injected:    "         << Injected << endl;
+      cout << "      MinThrottle: "         << MinThrottle << endl;
+
+      cout << endl;
+    }
   }
   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
     if (from == 0) cout << "Instantiated: FGTurbine" << endl;
index a7c488bc6f07138d14903bfafa475062a942722f..8361595c7d6f1bcc1f598aa522e39763cb695daf 100644 (file)
@@ -1,10 +1,10 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
  Header:       FGTurbine.h
- Author:       Jon S. Berndt
- Date started: 08/23/2002
+ Author:       David Culp
+ Date started: 03/11/2003
 
- ------------- Copyright (C) 2002  Jon S. Berndt (jsb@hal-pc.org) --------------
+ ------------- Copyright (C) 2003  David Culp (davidculp2@comcast.net)----------
 
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
@@ -25,7 +25,9 @@
 
 HISTORY
 --------------------------------------------------------------------------------
-08/23/2002  JSB  Created
+03/11/2003  DPC  Created, based on FGTurbine
+09/22/2003  DPC  Added starting, stopping, new framework
+04/29/2004  DPC  Renamed from FGSimTurbine to FGTurbine
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 SENTRY
@@ -51,6 +53,83 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** This class models a turbine engine.  Based on Jon Berndt's FGTurbine module.
+    Here the term "phase" signifies the engine's mode of operation.  At any given
+    time the engine is in only one phase.  At simulator startup the engine will be
+    placed in the Trim phase in order to provide a simplified thrust value without
+    throttle lag.  When trimming is complete the engine will go to the Off phase,
+    unless the value FGEngine::Running has been previously set to true, in which
+    case the engine will go to the Run phase.  Once an engine is in the Off phase
+    the full starting procedure (or airstart) must be used to get it running.
+<P>
+    - STARTING (on ground):
+      -# Set the control FGEngine::Starter to true.  The engine will spin up to
+         a maximum of about %25 N2 (%5.2 N1).  This simulates the action of a
+         pneumatic starter.
+      -# After reaching %15 N2 set the control FGEngine::Cutoff to false. If fuel
+         is available the engine will now accelerate to idle.  The starter will
+         automatically be set to false after the start cycle.
+<P>
+    - STARTING (in air):
+      -# Increase speed to obtain a minimum of %15 N2.  If this is not possible,
+         the starter may be used to assist.
+      -# Place the control FGEngine::Cutoff to false.
+<P>
+    Ignition is assumed to be on anytime the Cutoff control is set to false,
+    therefore a seperate ignition system is not modeled.
+
+Configuration File Format
+<pre>
+\<FG_TURBINE NAME="<name>">
+  MILTHRUST   \<thrust>
+  MAXTHRUST   \<thrust>
+  BYPASSRATIO \<bypass ratio>
+  TSFC        \<thrust specific fuel consumption>
+  ATSFC       \<afterburning thrust specific fuel consumption>
+  IDLEN1      \<idle N1>
+  IDLEN2      \<idle N2>
+  MAXN1       \<max N1>
+  MAXN2       \<max N2>
+  AUGMENTED   \<0|1>
+  AUGMETHOD   \<0|1>
+  INJECTED    \<0|1>
+  ...
+\</FG_TURBINE>
+</pre>
+Definition of the turbine engine configuration file parameters:
+<pre>
+<b>MILTHRUST</b> - Maximum thrust, static, at sea level, lbf.
+<b>MAXTHRUST</b> - Afterburning thrust, static, at sea level, lbf
+[this value will be ignored when AUGMENTED is zero (false)].
+<b>BYPASSRATIO</b> - Ratio of bypass air flow to core air flow.
+<b>TSFC</b> - Thrust-specific fuel consumption, lbm/hr/lbf
+[i.e. fuel flow divided by thrust].
+<b>ATSFC</b> - Afterburning TSFC, lbm/hr/lbf
+[this value will be ignored when AUGMENTED is zero (false)]
+<b>IDLEN1</b> - Fan rotor rpm (% of max) at idle
+<b>IDLEN2</b> - Core rotor rpm (% of max) at idle
+<b>MAXN1</b> - Fan rotor rpm (% of max) at full throttle [not always 100!]
+<b>MAXN2</b> - Core rotor rpm (% of max) at full throttle [not always 100!]
+<b>AUGMENTED</b>
+  0 == afterburner not installed
+  1 == afterburner installed
+<b>AUGMETHOD</b>
+  0 == afterburner activated by property /engines/engine[n]/augmentation
+  1 == afterburner activated by pushing throttle above 99% position
+  2 == throttle range is expanded in the FCS, and values above 1.0 are afterburner range
+  [this item will be ignored when AUGMENTED == 0]
+<b>INJECTED</b>
+  0 == Water injection not installed
+  1 == Water injection installed
+</pre>
+    @author David P. Culp
+    @version "$Id$"
+*/
+
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DECLARATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -58,38 +137,112 @@ CLASS DECLARATION
 class FGTurbine : public FGEngine
 {
 public:
-  FGTurbine(FGFDMExec* exec, FGConfigFile* Eng_cfg);
+  /** Constructor
+      @param Executive pointer to executive structure
+      @param Eng_cfg pointer to engine config file instance */
+  FGTurbine(FGFDMExec* Executive, FGConfigFile* Eng_cfg);
+  /// Destructor
   ~FGTurbine();
 
-  double Calculate(double);
-  double GetPowerAvailable(void) { return PowerCommand; }
+  enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
+
+  double Calculate(void);
+  double CalcFuelNeed(void);
+  double GetPowerAvailable(void);
+  double Seek(double* var, double target, double accel, double decel);
+
+  phaseType GetPhase(void) { return phase; }
+
+  bool GetOvertemp(void)  {return Overtemp; }
+  bool GetInjection(void) {return Injection;}
+  bool GetFire(void) { return Fire; }
+  bool GetAugmentation(void) {return Augmentation;}
+  bool GetReversed(void) { return Reversed; }
+  bool GetCutoff(void) { return Cutoff; }
+  int GetIgnition(void) {return Ignition;}
+
+  double GetInlet(void) { return InletPosition; }
+  double GetNozzle(void) { return NozzlePosition; }
+  double GetBleedDemand(void) {return BleedDemand;}
+  double GetN1(void) {return N1;}
+  double GetN2(void) {return N2;}
+  double GetEPR(void) {return EPR;}
+  double GetEGT(void) {return EGT_degC;}
+
+  double getOilPressure_psi () const {return OilPressure_psi;}
+  double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);}
+
+  void SetInjection(bool injection) {Injection = injection;}
+  void SetIgnition(int ignition) {Ignition = ignition;}
+  void SetAugmentation(bool augmentation) {Augmentation = augmentation;}
+  void SetPhase( phaseType p ) { phase = p; }
+  void SetEPR(double epr) {EPR = epr;}
+  void SetBleedDemand(double bleedDemand) {BleedDemand = bleedDemand;}
+  void SetReverse(bool reversed) { Reversed = reversed; }
+  void SetCutoff(bool cutoff) { Cutoff = cutoff; }
+
+  string GetEngineLabels(void);
+  string GetEngineValues(void);
 
 private:
+
   typedef vector<FGCoefficient*> CoeffArray;
   CoeffArray ThrustTables;
 
-  string name;
-  double MaxMilThrust;
-  double MaxAugThrust;
-  
-  double PowerCommand;
-  
-  double ThrottleToPowerCommand(double throttle);
-  double PowerLag(double actual_power, double power_command);
-  double rtau(double delta_power);
-
-  void doInlet(void);
-  void doCompressor(void);
-  void doBleedDuct(void);
-  void doCombustor(void);
-  void doTurbine(void);
-  void doConvergingNozzle(void);
-
-  void doTransition(void);
-
+  phaseType phase;         ///< Operating mode, or "phase"
+  double MilThrust;        ///< Maximum Unaugmented Thrust, static @ S.L. (lbf)
+  double MaxThrust;        ///< Maximum Augmented Thrust, static @ S.L. (lbf)
+  double BypassRatio;      ///< Bypass Ratio
+  double TSFC;             ///< Thrust Specific Fuel Consumption (lbm/hr/lbf)
+  double ATSFC;            ///< Augmented TSFC (lbm/hr/lbf)
+  double IdleN1;           ///< Idle N1
+  double IdleN2;           ///< Idle N2
+  double N1;               ///< N1
+  double N2;               ///< N2
+  double MaxN1;            ///< N1 at 100% throttle
+  double MaxN2;            ///< N2 at 100% throttle
+  double IdleFF;           ///< Idle Fuel Flow (lbm/hr)
+  double delay;            ///< Inverse spool-up time from idle to 100% (seconds)
+  double dt;               ///< Simulator time slice
+  double N1_factor;        ///< factor to tie N1 and throttle
+  double N2_factor;        ///< factor to tie N2 and throttle
+  double ThrottlePos;      ///< FCS-supplied throttle position
+  double AugmentCmd;       ///< modulated afterburner command (0.0 to 1.0)
+  double TAT;              ///< total air temperature (deg C)
+  bool Stalled;            ///< true if engine is compressor-stalled
+  bool Seized;             ///< true if inner spool is seized
+  bool Overtemp;           ///< true if EGT exceeds limits
+  bool Fire;               ///< true if engine fire detected
+  bool Injection;
+  bool Augmentation;
+  bool Reversed;
+  bool Cutoff;
+  int Injected;            ///< = 1 if water injection installed
+  int Ignition;
+  int Augmented;           ///< = 1 if augmentation installed
+  int AugMethod;           ///< = 0 if using property /engine[n]/augmentation
+                           ///< = 1 if using last 1% of throttle movement
+                           ///< = 2 if using FCS-defined throttle
+  double EGT_degC;
+  double EPR;
+  double OilPressure_psi;
+  double OilTemp_degK;
+  double BleedDemand;
+  double InletPosition;
+  double NozzlePosition;
+
+  double Off(void);
+  double Run(void);
+  double SpinUp(void);
+  double Start(void);
+  double Stall(void);
+  double Seize(void);
+  double Trim(void);
+
+  void SetDefaults(void);
   bool Load(FGConfigFile *ENG_cfg);
-
   void Debug(int from);
+
 };
 }
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/FGUtility.cpp b/src/FDM/JSBSim/FGUtility.cpp
deleted file mode 100644 (file)
index c6d0b20..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGUtility.cpp
- Author:       Jon Berndt
- Date started: 01/09/99
- Purpose:      Contains utility classes for the FG FDM
- Called by:    FGPosition, et. al.
-
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-This class is a container for all utility classes used by the flight dynamics
-model.
-
-HISTORY
---------------------------------------------------------------------------------
-01/09/99   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-                                                        
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <cmath>
-#  else
-#    include <math.h>
-#  endif
-#else
-#  if defined(sgi) && !defined(__GNUC__)
-#    include <math.h>
-#  else
-#    include <cmath>
-#  endif
-#endif
-
-#include "FGUtility.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_UTILITY;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGUtility::FGUtility()
-{
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGUtility::~FGUtility()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    The bitmasked value choices are as follows:
-//    unset: In this case (the default) JSBSim would only print
-//       out the normally expected messages, essentially echoing
-//       the config files as they are read. If the environment
-//       variable is not set, debug_lvl is set to 1 internally
-//    0: This requests JSBSim not to output any messages
-//       whatsoever.
-//    1: This value explicity requests the normal JSBSim
-//       startup messages
-//    2: This value asks for a message to be printed out when
-//       a class is instantiated
-//    4: When this value is set, a message is displayed when a
-//       FGModel object executes its Run() method
-//    8: When this value is set, various runtime state variables
-//       are printed out periodically
-//    16: When set various parameters are sanity checked and
-//       a message is printed out when they go out of bounds
-
-void FGUtility::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGUtility" << endl;
-    if (from == 1) cout << "Destroyed:    FGUtility" << endl;
-  }
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
-  }
-  if (debug_lvl & 8 ) { // Runtime state variables
-  }
-  if (debug_lvl & 16) { // Sanity checking
-  }
-  if (debug_lvl & 64) {
-    if (from == 0) { // Constructor
-      cout << IdSrc << endl;
-      cout << IdHdr << endl;
-    }
-  }
-}
-}
diff --git a/src/FDM/JSBSim/FGUtility.h b/src/FDM/JSBSim/FGUtility.h
deleted file mode 100644 (file)
index 3aa34c5..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGUtility.h
- Author:       Jon Berndt
- Date started: 01/09/99
-
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA  02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-HISTORY
---------------------------------------------------------------------------------
-01/09/99   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGUTILITY_H
-#define FGUTILITY_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGJSBBase.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_UTILITY "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGFDMExec;
-class FGState;
-
-class FGUtility : public FGJSBBase
-{
-public:
-  FGUtility(void);
-  ~FGUtility();
-
-private:
-  FGState* State;
-  FGFDMExec* FDMExec;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
index ebcacf96d3e0e36d159611091fe635d67e94c14a..ec9eb014b18b1420cc219ab0dbda688306659688 100644 (file)
 #include <FDM/JSBSim/FGFDMExec.h>
 #include <FDM/JSBSim/FGAircraft.h>
 #include <FDM/JSBSim/FGFCS.h>
-#include <FDM/JSBSim/FGPosition.h>
-#include <FDM/JSBSim/FGRotation.h>
+#include <FDM/JSBSim/FGPropagate.h>
 #include <FDM/JSBSim/FGState.h>
-#include <FDM/JSBSim/FGTranslation.h>
 #include <FDM/JSBSim/FGAuxiliary.h>
 #include <FDM/JSBSim/FGInitialCondition.h>
 #include <FDM/JSBSim/FGTrim.h>
 #include <FDM/JSBSim/FGPropertyManager.h>
 #include <FDM/JSBSim/FGEngine.h>
 #include <FDM/JSBSim/FGPiston.h>
-#include <FDM/JSBSim/FGSimTurbine.h>
+#include <FDM/JSBSim/FGTurbine.h>
 #include <FDM/JSBSim/FGRocket.h>
+#include <FDM/JSBSim/FGElectric.h>
 #include <FDM/JSBSim/FGNozzle.h>
 #include <FDM/JSBSim/FGPropeller.h>
 #include <FDM/JSBSim/FGRotor.h>
+#include <FDM/JSBSim/FGTank.h>
 #include "JSBSim.hxx"
 
 static inline double
@@ -117,9 +117,7 @@ FGJSBsim::FGJSBsim( double dt )
     MassBalance     = fdmex->GetMassBalance();
     Propulsion      = fdmex->GetPropulsion();
     Aircraft        = fdmex->GetAircraft();
-    Translation     = fdmex->GetTranslation();
-    Rotation        = fdmex->GetRotation();
-    Position        = fdmex->GetPosition();
+    Propagate        = fdmex->GetPropagate();
     Auxiliary       = fdmex->GetAuxiliary();
     Aerodynamics    = fdmex->GetAerodynamics();
     GroundReactions = fdmex->GetGroundReactions();
@@ -127,10 +125,9 @@ FGJSBsim::FGJSBsim( double dt )
     fgic=fdmex->GetIC();
     needTrim=true;
 
-    SGPath aircraft_path( globals->get_fg_root() );
-    aircraft_path.append( "Aircraft" );
+    SGPath aircraft_path( fgGetString("/sim/aircraft-dir") );
 
-    SGPath engine_path( globals->get_fg_root() );
+    SGPath engine_path( fgGetString("/sim/aircraft-dir") );
     engine_path.append( "Engine" );
     State->Setdt( dt );
 
@@ -157,9 +154,9 @@ FGJSBsim::FGJSBsim( double dt )
         SG_LOG( SG_FLIGHT, SG_ALERT, "num gear units = "
                 << GroundReactions->GetNumGearUnits() );
         SG_LOG( SG_FLIGHT, SG_ALERT, "This is a very bad thing because with 0 gear units, the ground trimming");
-         SG_LOG( SG_FLIGHT, SG_ALERT, "routine (coming up later in the code) will core dump.");
-         SG_LOG( SG_FLIGHT, SG_ALERT, "Halting the sim now, and hoping a solution will present itself soon!");
-         exit(-1);
+        SG_LOG( SG_FLIGHT, SG_ALERT, "routine (coming up later in the code) will core dump.");
+        SG_LOG( SG_FLIGHT, SG_ALERT, "Halting the sim now, and hoping a solution will present itself soon!");
+        exit(-1);
     }
 
     init_gear();
@@ -225,8 +222,8 @@ FGJSBsim::FGJSBsim( double dt )
 
     for (unsigned int i = 0; i < Propulsion->GetNumEngines(); i++) {
       SGPropertyNode * node = fgGetNode("engines/engine", i, true);
-      Propulsion->GetThruster(i)->SetRPM(node->getDoubleValue("rpm") /
-                     Propulsion->GetThruster(i)->GetGearRatio());
+      Propulsion->GetEngine(i)->GetThruster()->SetRPM(node->getDoubleValue("rpm") /
+                     Propulsion->GetEngine(i)->GetThruster()->GetGearRatio());
     }
 }
 
@@ -250,6 +247,9 @@ void FGJSBsim::init()
     // Explicitly call the superclass's
     // init method first.
 
+#ifdef FG_WEATHERCM
+    Atmosphere->UseInternal();
+#else
     if (fgGetBool("/environment/params/control-fdm-atmosphere")) {
       Atmosphere->UseExternal();
       Atmosphere->SetExTemperature(
@@ -266,6 +266,7 @@ void FGJSBsim::init()
     } else {
       Atmosphere->UseInternal();
     }
+#endif
 
     fgic->SetVnorthFpsIC( wind_from_north->getDoubleValue() );
     fgic->SetVeastFpsIC( wind_from_east->getDoubleValue() );
@@ -289,19 +290,19 @@ void FGJSBsim::init()
     switch(fgic->GetSpeedSet()) {
     case setned:
         SG_LOG(SG_FLIGHT,SG_INFO, "  Vn,Ve,Vd= "
-               << Position->GetVn() << ", "
-               << Position->GetVe() << ", "
-               << Position->GetVd() << " ft/s");
+               << Propagate->GetVel(eNorth) << ", "
+               << Propagate->GetVel(eEast) << ", "
+               << Propagate->GetVel(eDown) << " ft/s");
     break;
     case setuvw:
         SG_LOG(SG_FLIGHT,SG_INFO, "  U,V,W= "
-               << Translation->GetUVW(1) << ", "
-               << Translation->GetUVW(2) << ", "
-               << Translation->GetUVW(3) << " ft/s");
+               << Propagate->GetUVW(1) << ", "
+               << Propagate->GetUVW(2) << ", "
+               << Propagate->GetUVW(3) << " ft/s");
     break;
     case setmach:
         SG_LOG(SG_FLIGHT,SG_INFO, "  Mach: "
-               << Translation->GetMach() );
+               << Auxiliary->GetMach() );
     break;
     case setvc:
     default:
@@ -313,17 +314,17 @@ void FGJSBsim::init()
     stall_warning->setDoubleValue(0);
 
     SG_LOG( SG_FLIGHT, SG_INFO, "  Bank Angle: "
-            <<  Rotation->Getphi()*RADTODEG << " deg" );
+            << Propagate->Getphi()*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Pitch Angle: "
-            << Rotation->Gettht()*RADTODEG << " deg" );
+            << Propagate->Gettht()*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  True Heading: "
-            << Rotation->Getpsi()*RADTODEG << " deg" );
+            << Propagate->Getpsi()*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Latitude: "
-            << Position->GetLatitude() << " deg" );
+            << Propagate->GetLocation().GetLatitudeDeg() << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Longitude: "
-            << Position->GetLongitude() << " deg" );
+            << Propagate->GetLocation().GetLongitudeDeg() << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Altitude: "
-        << Position->Geth() << " feet" );
+            << Propagate->Geth() << " feet" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  loaded initial conditions" );
 
     SG_LOG( SG_FLIGHT, SG_INFO, "  set dt" );
@@ -441,16 +442,16 @@ bool FGJSBsim::copy_to_JSBsim()
         eng->SetMagnetos( globals->get_controls()->get_magnetos(i) );
         break;
         } // end FGPiston code block
-      case FGEngine::etSimTurbine:
-        { // FGSimTurbine code block
-        FGSimTurbine* eng = (FGSimTurbine*)Propulsion->GetEngine(i);
+      case FGEngine::etTurbine:
+        { // FGTurbine code block
+        FGTurbine* eng = (FGTurbine*)Propulsion->GetEngine(i);
         eng->SetAugmentation( globals->get_controls()->get_augmentation(i) );
         eng->SetReverse( globals->get_controls()->get_reverser(i) );
         eng->SetInjection( globals->get_controls()->get_water_injection(i) );
         eng->SetCutoff( globals->get_controls()->get_cutoff(i) );
         eng->SetIgnition( globals->get_controls()->get_ignition(i) );
         break;
-        } // end FGSimTurbine code block
+        } // end FGTurbine code block
       case FGEngine::etRocket:
         { // FGRocket code block
         FGRocket* eng = (FGRocket*)Propulsion->GetEngine(i);
@@ -466,9 +467,10 @@ bool FGJSBsim::copy_to_JSBsim()
       } // end FGEngine code block
     }
 
     _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() );
-    Position->SetSeaLevelRadius( get_Sea_level_radius() );
-    Position->SetRunwayRadius( get_Runway_altitude()
+    Propagate->SetSeaLevelRadius( get_Sea_level_radius() );
+    Propagate->SetRunwayRadius( get_Runway_altitude()
                                + get_Sea_level_radius() );
 
     Atmosphere->SetExTemperature(
@@ -496,6 +498,8 @@ bool FGJSBsim::copy_to_JSBsim()
       tank->SetContents(node->getDoubleValue("level-gal_us") * 6.6);
 //       tank->SetContents(node->getDoubleValue("level-lb"));
     }
+    SGPropertyNode* node = fgGetNode("/systems/refuel", true);
+    Propulsion->SetRefuel(node->getDoubleValue("contact"));
 
     return true;
 }
@@ -534,72 +538,62 @@ bool FGJSBsim::copy_from_JSBsim()
 
     // Velocities
 
-    _set_Velocities_Local( Position->GetVn(),
-                           Position->GetVe(),
-                           Position->GetVd() );
+    _set_Velocities_Local( Propagate->GetVel(eNorth),
+                           Propagate->GetVel(eEast),
+                           Propagate->GetVel(eDown) );
 
-    _set_Velocities_Wind_Body( Translation->GetUVW(1),
-                               Translation->GetUVW(2),
-                               Translation->GetUVW(3) );
+    _set_Velocities_Wind_Body( Propagate->GetUVW(1),
+                               Propagate->GetUVW(2),
+                               Propagate->GetUVW(3) );
 
     // Make the HUD work ...
-    _set_Velocities_Ground( Position->GetVn(),
-                            Position->GetVe(),
-                            -Position->GetVd() );
+    _set_Velocities_Ground( Propagate->GetVel(eNorth),
+                            Propagate->GetVel(eEast),
+                            -Propagate->GetVel(eDown) );
 
-    _set_V_rel_wind( Translation->GetVt() );
+    _set_V_rel_wind( Auxiliary->GetVt() );
 
     _set_V_equiv_kts( Auxiliary->GetVequivalentKTS() );
 
     _set_V_calibrated_kts( Auxiliary->GetVcalibratedKTS() );
 
-    _set_V_ground_speed( Position->GetVground() );
-
-    _set_Omega_Body( Rotation->GetPQR(1),
-                     Rotation->GetPQR(2),
-                     Rotation->GetPQR(3) );
-
-    _set_Euler_Rates( Rotation->GetEulerRates(1),
-                      Rotation->GetEulerRates(2),
-                      Rotation->GetEulerRates(3) );
+    _set_V_ground_speed( Auxiliary->GetVground() );
 
-    _set_Geocentric_Rates(Position->GetLatitudeDot(),
-                          Position->GetLongitudeDot(),
-                          Position->Gethdot() );
+    _set_Omega_Body( Propagate->GetPQR(eP),
+                     Propagate->GetPQR(eQ),
+                     Propagate->GetPQR(eR) );
 
-    _set_Mach_number( Translation->GetMach() );
+    _set_Euler_Rates( Auxiliary->GetEulerRates(ePhi),
+                      Auxiliary->GetEulerRates(eTht),
+                      Auxiliary->GetEulerRates(ePsi) );
 
-    // Positions
-    _updateGeocentricPosition( Position->GetLatitude(),
-             Position->GetLongitude(),
-             Position->Geth() );
+    _set_Mach_number( Auxiliary->GetMach() );
 
     // Positions of Visual Reference Point
-/*
-    _updateGeocentricPosition( Position->GetLatitudeVRP(),
-             Position->GetLongitudeVRP(),
-             Position->GethVRP() );
-*/
-    _set_Altitude_AGL( Position->GetDistanceAGL() );
+    _updateGeocentricPosition( Auxiliary->GetLocationVRP().GetLatitude(),
+                               Auxiliary->GetLocationVRP().GetLongitude(),
+                               Auxiliary->GethVRP() );
 
-    _set_Euler_Angles( Rotation->Getphi(),
-                       Rotation->Gettht(),
-                       Rotation->Getpsi() );
+    _set_Altitude_AGL( Propagate->GetDistanceAGL() );
 
-    _set_Alpha( Translation->Getalpha() );
-    _set_Beta( Translation->Getbeta() );
+    _set_Euler_Angles( Propagate->Getphi(),
+                       Propagate->Gettht(),
+                       Propagate->Getpsi() );
 
+    _set_Alpha( Auxiliary->Getalpha() );
+    _set_Beta( Auxiliary->Getbeta() );
 
-    _set_Gamma_vert_rad( Position->GetGamma() );
 
-    _set_Earth_position_angle( Auxiliary->GetEarthPositionAngle() );
+    _set_Gamma_vert_rad( Auxiliary->GetGamma() );
 
-    _set_Climb_Rate( Position->Gethdot() );
+    _set_Earth_position_angle( Auxiliary->GetEarthPositionAngle() );
 
+    _set_Climb_Rate( Propagate->Gethdot() );
 
+    const FGMatrix33& Tl2b = Propagate->GetTl2b();
     for ( i = 1; i <= 3; i++ ) {
         for ( j = 1; j <= 3; j++ ) {
-            _set_T_Local_to_Body( i, j, State->GetTl2b(i,j) );
+            _set_T_Local_to_Body( i, j, Tl2b(i,j) );
         }
     }
 
@@ -609,7 +603,7 @@ bool FGJSBsim::copy_from_JSBsim()
       char buf[30];
       sprintf(buf, "engines/engine[%d]/thruster", i);
       SGPropertyNode * tnode = fgGetNode(buf, true);
-      FGThruster * thruster = Propulsion->GetThruster(i);
+      FGThruster * thruster = Propulsion->GetEngine(i)->GetThruster();
 
       switch (Propulsion->GetEngine(i)->GetType()) {
       case FGEngine::etPiston:
@@ -628,9 +622,9 @@ bool FGJSBsim::copy_from_JSBsim()
         FGRocket* eng = (FGRocket*)Propulsion->GetEngine(i);
         } // end FGRocket code block
         break;
-      case FGEngine::etSimTurbine:
-        { // FGSimTurbine code block
-        FGSimTurbine* eng = (FGSimTurbine*)Propulsion->GetEngine(i);
+      case FGEngine::etTurbine:
+        { // FGTurbine code block
+        FGTurbine* eng = (FGTurbine*)Propulsion->GetEngine(i);
         node->setDoubleValue("n1", eng->GetN1());
         node->setDoubleValue("n2", eng->GetN2());
         node->setDoubleValue("egt_degf", 32 + eng->GetEGT()*9/5);
@@ -642,11 +636,18 @@ bool FGJSBsim::copy_from_JSBsim()
         node->setDoubleValue("oil-pressure-psi", eng->getOilPressure_psi());
         node->setBoolValue("reversed", eng->GetReversed());
         node->setBoolValue("cutoff", eng->GetCutoff());
+        node->setDoubleValue("epr", eng->GetEPR());
         globals->get_controls()->set_reverser(i, eng->GetReversed() );
         globals->get_controls()->set_cutoff(i, eng->GetCutoff() );
         globals->get_controls()->set_water_injection(i, eng->GetInjection() );
         globals->get_controls()->set_augmentation(i, eng->GetAugmentation() );
-        } // end FGSimTurbine code block
+        } // end FGTurbine code block
+        break;
+      case FGEngine::etElectric:
+        { // FGElectric code block
+        FGElectric* eng = (FGElectric*)Propulsion->GetEngine(i);
+        node->setDoubleValue("rpm", eng->getRPM());
+        } // end FGElectric code block
         break;
       }
 
@@ -695,10 +696,12 @@ bool FGJSBsim::copy_from_JSBsim()
     if ( ! fuel_freeze->getBoolValue() ) {
       for (i = 0; i < Propulsion->GetNumTanks(); i++) {
         SGPropertyNode * node = fgGetNode("/consumables/fuel/tank", i, true);
-        double contents = Propulsion->GetTank(i)->GetContents();
+        FGTank* tank = Propulsion->GetTank(i);
+        double contents = tank->GetContents();
+        double temp = tank->GetTemperature_degC();
         node->setDoubleValue("level-gal_us", contents/6.6);
         node->setDoubleValue("level-lb", contents);
-        // node->setDoubleValue("temperature_degC",
+        if (temp != -9999.0) node->setDoubleValue("temperature_degC", temp);
       }
     }
 
index 3e11f54ab78ad7bcdcd9f64bd7b07183dd699f5a..d1a54a5a3d66d676293765b5ab97fb70091e4869 100644 (file)
@@ -66,9 +66,7 @@ class FGMassBalance;
 class FGAerodynamics;
 class FGInertial;
 class FGAircraft;
-class FGTranslation;
-class FGRotation;
-class FGPosition;
+class FGPropagate;
 class FGAuxiliary;
 class FGOutput;
 class FGInitialCondition;
@@ -116,17 +114,17 @@ public:
     //@{
     /** Set geocentric latitude
         @param lat latitude in radians measured from the 0 meridian where
-                        the westerly direction is positive and east is negative */
+                   the westerly direction is positive and east is negative */
     void set_Latitude(double lat);  // geocentric
 
     /** Set longitude
         @param lon longitude in radians measured from the equator where
-                        the northerly direction is positive and south is negative */
+                   the northerly direction is positive and south is negative */
     void set_Longitude(double lon);
 
     /** Set altitude
         Note: this triggers a recalculation of AGL altitude
-             @param alt altitude in feet */
+        @param alt altitude in feet */
     void set_Altitude(double alt);        // triggers re-calc of AGL altitude
     //@}
 
@@ -136,33 +134,33 @@ public:
     //@{
     /** Sets calibrated airspeed
         Setting this will trigger a recalc of the other velocity terms.
-             @param vc Calibrated airspeed in ft/sec */
+        @param vc Calibrated airspeed in ft/sec */
     void set_V_calibrated_kts(double vc);
 
     /** Sets Mach number.
         Setting this will trigger a recalc of the other velocity terms.
-             @param mach Mach number */
+        @param mach Mach number */
     void set_Mach_number(double mach);
 
     /** Sets velocity in N-E-D coordinates.
         Setting this will trigger a recalc of the other velocity terms.
-             @param north velocity northward in ft/sec
-             @param east velocity eastward in ft/sec
-             @param down velocity downward in ft/sec */
+        @param north velocity northward in ft/sec
+        @param east velocity eastward in ft/sec
+        @param down velocity downward in ft/sec */
     void set_Velocities_Local( double north, double east, double down );
 
     /** Sets aircraft velocity in stability frame.
         Setting this will trigger a recalc of the other velocity terms.
-             @param u X velocity in ft/sec
-             @param v Y velocity  in ft/sec
-             @param w Z velocity in ft/sec */
+        @param u X velocity in ft/sec
+        @param v Y velocity  in ft/sec
+        @param w Z velocity in ft/sec */
     void set_Velocities_Wind_Body( double u, double v, double w);
     //@}
 
     /** Euler Angle Parameter Set
         @param phi roll angle in radians
-             @param theta pitch angle in radians
-             @param psi heading angle in radians */
+        @param theta pitch angle in radians
+        @param psi heading angle in radians */
     void set_Euler_Angles( double phi, double theta, double psi );
 
     /// @name Flight Path Parameter Set
@@ -218,9 +216,7 @@ private:
     FGPropulsion*   Propulsion;
     FGMassBalance*  MassBalance;
     FGAircraft*     Aircraft;
-    FGTranslation*  Translation;
-    FGRotation*     Rotation;
-    FGPosition*     Position;
+    FGPropagate*    Propagate;
     FGAuxiliary*    Auxiliary;
     FGAerodynamics* Aerodynamics;
     FGGroundReactions *GroundReactions;
@@ -228,7 +224,7 @@ private:
     int runcount;
     float trim_elev;
     float trim_throttle;
-    
+
     SGPropertyNode *startup_trim;
     SGPropertyNode *trimmed;
     SGPropertyNode *pitch_trim;
@@ -236,14 +232,14 @@ private:
     SGPropertyNode *aileron_trim;
     SGPropertyNode *rudder_trim;
     SGPropertyNode *stall_warning;
-    
+
     /* SGPropertyNode *elevator_pos_deg;
     SGPropertyNode *left_aileron_pos_deg;
     SGPropertyNode *right_aileron_pos_deg;
     SGPropertyNode *rudder_pos_deg;
     SGPropertyNode *flap_pos_deg; */
 
-    
+
     SGPropertyNode *elevator_pos_pct;
     SGPropertyNode *left_aileron_pos_pct;
     SGPropertyNode *right_aileron_pos_pct;
@@ -251,22 +247,22 @@ private:
     SGPropertyNode *flap_pos_pct;
     SGPropertyNode *speedbrake_pos_pct;
     SGPropertyNode *spoilers_pos_pct;
-    
+
     SGPropertyNode *gear_pos_pct;
-    
+
     SGPropertyNode *temperature;
     SGPropertyNode *pressure;
     SGPropertyNode *density;
     SGPropertyNode *turbulence_gain;
     SGPropertyNode *turbulence_rate;
-    
+
     SGPropertyNode *wind_from_north;
     SGPropertyNode *wind_from_east;
     SGPropertyNode *wind_from_down;
-    
+
     void init_gear(void);
     void update_gear(void);
-    
+
 };
 
 
index bbb2d20cfd819dc39bf27bba42e2005bdc71a64e..0f56fe52084bc3940c17fe76ce84f7cf32159b07 100644 (file)
@@ -11,9 +11,7 @@ libJSBSim_a_SOURCES = \
        FGAuxiliary.cpp FGAuxiliary.h \
        FGCoefficient.cpp FGCoefficient.h \
         FGColumnVector3.cpp FGColumnVector3.h \
-        FGColumnVector4.cpp FGColumnVector4.h \
        FGConfigFile.cpp FGConfigFile.h \
-       FGDefs.h \
        FGFCS.cpp FGFCS.h \
        FGFDMExec.cpp FGFDMExec.h \
        FGFactorGroup.cpp FGFactorGroup.h \
@@ -31,25 +29,24 @@ libJSBSim_a_SOURCES = \
         FGPiston.cpp FGPiston.h \
         FGPropeller.cpp FGPropeller.h \
         FGPropulsion.cpp FGPropulsion.h \
-       FGPosition.cpp FGPosition.h \
-       FGRotation.cpp FGRotation.h \
        FGRotor.cpp FGRotor.h \
        FGRocket.cpp FGRocket.h \
        FGScript.cpp FGScript.h \
        FGState.cpp FGState.h \
        FGTable.cpp FGTable.h \
        FGThruster.cpp FGThruster.h \
-       FGTranslation.cpp FGTranslation.h \
        FGTrim.cpp FGTrim.h \
        FGTrimAxis.cpp FGTrimAxis.h \
        FGTurbine.cpp FGTurbine.h \
-       FGUtility.cpp FGUtility.h \
        FGEngine.cpp FGEngine.h \
        FGTank.cpp FGTank.h \
        FGfdmSocket.cpp FGfdmSocket.h \
        FGTurbine.cpp FGTurbine.h \
        FGPropertyManager.cpp FGPropertyManager.h  \
-       FGSimTurbine.cpp FGSimTurbine.h \
+       FGPropagate.cpp FGPropagate.h \
+       FGLocation.cpp FGLocation.h \
+       FGQuaternion.cpp FGQuaternion.h \
+       FGElectric.cpp FGElectric.h \
        JSBSim.cxx JSBSim.hxx
 
 
index c8ba414e8585b23b8ef88aea2c2d0808517c0773..d2c2dd88ac5d4d8de0672e41f2acfe74212b04de 100644 (file)
@@ -3,7 +3,7 @@
  Module:       FGFilter.cpp
  Author:       Jon S. Berndt
  Date started: 11/2000
+
  ------------- Copyright (C) 2000 -------------
 
  This program is free software; you can redistribute it and/or modify it under
@@ -92,7 +92,7 @@ FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
       } else  {
         *AC_cfg >> token;
         InputNodes.push_back( resolveSymbol(token) );
-      }  
+      }
     }
     else if (token == "OUTPUT")
     {
@@ -115,7 +115,7 @@ FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
       denom = 2.00*C3 + dt*C4;
       ca = (2.00*C1 + dt*C2) / denom;
       cb = (dt*C2 - 2.00*C1) / denom;
-      cc = (2.00*C3 - dt*C2) / denom;
+      cc = (2.00*C3 - dt*C4) / denom;
       break;
     case eOrder2:
       denom = 4.0*C4 + 2.0*C5*dt + C6*dt*dt;
@@ -182,7 +182,7 @@ bool FGFilter::Run(void)
         break;
       case eOrder2:
         Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc
-                                 - PreviousOutput1 * cd - PreviousOutput2 * ce;
+                            - PreviousOutput1 * cd - PreviousOutput2 * ce;
         break;
       case eWashout:
         Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
index 567547e586902da12e90f6439394b6b0d59af2c7..6e3f1bd4084d28a89814d237ba89623da0823bb4 100644 (file)
@@ -3,7 +3,7 @@
  Module:       FGGain.cpp
  Author:       Jon S. Berndt
  Date started: 4/2000
+
  ------------- Copyright (C) 2000 -------------
 
  This program is free software; you can redistribute it and/or modify it under
@@ -37,7 +37,7 @@ COMMENTS, REFERENCES,  and NOTES
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include "FGGain.h" 
+#include "FGGain.h"
 
 namespace JSBSim {
 
@@ -64,6 +64,8 @@ FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
   OutputPct = 0;
   invert = false;
   ScheduledBy = 0;
+  clip = false;
+  clipmin = clipmax = 0.0;
 
   Type = AC_cfg->GetValue("TYPE");
   Name = AC_cfg->GetValue("NAME");
@@ -91,23 +93,27 @@ FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
       *AC_cfg >> Min;
     } else if (token == "MAX") {
       *AC_cfg >> Max;
+    } else if (token == "CLIPTO") {
+      *AC_cfg >> clipmin >> clipmax;
+      if (clipmax > clipmin) {
+        clip = true;
+      }
     } else if (token == "INVERT") {
       invert = true;
       cerr << endl << "The INVERT keyword is being deprecated and will not be "
                       "supported in the future. Please use a minus sign in front "
-                                 "of an input property in the future." << endl << endl;
+                      "of an input property in the future." << endl << endl;
     } else if (token == "ROWS") {
       *AC_cfg >> Rows;
       Table = new FGTable(Rows);
     } else if (token == "SCHEDULED_BY") {
       token = AC_cfg->GetValue("SCHEDULED_BY");
       *AC_cfg >> strScheduledBy;
-      ScheduledBy = PropertyManager->GetNode( strScheduledBy ); 
+      ScheduledBy = PropertyManager->GetNode( strScheduledBy );
     } else if (token == "OUTPUT") {
       IsOutput = true;
-      *AC_cfg >> sOutputIdx;      
-      OutputNode = PropertyManager->GetNode( sOutputIdx );
-
+      *AC_cfg >> sOutputIdx;
+      OutputNode = PropertyManager->GetNode( sOutputIdx, true );
     } else {
       AC_cfg->ResetLineIndexToZero();
       *Table << *AC_cfg;
@@ -159,6 +165,11 @@ bool FGGain::Run(void )
 
   }
 
+  if (clip) {
+    if (Output > clipmax)      Output = clipmax;
+    else if (Output < clipmin) Output = clipmin;
+  }
+
   if (IsOutput) SetOutput();
 
   return true;
index 7031d7efd4a156c61bfdab7d20e7aff43e8c7988..ef275e9f7d51dcb2a18b54fd2f36a73d2f08cb5c 100644 (file)
@@ -1,8 +1,8 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
  Header:       FGGain.h
- Author:       
- Date started: 
+ Author:
+ Date started:
 
  ------------- Copyright (C)  -------------
 
@@ -94,6 +94,7 @@ CLASS DOCUMENTATION
       ROWS \<number_of_rows>
       \<lookup_value  gain_value>
       ?
+      [CLIPTO \<min> \<max> 1]
       [OUTPUT \<property>]
     \</COMPONENT>
     </pre>
@@ -170,9 +171,9 @@ class FGGain  : public FGFCSComponent
 public:
   FGGain(FGFCS* fcs, FGConfigFile* AC_cfg);
   ~FGGain();
-  
+
   double GetOutputPct() const { return OutputPct; }
-  
+
   bool Run (void);
 
 private:
@@ -181,8 +182,9 @@ private:
   FGState* State;
   double Gain;
   double Min, Max;
+  double clipmin, clipmax;
   double OutputPct;
-  bool invert;
+  bool invert, clip;
   int Rows;
   FGPropertyManager* ScheduledBy;
 
index feb5e5e8a24a4f878e899174d7e42b4146a7d132..d908fc4e3a309d33a90c19bf11776bb09746ec08 100644 (file)
@@ -121,7 +121,7 @@ bool FGKinemat::Run(void )
 
   Input = InputNodes[0]->getDoubleValue();
 
-  if (DoScale)  Input *= Detents[NumDetents-1];
+  if (DoScale) Input *= Detents[NumDetents-1];
 
   Output = OutputNode->getDoubleValue();
 
@@ -132,7 +132,7 @@ bool FGKinemat::Run(void )
 
   // Process all detent intervals the movement traverses until either the
   // final value is reached or the time interval has finished.
-  while (0.0 < dt && Input != Output) {
+  while ( 0.0 < dt && !EqualToRoundoff(Input, Output) ) {
 
     // Find the area where Output is in
     int ind;
@@ -154,16 +154,20 @@ bool FGKinemat::Run(void )
       if (Detents[ind] < ThisInput)     ThisInput = Detents[ind];
       // Compute the time to reach the value in ThisInput
       double ThisDt = fabs((ThisInput-Output)/Rate);
-      if (ThisDt == 0.0)
-         break;
+
       // and clip to the timestep size
-      if (dt < ThisDt) ThisDt = dt;
+      if (dt < ThisDt) {
+        ThisDt = dt;
+        if (Output < Input)
+          Output += ThisDt*Rate;
+        else
+          Output -= ThisDt*Rate;
+      } else
+        // Handle this case separate to make shure the termination condition
+        // is met even in inexact arithmetics ...
+        Output = ThisInput;
+
       dt -= ThisDt;
-      // Do the output calculation
-      if (Output < Input)
-        Output += ThisDt*Rate;
-      else
-        Output -= ThisDt*Rate;
     }
   }
 
index f00ca9a9a13273ef57d8ca0d1c3892b32ff36651..9c2339af63091f51cefab0d6e8d0cb69da56ad3b 100644 (file)
@@ -77,11 +77,29 @@ CLASS DECLARATION
 
 class FGKinemat  : public FGFCSComponent {
 public:
+  /** Initializer.
+      @param fcs A reference to the ccurrent flightcontrolsystem.
+      @param AC_cfg reference to the current aircraft configuration file.
+      Initializes the FGKinemat object from the given configuration
+      file. The Configuration file is expected to be at the stream
+      position where the KINEMAT object starts. Also it is expected to
+      be past the end of the current KINEMAT configuration on exit.
+   */
   FGKinemat(FGFCS* fcs, FGConfigFile* AC_cfg);
+
+  /** Destructor.
+   */
   ~FGKinemat();
   
+  /** Kinemat output value.
+      @return the current output of the kinemat object on the range of [0,1].
+   */
   double GetOutputPct() const { return OutputPct; }
     
+  /** Run method, overwrites FGModel::Run().
+      @return false on success, true on failure.
+      The routine doing the work.
+   */
   bool Run (void);
   
 private:
index 71f7b0a23346287a2104438eb8215cb59f1e2375..1d369524457f898b7cb7dfc580f28a517653a4e9 100644 (file)
@@ -87,7 +87,7 @@ FGSummer::FGSummer(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
     } else if (token == "OUTPUT") {
       IsOutput = true;
       *AC_cfg >> sOutputIdx;
-      OutputNode = PropertyManager->GetNode(sOutputIdx);
+      OutputNode = PropertyManager->GetNode(sOutputIdx, true);
     }
   }
  
index cf323fcb64e11e6d83286e9addccb1617b2495a0..d5c121775485921e17d95eee743f27898446bd7b 100644 (file)
@@ -75,7 +75,7 @@ FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
 {
   string token, value;
   struct test *current_test;
-  struct FGCondition *current_condition;
+  string sOutputIdx;
 
   Type = AC_cfg->GetValue("TYPE");
   Name = AC_cfg->GetValue("NAME");
@@ -124,8 +124,13 @@ FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
       while (AC_cfg->GetValue() != string("/TEST")) {
         current_test->conditions.push_back(FGCondition(AC_cfg, PropertyManager));
       }
+      AC_cfg->GetNextConfigLine();
+    } else if (token == "OUTPUT") {
+      IsOutput = true;
+      *AC_cfg >> sOutputIdx;
+      *AC_cfg >> sOutputIdx;
+      OutputNode = PropertyManager->GetNode( sOutputIdx, true );
     }
-    AC_cfg->GetNextConfigLine();
   }
 
   FGFCSComponent::bind();
@@ -178,6 +183,8 @@ bool FGSwitch::Run(void )
     *iTests++;
   }
 
+  if (IsOutput) SetOutput();
+
   return true;
 }
 
@@ -256,6 +263,7 @@ void FGSwitch::Debug(int from)
         cout << endl;
         *iTests++;
       }
+      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
     }
   }
   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
index fef43f2c0a597fe6ba3f11347a8db7c1b5ca517b..48247d9ae73220bec4d14334308b1f8f081b092b 100644 (file)
@@ -86,7 +86,7 @@ additional conditions, as well as possibly additional CONDITION_GROUPs.
 
 <pre>
 \<COMPONENT NAME="switch1" TYPE="SWITCH"\>
-  \<TEST LOGIC="{AND|OR|DEFAULT}" OUTPUT="{property|value}"\>
+  \<TEST LOGIC="{AND|OR|DEFAULT}" VALUE="{property|value}"\>
     {property} {conditional} {property|value}
     \<CONDITION_GROUP LOGIC="{AND|OR}"\>
       {property} {conditional} {property|value}
@@ -94,11 +94,12 @@ additional conditions, as well as possibly additional CONDITION_GROUPs.
     \</CONDITION_GROUP\>
     ...
   \</TEST>
-  \<TEST LOGIC="{AND|OR}" OUTPUT="{property|value}"\>
+  \<TEST LOGIC="{AND|OR}" VALUE="{property|value}"\>
     {property} {conditional} {property|value}
     ...
   \</TEST\>
   ...
+  [OUTPUT \<property>]
 \</COMPONENT\>
 </pre>